diff --git a/404.html b/404.html index 2b7476866..6912d3223 100644 --- a/404.html +++ b/404.html @@ -3,8 +3,8 @@ -Page Not Found | Cadence - +Page Not Found | Cadence + @@ -15,13 +15,13 @@ - - - + + + -
Skip to main content

Page Not Found

We could not find what you were looking for.

Please contact the owner of the site that linked you to the original URL and let them know their link is broken.

+
Skip to main content

Page Not Found

We could not find what you were looking for.

Please contact the owner of the site that linked you to the original URL and let them know their link is broken.

\ No newline at end of file diff --git a/assets/js/003b6e74.14cbdba7.js b/assets/js/003b6e74.14cbdba7.js new file mode 100644 index 000000000..1f9ed4b9f --- /dev/null +++ b/assets/js/003b6e74.14cbdba7.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[7562],{9430:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>c,contentTitle:()=>l,default:()=>u,frontMatter:()=>i,metadata:()=>r,toc:()=>a});const r=JSON.parse('{"id":"go-client/distributed-cron","title":"Distributed CRON","description":"It is relatively straightforward to turn any Cadence into a Cron. All you need","source":"@site/docs/05-go-client/16-distributed-cron.md","sourceDirName":"05-go-client","slug":"/go-client/distributed-cron","permalink":"/Cadence-Docs/docs/go-client/distributed-cron","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/05-go-client/16-distributed-cron.md","tags":[],"version":"current","sidebarPosition":16,"frontMatter":{"layout":"default","title":"Distributed CRON","permalink":"/docs/go-client/distributed-cron"},"sidebar":"docsSidebar","previous":{"title":"Sessions","permalink":"/Cadence-Docs/docs/go-client/sessions"},"next":{"title":"Tracing and context propagation","permalink":"/Cadence-Docs/docs/go-client/tracing"}}');var o=n(4848),s=n(8453);const i={layout:"default",title:"Distributed CRON",permalink:"/docs/go-client/distributed-cron"},l="Distributed CRON",c={},a=[{value:"Convert existing cron workflow",id:"convert-existing-cron-workflow",level:2},{value:"Retrieve last successful result",id:"retrieve-last-successful-result",level:2}];function d(e){const t={a:"a",code:"code",h1:"h1",h2:"h2",header:"header",li:"li",p:"p",pre:"pre",ul:"ul",...(0,s.R)(),...e.components};return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsx)(t.header,{children:(0,o.jsx)(t.h1,{id:"distributed-cron",children:"Distributed CRON"})}),"\n",(0,o.jsxs)(t.p,{children:["It is relatively straightforward to turn any Cadence workflow into a Cron workflow. All you need\nis to supply a cron schedule when starting the workflow using the CronSchedule\nparameter of\n",(0,o.jsx)(t.a,{href:"https://godoc.org/go.uber.org/cadence/internal#StartWorkflowOptions",children:"StartWorkflowOptions"}),"."]}),"\n",(0,o.jsxs)(t.p,{children:["You can also start a workflow using the Cadence CLI with an optional cron schedule using the ",(0,o.jsx)(t.code,{children:"--cron"})," argument."]}),"\n",(0,o.jsx)(t.p,{children:"For workflows with CronSchedule:"}),"\n",(0,o.jsxs)(t.ul,{children:["\n",(0,o.jsx)(t.li,{children:'Cron schedule is based on UTC time. For example cron schedule "15 8 * * *"\nwill run daily at 8:15am UTC. Another example "*/2 * * * 5-6" will schedule a workflow every two minutes on fridays\nand saturdays.'}),"\n",(0,o.jsx)(t.li,{children:"If a workflow failed and a RetryPolicy is supplied to the StartWorkflowOptions\nas well, the workflow will retry based on the RetryPolicy. While the workflow is\nretrying, the server will not schedule the next cron run."}),"\n",(0,o.jsx)(t.li,{children:"Cadence server only schedules the next cron run after the current run is\ncompleted. If the next schedule is due while a workflow is running (or retrying),\nthen it will skip that schedule."}),"\n",(0,o.jsx)(t.li,{children:"Cron workflows will not stop until they are terminated or cancelled."}),"\n"]}),"\n",(0,o.jsx)(t.p,{children:"Cadence supports the standard cron spec:"}),"\n",(0,o.jsx)(t.pre,{children:(0,o.jsx)(t.code,{className:"language-go",children:"// CronSchedule - Optional cron schedule for workflow. If a cron schedule is specified, the workflow will run\n// as a cron based on the schedule. The scheduling will be based on UTC time. The schedule for next run only happen\n// after the current run is completed/failed/timeout. If a RetryPolicy is also supplied, and the workflow failed\n// or timed out, the workflow will be retried based on the retry policy. While the workflow is retrying, it won't\n// schedule its next run. If next schedule is due while the workflow is running (or retrying), then it will skip that\n// schedule. Cron workflow will not stop until it is terminated or cancelled (by returning cadence.CanceledError).\n// The cron spec is as following:\n// \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 minute (0 - 59)\n// \u2502 \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 hour (0 - 23)\n// \u2502 \u2502 \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 day of the month (1 - 31)\n// \u2502 \u2502 \u2502 \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 month (1 - 12)\n// \u2502 \u2502 \u2502 \u2502 \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 day of the week (0 - 6) (Sunday to Saturday)\n// \u2502 \u2502 \u2502 \u2502 \u2502\n// \u2502 \u2502 \u2502 \u2502 \u2502\n// * * * * *\nCronSchedule string\n"})}),"\n",(0,o.jsxs)(t.p,{children:["Cadence also supports more ",(0,o.jsx)(t.a,{href:"https://pkg.go.dev/github.com/robfig/cron#hdr-CRON_Expression_Format",children:"advanced cron expressions"}),"."]}),"\n",(0,o.jsxs)(t.p,{children:["The ",(0,o.jsx)(t.a,{href:"https://crontab.guru/",children:"crontab guru site"})," is useful for testing your cron expressions."]}),"\n",(0,o.jsx)(t.h2,{id:"convert-existing-cron-workflow",children:"Convert existing cron workflow"}),"\n",(0,o.jsxs)(t.p,{children:["Before CronSchedule was available, the previous approach to implementing cron\nworkflows was to use a delay timer as the last step and then return\n",(0,o.jsx)(t.code,{children:"ContinueAsNew"}),". One problem with that implementation is that if the workflow\nfails or times out, the cron would stop."]}),"\n",(0,o.jsxs)(t.p,{children:["To convert those workflows to make use of Cadence CronSchedule, all you need is to\nremove the delay timer and return without using\n",(0,o.jsx)(t.code,{children:"ContinueAsNew"}),". Then start the workflow with the desired CronSchedule."]}),"\n",(0,o.jsx)(t.h2,{id:"retrieve-last-successful-result",children:"Retrieve last successful result"}),"\n",(0,o.jsxs)(t.p,{children:["Sometimes it is useful to obtain the progress of previous successful runs.\nThis is supported by two new APIs in the client library:\n",(0,o.jsx)(t.code,{children:"HasLastCompletionResult"})," and ",(0,o.jsx)(t.code,{children:"GetLastCompletionResult"}),". Below is an example of how\nto use this in Go:"]}),"\n",(0,o.jsx)(t.pre,{children:(0,o.jsx)(t.code,{className:"language-go",children:"func CronWorkflow(ctx workflow.Context) (CronResult, error) {\n startTimestamp := time.Time{} // By default start from 0 time.\n if workflow.HasLastCompletionResult(ctx) {\n var progress CronResult\n if err := workflow.GetLastCompletionResult(ctx, &progress); err == nil {\n startTimestamp = progress.LastSyncTimestamp\n }\n }\n endTimestamp := workflow.Now(ctx)\n\n // Process work between startTimestamp (exclusive), endTimestamp (inclusive).\n // Business logic implementation goes here.\n\n result := CronResult{LastSyncTimestamp: endTimestamp}\n return result, nil\n}\n"})}),"\n",(0,o.jsx)(t.p,{children:"Note that this works even if one of the cron schedule runs failed. The\nnext schedule will still get the last successful result if it ever successfully\ncompleted at least once. For example, for a daily cron workflow, if the first day\nrun succeeds and the second day fails, then the third day run will still get\nthe result from first day's run using these APIs."})]})}function u(e={}){const{wrapper:t}={...(0,s.R)(),...e.components};return t?(0,o.jsx)(t,{...e,children:(0,o.jsx)(d,{...e})}):d(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>i,x:()=>l});var r=n(6540);const o={},s=r.createContext(o);function i(e){const t=r.useContext(s);return r.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function l(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:i(e.components),r.createElement(s.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/003b6e74.814290f3.js b/assets/js/003b6e74.814290f3.js deleted file mode 100644 index 602e677b7..000000000 --- a/assets/js/003b6e74.814290f3.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[7562],{9430:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>c,contentTitle:()=>l,default:()=>u,frontMatter:()=>i,metadata:()=>r,toc:()=>a});const r=JSON.parse('{"id":"go-client/distributed-cron","title":"Distributed CRON","description":"It is relatively straightforward to turn any Cadence into a Cron. All you need","source":"@site/docs/05-go-client/16-distributed-cron.md","sourceDirName":"05-go-client","slug":"/go-client/distributed-cron","permalink":"/docs/go-client/distributed-cron","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/05-go-client/16-distributed-cron.md","tags":[],"version":"current","sidebarPosition":16,"frontMatter":{"layout":"default","title":"Distributed CRON","permalink":"/docs/go-client/distributed-cron"},"sidebar":"docsSidebar","previous":{"title":"Sessions","permalink":"/docs/go-client/sessions"},"next":{"title":"Tracing and context propagation","permalink":"/docs/go-client/tracing"}}');var o=n(4848),s=n(8453);const i={layout:"default",title:"Distributed CRON",permalink:"/docs/go-client/distributed-cron"},l="Distributed CRON",c={},a=[{value:"Convert existing cron workflow",id:"convert-existing-cron-workflow",level:2},{value:"Retrieve last successful result",id:"retrieve-last-successful-result",level:2}];function d(e){const t={a:"a",code:"code",h1:"h1",h2:"h2",header:"header",li:"li",p:"p",pre:"pre",ul:"ul",...(0,s.R)(),...e.components};return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsx)(t.header,{children:(0,o.jsx)(t.h1,{id:"distributed-cron",children:"Distributed CRON"})}),"\n",(0,o.jsxs)(t.p,{children:["It is relatively straightforward to turn any Cadence workflow into a Cron workflow. All you need\nis to supply a cron schedule when starting the workflow using the CronSchedule\nparameter of\n",(0,o.jsx)(t.a,{href:"https://godoc.org/go.uber.org/cadence/internal#StartWorkflowOptions",children:"StartWorkflowOptions"}),"."]}),"\n",(0,o.jsxs)(t.p,{children:["You can also start a workflow using the Cadence CLI with an optional cron schedule using the ",(0,o.jsx)(t.code,{children:"--cron"})," argument."]}),"\n",(0,o.jsx)(t.p,{children:"For workflows with CronSchedule:"}),"\n",(0,o.jsxs)(t.ul,{children:["\n",(0,o.jsx)(t.li,{children:'Cron schedule is based on UTC time. For example cron schedule "15 8 * * *"\nwill run daily at 8:15am UTC. Another example "*/2 * * * 5-6" will schedule a workflow every two minutes on fridays\nand saturdays.'}),"\n",(0,o.jsx)(t.li,{children:"If a workflow failed and a RetryPolicy is supplied to the StartWorkflowOptions\nas well, the workflow will retry based on the RetryPolicy. While the workflow is\nretrying, the server will not schedule the next cron run."}),"\n",(0,o.jsx)(t.li,{children:"Cadence server only schedules the next cron run after the current run is\ncompleted. If the next schedule is due while a workflow is running (or retrying),\nthen it will skip that schedule."}),"\n",(0,o.jsx)(t.li,{children:"Cron workflows will not stop until they are terminated or cancelled."}),"\n"]}),"\n",(0,o.jsx)(t.p,{children:"Cadence supports the standard cron spec:"}),"\n",(0,o.jsx)(t.pre,{children:(0,o.jsx)(t.code,{className:"language-go",children:"// CronSchedule - Optional cron schedule for workflow. If a cron schedule is specified, the workflow will run\n// as a cron based on the schedule. The scheduling will be based on UTC time. The schedule for next run only happen\n// after the current run is completed/failed/timeout. If a RetryPolicy is also supplied, and the workflow failed\n// or timed out, the workflow will be retried based on the retry policy. While the workflow is retrying, it won't\n// schedule its next run. If next schedule is due while the workflow is running (or retrying), then it will skip that\n// schedule. Cron workflow will not stop until it is terminated or cancelled (by returning cadence.CanceledError).\n// The cron spec is as following:\n// \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 minute (0 - 59)\n// \u2502 \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 hour (0 - 23)\n// \u2502 \u2502 \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 day of the month (1 - 31)\n// \u2502 \u2502 \u2502 \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 month (1 - 12)\n// \u2502 \u2502 \u2502 \u2502 \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 day of the week (0 - 6) (Sunday to Saturday)\n// \u2502 \u2502 \u2502 \u2502 \u2502\n// \u2502 \u2502 \u2502 \u2502 \u2502\n// * * * * *\nCronSchedule string\n"})}),"\n",(0,o.jsxs)(t.p,{children:["Cadence also supports more ",(0,o.jsx)(t.a,{href:"https://pkg.go.dev/github.com/robfig/cron#hdr-CRON_Expression_Format",children:"advanced cron expressions"}),"."]}),"\n",(0,o.jsxs)(t.p,{children:["The ",(0,o.jsx)(t.a,{href:"https://crontab.guru/",children:"crontab guru site"})," is useful for testing your cron expressions."]}),"\n",(0,o.jsx)(t.h2,{id:"convert-existing-cron-workflow",children:"Convert existing cron workflow"}),"\n",(0,o.jsxs)(t.p,{children:["Before CronSchedule was available, the previous approach to implementing cron\nworkflows was to use a delay timer as the last step and then return\n",(0,o.jsx)(t.code,{children:"ContinueAsNew"}),". One problem with that implementation is that if the workflow\nfails or times out, the cron would stop."]}),"\n",(0,o.jsxs)(t.p,{children:["To convert those workflows to make use of Cadence CronSchedule, all you need is to\nremove the delay timer and return without using\n",(0,o.jsx)(t.code,{children:"ContinueAsNew"}),". Then start the workflow with the desired CronSchedule."]}),"\n",(0,o.jsx)(t.h2,{id:"retrieve-last-successful-result",children:"Retrieve last successful result"}),"\n",(0,o.jsxs)(t.p,{children:["Sometimes it is useful to obtain the progress of previous successful runs.\nThis is supported by two new APIs in the client library:\n",(0,o.jsx)(t.code,{children:"HasLastCompletionResult"})," and ",(0,o.jsx)(t.code,{children:"GetLastCompletionResult"}),". Below is an example of how\nto use this in Go:"]}),"\n",(0,o.jsx)(t.pre,{children:(0,o.jsx)(t.code,{className:"language-go",children:"func CronWorkflow(ctx workflow.Context) (CronResult, error) {\n startTimestamp := time.Time{} // By default start from 0 time.\n if workflow.HasLastCompletionResult(ctx) {\n var progress CronResult\n if err := workflow.GetLastCompletionResult(ctx, &progress); err == nil {\n startTimestamp = progress.LastSyncTimestamp\n }\n }\n endTimestamp := workflow.Now(ctx)\n\n // Process work between startTimestamp (exclusive), endTimestamp (inclusive).\n // Business logic implementation goes here.\n\n result := CronResult{LastSyncTimestamp: endTimestamp}\n return result, nil\n}\n"})}),"\n",(0,o.jsx)(t.p,{children:"Note that this works even if one of the cron schedule runs failed. The\nnext schedule will still get the last successful result if it ever successfully\ncompleted at least once. For example, for a daily cron workflow, if the first day\nrun succeeds and the second day fails, then the third day run will still get\nthe result from first day's run using these APIs."})]})}function u(e={}){const{wrapper:t}={...(0,s.R)(),...e.components};return t?(0,o.jsx)(t,{...e,children:(0,o.jsx)(d,{...e})}):d(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>i,x:()=>l});var r=n(6540);const o={},s=r.createContext(o);function i(e){const t=r.useContext(s);return r.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function l(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:i(e.components),r.createElement(s.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/004bd3e7.cbcda52b.js b/assets/js/004bd3e7.cbcda52b.js deleted file mode 100644 index e46703833..000000000 --- a/assets/js/004bd3e7.cbcda52b.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[1594],{2701:e=>{e.exports=JSON.parse('{"author":{"name":"Taylan Isikdemir","title":"Sr. Staff Software Engineer @ Uber","url":"https://www.linkedin.com/in/taylan-isikdemir","page":{"permalink":"/blog/authors/taylanisikdemir"},"socials":{"linkedin":"https://www.linkedin.com/in/taylan-isikdemir","github":"https://github.com/taylanisikdemir"},"imageURL":"https://github.com/taylanisikdemir.png","key":"taylanisikdemir","count":1},"listMetadata":{"permalink":"/blog/authors/taylanisikdemir","page":1,"postsPerPage":10,"totalPages":1,"totalCount":1,"blogDescription":"The latest news and updates from the Cadence team","blogTitle":"Cadence Blog"}}')}}]); \ No newline at end of file diff --git a/assets/js/0058b4c6.a81002c0.js b/assets/js/0058b4c6.a81002c0.js deleted file mode 100644 index fa9f7bc2f..000000000 --- a/assets/js/0058b4c6.a81002c0.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[849],{6164:e=>{e.exports=JSON.parse('{"version":{"pluginId":"default","version":"current","label":"Next","banner":null,"badge":false,"noIndex":false,"className":"docs-version-current","isLast":true,"docsSidebars":{"docsSidebar":[{"label":"Get Started","type":"category","items":[{"type":"link","label":"Overview","href":"/docs/get-started/","docId":"get-started/index","unlisted":false},{"type":"link","label":"Server Installation","href":"/docs/get-started/server-installation","docId":"get-started/server-installation","unlisted":false},{"type":"link","label":"Java hello world","href":"/docs/get-started/java-hello-world","docId":"get-started/java-hello-world","unlisted":false},{"type":"link","label":"Golang hello world","href":"/docs/get-started/golang-hello-world","docId":"get-started/golang-hello-world","unlisted":false},{"type":"link","label":"Video Tutorials","href":"/docs/get-started/video-tutorials","docId":"get-started/video-tutorials","unlisted":false}],"collapsed":true,"collapsible":true},{"label":"Use Cases","type":"category","items":[{"type":"link","label":"Introduction","href":"/docs/use-cases/","docId":"use-cases/index","unlisted":false},{"type":"link","label":"Periodic execution","href":"/docs/use-cases/periodic-execution","docId":"use-cases/periodic-execution","unlisted":false},{"type":"link","label":"Orchestration","href":"/docs/use-cases/orchestration","docId":"use-cases/orchestration","unlisted":false},{"type":"link","label":"Polling","href":"/docs/use-cases/polling","docId":"use-cases/polling","unlisted":false},{"type":"link","label":"Event driven application","href":"/docs/use-cases/event-driven","docId":"use-cases/event-driven","unlisted":false},{"type":"link","label":"Storage scan","href":"/docs/use-cases/partitioned-scan","docId":"use-cases/partitioned-scan","unlisted":false},{"type":"link","label":"Batch job","href":"/docs/use-cases/batch-job","docId":"use-cases/batch-job","unlisted":false},{"type":"link","label":"Infrastructure provisioning","href":"/docs/use-cases/provisioning","docId":"use-cases/provisioning","unlisted":false},{"type":"link","label":"Deployment","href":"/docs/use-cases/deployment","docId":"use-cases/deployment","unlisted":false},{"type":"link","label":"Operational management","href":"/docs/use-cases/operational-management","docId":"use-cases/operational-management","unlisted":false},{"type":"link","label":"Interactive application","href":"/docs/use-cases/interactive","docId":"use-cases/interactive","unlisted":false},{"type":"link","label":"DSL workflows","href":"/docs/use-cases/dsl","docId":"use-cases/dsl","unlisted":false},{"type":"link","label":"Big data and ML","href":"/docs/use-cases/big-ml","docId":"use-cases/big-ml","unlisted":false}],"collapsed":true,"collapsible":true},{"label":"Concepts","type":"category","items":[{"type":"link","label":"Introduction","href":"/docs/concepts/","docId":"concepts/index","unlisted":false},{"type":"link","label":"Activities","href":"/docs/concepts/activities","docId":"concepts/activities","unlisted":false},{"type":"link","label":"Event handling","href":"/docs/concepts/events","docId":"concepts/events","unlisted":false},{"type":"link","label":"Synchronous query","href":"/docs/concepts/queries","docId":"concepts/queries","unlisted":false},{"type":"link","label":"Deployment topology","href":"/docs/concepts/topology","docId":"concepts/topology","unlisted":false},{"type":"link","label":"Task lists","href":"/docs/concepts/task-lists","docId":"concepts/task-lists","unlisted":false},{"type":"link","label":"Archival","href":"/docs/concepts/archival","docId":"concepts/archival","unlisted":false},{"type":"link","label":"Cross DC replication","href":"/docs/concepts/cross-dc-replication","docId":"concepts/cross-dc-replication","unlisted":false},{"type":"link","label":"Search workflows(Advanced visibility)","href":"/docs/concepts/search-workflows","docId":"concepts/search-workflows","unlisted":false},{"type":"link","label":"HTTP API","href":"/docs/concepts/http-api","docId":"concepts/http-api","unlisted":false}],"collapsed":true,"collapsible":true},{"label":"Java Client","type":"category","items":[{"type":"link","label":"Introduction","href":"/docs/java-client/","docId":"java-client/index","unlisted":false},{"type":"link","label":"Client SDK Overview","href":"/docs/java-client/client-overview","docId":"java-client/client-overview","unlisted":false},{"type":"link","label":"Workflow interface","href":"/docs/java-client/workflow-interface","docId":"java-client/workflow-interface","unlisted":false},{"type":"link","label":"Implementing workflows","href":"/docs/java-client/implementing-workflows","docId":"java-client/implementing-workflows","unlisted":false},{"type":"link","label":"Starting workflows","href":"/docs/java-client/starting-workflow-executions","docId":"java-client/starting-workflow-executions","unlisted":false},{"type":"link","label":"Activity interface","href":"/docs/java-client/activity-interface","docId":"java-client/activity-interface","unlisted":false},{"type":"link","label":"Versioning","href":"/docs/java-client/versioning","docId":"java-client/versioning","unlisted":false},{"type":"link","label":"Distributed CRON","href":"/docs/java-client/distributed-cron","docId":"java-client/distributed-cron","unlisted":false},{"type":"link","label":"Worker service","href":"/docs/java-client/workers","docId":"java-client/workers","unlisted":false},{"type":"link","label":"Signals","href":"/docs/java-client/signals","docId":"java-client/signals","unlisted":false},{"type":"link","label":"Queries","href":"/docs/java-client/queries","docId":"java-client/queries","unlisted":false},{"type":"link","label":"Retries","href":"/docs/java-client/retries","docId":"java-client/retries","unlisted":false},{"type":"link","label":"Child workflows","href":"/docs/java-client/child-workflows","docId":"java-client/child-workflows","unlisted":false},{"type":"link","label":"Exception Handling","href":"/docs/java-client/exception-handling","docId":"java-client/exception-handling","unlisted":false},{"type":"link","label":"Continue As New","href":"/docs/java-client/continue-as-new","docId":"java-client/continue-as-new","unlisted":false},{"type":"link","label":"Side Effect","href":"/docs/java-client/side-effect","docId":"java-client/side-effect","unlisted":false},{"type":"link","label":"Testing","href":"/docs/java-client/testing","docId":"java-client/testing","unlisted":false},{"type":"link","label":"Workflow Replay and Shadowing","href":"/docs/java-client/workflow-replay-shadowing","docId":"java-client/workflow-replay-shadowing","unlisted":false}],"collapsed":true,"collapsible":true},{"label":"Go Client","type":"category","items":[{"type":"link","label":"Introduction","href":"/docs/go-client/","docId":"go-client/index","unlisted":false},{"type":"link","label":"Worker service","href":"/docs/go-client/workers","docId":"go-client/workers","unlisted":false},{"type":"link","label":"Creating workflows","href":"/docs/go-client/create-workflows","docId":"go-client/create-workflows","unlisted":false},{"type":"link","label":"Starting workflows","href":"/docs/go-client/02.5-starting-workflows","docId":"go-client/02.5-starting-workflows","unlisted":false},{"type":"link","label":"Activity overview","href":"/docs/go-client/activities","docId":"go-client/activities","unlisted":false},{"type":"link","label":"Executing activities","href":"/docs/go-client/execute-activity","docId":"go-client/execute-activity","unlisted":false},{"type":"link","label":"Child workflows","href":"/docs/go-client/child-workflows","docId":"go-client/child-workflows","unlisted":false},{"type":"link","label":"Activity and workflow retries","href":"/docs/go-client/retries","docId":"go-client/retries","unlisted":false},{"type":"link","label":"Error handling","href":"/docs/go-client/error-handling","docId":"go-client/error-handling","unlisted":false},{"type":"link","label":"Signals","href":"/docs/go-client/signals","docId":"go-client/signals","unlisted":false},{"type":"link","label":"Continue as new","href":"/docs/go-client/continue-as-new","docId":"go-client/continue-as-new","unlisted":false},{"type":"link","label":"Side effect","href":"/docs/go-client/side-effect","docId":"go-client/side-effect","unlisted":false},{"type":"link","label":"Queries","href":"/docs/go-client/queries","docId":"go-client/queries","unlisted":false},{"type":"link","label":"Async activity completion","href":"/docs/go-client/activity-async-completion","docId":"go-client/activity-async-completion","unlisted":false},{"type":"link","label":"Testing","href":"/docs/go-client/workflow-testing","docId":"go-client/workflow-testing","unlisted":false},{"type":"link","label":"Versioning","href":"/docs/go-client/workflow-versioning","docId":"go-client/workflow-versioning","unlisted":false},{"type":"link","label":"Sessions","href":"/docs/go-client/sessions","docId":"go-client/sessions","unlisted":false},{"type":"link","label":"Distributed CRON","href":"/docs/go-client/distributed-cron","docId":"go-client/distributed-cron","unlisted":false},{"type":"link","label":"Tracing and context propagation","href":"/docs/go-client/tracing","docId":"go-client/tracing","unlisted":false},{"type":"link","label":"Workflow Replay and Shadowing","href":"/docs/go-client/workflow-replay-shadowing","docId":"go-client/workflow-replay-shadowing","unlisted":false}],"collapsed":true,"collapsible":true},{"label":"Command Line Interface","type":"category","items":[{"type":"link","label":"Introduction","href":"/docs/cli/","docId":"cli/index","unlisted":false}],"collapsed":true,"collapsible":true},{"label":"Production Operation","type":"category","items":[{"type":"link","label":"Overview","href":"/docs/operation-guide/","docId":"operation-guide/index","unlisted":false},{"type":"link","label":"Cluster Configuration","href":"/docs/operation-guide/setup","docId":"operation-guide/setup","unlisted":false},{"type":"link","label":"Cluster Maintenance","href":"/docs/operation-guide/maintain","docId":"operation-guide/maintain","unlisted":false},{"type":"link","label":"Cluster Monitoring","href":"/docs/operation-guide/monitoring","docId":"operation-guide/monitoring","unlisted":false},{"type":"link","label":"Cluster Troubleshooting","href":"/docs/operation-guide/troubleshooting","docId":"operation-guide/troubleshooting","unlisted":false},{"type":"link","label":"Cluster Migration","href":"/docs/operation-guide/migration","docId":"operation-guide/migration","unlisted":false}],"collapsed":true,"collapsible":true},{"label":"Workflow Troubleshooting","type":"category","items":[{"type":"link","label":"Overview","href":"/docs/workflow-troubleshooting/","docId":"workflow-troubleshooting/index","unlisted":false},{"type":"link","label":"Timeouts","href":"/docs/workflow-troubleshooting/timeouts","docId":"workflow-troubleshooting/timeouts","unlisted":false},{"type":"link","label":"Activity Failures","href":"/docs/workflow-troubleshooting/activity-failures","docId":"workflow-troubleshooting/activity-failures","unlisted":false},{"type":"link","label":"Retries","href":"/docs/workflow-troubleshooting/retries","docId":"workflow-troubleshooting/retries","unlisted":false}],"collapsed":true,"collapsible":true},{"label":"About","type":"category","items":[{"type":"link","label":"Contact us","href":"/docs/about/","docId":"about/index","unlisted":false},{"type":"link","label":"MIT License","href":"/docs/about/license","docId":"about/license","unlisted":false}],"collapsed":true,"collapsible":true}]},"docs":{"about/index":{"id":"about/index","title":"Contact us","description":"If you have a question, check whether it is already answered at stackoverflow under cadence-workflow tag.","sidebar":"docsSidebar"},"about/license":{"id":"about/license","title":"MIT License","description":"","sidebar":"docsSidebar"},"cli/index":{"id":"cli/index","title":"Introduction","description":"The Cadence is a command-line tool you can use to perform varioustasks: on a Cadence server. It can perform","sidebar":"docsSidebar"},"concepts/activities":{"id":"concepts/activities","title":"Activities","description":"Fault-oblivious stateful code is the core abstraction of Cadence. But, due to deterministic execution requirements, they are not allowed to call any external API directly.","sidebar":"docsSidebar"},"concepts/archival":{"id":"concepts/archival","title":"Archival","description":"Archivalworkflow","sidebar":"docsSidebar"},"concepts/cross-dc-replication":{"id":"concepts/cross-dc-replication","title":"Cross DC replication","description":"The Cadence GlobalDomainworkflow_execution: from another","sidebar":"docsSidebar"},"concepts/events":{"id":"concepts/events","title":"Event handling","description":"Fault-oblivious statefulworkflowssignal about an external. A is always point to point destined to a specific instance.Signals: are always processed in the order in which they are received.","sidebar":"docsSidebar"},"concepts/http-api":{"id":"concepts/http-api","title":"HTTP API","description":"Introduction","sidebar":"docsSidebar"},"concepts/index":{"id":"concepts/index","title":"Introduction","description":"Cadence is a new developer friendly way to develop distributed applications.","sidebar":"docsSidebar"},"concepts/queries":{"id":"concepts/queries","title":"Synchronous query","description":"Workflowworkflow_executionqueryworkflowqueryworkflow: type exposing different information to different external systems.","sidebar":"docsSidebar"},"concepts/search-workflows":{"id":"concepts/search-workflows","title":"Search workflows(Advanced visibility)","description":"Introduction","sidebar":"docsSidebar"},"concepts/task-lists":{"id":"concepts/task-lists","title":"Task lists","description":"When a invokes an, it sends the `ScheduleActivityTask` to the","sidebar":"docsSidebar"},"concepts/topology":{"id":"concepts/topology","title":"Deployment topology","description":"Overview","sidebar":"docsSidebar"},"concepts/workflows":{"id":"concepts/workflows","title":"Workflows","description":"Overview"},"get-started/golang-hello-world":{"id":"get-started/golang-hello-world","title":"Golang hello world","description":"This section provides step-by-step instructions on how to write and run a HelloWorld workflow in Cadence with Golang. You will learn two critical building blocks of Cadence: activities and workflows. First, you will write an activity function that prints a \\"Hello World!\\" message in the log. Then, you will write a workflow function that executes this activity.","sidebar":"docsSidebar"},"get-started/index":{"id":"get-started/index","title":"Overview","description":"A large number of use cases span beyond a single request-reply, require tracking of a complex state, respond to asynchronous events, and communicate to external unreliable dependencies.","sidebar":"docsSidebar"},"get-started/java-hello-world":{"id":"get-started/java-hello-world","title":"Java hello world","description":"This section provides step by step instructions on how to write and run a HelloWorld with Java.","sidebar":"docsSidebar"},"get-started/server-installation":{"id":"get-started/server-installation","title":"Server Installation","description":"To get started with Cadence, you need to set up three components successfully.","sidebar":"docsSidebar"},"get-started/video-tutorials":{"id":"get-started/video-tutorials","title":"Video Tutorials","description":"An Introduction to the Cadence programming model and value proposition.","sidebar":"docsSidebar"},"glossary":{"id":"glossary","title":"Glossary","description":"--\x3e"},"go-client/02.5-starting-workflows":{"id":"go-client/02.5-starting-workflows","title":"Starting workflows","description":"Starting workflows can be done from any service that can send requests to","sidebar":"docsSidebar"},"go-client/activities":{"id":"go-client/activities","title":"Activity overview","description":"An is the implementation of a particular in the business logic.","sidebar":"docsSidebar"},"go-client/activity-async-completion":{"id":"go-client/activity-async-completion","title":"Async activity completion","description":"There are certain scenarios when completing an upon completion of its function is not possible","sidebar":"docsSidebar"},"go-client/child-workflows":{"id":"go-client/child-workflows","title":"Child workflows","description":"workflow.ExecuteChildWorkflow enables the scheduling of otherworkflowsworkflow\'s","sidebar":"docsSidebar"},"go-client/continue-as-new":{"id":"go-client/continue-as-new","title":"Continue as new","description":"Workflows: that need to rerun periodically could naively be implemented as a big for loop with","sidebar":"docsSidebar"},"go-client/create-workflows":{"id":"go-client/create-workflows","title":"Creating workflows","description":"The is the implementation of the coordination logic. The Cadence programming framework","sidebar":"docsSidebar"},"go-client/distributed-cron":{"id":"go-client/distributed-cron","title":"Distributed CRON","description":"It is relatively straightforward to turn any Cadence into a Cron. All you need","sidebar":"docsSidebar"},"go-client/error-handling":{"id":"go-client/error-handling","title":"Error handling","description":"An, or child, might fail and you could handle errors differently based on different","sidebar":"docsSidebar"},"go-client/execute-activity":{"id":"go-client/execute-activity","title":"Executing activities","description":"The primary responsibility of a implementation is to scheduleactivities: for execution. The","sidebar":"docsSidebar"},"go-client/index":{"id":"go-client/index","title":"Introduction","description":"Overview","sidebar":"docsSidebar"},"go-client/queries":{"id":"go-client/queries","title":"Queries","description":"If a has been stuck at a state for longer than an expected period of time, you","sidebar":"docsSidebar"},"go-client/retries":{"id":"go-client/retries","title":"Activity and workflow retries","description":"Activitiesworkflow can fail due to various intermediate conditions. In those cases, we want","sidebar":"docsSidebar"},"go-client/sessions":{"id":"go-client/sessions","title":"Sessions","description":"The session framework provides a straightforward interface for scheduling multipleactivitiesworkertask_list: name. It also includes features like concurrent session limitation and worker failure detection.","sidebar":"docsSidebar"},"go-client/side-effect":{"id":"go-client/side-effect","title":"Side effect","description":"workflow.SideEffect is useful for short, nondeterministic code snippets, such as getting a random","sidebar":"docsSidebar"},"go-client/signals":{"id":"go-client/signals","title":"Signals","description":"Signalsworkflow:. Previously, you had","sidebar":"docsSidebar"},"go-client/tracing":{"id":"go-client/tracing","title":"Tracing and context propagation","description":"Tracing","sidebar":"docsSidebar"},"go-client/workers":{"id":"go-client/workers","title":"Worker service","description":"A or service is a service that hosts the and implementations. The polls the Cadence service fortaskstask, and communicates execution results back to the Cadence service.Worker: services are developed, deployed, and operated by Cadence customers.","sidebar":"docsSidebar"},"go-client/workflow-non-deterministic-error":{"id":"go-client/workflow-non-deterministic-error","title":"Workflow Non-deterministic errors","description":"Root cause of non-deterministic errors"},"go-client/workflow-replay-shadowing":{"id":"go-client/workflow-replay-shadowing","title":"Workflow Replay and Shadowing","description":"In the Versioning section, we mentioned that incompatible changes to workflow definition code could cause non-deterministic issues when processing workflow tasks if versioning is not done correctly. However, it may be hard for you to tell if a particular change is incompatible or not and whether versioning logic is needed. To help you identify incompatible changes and catch them before production traffic is impacted, we implemented Workflow Replayer and Workflow Shadower.","sidebar":"docsSidebar"},"go-client/workflow-testing":{"id":"go-client/workflow-testing","title":"Testing","description":"The Cadence Go client library provides a test framework to facilitate testing implementations.","sidebar":"docsSidebar"},"go-client/workflow-versioning":{"id":"go-client/workflow-versioning","title":"Versioning","description":"The definition code of a Cadence must be deterministic because Cadence uses sourcing","sidebar":"docsSidebar"},"java-client/activity-interface":{"id":"java-client/activity-interface","title":"Activity interface","description":"An is a manifestation of a particular in the business logic.","sidebar":"docsSidebar"},"java-client/child-workflows":{"id":"java-client/child-workflows","title":"Child workflows","description":"Besidesactivitiesworkflowworkflow.","sidebar":"docsSidebar"},"java-client/client-overview":{"id":"java-client/client-overview","title":"Client SDK Overview","description":"- Samples//github.com/cadence-workflow/cadence-java-samples","sidebar":"docsSidebar"},"java-client/continue-as-new":{"id":"java-client/continue-as-new","title":"Continue As New","description":"Workflows: that need to rerun periodically could naively be implemented as a big for loop with","sidebar":"docsSidebar"},"java-client/distributed-cron":{"id":"java-client/distributed-cron","title":"Distributed CRON","description":"It is relatively straightforward to turn any Cadence into a Cron. All you need","sidebar":"docsSidebar"},"java-client/exception-handling":{"id":"java-client/exception-handling","title":"Exception Handling","description":"By default, Exceptions thrown by an activity are received by the workflow wrapped into an com.uber.cadence.workflow.ActivityFailureException,","sidebar":"docsSidebar"},"java-client/implementing-activities":{"id":"java-client/implementing-activities","title":"Implementing activities","description":"Activityactivityactivity implementation"},"java-client/implementing-workflows":{"id":"java-client/implementing-workflows","title":"Implementing workflows","description":"A implementation implements a interface. Each time a new is started,","sidebar":"docsSidebar"},"java-client/index":{"id":"java-client/index","title":"Introduction","description":"The following are important links for the Cadence Java client:","sidebar":"docsSidebar"},"java-client/queries":{"id":"java-client/queries","title":"Queries","description":"Query is to expose this internal state to the external world Cadence provides a synchronous feature. From the implementer point of view the is exposed as a synchronous callback that is invoked by external entities. Multiple such callbacks can be provided per type exposing different information to different external systems.","sidebar":"docsSidebar"},"java-client/retries":{"id":"java-client/retries","title":"Retries","description":"Activitiesworkflow can fail due to various intermediate conditions. In those cases, we want","sidebar":"docsSidebar"},"java-client/side-effect":{"id":"java-client/side-effect","title":"Side Effect","description":"Side Effect allow workflow executes the provided function once, records its result into the workflow history.","sidebar":"docsSidebar"},"java-client/signals":{"id":"java-client/signals","title":"Signals","description":"Signalsworkflow:. Previously, you had","sidebar":"docsSidebar"},"java-client/starting-workflow-executions":{"id":"java-client/starting-workflow-executions","title":"Starting workflows","description":"Creating a WorkflowClient","sidebar":"docsSidebar"},"java-client/testing":{"id":"java-client/testing","title":"Testing","description":"TestActivityEnvironment is the helper class for unit testing activity implementations. Supports calls to Activity methods from the tested activities. An example test:","sidebar":"docsSidebar"},"java-client/versioning":{"id":"java-client/versioning","title":"Versioning","description":"As outlined in the Workflow Implementation Constraints section, code has to be deterministic by taking the same","sidebar":"docsSidebar"},"java-client/workers":{"id":"java-client/workers","title":"Worker service","description":"A or service is a service that hosts the and implementations. The polls the Cadence service fortaskstask, and communicates execution results back to the Cadence service.Worker: services are developed, deployed, and operated by Cadence customers.","sidebar":"docsSidebar"},"java-client/workflow-interface":{"id":"java-client/workflow-interface","title":"Workflow interface","description":"Workflowactivity and childworkflows:.","sidebar":"docsSidebar"},"java-client/workflow-replay-shadowing":{"id":"java-client/workflow-replay-shadowing","title":"Workflow Replay and Shadowing","description":"In the Versioning section, we mentioned that incompatible changes to workflow definition code could cause non-deterministic issues when processing workflow tasks if versioning is not done correctly. However, it may be hard for you to tell if a particular change is incompatible or not and whether versioning logic is needed. To help you identify incompatible changes and catch them before production traffic is impacted, we implemented Workflow Replayer and Workflow Shadower.","sidebar":"docsSidebar"},"operation-guide/index":{"id":"operation-guide/index","title":"Overview","description":"This document will cover things that you need to know to run a Cadence cluster in production. Topics including: setup, monitoring, maintenance and troubleshooting.","sidebar":"docsSidebar"},"operation-guide/maintain":{"id":"operation-guide/maintain","title":"Cluster Maintenance","description":"This includes how to use and maintain a Cadence cluster for both clients and server clusters.","sidebar":"docsSidebar"},"operation-guide/migration":{"id":"operation-guide/migration","title":"Cluster Migration","description":"There could be some reasons that you need to migrate Cadence clusters:","sidebar":"docsSidebar"},"operation-guide/monitoring":{"id":"operation-guide/monitoring","title":"Cluster Monitoring","description":"Instructions","sidebar":"docsSidebar"},"operation-guide/setup":{"id":"operation-guide/setup","title":"Cluster Configuration","description":"This section will help to understand what you need for setting up a Cadence cluster.","sidebar":"docsSidebar"},"operation-guide/troubleshooting":{"id":"operation-guide/troubleshooting","title":"Cluster Troubleshooting","description":"This section is to cover some common operation issues as a RunBook. Feel free to add more, or raise issues in the to ask for more in cadence-docs project.Or talk to us in Slack support channel!","sidebar":"docsSidebar"},"use-cases/batch-job":{"id":"use-cases/batch-job","title":"Batch job","description":"A lot of batch jobs are not pure data manipulation programs. For those, the existing big data frameworks are the best fit.","sidebar":"docsSidebar"},"use-cases/big-ml":{"id":"use-cases/big-ml","title":"Big data and ML","description":"A lot of companies build custom ETL and ML training and deployment solutions. Cadence is a good fit for a control plane for such applications.","sidebar":"docsSidebar"},"use-cases/deployment":{"id":"use-cases/deployment","title":"Deployment","description":"Implementing CI/CD pipelines and deployment of applications to containers or virtual or physical machines is a non-trivial process.","sidebar":"docsSidebar"},"use-cases/dsl":{"id":"use-cases/dsl","title":"DSL workflows","description":"Cadence supports implementing business logic directly in programming languages like Java and Go. But there are cases when","sidebar":"docsSidebar"},"use-cases/event-driven":{"id":"use-cases/event-driven","title":"Event driven application","description":"Many applications listen to multiple sources, update the state of correspondent business entities,","sidebar":"docsSidebar"},"use-cases/index":{"id":"use-cases/index","title":"Introduction","description":"As Cadence developers, we face a difficult non-technical problem: How to position and describe the Cadence platform.","sidebar":"docsSidebar"},"use-cases/interactive":{"id":"use-cases/interactive","title":"Interactive application","description":"Cadence is performant and scalable enough to support interactive applications. It can be used to track UI session state and","sidebar":"docsSidebar"},"use-cases/operational-management":{"id":"use-cases/operational-management","title":"Operational management","description":"Imagine that you have to create a self operating database similar to Amazon RDS. Cadence is used in multiple projects","sidebar":"docsSidebar"},"use-cases/orchestration":{"id":"use-cases/orchestration","title":"Orchestration","description":"It is common that some business processes are implemented as multiple microservice calls.","sidebar":"docsSidebar"},"use-cases/partitioned-scan":{"id":"use-cases/partitioned-scan","title":"Storage scan","description":"It is common to have large data sets partitioned across a large number of hosts or databases, or having billions of files in an Amazon S3 bucket.","sidebar":"docsSidebar"},"use-cases/periodic-execution":{"id":"use-cases/periodic-execution","title":"Periodic execution","description":"Periodic execution, frequently referred to as distributed cron, is when you execute business logic periodically. The advantage of Cadence for these scenarios is that it guarantees execution, sophisticated error handling, retry policies, and visibility into execution history.","sidebar":"docsSidebar"},"use-cases/polling":{"id":"use-cases/polling","title":"Polling","description":"Polling is executing a periodic action checking for a state change. Examples are pinging a host, calling a REST API, or listing an Amazon S3 bucket for newly uploaded files.","sidebar":"docsSidebar"},"use-cases/provisioning":{"id":"use-cases/provisioning","title":"Infrastructure provisioning","description":"Provisioning a new datacenter or a pool of machines in a public cloud is a potentially long running operation with","sidebar":"docsSidebar"},"workflow-troubleshooting/activity-failures":{"id":"workflow-troubleshooting/activity-failures","title":"Activity Failures","description":"An activity fails when it encounters an error during its execution. This results in ActivityTaskFailed event in the workflow execution with some details of the error. The different kinds of errors that can be seen in activity failures are listed here.","sidebar":"docsSidebar"},"workflow-troubleshooting/index":{"id":"workflow-troubleshooting/index","title":"Overview","description":"This document will serve as a guide for troubleshooting a workflow for potential issues.","sidebar":"docsSidebar"},"workflow-troubleshooting/retries":{"id":"workflow-troubleshooting/retries","title":"Retries","description":"Cadence has a retry feature where a retry policy can be configured so that an activity or a workflow will be retried when it fails or times out.","sidebar":"docsSidebar"},"workflow-troubleshooting/timeouts":{"id":"workflow-troubleshooting/timeouts","title":"Timeouts","description":"A workflow could fail if an activity times out and will timeout when the entire workflow execution times out. Workflows or activities time out when their time to execute or time to start has been longer than their configured timeout. Some of the common causes for timeouts have been listed here.","sidebar":"docsSidebar"}}}}')}}]); \ No newline at end of file diff --git a/assets/js/02de9280.f379b4d1.js b/assets/js/02de9280.f379b4d1.js new file mode 100644 index 000000000..aa78f3df2 --- /dev/null +++ b/assets/js/02de9280.f379b4d1.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[9533],{9221:e=>{e.exports=JSON.parse('{"metadata":{"permalink":"/Cadence-Docs/blog","page":1,"postsPerPage":10,"totalPages":4,"totalCount":35,"nextPage":"/Cadence-Docs/blog/page/2","blogDescription":"The latest news and updates from the Cadence team","blogTitle":"Cadence Blog"}}')}}]); \ No newline at end of file diff --git a/assets/js/02fb669a.1b3e222c.js b/assets/js/02fb669a.1b3e222c.js deleted file mode 100644 index d072fbddb..000000000 --- a/assets/js/02fb669a.1b3e222c.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[1839],{3839:(e,i,t)=>{t.r(i),t.d(i,{assets:()=>l,contentTitle:()=>a,default:()=>h,frontMatter:()=>r,metadata:()=>n,toc:()=>c});const n=JSON.parse('{"id":"concepts/workflows","title":"Workflows","description":"Overview","source":"@site/docs/03-concepts/01-workflows.md","sourceDirName":"03-concepts","slug":"/concepts/workflows","permalink":"/docs/concepts/workflows","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/03-concepts/01-workflows.md","tags":[],"version":"current","sidebarPosition":1,"frontMatter":{"layout":"default","title":"Workflows","permalink":"/docs/concepts/workflows"}}');var o=t(4848),s=t(8453);const r={layout:"default",title:"Workflows",permalink:"/docs/concepts/workflows"},a="Fault-oblivious stateful workflow code",l={},c=[{value:"Overview",id:"overview",level:2},{value:"Example",id:"example",level:2},{value:"State Recovery and Determinism",id:"state-recovery-and-determinism",level:2},{value:"ID Uniqueness",id:"id-uniqueness",level:2},{value:"Child Workflow",id:"child-workflow",level:2},{value:"Workflow Retries",id:"workflow-retries",level:2},{value:"How does workflow run",id:"how-does-workflow-run",level:2}];function d(e){const i={a:"a",code:"code",em:"em",h1:"h1",h2:"h2",header:"header",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,s.R)(),...e.components};return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsx)(i.header,{children:(0,o.jsx)(i.h1,{id:"fault-oblivious-stateful-workflow-code",children:"Fault-oblivious stateful workflow code"})}),"\n",(0,o.jsx)(i.h2,{id:"overview",children:"Overview"}),"\n",(0,o.jsxs)(i.p,{children:["Cadence core abstraction is a ",(0,o.jsx)(i.strong,{children:"fault-oblivious stateful workflow"}),". The state of the workflow code, including local variables and threads it creates, is immune to process and Cadence service failures.\nThis is a very powerful concept as it encapsulates state, processing threads, durable timers and event handlers."]}),"\n",(0,o.jsx)(i.h2,{id:"example",children:"Example"}),"\n",(0,o.jsx)(i.p,{children:"Let's look at a use case. A customer signs up for an application with a trial period. After the period, if the customer has not cancelled, he should be charged once a month for the renewal. The customer has to be notified by email about the charges and should be able to cancel the subscription at any time."}),"\n",(0,o.jsx)(i.p,{children:"The business logic of this use case is not very complicated and can be expressed in a few dozen lines of code. But any practical implementation has to ensure that the business process is fault tolerant and scalable. There are various ways to approach the design of such a system."}),"\n",(0,o.jsx)(i.p,{children:"One approach is to center it around a database. An application process would periodically scan database tables for customers in specific states, execute necessary actions, and update the state to reflect that. While feasible, this approach has various drawbacks. The most obvious is that the state machine of the customer state quickly becomes extremely complicated. For example, charging a credit card or sending emails can fail due to a downstream system unavailability. The failed calls might need to be retried for a long time, ideally using an exponential retry policy. These calls should be throttled to not overload external systems. There should be support for poison pills to avoid blocking the whole process if a single customer record cannot be processed for whatever reason. The database-based approach also usually has performance problems. Databases are not efficient for scenarios that require constant polling for records in a specific state."}),"\n",(0,o.jsx)(i.p,{children:"Another commonly employed approach is to use a timer service and queues. Any update is pushed to a queue and then a worker that consumes from it updates a database and possibly pushes more messages in downstream queues. For operations that require scheduling, an external timer service can be used. This approach usually scales much better because a database is not constantly polled for changes. But it makes the programming model more complex and error prone as usually there is no transactional update between a queuing system and a database."}),"\n",(0,o.jsx)(i.p,{children:"With Cadence, the entire logic can be encapsulated in a simple durable function that directly implements the business logic. Because the function is stateful, the implementer doesn't need to employ any additional systems to ensure durability and fault tolerance."}),"\n",(0,o.jsx)(i.p,{children:"Here is an example workflow that implements the subscription management use case. It is in Java, but Go is also supported. The Python and .NET libraries are under active development."}),"\n",(0,o.jsx)(i.pre,{children:(0,o.jsx)(i.code,{className:"language-java",children:"// This SubscriptionWorkflow interface is an example of defining a workflow in Cadence\npublic interface SubscriptionWorkflow {\n @WorkflowMethod\n void manageSubscription(String customerId);\n @SignalMethod\n void cancelSubscription();\n @SignalMethod \n void updateBillingPeriodChargeAmount(int billingPeriodChargeAmount);\n @QueryMethod \n String queryCustomerId();\n @QueryMethod \n int queryBillingPeriodNumber();\n @QueryMethod \n int queryBillingPeriodChargeAmount();\n}\n\n// Workflow implementation is independent from interface. That way, application that start/signal/query workflows only need to know the interface\npublic class SubscriptionWorkflowImpl implements SubscriptionWorkflow {\n\n private int billingPeriodNum;\n private boolean subscriptionCancelled;\n private Customer customer;\n \n private final SubscriptionActivities activities =\n Workflow.newActivityStub(SubscriptionActivities.class);\n\n // This manageSubscription function is an example of a workflow using Cadence\n @Override\n public void manageSubscription(Customer customer) {\n // Set the Workflow customer to class properties so that it can be used by other methods like Query/Signal\n this.customer = customer;\n\n // sendWelcomeEmail is an activity in Cadence. It is implemented in user code and Cadence executes this activity on a worker node when needed.\n activities.sendWelcomeEmail(customer);\n\n // for this example, there are a fixed number of periods in the subscription\n // Cadence supports indefinitely running workflow but some advanced techniques are needed\n while (billingPeriodNum < customer.getSubscription().getPeriodsInSubcription()) {\n\n // Workflow.await tells Cadence to pause the workflow at this stage (saving it's state to the database)\n // Execution restarts when the billing period time has passed or the subscriptionCancelled event is received , whichever comes first\n Workflow.await(customer.getSubscription().getBillingPeriod(), () -> subscriptionCancelled);\n\n if (subscriptionCancelled) {\n activities.sendCancellationEmailDuringActiveSubscription(customer);\n break;\n }\n \n // chargeCustomerForBillingPeriod is another activity\n // Cadence will automatically handle issues such as your billing service being unavailable at the time\n // this activity is invoked\n activities.chargeCustomerForBillingPeriod(customer, billingPeriodNum);\n\n billingPeriodNum++;\n }\n\n if (!subscriptionCancelled) {\n activities.sendSubscriptionOverEmail(customer);\n }\n \n // the workflow is finished once this function returns\n }\n\n @Override\n public void cancelSubscription() {\n subscriptionCancelled = true;\n }\n\n @Override\n public void updateBillingPeriodChargeAmount(int billingPeriodChargeAmount) {\n customer.getSubscription().setBillingPeriodCharge(billingPeriodChargeAmount);\n }\n\n @Override\n public String queryCustomerId() {\n return customer.getId();\n }\n\n @Override\n public int queryBillingPeriodNumber() {\n return billingPeriodNum;\n }\n\n @Override\n public int queryBillingPeriodChargeAmount() {\n return customer.getSubscription().getBillingPeriodCharge();\n }\n}\n\n"})}),"\n",(0,o.jsxs)(i.p,{children:["Again, note that this code directly implements the business logic. If any of the invoked operations (aka activities) takes a long time, the code is not going to change. It is okay to block on ",(0,o.jsx)(i.code,{children:"chargeCustomerForBillingPeriod"})," for a day if the downstream processing service is down that long. The same way that blocking sleep for a billing period like 30 days is a normal operation inside the workflow code."]}),"\n",(0,o.jsx)(i.p,{children:"Cadence has practically no scalability limits on the number of open workflow instances. So even if your site has hundreds of millions of consumers, the above code is not going to change."}),"\n",(0,o.jsxs)(i.p,{children:['The commonly asked question by developers that learn Cadence is "How do I handle workflow_worker process failure/restart in my workflow"? The answer is that you do not. ',(0,o.jsx)(i.strong,{children:"The workflow code is completely oblivious to any failures and downtime of workers or even the Cadence service itself"}),". As soon as they are recovered and the workflow needs to handle some event, like timer or an activity completion, the current state of the workflow is fully restored and the execution is continued. The only reason for a workflow failure is the workflow business code throwing an exception, not underlying infrastructure outages."]}),"\n",(0,o.jsx)(i.p,{children:"Another commonly asked question is whether a worker can handle more workflow instances than its cache size or number of threads it can support. The answer is that a workflow, when in a blocked state, can be safely removed from a worker.\nLater it can be resurrected on a different or the same worker when the need (in the form of an external event) arises. So a single worker can handle millions of open workflow_executions, assuming it can handle the update rate."}),"\n",(0,o.jsx)(i.h2,{id:"state-recovery-and-determinism",children:"State Recovery and Determinism"}),"\n",(0,o.jsx)(i.p,{children:"The workflow state recovery utilizes event sourcing which puts a few restrictions on how the code is written. The main restriction is that the workflow code must be deterministic which means that it must produce exactly the same result if executed multiple times. This rules out any external API calls from the workflow code as external calls can fail intermittently or change its output any time. That is why all communication with the external world should happen through activities. For the same reason, workflow code must use Cadence APIs to get current time, sleep, and create new threads."}),"\n",(0,o.jsx)(i.p,{children:"To understand the Cadence execution model as well as the recovery mechanism, watch the following webcast. The animation covering recovery starts at 15:50."}),"\n",(0,o.jsx)("figure",{class:"video-container",children:(0,o.jsx)("iframe",{src:"https://www.youtube.com/embed/qce_AqCkFys?start=960",frameborder:"0",height:"315",allowfullscreen:!0,width:"560"})}),"\n",(0,o.jsx)(i.h2,{id:"id-uniqueness",children:"ID Uniqueness"}),"\n",(0,o.jsx)(i.p,{children:"Workflow_ID is assigned by a client when starting a workflow. It is usually a business level ID like customer ID or order ID."}),"\n",(0,o.jsxs)(i.p,{children:["Cadence guarantees that there could be only one workflow (across all workflow types) with a given ID open per domain at any time. An attempt to start a workflow with the same ID is going to fail with ",(0,o.jsx)(i.code,{children:"WorkflowExecutionAlreadyStarted"})," error."]}),"\n",(0,o.jsxs)(i.p,{children:["An attempt to start a workflow if there is a completed workflow with the same ID depends on a ",(0,o.jsx)(i.code,{children:"WorkflowIdReusePolicy"})," option:"]}),"\n",(0,o.jsxs)(i.ul,{children:["\n",(0,o.jsxs)(i.li,{children:[(0,o.jsx)(i.code,{children:"AllowDuplicateFailedOnly"})," means that it is allowed to start a workflow only if a previously executed workflow with the same ID failed."]}),"\n",(0,o.jsxs)(i.li,{children:[(0,o.jsx)(i.code,{children:"AllowDuplicate"})," means that it is allowed to start independently of the previous workflow completion status."]}),"\n",(0,o.jsxs)(i.li,{children:[(0,o.jsx)(i.code,{children:"RejectDuplicate"})," means that it is not allowed to start a workflow_execution using the same workflow_ID at all."]}),"\n",(0,o.jsxs)(i.li,{children:[(0,o.jsx)(i.code,{children:"TerminateIfRunning"})," means terminating the current running workflow if one exists, and start a new one."]}),"\n"]}),"\n",(0,o.jsxs)(i.p,{children:["The default is ",(0,o.jsx)(i.code,{children:"AllowDuplicateFailedOnly"}),"."]}),"\n",(0,o.jsxs)(i.p,{children:["To distinguish multiple runs of a workflow with the same workflow_ID, Cadence identifies a workflow with two IDs: ",(0,o.jsx)(i.code,{children:"Workflow ID"})," and ",(0,o.jsx)(i.code,{children:"Run ID"}),". ",(0,o.jsx)(i.code,{children:"Run ID"})," is a service-assigned UUID. To be precise, any workflow is uniquely identified by a triple: ",(0,o.jsx)(i.code,{children:"Domain Name"}),", ",(0,o.jsx)(i.code,{children:"Workflow ID"})," and ",(0,o.jsx)(i.code,{children:"Run ID"}),"."]}),"\n",(0,o.jsx)(i.h2,{id:"child-workflow",children:"Child Workflow"}),"\n",(0,o.jsxs)(i.p,{children:["A workflow can execute other workflows as ",(0,o.jsx)(i.code,{children:"child :workflow:workflows:"}),". A child workflow completion or failure is reported to its parent."]}),"\n",(0,o.jsx)(i.p,{children:"Some reasons to use child workflows are:"}),"\n",(0,o.jsxs)(i.ul,{children:["\n",(0,o.jsx)(i.li,{children:"A child workflow can be hosted by a separate set of workers which don't contain the parent workflow code. So it would act as a separate service that can be invoked from multiple other workflows."}),"\n",(0,o.jsx)(i.li,{children:"A single workflow has a limited size. For example, it cannot execute 100k activities. Child workflows can be used to partition the problem into smaller chunks. One parent with 1000 children each executing 1000 activities is 1 million executed activities."}),"\n",(0,o.jsx)(i.li,{children:"A child workflow can be used to manage some resource using its ID to guarantee uniqueness. For example, a workflow that manages host upgrades can have a child workflow per host (host name being a workflow_ID) and use them to ensure that all operations on the host are serialized."}),"\n",(0,o.jsx)(i.li,{children:"A child workflow can be used to execute some periodic logic without blowing up the parent history size. When a parent starts a child, it executes periodic logic calling that continues as many times as needed, then completes. From the parent point if view, it is just a single child workflow invocation."}),"\n"]}),"\n",(0,o.jsx)(i.p,{children:"The main limitation of a child workflow versus collocating all the application logic in a single workflow is lack of the shared state. Parent and child can communicate only through asynchronous signals. But if there is a tight coupling between them, it might be simpler to use a single workflow and just rely on a shared object state."}),"\n",(0,o.jsx)(i.p,{children:"We recommended starting from a single workflow implementation if your problem has bounded size in terms of number of executed activities and processed signals. It is more straightforward than multiple asynchronously communicating workflows."}),"\n",(0,o.jsx)(i.h2,{id:"workflow-retries",children:"Workflow Retries"}),"\n",(0,o.jsx)(i.p,{children:"Workflow code is unaffected by infrastructure level downtime and failures. But it still can fail due to business logic level failures. For example, an activity can fail due to exceeding the retry interval and the error is not handled by application code, or the workflow code having a bug."}),"\n",(0,o.jsxs)(i.p,{children:["Some workflows require a guarantee that they keep running even in presence of such failures. To support such use cases, an optional exponential ",(0,o.jsx)(i.em,{children:"retry policy"})," can be specified when starting a workflow. When it is specified, a workflow failure restarts a workflow from the beginning after the calculated retry interval. Following are the retry policy parameters:"]}),"\n",(0,o.jsxs)(i.ul,{children:["\n",(0,o.jsxs)(i.li,{children:[(0,o.jsx)(i.code,{children:"InitialInterval"})," is a delay before the first retry."]}),"\n",(0,o.jsxs)(i.li,{children:[(0,o.jsx)(i.code,{children:"BackoffCoefficient"}),". Retry policies are exponential. The coefficient specifies how fast the retry interval is growing. The coefficient of 1 means that the retry interval is always equal to the ",(0,o.jsx)(i.code,{children:"InitialInterval"}),"."]}),"\n",(0,o.jsxs)(i.li,{children:[(0,o.jsx)(i.code,{children:"MaximumInterval"})," specifies the maximum interval between retries. Useful for coefficients of more than 1."]}),"\n",(0,o.jsxs)(i.li,{children:[(0,o.jsx)(i.code,{children:"MaximumAttempts"})," specifies how many times to attempt to execute a workflow in the presence of failures. If this limit is exceeded, the workflow fails without retry. Not required if ",(0,o.jsx)(i.code,{children:"ExpirationInterval"})," is specified."]}),"\n",(0,o.jsxs)(i.li,{children:[(0,o.jsx)(i.code,{children:"ExpirationInterval"})," specifies for how long to attempt executing a workflow in the presence of failures. If this interval is exceeded, the workflow fails without retry. Not required if ",(0,o.jsx)(i.code,{children:"MaximumAttempts"})," is specified."]}),"\n",(0,o.jsxs)(i.li,{children:[(0,o.jsx)(i.code,{children:"NonRetryableErrorReasons"})," allows to specify errors that shouldn't be retried. For example, retrying invalid arguments error doesn't make sense in some scenarios."]}),"\n"]}),"\n",(0,o.jsx)(i.h2,{id:"how-does-workflow-run",children:"How does workflow run"}),"\n",(0,o.jsxs)(i.p,{children:["You may wonder how it works. Behind the scenes, workflow decision is driving the whole workflow running. It's the internal entities for client and server to run your workflows. If this is interesting to you, read this ",(0,o.jsx)(i.a,{href:"https://stackoverflow.com/questions/62904129/what-exactly-is-a-cadence-decision-task/63964726#63964726",children:"stack Overflow QA"}),"."]})]})}function h(e={}){const{wrapper:i}={...(0,s.R)(),...e.components};return i?(0,o.jsx)(i,{...e,children:(0,o.jsx)(d,{...e})}):d(e)}},8453:(e,i,t)=>{t.d(i,{R:()=>r,x:()=>a});var n=t(6540);const o={},s=n.createContext(o);function r(e){const i=n.useContext(s);return n.useMemo((function(){return"function"==typeof e?e(i):{...i,...e}}),[i,e])}function a(e){let i;return i=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:r(e.components),n.createElement(s.Provider,{value:i},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/02fb669a.2aa7c065.js b/assets/js/02fb669a.2aa7c065.js new file mode 100644 index 000000000..bcbafc954 --- /dev/null +++ b/assets/js/02fb669a.2aa7c065.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[1839],{3839:(e,i,t)=>{t.r(i),t.d(i,{assets:()=>l,contentTitle:()=>a,default:()=>h,frontMatter:()=>r,metadata:()=>n,toc:()=>c});const n=JSON.parse('{"id":"concepts/workflows","title":"Workflows","description":"Overview","source":"@site/docs/03-concepts/01-workflows.md","sourceDirName":"03-concepts","slug":"/concepts/workflows","permalink":"/Cadence-Docs/docs/concepts/workflows","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/03-concepts/01-workflows.md","tags":[],"version":"current","sidebarPosition":1,"frontMatter":{"layout":"default","title":"Workflows","permalink":"/docs/concepts/workflows"}}');var o=t(4848),s=t(8453);const r={layout:"default",title:"Workflows",permalink:"/docs/concepts/workflows"},a="Fault-oblivious stateful workflow code",l={},c=[{value:"Overview",id:"overview",level:2},{value:"Example",id:"example",level:2},{value:"State Recovery and Determinism",id:"state-recovery-and-determinism",level:2},{value:"ID Uniqueness",id:"id-uniqueness",level:2},{value:"Child Workflow",id:"child-workflow",level:2},{value:"Workflow Retries",id:"workflow-retries",level:2},{value:"How does workflow run",id:"how-does-workflow-run",level:2}];function d(e){const i={a:"a",code:"code",em:"em",h1:"h1",h2:"h2",header:"header",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,s.R)(),...e.components};return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsx)(i.header,{children:(0,o.jsx)(i.h1,{id:"fault-oblivious-stateful-workflow-code",children:"Fault-oblivious stateful workflow code"})}),"\n",(0,o.jsx)(i.h2,{id:"overview",children:"Overview"}),"\n",(0,o.jsxs)(i.p,{children:["Cadence core abstraction is a ",(0,o.jsx)(i.strong,{children:"fault-oblivious stateful workflow"}),". The state of the workflow code, including local variables and threads it creates, is immune to process and Cadence service failures.\nThis is a very powerful concept as it encapsulates state, processing threads, durable timers and event handlers."]}),"\n",(0,o.jsx)(i.h2,{id:"example",children:"Example"}),"\n",(0,o.jsx)(i.p,{children:"Let's look at a use case. A customer signs up for an application with a trial period. After the period, if the customer has not cancelled, he should be charged once a month for the renewal. The customer has to be notified by email about the charges and should be able to cancel the subscription at any time."}),"\n",(0,o.jsx)(i.p,{children:"The business logic of this use case is not very complicated and can be expressed in a few dozen lines of code. But any practical implementation has to ensure that the business process is fault tolerant and scalable. There are various ways to approach the design of such a system."}),"\n",(0,o.jsx)(i.p,{children:"One approach is to center it around a database. An application process would periodically scan database tables for customers in specific states, execute necessary actions, and update the state to reflect that. While feasible, this approach has various drawbacks. The most obvious is that the state machine of the customer state quickly becomes extremely complicated. For example, charging a credit card or sending emails can fail due to a downstream system unavailability. The failed calls might need to be retried for a long time, ideally using an exponential retry policy. These calls should be throttled to not overload external systems. There should be support for poison pills to avoid blocking the whole process if a single customer record cannot be processed for whatever reason. The database-based approach also usually has performance problems. Databases are not efficient for scenarios that require constant polling for records in a specific state."}),"\n",(0,o.jsx)(i.p,{children:"Another commonly employed approach is to use a timer service and queues. Any update is pushed to a queue and then a worker that consumes from it updates a database and possibly pushes more messages in downstream queues. For operations that require scheduling, an external timer service can be used. This approach usually scales much better because a database is not constantly polled for changes. But it makes the programming model more complex and error prone as usually there is no transactional update between a queuing system and a database."}),"\n",(0,o.jsx)(i.p,{children:"With Cadence, the entire logic can be encapsulated in a simple durable function that directly implements the business logic. Because the function is stateful, the implementer doesn't need to employ any additional systems to ensure durability and fault tolerance."}),"\n",(0,o.jsx)(i.p,{children:"Here is an example workflow that implements the subscription management use case. It is in Java, but Go is also supported. The Python and .NET libraries are under active development."}),"\n",(0,o.jsx)(i.pre,{children:(0,o.jsx)(i.code,{className:"language-java",children:"// This SubscriptionWorkflow interface is an example of defining a workflow in Cadence\npublic interface SubscriptionWorkflow {\n @WorkflowMethod\n void manageSubscription(String customerId);\n @SignalMethod\n void cancelSubscription();\n @SignalMethod \n void updateBillingPeriodChargeAmount(int billingPeriodChargeAmount);\n @QueryMethod \n String queryCustomerId();\n @QueryMethod \n int queryBillingPeriodNumber();\n @QueryMethod \n int queryBillingPeriodChargeAmount();\n}\n\n// Workflow implementation is independent from interface. That way, application that start/signal/query workflows only need to know the interface\npublic class SubscriptionWorkflowImpl implements SubscriptionWorkflow {\n\n private int billingPeriodNum;\n private boolean subscriptionCancelled;\n private Customer customer;\n \n private final SubscriptionActivities activities =\n Workflow.newActivityStub(SubscriptionActivities.class);\n\n // This manageSubscription function is an example of a workflow using Cadence\n @Override\n public void manageSubscription(Customer customer) {\n // Set the Workflow customer to class properties so that it can be used by other methods like Query/Signal\n this.customer = customer;\n\n // sendWelcomeEmail is an activity in Cadence. It is implemented in user code and Cadence executes this activity on a worker node when needed.\n activities.sendWelcomeEmail(customer);\n\n // for this example, there are a fixed number of periods in the subscription\n // Cadence supports indefinitely running workflow but some advanced techniques are needed\n while (billingPeriodNum < customer.getSubscription().getPeriodsInSubcription()) {\n\n // Workflow.await tells Cadence to pause the workflow at this stage (saving it's state to the database)\n // Execution restarts when the billing period time has passed or the subscriptionCancelled event is received , whichever comes first\n Workflow.await(customer.getSubscription().getBillingPeriod(), () -> subscriptionCancelled);\n\n if (subscriptionCancelled) {\n activities.sendCancellationEmailDuringActiveSubscription(customer);\n break;\n }\n \n // chargeCustomerForBillingPeriod is another activity\n // Cadence will automatically handle issues such as your billing service being unavailable at the time\n // this activity is invoked\n activities.chargeCustomerForBillingPeriod(customer, billingPeriodNum);\n\n billingPeriodNum++;\n }\n\n if (!subscriptionCancelled) {\n activities.sendSubscriptionOverEmail(customer);\n }\n \n // the workflow is finished once this function returns\n }\n\n @Override\n public void cancelSubscription() {\n subscriptionCancelled = true;\n }\n\n @Override\n public void updateBillingPeriodChargeAmount(int billingPeriodChargeAmount) {\n customer.getSubscription().setBillingPeriodCharge(billingPeriodChargeAmount);\n }\n\n @Override\n public String queryCustomerId() {\n return customer.getId();\n }\n\n @Override\n public int queryBillingPeriodNumber() {\n return billingPeriodNum;\n }\n\n @Override\n public int queryBillingPeriodChargeAmount() {\n return customer.getSubscription().getBillingPeriodCharge();\n }\n}\n\n"})}),"\n",(0,o.jsxs)(i.p,{children:["Again, note that this code directly implements the business logic. If any of the invoked operations (aka activities) takes a long time, the code is not going to change. It is okay to block on ",(0,o.jsx)(i.code,{children:"chargeCustomerForBillingPeriod"})," for a day if the downstream processing service is down that long. The same way that blocking sleep for a billing period like 30 days is a normal operation inside the workflow code."]}),"\n",(0,o.jsx)(i.p,{children:"Cadence has practically no scalability limits on the number of open workflow instances. So even if your site has hundreds of millions of consumers, the above code is not going to change."}),"\n",(0,o.jsxs)(i.p,{children:['The commonly asked question by developers that learn Cadence is "How do I handle workflow_worker process failure/restart in my workflow"? The answer is that you do not. ',(0,o.jsx)(i.strong,{children:"The workflow code is completely oblivious to any failures and downtime of workers or even the Cadence service itself"}),". As soon as they are recovered and the workflow needs to handle some event, like timer or an activity completion, the current state of the workflow is fully restored and the execution is continued. The only reason for a workflow failure is the workflow business code throwing an exception, not underlying infrastructure outages."]}),"\n",(0,o.jsx)(i.p,{children:"Another commonly asked question is whether a worker can handle more workflow instances than its cache size or number of threads it can support. The answer is that a workflow, when in a blocked state, can be safely removed from a worker.\nLater it can be resurrected on a different or the same worker when the need (in the form of an external event) arises. So a single worker can handle millions of open workflow_executions, assuming it can handle the update rate."}),"\n",(0,o.jsx)(i.h2,{id:"state-recovery-and-determinism",children:"State Recovery and Determinism"}),"\n",(0,o.jsx)(i.p,{children:"The workflow state recovery utilizes event sourcing which puts a few restrictions on how the code is written. The main restriction is that the workflow code must be deterministic which means that it must produce exactly the same result if executed multiple times. This rules out any external API calls from the workflow code as external calls can fail intermittently or change its output any time. That is why all communication with the external world should happen through activities. For the same reason, workflow code must use Cadence APIs to get current time, sleep, and create new threads."}),"\n",(0,o.jsx)(i.p,{children:"To understand the Cadence execution model as well as the recovery mechanism, watch the following webcast. The animation covering recovery starts at 15:50."}),"\n",(0,o.jsx)("figure",{class:"video-container",children:(0,o.jsx)("iframe",{src:"https://www.youtube.com/embed/qce_AqCkFys?start=960",frameborder:"0",height:"315",allowfullscreen:!0,width:"560"})}),"\n",(0,o.jsx)(i.h2,{id:"id-uniqueness",children:"ID Uniqueness"}),"\n",(0,o.jsx)(i.p,{children:"Workflow_ID is assigned by a client when starting a workflow. It is usually a business level ID like customer ID or order ID."}),"\n",(0,o.jsxs)(i.p,{children:["Cadence guarantees that there could be only one workflow (across all workflow types) with a given ID open per domain at any time. An attempt to start a workflow with the same ID is going to fail with ",(0,o.jsx)(i.code,{children:"WorkflowExecutionAlreadyStarted"})," error."]}),"\n",(0,o.jsxs)(i.p,{children:["An attempt to start a workflow if there is a completed workflow with the same ID depends on a ",(0,o.jsx)(i.code,{children:"WorkflowIdReusePolicy"})," option:"]}),"\n",(0,o.jsxs)(i.ul,{children:["\n",(0,o.jsxs)(i.li,{children:[(0,o.jsx)(i.code,{children:"AllowDuplicateFailedOnly"})," means that it is allowed to start a workflow only if a previously executed workflow with the same ID failed."]}),"\n",(0,o.jsxs)(i.li,{children:[(0,o.jsx)(i.code,{children:"AllowDuplicate"})," means that it is allowed to start independently of the previous workflow completion status."]}),"\n",(0,o.jsxs)(i.li,{children:[(0,o.jsx)(i.code,{children:"RejectDuplicate"})," means that it is not allowed to start a workflow_execution using the same workflow_ID at all."]}),"\n",(0,o.jsxs)(i.li,{children:[(0,o.jsx)(i.code,{children:"TerminateIfRunning"})," means terminating the current running workflow if one exists, and start a new one."]}),"\n"]}),"\n",(0,o.jsxs)(i.p,{children:["The default is ",(0,o.jsx)(i.code,{children:"AllowDuplicateFailedOnly"}),"."]}),"\n",(0,o.jsxs)(i.p,{children:["To distinguish multiple runs of a workflow with the same workflow_ID, Cadence identifies a workflow with two IDs: ",(0,o.jsx)(i.code,{children:"Workflow ID"})," and ",(0,o.jsx)(i.code,{children:"Run ID"}),". ",(0,o.jsx)(i.code,{children:"Run ID"})," is a service-assigned UUID. To be precise, any workflow is uniquely identified by a triple: ",(0,o.jsx)(i.code,{children:"Domain Name"}),", ",(0,o.jsx)(i.code,{children:"Workflow ID"})," and ",(0,o.jsx)(i.code,{children:"Run ID"}),"."]}),"\n",(0,o.jsx)(i.h2,{id:"child-workflow",children:"Child Workflow"}),"\n",(0,o.jsxs)(i.p,{children:["A workflow can execute other workflows as ",(0,o.jsx)(i.code,{children:"child :workflow:workflows:"}),". A child workflow completion or failure is reported to its parent."]}),"\n",(0,o.jsx)(i.p,{children:"Some reasons to use child workflows are:"}),"\n",(0,o.jsxs)(i.ul,{children:["\n",(0,o.jsx)(i.li,{children:"A child workflow can be hosted by a separate set of workers which don't contain the parent workflow code. So it would act as a separate service that can be invoked from multiple other workflows."}),"\n",(0,o.jsx)(i.li,{children:"A single workflow has a limited size. For example, it cannot execute 100k activities. Child workflows can be used to partition the problem into smaller chunks. One parent with 1000 children each executing 1000 activities is 1 million executed activities."}),"\n",(0,o.jsx)(i.li,{children:"A child workflow can be used to manage some resource using its ID to guarantee uniqueness. For example, a workflow that manages host upgrades can have a child workflow per host (host name being a workflow_ID) and use them to ensure that all operations on the host are serialized."}),"\n",(0,o.jsx)(i.li,{children:"A child workflow can be used to execute some periodic logic without blowing up the parent history size. When a parent starts a child, it executes periodic logic calling that continues as many times as needed, then completes. From the parent point if view, it is just a single child workflow invocation."}),"\n"]}),"\n",(0,o.jsx)(i.p,{children:"The main limitation of a child workflow versus collocating all the application logic in a single workflow is lack of the shared state. Parent and child can communicate only through asynchronous signals. But if there is a tight coupling between them, it might be simpler to use a single workflow and just rely on a shared object state."}),"\n",(0,o.jsx)(i.p,{children:"We recommended starting from a single workflow implementation if your problem has bounded size in terms of number of executed activities and processed signals. It is more straightforward than multiple asynchronously communicating workflows."}),"\n",(0,o.jsx)(i.h2,{id:"workflow-retries",children:"Workflow Retries"}),"\n",(0,o.jsx)(i.p,{children:"Workflow code is unaffected by infrastructure level downtime and failures. But it still can fail due to business logic level failures. For example, an activity can fail due to exceeding the retry interval and the error is not handled by application code, or the workflow code having a bug."}),"\n",(0,o.jsxs)(i.p,{children:["Some workflows require a guarantee that they keep running even in presence of such failures. To support such use cases, an optional exponential ",(0,o.jsx)(i.em,{children:"retry policy"})," can be specified when starting a workflow. When it is specified, a workflow failure restarts a workflow from the beginning after the calculated retry interval. Following are the retry policy parameters:"]}),"\n",(0,o.jsxs)(i.ul,{children:["\n",(0,o.jsxs)(i.li,{children:[(0,o.jsx)(i.code,{children:"InitialInterval"})," is a delay before the first retry."]}),"\n",(0,o.jsxs)(i.li,{children:[(0,o.jsx)(i.code,{children:"BackoffCoefficient"}),". Retry policies are exponential. The coefficient specifies how fast the retry interval is growing. The coefficient of 1 means that the retry interval is always equal to the ",(0,o.jsx)(i.code,{children:"InitialInterval"}),"."]}),"\n",(0,o.jsxs)(i.li,{children:[(0,o.jsx)(i.code,{children:"MaximumInterval"})," specifies the maximum interval between retries. Useful for coefficients of more than 1."]}),"\n",(0,o.jsxs)(i.li,{children:[(0,o.jsx)(i.code,{children:"MaximumAttempts"})," specifies how many times to attempt to execute a workflow in the presence of failures. If this limit is exceeded, the workflow fails without retry. Not required if ",(0,o.jsx)(i.code,{children:"ExpirationInterval"})," is specified."]}),"\n",(0,o.jsxs)(i.li,{children:[(0,o.jsx)(i.code,{children:"ExpirationInterval"})," specifies for how long to attempt executing a workflow in the presence of failures. If this interval is exceeded, the workflow fails without retry. Not required if ",(0,o.jsx)(i.code,{children:"MaximumAttempts"})," is specified."]}),"\n",(0,o.jsxs)(i.li,{children:[(0,o.jsx)(i.code,{children:"NonRetryableErrorReasons"})," allows to specify errors that shouldn't be retried. For example, retrying invalid arguments error doesn't make sense in some scenarios."]}),"\n"]}),"\n",(0,o.jsx)(i.h2,{id:"how-does-workflow-run",children:"How does workflow run"}),"\n",(0,o.jsxs)(i.p,{children:["You may wonder how it works. Behind the scenes, workflow decision is driving the whole workflow running. It's the internal entities for client and server to run your workflows. If this is interesting to you, read this ",(0,o.jsx)(i.a,{href:"https://stackoverflow.com/questions/62904129/what-exactly-is-a-cadence-decision-task/63964726#63964726",children:"stack Overflow QA"}),"."]})]})}function h(e={}){const{wrapper:i}={...(0,s.R)(),...e.components};return i?(0,o.jsx)(i,{...e,children:(0,o.jsx)(d,{...e})}):d(e)}},8453:(e,i,t)=>{t.d(i,{R:()=>r,x:()=>a});var n=t(6540);const o={},s=n.createContext(o);function r(e){const i=n.useContext(s);return n.useMemo((function(){return"function"==typeof e?e(i):{...i,...e}}),[i,e])}function a(e){let i;return i=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:r(e.components),n.createElement(s.Provider,{value:i},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/04634098.b49ec1e6.js b/assets/js/04634098.b49ec1e6.js new file mode 100644 index 000000000..b24adefaf --- /dev/null +++ b/assets/js/04634098.b49ec1e6.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[9053],{7858:e=>{e.exports=JSON.parse('{"tag":{"label":"Announcement","permalink":"/Cadence-Docs/blog/tags/announcements","description":"Announcement tag description","allTagsPath":"/Cadence-Docs/blog/tags","count":7,"unlisted":false},"listMetadata":{"permalink":"/Cadence-Docs/blog/tags/announcements","page":1,"postsPerPage":10,"totalPages":1,"totalCount":7,"blogDescription":"The latest news and updates from the Cadence team","blogTitle":"Cadence Blog"}}')}}]); \ No newline at end of file diff --git a/assets/js/04e595f1.dc6f2f6f.js b/assets/js/04e595f1.dc6f2f6f.js deleted file mode 100644 index ae7f1f38c..000000000 --- a/assets/js/04e595f1.dc6f2f6f.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[908],{3420:e=>{e.exports=JSON.parse('{"tag":{"label":"Announcement","permalink":"/blog/tags/announcements","description":"Announcement tag description","allTagsPath":"/blog/tags","count":7,"unlisted":false},"listMetadata":{"permalink":"/blog/tags/announcements","page":1,"postsPerPage":10,"totalPages":1,"totalCount":7,"blogDescription":"The latest news and updates from the Cadence team","blogTitle":"Cadence Blog"}}')}}]); \ No newline at end of file diff --git a/assets/js/05d44d04.8787bf98.js b/assets/js/05d44d04.8787bf98.js deleted file mode 100644 index 752d5ef6a..000000000 --- a/assets/js/05d44d04.8787bf98.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[3774],{79:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>l,contentTitle:()=>c,default:()=>h,frontMatter:()=>o,metadata:()=>a,toc:()=>r});const a=JSON.parse('{"id":"java-client/versioning","title":"Versioning","description":"As outlined in the Workflow Implementation Constraints section, code has to be deterministic by taking the same","source":"@site/docs/04-java-client/07-versioning.md","sourceDirName":"04-java-client","slug":"/java-client/versioning","permalink":"/docs/java-client/versioning","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/04-java-client/07-versioning.md","tags":[],"version":"current","sidebarPosition":7,"frontMatter":{"layout":"default","title":"Versioning","permalink":"/docs/java-client/versioning"},"sidebar":"docsSidebar","previous":{"title":"Activity interface","permalink":"/docs/java-client/activity-interface"},"next":{"title":"Distributed CRON","permalink":"/docs/java-client/distributed-cron"}}');var i=t(4848),s=t(8453);const o={layout:"default",title:"Versioning",permalink:"/docs/java-client/versioning"},c="Versioning",l={},r=[];function d(e){const n={code:"code",em:"em",h1:"h1",header:"header",p:"p",pre:"pre",...(0,s.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.header,{children:(0,i.jsx)(n.h1,{id:"versioning",children:"Versioning"})}),"\n",(0,i.jsxs)(n.p,{children:["As outlined in the ",(0,i.jsx)(n.em,{children:"Workflow Implementation Constraints"})," section, workflow code has to be deterministic by taking the same\ncode path when replaying history events. Any workflow code change that affects the order in which decisions are generated breaks\nthis assumption. The solution that allows updating code of already running workflows is to keep both the old and new code.\nWhen replaying, use the code version that the events were generated with and when executing a new code path, always take the\nnew code."]}),"\n",(0,i.jsxs)(n.p,{children:["Use the ",(0,i.jsx)(n.code,{children:"Workflow.getVersion"})," function to return a version of the code that should be executed and then use the returned\nvalue to pick a correct branch. Let's look at an example."]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",children:"public void processFile(Arguments args) {\n String localName = null;\n String processedName = null;\n try {\n localName = activities.download(args.getSourceBucketName(), args.getSourceFilename());\n processedName = activities.processFile(localName);\n activities.upload(args.getTargetBucketName(), args.getTargetFilename(), processedName);\n } finally {\n if (localName != null) { // File was downloaded.\n activities.deleteLocalFile(localName);\n }\n if (processedName != null) { // File was processed.\n activities.deleteLocalFile(processedName);\n }\n }\n}\n"})}),"\n",(0,i.jsx)(n.p,{children:"Now we decide to calculate the processed file checksum and pass it to upload.\nThe correct way to implement this change is:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",children:'public void processFile(Arguments args) {\n String localName = null;\n String processedName = null;\n try {\n localName = activities.download(args.getSourceBucketName(), args.getSourceFilename());\n processedName = activities.processFile(localName);\n int version = Workflow.getVersion("checksumAdded", Workflow.DEFAULT_VERSION, 1);\n if (version == Workflow.DEFAULT_VERSION) {\n activities.upload(args.getTargetBucketName(), args.getTargetFilename(), processedName);\n } else {\n long checksum = activities.calculateChecksum(processedName);\n activities.uploadWithChecksum(\n args.getTargetBucketName(), args.getTargetFilename(), processedName, checksum);\n }\n } finally {\n if (localName != null) { // File was downloaded.\n activities.deleteLocalFile(localName);\n }\n if (processedName != null) { // File was processed.\n activities.deleteLocalFile(processedName);\n }\n }\n}\n'})}),"\n",(0,i.jsx)(n.p,{children:"Later, when all workflows that use the old version are completed, the old branch can be removed."}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",children:'public void processFile(Arguments args) {\n String localName = null;\n String processedName = null;\n try {\n localName = activities.download(args.getSourceBucketName(), args.getSourceFilename());\n processedName = activities.processFile(localName);\n // getVersion call is left here to ensure that any attempt to replay history\n // for a different version fails. It can be removed later when there is no possibility\n // of this happening.\n Workflow.getVersion("checksumAdded", 1, 1);\n long checksum = activities.calculateChecksum(processedName);\n activities.uploadWithChecksum(\n args.getTargetBucketName(), args.getTargetFilename(), processedName, checksum);\n } finally {\n if (localName != null) { // File was downloaded.\n activities.deleteLocalFile(localName);\n }\n if (processedName != null) { // File was processed.\n activities.deleteLocalFile(processedName);\n }\n }\n}\n'})}),"\n",(0,i.jsxs)(n.p,{children:["The ID that is passed to the ",(0,i.jsx)(n.code,{children:"getVersion"})," call identifies the change. Each change is expected to have its own ID. But if\na change spawns multiple places in the workflow code and the new code should be either executed in all of them or\nin none of them, then they have to share the ID."]})]})}function h(e={}){const{wrapper:n}={...(0,s.R)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(d,{...e})}):d(e)}},8453:(e,n,t)=>{t.d(n,{R:()=>o,x:()=>c});var a=t(6540);const i={},s=a.createContext(i);function o(e){const n=a.useContext(s);return a.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function c(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:o(e.components),a.createElement(s.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/05d44d04.c5c1b724.js b/assets/js/05d44d04.c5c1b724.js new file mode 100644 index 000000000..cfc7bb78d --- /dev/null +++ b/assets/js/05d44d04.c5c1b724.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[3774],{79:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>l,contentTitle:()=>c,default:()=>h,frontMatter:()=>o,metadata:()=>a,toc:()=>r});const a=JSON.parse('{"id":"java-client/versioning","title":"Versioning","description":"As outlined in the Workflow Implementation Constraints section, code has to be deterministic by taking the same","source":"@site/docs/04-java-client/07-versioning.md","sourceDirName":"04-java-client","slug":"/java-client/versioning","permalink":"/Cadence-Docs/docs/java-client/versioning","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/04-java-client/07-versioning.md","tags":[],"version":"current","sidebarPosition":7,"frontMatter":{"layout":"default","title":"Versioning","permalink":"/docs/java-client/versioning"},"sidebar":"docsSidebar","previous":{"title":"Activity interface","permalink":"/Cadence-Docs/docs/java-client/activity-interface"},"next":{"title":"Distributed CRON","permalink":"/Cadence-Docs/docs/java-client/distributed-cron"}}');var i=t(4848),s=t(8453);const o={layout:"default",title:"Versioning",permalink:"/docs/java-client/versioning"},c="Versioning",l={},r=[];function d(e){const n={code:"code",em:"em",h1:"h1",header:"header",p:"p",pre:"pre",...(0,s.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.header,{children:(0,i.jsx)(n.h1,{id:"versioning",children:"Versioning"})}),"\n",(0,i.jsxs)(n.p,{children:["As outlined in the ",(0,i.jsx)(n.em,{children:"Workflow Implementation Constraints"})," section, workflow code has to be deterministic by taking the same\ncode path when replaying history events. Any workflow code change that affects the order in which decisions are generated breaks\nthis assumption. The solution that allows updating code of already running workflows is to keep both the old and new code.\nWhen replaying, use the code version that the events were generated with and when executing a new code path, always take the\nnew code."]}),"\n",(0,i.jsxs)(n.p,{children:["Use the ",(0,i.jsx)(n.code,{children:"Workflow.getVersion"})," function to return a version of the code that should be executed and then use the returned\nvalue to pick a correct branch. Let's look at an example."]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",children:"public void processFile(Arguments args) {\n String localName = null;\n String processedName = null;\n try {\n localName = activities.download(args.getSourceBucketName(), args.getSourceFilename());\n processedName = activities.processFile(localName);\n activities.upload(args.getTargetBucketName(), args.getTargetFilename(), processedName);\n } finally {\n if (localName != null) { // File was downloaded.\n activities.deleteLocalFile(localName);\n }\n if (processedName != null) { // File was processed.\n activities.deleteLocalFile(processedName);\n }\n }\n}\n"})}),"\n",(0,i.jsx)(n.p,{children:"Now we decide to calculate the processed file checksum and pass it to upload.\nThe correct way to implement this change is:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",children:'public void processFile(Arguments args) {\n String localName = null;\n String processedName = null;\n try {\n localName = activities.download(args.getSourceBucketName(), args.getSourceFilename());\n processedName = activities.processFile(localName);\n int version = Workflow.getVersion("checksumAdded", Workflow.DEFAULT_VERSION, 1);\n if (version == Workflow.DEFAULT_VERSION) {\n activities.upload(args.getTargetBucketName(), args.getTargetFilename(), processedName);\n } else {\n long checksum = activities.calculateChecksum(processedName);\n activities.uploadWithChecksum(\n args.getTargetBucketName(), args.getTargetFilename(), processedName, checksum);\n }\n } finally {\n if (localName != null) { // File was downloaded.\n activities.deleteLocalFile(localName);\n }\n if (processedName != null) { // File was processed.\n activities.deleteLocalFile(processedName);\n }\n }\n}\n'})}),"\n",(0,i.jsx)(n.p,{children:"Later, when all workflows that use the old version are completed, the old branch can be removed."}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",children:'public void processFile(Arguments args) {\n String localName = null;\n String processedName = null;\n try {\n localName = activities.download(args.getSourceBucketName(), args.getSourceFilename());\n processedName = activities.processFile(localName);\n // getVersion call is left here to ensure that any attempt to replay history\n // for a different version fails. It can be removed later when there is no possibility\n // of this happening.\n Workflow.getVersion("checksumAdded", 1, 1);\n long checksum = activities.calculateChecksum(processedName);\n activities.uploadWithChecksum(\n args.getTargetBucketName(), args.getTargetFilename(), processedName, checksum);\n } finally {\n if (localName != null) { // File was downloaded.\n activities.deleteLocalFile(localName);\n }\n if (processedName != null) { // File was processed.\n activities.deleteLocalFile(processedName);\n }\n }\n}\n'})}),"\n",(0,i.jsxs)(n.p,{children:["The ID that is passed to the ",(0,i.jsx)(n.code,{children:"getVersion"})," call identifies the change. Each change is expected to have its own ID. But if\na change spawns multiple places in the workflow code and the new code should be either executed in all of them or\nin none of them, then they have to share the ID."]})]})}function h(e={}){const{wrapper:n}={...(0,s.R)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(d,{...e})}):d(e)}},8453:(e,n,t)=>{t.d(n,{R:()=>o,x:()=>c});var a=t(6540);const i={},s=a.createContext(i);function o(e){const n=a.useContext(s);return a.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function c(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:o(e.components),a.createElement(s.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/0826fbec.4c9925e7.js b/assets/js/0826fbec.4c9925e7.js new file mode 100644 index 000000000..4331f1012 --- /dev/null +++ b/assets/js/0826fbec.4c9925e7.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[8067],{3952:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>s,contentTitle:()=>c,default:()=>p,frontMatter:()=>i,metadata:()=>r,toc:()=>l});const r=JSON.parse('{"id":"go-client/tracing","title":"Tracing and context propagation","description":"Tracing","source":"@site/docs/05-go-client/17-tracing.md","sourceDirName":"05-go-client","slug":"/go-client/tracing","permalink":"/Cadence-Docs/docs/go-client/tracing","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/05-go-client/17-tracing.md","tags":[],"version":"current","sidebarPosition":17,"frontMatter":{"layout":"default","title":"Tracing and context propagation","permalink":"/docs/go-client/tracing"},"sidebar":"docsSidebar","previous":{"title":"Distributed CRON","permalink":"/Cadence-Docs/docs/go-client/distributed-cron"},"next":{"title":"Workflow Replay and Shadowing","permalink":"/Cadence-Docs/docs/go-client/workflow-replay-shadowing"}}');var o=n(4848),a=n(8453);const i={layout:"default",title:"Tracing and context propagation",permalink:"/docs/go-client/tracing"},c="Tracing and context propagation",s={},l=[{value:"Tracing",id:"tracing",level:2},{value:"Context Propagation",id:"context-propagation",level:2},{value:"Server-Side Headers Support",id:"server-side-headers-support",level:3},{value:"Context Propagators",id:"context-propagators",level:3},{value:"Q & A",id:"q--a",level:2},{value:"Is there a complete example?",id:"is-there-a-complete-example",level:3},{value:"Can I configure multiple context propagators?",id:"can-i-configure-multiple-context-propagators",level:3}];function d(e){const t={a:"a",code:"code",h1:"h1",h2:"h2",h3:"h3",header:"header",li:"li",p:"p",pre:"pre",ul:"ul",...(0,a.R)(),...e.components};return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsx)(t.header,{children:(0,o.jsx)(t.h1,{id:"tracing-and-context-propagation",children:"Tracing and context propagation"})}),"\n",(0,o.jsx)(t.h2,{id:"tracing",children:"Tracing"}),"\n",(0,o.jsxs)(t.p,{children:["The Go client provides distributed tracing support through ",(0,o.jsx)(t.a,{href:"https://opentracing.io/",children:"OpenTracing"}),". Tracing can be\nconfigured by providing an ",(0,o.jsx)(t.a,{href:"https://godoc.org/github.com/opentracing/opentracing-go#Tracer",children:"opentracing.Tracer"}),"\nimplementation in ",(0,o.jsx)(t.a,{href:"https://godoc.org/go.uber.org/cadence/internal#ClientOptions",children:"ClientOptions"}),"\nand ",(0,o.jsx)(t.a,{href:"https://godoc.org/go.uber.org/cadence/internal#WorkerOptions",children:"WorkerOptions"})," during client and worker instantiation,\nrespectively. Tracing allows\nyou to view the call graph of a workflow along with its activities, child workflows etc. For more details on how to\nconfigure and leverage tracing, see the ",(0,o.jsx)(t.a,{href:"https://opentracing.io/docs/getting-started/",children:"OpenTracing documentation"}),".\nThe OpenTracing support has been validated using ",(0,o.jsx)(t.a,{href:"https://www.jaegertracing.io/",children:"Jaeger"}),", but other implementations\nmentioned ",(0,o.jsx)(t.a,{href:"https://opentracing.io/docs/supported-tracers/",children:"here"})," should also work. Tracing support utilizes generic context\npropagation support provided by the client."]}),"\n",(0,o.jsx)(t.h2,{id:"context-propagation",children:"Context Propagation"}),"\n",(0,o.jsxs)(t.p,{children:["We provide a standard way to propagate custom context across a workflow.\n",(0,o.jsx)(t.a,{href:"https://godoc.org/go.uber.org/cadence/internal#ClientOptions",children:"ClientOptions"})," and ",(0,o.jsx)(t.a,{href:"https://godoc.org/go.uber.org/cadence/internal#WorkerOptions",children:"WorkerOptions"}),"\nallow configuring a context propagator. The context propagator extracts and passes on information present in the ",(0,o.jsx)(t.code,{children:"context.Context"}),"\nand ",(0,o.jsx)(t.code,{children:"workflow.Context"})," objects across the workflow. Once a context propagator is configured, you should be able to access the required values\nin the context objects as you would normally do in Go.\nFor a sample, the Go client implements a ",(0,o.jsx)(t.a,{href:"https://github.com/cadence-workflow/cadence-go-client/blob/master/internal/tracer.go",children:"tracing context propagator"}),"."]}),"\n",(0,o.jsx)(t.h3,{id:"server-side-headers-support",children:"Server-Side Headers Support"}),"\n",(0,o.jsx)(t.p,{children:"On the server side, Cadence provides a mechanism to propagate what it calls headers across different workflow\ntransitions."}),"\n",(0,o.jsx)(t.pre,{children:(0,o.jsx)(t.code,{className:"language-go",children:"struct Header {\n 10: optional map fields\n}\n"})}),"\n",(0,o.jsxs)(t.p,{children:["The client leverages this to pass around selected context information. ",(0,o.jsx)(t.a,{href:"https://godoc.org/go.uber.org/cadence/internal#HeaderReader",children:"HeaderReader"}),"\nand ",(0,o.jsx)(t.a,{href:"https://godoc.org/go.uber.org/cadence/internal#HeaderWriter",children:"HeaderWriter"})," are interfaces\nthat allow reading and writing to the Cadence server headers. The client already provides ",(0,o.jsx)(t.a,{href:"https://github.com/cadence-workflow/cadence-go-client/blob/master/internal/headers.go",children:"implementations"}),"\nfor these. ",(0,o.jsx)(t.code,{children:"HeaderWriter"})," sets a field in the header. Headers is a map, so setting a value for the the same key\nmultiple times will overwrite the previous values. ",(0,o.jsx)(t.code,{children:"HeaderReader"})," iterates through the headers map and runs the\nprovided handler function on each key/value pair, allowing you to deal with the fields you are interested in."]}),"\n",(0,o.jsx)(t.pre,{children:(0,o.jsx)(t.code,{className:"language-go",children:"type HeaderWriter interface {\n Set(string, []byte)\n}\n\ntype HeaderReader interface {\n ForEachKey(handler func(string, []byte) error) error\n}\n"})}),"\n",(0,o.jsx)(t.h3,{id:"context-propagators",children:"Context Propagators"}),"\n",(0,o.jsx)(t.p,{children:"Context propagators require implementing the following four methods to propagate selected context across a workflow:"}),"\n",(0,o.jsxs)(t.ul,{children:["\n",(0,o.jsxs)(t.li,{children:[(0,o.jsx)(t.code,{children:"Inject"})," is meant to pick out the context keys of interest from a Go ",(0,o.jsx)(t.a,{href:"https://golang.org/pkg/context/#Context",children:"context.Context"})," object and write that into the\nheaders using the ",(0,o.jsx)(t.a,{href:"https://godoc.org/go.uber.org/cadence/internal#HeaderWriter",children:"HeaderWriter"})," interface"]}),"\n",(0,o.jsxs)(t.li,{children:[(0,o.jsx)(t.code,{children:"InjectFromWorkflow"})," is the same as above, but operates on a ",(0,o.jsx)(t.a,{href:"https://godoc.org/go.uber.org/cadence/internal#Context",children:"workflow.Context"})," object"]}),"\n",(0,o.jsxs)(t.li,{children:[(0,o.jsx)(t.code,{children:"Extract"})," reads the headers and places the information of interest back into the ",(0,o.jsx)(t.a,{href:"https://golang.org/pkg/context/#Context",children:"context.Context"})," object"]}),"\n",(0,o.jsxs)(t.li,{children:[(0,o.jsx)(t.code,{children:"ExtractToWorkflow"})," is the same as above, but operates on a ",(0,o.jsx)(t.a,{href:"https://godoc.org/go.uber.org/cadence/internal#Context",children:"workflow.Context"})," object"]}),"\n"]}),"\n",(0,o.jsxs)(t.p,{children:["The ",(0,o.jsx)(t.a,{href:"https://github.com/cadence-workflow/cadence-go-client/blob/master/internal/tracer.go",children:"tracing context propagator"}),"\nshows a sample implementation of context propagation."]}),"\n",(0,o.jsx)(t.pre,{children:(0,o.jsx)(t.code,{className:"language-go",children:"type ContextPropagator interface {\n Inject(context.Context, HeaderWriter) error\n\n Extract(context.Context, HeaderReader) (context.Context, error)\n\n InjectFromWorkflow(Context, HeaderWriter) error\n\n ExtractToWorkflow(Context, HeaderReader) (Context, error)\n}\n"})}),"\n",(0,o.jsx)(t.h2,{id:"q--a",children:"Q & A"}),"\n",(0,o.jsx)(t.h3,{id:"is-there-a-complete-example",children:"Is there a complete example?"}),"\n",(0,o.jsxs)(t.p,{children:["The ",(0,o.jsx)(t.a,{href:"https://github.com/cadence-workflow/cadence-samples/blob/master/cmd/samples/recipes/ctxpropagation/workflow.go",children:"context propagation sample"}),"\nconfigures a custom context propagator and shows context propagation of custom keys across a workflow and an activity."]}),"\n",(0,o.jsx)(t.h3,{id:"can-i-configure-multiple-context-propagators",children:"Can I configure multiple context propagators?"}),"\n",(0,o.jsx)(t.p,{children:"Yes, we recommended that you configure multiple context propagators with each propagator meant to propagate a particular type of context."})]})}function p(e={}){const{wrapper:t}={...(0,a.R)(),...e.components};return t?(0,o.jsx)(t,{...e,children:(0,o.jsx)(d,{...e})}):d(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>i,x:()=>c});var r=n(6540);const o={},a=r.createContext(o);function i(e){const t=r.useContext(a);return r.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function c(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:i(e.components),r.createElement(a.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/0826fbec.637d09dd.js b/assets/js/0826fbec.637d09dd.js deleted file mode 100644 index 8ce364c8e..000000000 --- a/assets/js/0826fbec.637d09dd.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[8067],{3952:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>s,contentTitle:()=>c,default:()=>p,frontMatter:()=>i,metadata:()=>r,toc:()=>l});const r=JSON.parse('{"id":"go-client/tracing","title":"Tracing and context propagation","description":"Tracing","source":"@site/docs/05-go-client/17-tracing.md","sourceDirName":"05-go-client","slug":"/go-client/tracing","permalink":"/docs/go-client/tracing","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/05-go-client/17-tracing.md","tags":[],"version":"current","sidebarPosition":17,"frontMatter":{"layout":"default","title":"Tracing and context propagation","permalink":"/docs/go-client/tracing"},"sidebar":"docsSidebar","previous":{"title":"Distributed CRON","permalink":"/docs/go-client/distributed-cron"},"next":{"title":"Workflow Replay and Shadowing","permalink":"/docs/go-client/workflow-replay-shadowing"}}');var o=n(4848),a=n(8453);const i={layout:"default",title:"Tracing and context propagation",permalink:"/docs/go-client/tracing"},c="Tracing and context propagation",s={},l=[{value:"Tracing",id:"tracing",level:2},{value:"Context Propagation",id:"context-propagation",level:2},{value:"Server-Side Headers Support",id:"server-side-headers-support",level:3},{value:"Context Propagators",id:"context-propagators",level:3},{value:"Q & A",id:"q--a",level:2},{value:"Is there a complete example?",id:"is-there-a-complete-example",level:3},{value:"Can I configure multiple context propagators?",id:"can-i-configure-multiple-context-propagators",level:3}];function d(e){const t={a:"a",code:"code",h1:"h1",h2:"h2",h3:"h3",header:"header",li:"li",p:"p",pre:"pre",ul:"ul",...(0,a.R)(),...e.components};return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsx)(t.header,{children:(0,o.jsx)(t.h1,{id:"tracing-and-context-propagation",children:"Tracing and context propagation"})}),"\n",(0,o.jsx)(t.h2,{id:"tracing",children:"Tracing"}),"\n",(0,o.jsxs)(t.p,{children:["The Go client provides distributed tracing support through ",(0,o.jsx)(t.a,{href:"https://opentracing.io/",children:"OpenTracing"}),". Tracing can be\nconfigured by providing an ",(0,o.jsx)(t.a,{href:"https://godoc.org/github.com/opentracing/opentracing-go#Tracer",children:"opentracing.Tracer"}),"\nimplementation in ",(0,o.jsx)(t.a,{href:"https://godoc.org/go.uber.org/cadence/internal#ClientOptions",children:"ClientOptions"}),"\nand ",(0,o.jsx)(t.a,{href:"https://godoc.org/go.uber.org/cadence/internal#WorkerOptions",children:"WorkerOptions"})," during client and worker instantiation,\nrespectively. Tracing allows\nyou to view the call graph of a workflow along with its activities, child workflows etc. For more details on how to\nconfigure and leverage tracing, see the ",(0,o.jsx)(t.a,{href:"https://opentracing.io/docs/getting-started/",children:"OpenTracing documentation"}),".\nThe OpenTracing support has been validated using ",(0,o.jsx)(t.a,{href:"https://www.jaegertracing.io/",children:"Jaeger"}),", but other implementations\nmentioned ",(0,o.jsx)(t.a,{href:"https://opentracing.io/docs/supported-tracers/",children:"here"})," should also work. Tracing support utilizes generic context\npropagation support provided by the client."]}),"\n",(0,o.jsx)(t.h2,{id:"context-propagation",children:"Context Propagation"}),"\n",(0,o.jsxs)(t.p,{children:["We provide a standard way to propagate custom context across a workflow.\n",(0,o.jsx)(t.a,{href:"https://godoc.org/go.uber.org/cadence/internal#ClientOptions",children:"ClientOptions"})," and ",(0,o.jsx)(t.a,{href:"https://godoc.org/go.uber.org/cadence/internal#WorkerOptions",children:"WorkerOptions"}),"\nallow configuring a context propagator. The context propagator extracts and passes on information present in the ",(0,o.jsx)(t.code,{children:"context.Context"}),"\nand ",(0,o.jsx)(t.code,{children:"workflow.Context"})," objects across the workflow. Once a context propagator is configured, you should be able to access the required values\nin the context objects as you would normally do in Go.\nFor a sample, the Go client implements a ",(0,o.jsx)(t.a,{href:"https://github.com/cadence-workflow/cadence-go-client/blob/master/internal/tracer.go",children:"tracing context propagator"}),"."]}),"\n",(0,o.jsx)(t.h3,{id:"server-side-headers-support",children:"Server-Side Headers Support"}),"\n",(0,o.jsx)(t.p,{children:"On the server side, Cadence provides a mechanism to propagate what it calls headers across different workflow\ntransitions."}),"\n",(0,o.jsx)(t.pre,{children:(0,o.jsx)(t.code,{className:"language-go",children:"struct Header {\n 10: optional map fields\n}\n"})}),"\n",(0,o.jsxs)(t.p,{children:["The client leverages this to pass around selected context information. ",(0,o.jsx)(t.a,{href:"https://godoc.org/go.uber.org/cadence/internal#HeaderReader",children:"HeaderReader"}),"\nand ",(0,o.jsx)(t.a,{href:"https://godoc.org/go.uber.org/cadence/internal#HeaderWriter",children:"HeaderWriter"})," are interfaces\nthat allow reading and writing to the Cadence server headers. The client already provides ",(0,o.jsx)(t.a,{href:"https://github.com/cadence-workflow/cadence-go-client/blob/master/internal/headers.go",children:"implementations"}),"\nfor these. ",(0,o.jsx)(t.code,{children:"HeaderWriter"})," sets a field in the header. Headers is a map, so setting a value for the the same key\nmultiple times will overwrite the previous values. ",(0,o.jsx)(t.code,{children:"HeaderReader"})," iterates through the headers map and runs the\nprovided handler function on each key/value pair, allowing you to deal with the fields you are interested in."]}),"\n",(0,o.jsx)(t.pre,{children:(0,o.jsx)(t.code,{className:"language-go",children:"type HeaderWriter interface {\n Set(string, []byte)\n}\n\ntype HeaderReader interface {\n ForEachKey(handler func(string, []byte) error) error\n}\n"})}),"\n",(0,o.jsx)(t.h3,{id:"context-propagators",children:"Context Propagators"}),"\n",(0,o.jsx)(t.p,{children:"Context propagators require implementing the following four methods to propagate selected context across a workflow:"}),"\n",(0,o.jsxs)(t.ul,{children:["\n",(0,o.jsxs)(t.li,{children:[(0,o.jsx)(t.code,{children:"Inject"})," is meant to pick out the context keys of interest from a Go ",(0,o.jsx)(t.a,{href:"https://golang.org/pkg/context/#Context",children:"context.Context"})," object and write that into the\nheaders using the ",(0,o.jsx)(t.a,{href:"https://godoc.org/go.uber.org/cadence/internal#HeaderWriter",children:"HeaderWriter"})," interface"]}),"\n",(0,o.jsxs)(t.li,{children:[(0,o.jsx)(t.code,{children:"InjectFromWorkflow"})," is the same as above, but operates on a ",(0,o.jsx)(t.a,{href:"https://godoc.org/go.uber.org/cadence/internal#Context",children:"workflow.Context"})," object"]}),"\n",(0,o.jsxs)(t.li,{children:[(0,o.jsx)(t.code,{children:"Extract"})," reads the headers and places the information of interest back into the ",(0,o.jsx)(t.a,{href:"https://golang.org/pkg/context/#Context",children:"context.Context"})," object"]}),"\n",(0,o.jsxs)(t.li,{children:[(0,o.jsx)(t.code,{children:"ExtractToWorkflow"})," is the same as above, but operates on a ",(0,o.jsx)(t.a,{href:"https://godoc.org/go.uber.org/cadence/internal#Context",children:"workflow.Context"})," object"]}),"\n"]}),"\n",(0,o.jsxs)(t.p,{children:["The ",(0,o.jsx)(t.a,{href:"https://github.com/cadence-workflow/cadence-go-client/blob/master/internal/tracer.go",children:"tracing context propagator"}),"\nshows a sample implementation of context propagation."]}),"\n",(0,o.jsx)(t.pre,{children:(0,o.jsx)(t.code,{className:"language-go",children:"type ContextPropagator interface {\n Inject(context.Context, HeaderWriter) error\n\n Extract(context.Context, HeaderReader) (context.Context, error)\n\n InjectFromWorkflow(Context, HeaderWriter) error\n\n ExtractToWorkflow(Context, HeaderReader) (Context, error)\n}\n"})}),"\n",(0,o.jsx)(t.h2,{id:"q--a",children:"Q & A"}),"\n",(0,o.jsx)(t.h3,{id:"is-there-a-complete-example",children:"Is there a complete example?"}),"\n",(0,o.jsxs)(t.p,{children:["The ",(0,o.jsx)(t.a,{href:"https://github.com/cadence-workflow/cadence-samples/blob/master/cmd/samples/recipes/ctxpropagation/workflow.go",children:"context propagation sample"}),"\nconfigures a custom context propagator and shows context propagation of custom keys across a workflow and an activity."]}),"\n",(0,o.jsx)(t.h3,{id:"can-i-configure-multiple-context-propagators",children:"Can I configure multiple context propagators?"}),"\n",(0,o.jsx)(t.p,{children:"Yes, we recommended that you configure multiple context propagators with each propagator meant to propagate a particular type of context."})]})}function p(e={}){const{wrapper:t}={...(0,a.R)(),...e.components};return t?(0,o.jsx)(t,{...e,children:(0,o.jsx)(d,{...e})}):d(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>i,x:()=>c});var r=n(6540);const o={},a=r.createContext(o);function i(e){const t=r.useContext(a);return r.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function c(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:i(e.components),r.createElement(a.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/08e09fce.e5e53f8b.js b/assets/js/08e09fce.e5e53f8b.js new file mode 100644 index 000000000..eb0edd115 --- /dev/null +++ b/assets/js/08e09fce.e5e53f8b.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[4993],{7623:a=>{a.exports=JSON.parse('{"author":{"name":"Vytautas Karpavicius","title":"Software Engineer @ Uber","url":"https://www.linkedin.com/in/vytautas-karpavicius","page":{"permalink":"/Cadence-Docs/blog/authors/vytautas-karpavicius"},"socials":{"linkedin":"https://www.linkedin.com/in/vytautas-karpavicius","github":"https://github.com/vytautas-karpavicius"},"imageURL":"https://github.com/vytautas-karpavicius.png","key":"vytautas-karpavicius","count":1},"listMetadata":{"permalink":"/Cadence-Docs/blog/authors/vytautas-karpavicius","page":1,"postsPerPage":10,"totalPages":1,"totalCount":1,"blogDescription":"The latest news and updates from the Cadence team","blogTitle":"Cadence Blog"}}')}}]); \ No newline at end of file diff --git a/assets/js/0922f36e.e8603763.js b/assets/js/0922f36e.e8603763.js deleted file mode 100644 index 416481701..000000000 --- a/assets/js/0922f36e.e8603763.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[1640],{7683:a=>{a.exports=JSON.parse('{"author":{"name":"Josu\xe9 Alexander Ibarra","title":"Developer Advocate @ Uber","url":"https://github.com/ibarrajo/","page":{"permalink":"/blog/authors/ibarrajo"},"socials":{"github":"https://github.com/ibarrajo","linkedin":"https://www.linkedin.com/in/elninja/"},"imageURL":"https://github.com/ibarrajo.png","key":"ibarrajo","count":1},"listMetadata":{"permalink":"/blog/authors/ibarrajo","page":1,"postsPerPage":10,"totalPages":1,"totalCount":1,"blogDescription":"The latest news and updates from the Cadence team","blogTitle":"Cadence Blog"}}')}}]); \ No newline at end of file diff --git a/assets/js/0b211f8a.1ed54eec.js b/assets/js/0b211f8a.1ed54eec.js new file mode 100644 index 000000000..b940fc3da --- /dev/null +++ b/assets/js/0b211f8a.1ed54eec.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[6758],{8140:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>i,contentTitle:()=>r,default:()=>u,frontMatter:()=>s,metadata:()=>c,toc:()=>l});const c=JSON.parse('{"id":"about/index","title":"Contact us","description":"If you have a question, check whether it is already answered at stackoverflow under cadence-workflow tag.","source":"@site/docs/09-about/index.md","sourceDirName":"09-about","slug":"/about/","permalink":"/Cadence-Docs/docs/about/","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/09-about/index.md","tags":[],"version":"current","frontMatter":{"layout":"default","title":"Contact us","permalink":"/docs/about"},"sidebar":"docsSidebar","previous":{"title":"Retries","permalink":"/Cadence-Docs/docs/workflow-troubleshooting/retries"},"next":{"title":"MIT License","permalink":"/Cadence-Docs/docs/about/license"}}');var a=n(4848),o=n(8453);const s={layout:"default",title:"Contact us",permalink:"/docs/about"},r="Contact us",i={},l=[];function d(e){const t={a:"a",h1:"h1",header:"header",li:"li",p:"p",ul:"ul",...(0,o.R)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(t.header,{children:(0,a.jsx)(t.h1,{id:"contact-us",children:"Contact us"})}),"\n",(0,a.jsxs)(t.p,{children:["If you have a question, check whether it is already answered at stackoverflow under ",(0,a.jsx)(t.a,{href:"https://stackoverflow.com/questions/tagged/cadence-workflow",children:"cadence-workflow"})," tag."]}),"\n",(0,a.jsxs)(t.p,{children:["If you still need help, visit ",(0,a.jsx)("slack-link",{}),"."]}),"\n",(0,a.jsx)(t.p,{children:"If you have a feature request or a bug to report file an issue against one of the Cadence github repositories:"}),"\n",(0,a.jsxs)(t.ul,{children:["\n",(0,a.jsx)(t.li,{children:(0,a.jsx)(t.a,{href:"https://github.com/cadence-workflow/cadence",children:"Cadence Service and CLI"})}),"\n",(0,a.jsx)(t.li,{children:(0,a.jsx)(t.a,{href:"https://github.com/cadence-workflow/cadence-go-client",children:"Cadence Go Client"})}),"\n",(0,a.jsx)(t.li,{children:(0,a.jsx)(t.a,{href:"https://github.com/cadence-workflow/cadence-samples",children:"Cadence Go Client Samples"})}),"\n",(0,a.jsx)(t.li,{children:(0,a.jsx)(t.a,{href:"https://github.com/cadence-workflow/cadence-java-client",children:"Cadence Java Client"})}),"\n",(0,a.jsx)(t.li,{children:(0,a.jsx)(t.a,{href:"https://github.com/cadence-workflow/cadence-java-samples",children:"Cadence Java Client Samples"})}),"\n",(0,a.jsx)(t.li,{children:(0,a.jsx)(t.a,{href:"https://github.com/cadence-workflow/cadence-web",children:"Cadence Web UI"})}),"\n"]})]})}function u(e={}){const{wrapper:t}={...(0,o.R)(),...e.components};return t?(0,a.jsx)(t,{...e,children:(0,a.jsx)(d,{...e})}):d(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>s,x:()=>r});var c=n(6540);const a={},o=c.createContext(a);function s(e){const t=c.useContext(o);return c.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function r(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:s(e.components),c.createElement(o.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/0b211f8a.66a27957.js b/assets/js/0b211f8a.66a27957.js deleted file mode 100644 index f5e440380..000000000 --- a/assets/js/0b211f8a.66a27957.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[6758],{8140:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>i,contentTitle:()=>r,default:()=>u,frontMatter:()=>s,metadata:()=>c,toc:()=>l});const c=JSON.parse('{"id":"about/index","title":"Contact us","description":"If you have a question, check whether it is already answered at stackoverflow under cadence-workflow tag.","source":"@site/docs/09-about/index.md","sourceDirName":"09-about","slug":"/about/","permalink":"/docs/about/","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/09-about/index.md","tags":[],"version":"current","frontMatter":{"layout":"default","title":"Contact us","permalink":"/docs/about"},"sidebar":"docsSidebar","previous":{"title":"Retries","permalink":"/docs/workflow-troubleshooting/retries"},"next":{"title":"MIT License","permalink":"/docs/about/license"}}');var a=n(4848),o=n(8453);const s={layout:"default",title:"Contact us",permalink:"/docs/about"},r="Contact us",i={},l=[];function d(e){const t={a:"a",h1:"h1",header:"header",li:"li",p:"p",ul:"ul",...(0,o.R)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(t.header,{children:(0,a.jsx)(t.h1,{id:"contact-us",children:"Contact us"})}),"\n",(0,a.jsxs)(t.p,{children:["If you have a question, check whether it is already answered at stackoverflow under ",(0,a.jsx)(t.a,{href:"https://stackoverflow.com/questions/tagged/cadence-workflow",children:"cadence-workflow"})," tag."]}),"\n",(0,a.jsxs)(t.p,{children:["If you still need help, visit ",(0,a.jsx)("slack-link",{}),"."]}),"\n",(0,a.jsx)(t.p,{children:"If you have a feature request or a bug to report file an issue against one of the Cadence github repositories:"}),"\n",(0,a.jsxs)(t.ul,{children:["\n",(0,a.jsx)(t.li,{children:(0,a.jsx)(t.a,{href:"https://github.com/cadence-workflow/cadence",children:"Cadence Service and CLI"})}),"\n",(0,a.jsx)(t.li,{children:(0,a.jsx)(t.a,{href:"https://github.com/cadence-workflow/cadence-go-client",children:"Cadence Go Client"})}),"\n",(0,a.jsx)(t.li,{children:(0,a.jsx)(t.a,{href:"https://github.com/cadence-workflow/cadence-samples",children:"Cadence Go Client Samples"})}),"\n",(0,a.jsx)(t.li,{children:(0,a.jsx)(t.a,{href:"https://github.com/cadence-workflow/cadence-java-client",children:"Cadence Java Client"})}),"\n",(0,a.jsx)(t.li,{children:(0,a.jsx)(t.a,{href:"https://github.com/cadence-workflow/cadence-java-samples",children:"Cadence Java Client Samples"})}),"\n",(0,a.jsx)(t.li,{children:(0,a.jsx)(t.a,{href:"https://github.com/cadence-workflow/cadence-web",children:"Cadence Web UI"})}),"\n"]})]})}function u(e={}){const{wrapper:t}={...(0,o.R)(),...e.components};return t?(0,a.jsx)(t,{...e,children:(0,a.jsx)(d,{...e})}):d(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>s,x:()=>r});var c=n(6540);const a={},o=c.createContext(a);function s(e){const t=c.useContext(o);return c.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function r(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:s(e.components),c.createElement(o.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/0b21c5b6.91e86b39.js b/assets/js/0b21c5b6.91e86b39.js new file mode 100644 index 000000000..43f75a04f --- /dev/null +++ b/assets/js/0b21c5b6.91e86b39.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[62],{4751:e=>{e.exports=JSON.parse('{"tag":{"label":"Releases","permalink":"/Cadence-Docs/blog/tags/releases","description":"Releases tag description","allTagsPath":"/Cadence-Docs/blog/tags","count":2,"unlisted":false},"listMetadata":{"permalink":"/Cadence-Docs/blog/tags/releases","page":1,"postsPerPage":10,"totalPages":1,"totalCount":2,"blogDescription":"The latest news and updates from the Cadence team","blogTitle":"Cadence Blog"}}')}}]); \ No newline at end of file diff --git a/assets/js/0b5e41cc.aebef198.js b/assets/js/0b5e41cc.aebef198.js new file mode 100644 index 000000000..7b77e4ab6 --- /dev/null +++ b/assets/js/0b5e41cc.aebef198.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[672],{8426:e=>{e.exports=JSON.parse('{"author":{"name":"Sharan Foga","title":"Director of Operations & Customer Success @ Encube Technologies","url":"https://www.linkedin.com/in/sfoga/","page":{"permalink":"/Cadence-Docs/blog/authors/sharanf"},"socials":{"linkedin":"https://www.linkedin.com/in/sfoga/","github":"https://github.com/sharanf"},"imageURL":"https://github.com/sharanf.png","key":"sharanf","count":19},"listMetadata":{"permalink":"/Cadence-Docs/blog/authors/sharanf","page":1,"postsPerPage":10,"totalPages":2,"totalCount":19,"nextPage":"/Cadence-Docs/blog/authors/sharanf/authors/2","blogDescription":"The latest news and updates from the Cadence team","blogTitle":"Cadence Blog"}}')}}]); \ No newline at end of file diff --git a/assets/js/0b6b8c62.47f9e873.js b/assets/js/0b6b8c62.47f9e873.js new file mode 100644 index 000000000..05c30eeb4 --- /dev/null +++ b/assets/js/0b6b8c62.47f9e873.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[1314],{7802:e=>{e.exports=JSON.parse('{"version":{"pluginId":"community","version":"current","label":"Next","banner":null,"badge":false,"noIndex":false,"className":"docs-version-current","isLast":true,"docsSidebars":{"community":[{"type":"link","label":"Support","href":"/Cadence-Docs/community/support","docId":"support","unlisted":false},{"type":"link","label":"Team","href":"/Cadence-Docs/community/team","docId":"team","unlisted":false},{"type":"link","label":"Chat with us on Slack","href":"http://t.uber.com/cadence-slack"}]},"docs":{"contributing":{"id":"contributing","title":"Contributing","description":""},"resources":{"id":"resources","title":"Resources","description":"Cadence documentation"},"support":{"id":"support","title":"Support","description":"On this page we\'ve listed some Cadence-related communities that you can be a part of.","sidebar":"community"},"team":{"id":"team","title":"Team","description":"Core Team","sidebar":"community"}}}}')}}]); \ No newline at end of file diff --git a/assets/js/0bc129c0.1751af83.js b/assets/js/0bc129c0.0774e3d1.js similarity index 63% rename from assets/js/0bc129c0.1751af83.js rename to assets/js/0bc129c0.0774e3d1.js index 0f85ebe17..8b4b85597 100644 --- a/assets/js/0bc129c0.1751af83.js +++ b/assets/js/0bc129c0.0774e3d1.js @@ -1 +1 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[5371],{4425:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>c,contentTitle:()=>s,default:()=>p,frontMatter:()=>r,metadata:()=>o,toc:()=>l});var o=t(9871),a=t(4848),i=t(8453);const r={title:"Understanding components of Cadence application",date:new Date("2023-07-01T00:00:00.000Z"),authors:"chopincode",tags:["deep-dive","introduction-to-cadence"]},s=void 0,c={authorsImageUrls:[void 0]},l=[];function d(e){const n={a:"a",li:"li",ol:"ol",p:"p",...(0,i.R)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(n.p,{children:"Cadence is a powerful, scalable, and fault-tolerant workflow orchestration framework that helps developers implement and manage complex workflow tasks. In most cases, developers contribute activities and workflows directly to their codebases, and they may not have a full understanding of the components behind a running Cadence application. We receive numerous inquiries about setting up Cadence in a local environment from scratch for testing. Therefore, in this article, we will explore the components that power a Cadence cluster."}),"\n",(0,a.jsx)(n.p,{children:"There are three critical components that are essential for any Cadence application:"}),"\n",(0,a.jsxs)(n.ol,{children:["\n",(0,a.jsx)(n.li,{children:"A running Cadence backend server."}),"\n",(0,a.jsx)(n.li,{children:"A registered Cadence domain."}),"\n",(0,a.jsx)(n.li,{children:"A running Cadence worker that registers all workflows and activities."}),"\n"]}),"\n",(0,a.jsx)(n.p,{children:"Let's go over these components in more details."}),"\n",(0,a.jsxs)(n.p,{children:["The Cadence backend serves as the heart of your Cadence application. It is responsible for processing and scheduling your workflows and activities. While the backend relies on various dependencies, our team has conveniently packaged them into a single Docker image. You can follow the instructions provided ",(0,a.jsx)(n.a,{href:"/docs/get-started/server-installation",children:"here"}),"."]}),"\n",(0,a.jsx)(n.p,{children:"The Cadence domain functions as the namespace for your Cadence workflows. It helps segregate your workflows into manageable groups. When running workflows, you must specify the domain on which you want to execute them."}),"\n",(0,a.jsx)(n.p,{children:"The Cadence worker, also known as the worker service, is a separate binary process that you need to implement in order to host your workflows and activities. When developing a worker, ensure that all your workflows and activities are properly registered with it. The worker is an actively running application, and you have the freedom to choose the hosting technologies that best suit your needs, such as a simple HTTP or gRPC application."}),"\n",(0,a.jsx)(n.p,{children:"Ultimately, you will need to set up two running processes on your local machine: the Cadence server and the worker. Additionally, you must register the Cadence domain as a resource. Our team has packaged all these components into user-friendly tools, which you can find on our website."})]})}function p(e={}){const{wrapper:n}={...(0,i.R)(),...e.components};return n?(0,a.jsx)(n,{...e,children:(0,a.jsx)(d,{...e})}):d(e)}},8453:(e,n,t)=>{t.d(n,{R:()=>r,x:()=>s});var o=t(6540);const a={},i=o.createContext(a);function r(e){const n=o.useContext(i);return o.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function s(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:r(e.components),o.createElement(i.Provider,{value:n},e.children)}},9871:e=>{e.exports=JSON.parse('{"permalink":"/blog/2023/06/28/components-of-cadence-application-setup","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2023-06-28-components-of-cadence-application-setup.md","source":"@site/blog/2023-06-28-components-of-cadence-application-setup.md","title":"Understanding components of Cadence application","description":"Cadence is a powerful, scalable, and fault-tolerant workflow orchestration framework that helps developers implement and manage complex workflow tasks. In most cases, developers contribute activities and workflows directly to their codebases, and they may not have a full understanding of the components behind a running Cadence application. We receive numerous inquiries about setting up Cadence in a local environment from scratch for testing. Therefore, in this article, we will explore the components that power a Cadence cluster.","date":"2023-07-01T00:00:00.000Z","tags":[{"inline":false,"label":"Deep Dives","permalink":"/blog/tags/deep-dives","description":"Deep Dives tag description"},{"inline":false,"label":"Introduction to Cadence","permalink":"/blog/tags/introduction-to-cadence","description":"Introduction to Cadence tag description"}],"readingTime":1.615,"hasTruncateMarker":true,"authors":[{"name":"Chris Qin","title":"Applications Developer @ Uber","url":"https://www.linkedin.com/in/chrisqin0610/","page":{"permalink":"/blog/authors/chopincode"},"socials":{"linkedin":"https://www.linkedin.com/in/chrisqin0610/","github":"https://github.com/chopincode"},"imageURL":"https://github.com/chopincode.png","key":"chopincode"}],"frontMatter":{"title":"Understanding components of Cadence application","date":"2023-07-01T00:00:00.000Z","authors":"chopincode","tags":["deep-dive","introduction-to-cadence"]},"unlisted":false,"prevItem":{"title":"Implement a Cadence worker service from scratch","permalink":"/blog/2023/07/05/implement-cadence-worker-from-scratch"},"nextItem":{"title":"Cadence Community Spotlight Update - June 2023","permalink":"/blog/2023/06/30/community-spotlight-june-2023"}}')}}]); \ No newline at end of file +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[5371],{4425:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>c,contentTitle:()=>s,default:()=>p,frontMatter:()=>r,metadata:()=>o,toc:()=>l});var o=t(9871),a=t(4848),i=t(8453);const r={title:"Understanding components of Cadence application",date:new Date("2023-07-01T00:00:00.000Z"),authors:"chopincode",tags:["deep-dive","introduction-to-cadence"]},s=void 0,c={authorsImageUrls:[void 0]},l=[];function d(e){const n={a:"a",li:"li",ol:"ol",p:"p",...(0,i.R)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(n.p,{children:"Cadence is a powerful, scalable, and fault-tolerant workflow orchestration framework that helps developers implement and manage complex workflow tasks. In most cases, developers contribute activities and workflows directly to their codebases, and they may not have a full understanding of the components behind a running Cadence application. We receive numerous inquiries about setting up Cadence in a local environment from scratch for testing. Therefore, in this article, we will explore the components that power a Cadence cluster."}),"\n",(0,a.jsx)(n.p,{children:"There are three critical components that are essential for any Cadence application:"}),"\n",(0,a.jsxs)(n.ol,{children:["\n",(0,a.jsx)(n.li,{children:"A running Cadence backend server."}),"\n",(0,a.jsx)(n.li,{children:"A registered Cadence domain."}),"\n",(0,a.jsx)(n.li,{children:"A running Cadence worker that registers all workflows and activities."}),"\n"]}),"\n",(0,a.jsx)(n.p,{children:"Let's go over these components in more details."}),"\n",(0,a.jsxs)(n.p,{children:["The Cadence backend serves as the heart of your Cadence application. It is responsible for processing and scheduling your workflows and activities. While the backend relies on various dependencies, our team has conveniently packaged them into a single Docker image. You can follow the instructions provided ",(0,a.jsx)(n.a,{href:"/docs/get-started/server-installation",children:"here"}),"."]}),"\n",(0,a.jsx)(n.p,{children:"The Cadence domain functions as the namespace for your Cadence workflows. It helps segregate your workflows into manageable groups. When running workflows, you must specify the domain on which you want to execute them."}),"\n",(0,a.jsx)(n.p,{children:"The Cadence worker, also known as the worker service, is a separate binary process that you need to implement in order to host your workflows and activities. When developing a worker, ensure that all your workflows and activities are properly registered with it. The worker is an actively running application, and you have the freedom to choose the hosting technologies that best suit your needs, such as a simple HTTP or gRPC application."}),"\n",(0,a.jsx)(n.p,{children:"Ultimately, you will need to set up two running processes on your local machine: the Cadence server and the worker. Additionally, you must register the Cadence domain as a resource. Our team has packaged all these components into user-friendly tools, which you can find on our website."})]})}function p(e={}){const{wrapper:n}={...(0,i.R)(),...e.components};return n?(0,a.jsx)(n,{...e,children:(0,a.jsx)(d,{...e})}):d(e)}},8453:(e,n,t)=>{t.d(n,{R:()=>r,x:()=>s});var o=t(6540);const a={},i=o.createContext(a);function r(e){const n=o.useContext(i);return o.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function s(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:r(e.components),o.createElement(i.Provider,{value:n},e.children)}},9871:e=>{e.exports=JSON.parse('{"permalink":"/Cadence-Docs/blog/2023/06/28/components-of-cadence-application-setup","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2023-06-28-components-of-cadence-application-setup.md","source":"@site/blog/2023-06-28-components-of-cadence-application-setup.md","title":"Understanding components of Cadence application","description":"Cadence is a powerful, scalable, and fault-tolerant workflow orchestration framework that helps developers implement and manage complex workflow tasks. In most cases, developers contribute activities and workflows directly to their codebases, and they may not have a full understanding of the components behind a running Cadence application. We receive numerous inquiries about setting up Cadence in a local environment from scratch for testing. Therefore, in this article, we will explore the components that power a Cadence cluster.","date":"2023-07-01T00:00:00.000Z","tags":[{"inline":false,"label":"Deep Dives","permalink":"/Cadence-Docs/blog/tags/deep-dives","description":"Deep Dives tag description"},{"inline":false,"label":"Introduction to Cadence","permalink":"/Cadence-Docs/blog/tags/introduction-to-cadence","description":"Introduction to Cadence tag description"}],"readingTime":1.615,"hasTruncateMarker":true,"authors":[{"name":"Chris Qin","title":"Applications Developer @ Uber","url":"https://www.linkedin.com/in/chrisqin0610/","page":{"permalink":"/Cadence-Docs/blog/authors/chopincode"},"socials":{"linkedin":"https://www.linkedin.com/in/chrisqin0610/","github":"https://github.com/chopincode"},"imageURL":"https://github.com/chopincode.png","key":"chopincode"}],"frontMatter":{"title":"Understanding components of Cadence application","date":"2023-07-01T00:00:00.000Z","authors":"chopincode","tags":["deep-dive","introduction-to-cadence"]},"unlisted":false,"prevItem":{"title":"Implement a Cadence worker service from scratch","permalink":"/Cadence-Docs/blog/2023/07/05/implement-cadence-worker-from-scratch"},"nextItem":{"title":"Cadence Community Spotlight Update - June 2023","permalink":"/Cadence-Docs/blog/2023/06/30/community-spotlight-june-2023"}}')}}]); \ No newline at end of file diff --git a/assets/js/0cfc60d3.8c2ddb40.js b/assets/js/0cfc60d3.8c2ddb40.js deleted file mode 100644 index a7db5c31b..000000000 --- a/assets/js/0cfc60d3.8c2ddb40.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[8396],{3215:e=>{e.exports=JSON.parse('{"author":{"name":"Zijian Chen","title":"Software Engineer @ Uber","url":"https://www.linkedin.com/in/zijian-chen-5868938b/","page":{"permalink":"/blog/authors/shaddoll"},"socials":{"linkedin":"https://www.linkedin.com/in/zijian-chen-5868938b/","github":"https://github.com/Shaddoll"},"imageURL":"https://github.com/Shaddoll.png","key":"shaddoll","count":1},"listMetadata":{"permalink":"/blog/authors/shaddoll","page":1,"postsPerPage":10,"totalPages":1,"totalCount":1,"blogDescription":"The latest news and updates from the Cadence team","blogTitle":"Cadence Blog"}}')}}]); \ No newline at end of file diff --git a/assets/js/0ece390c.89ee49b3.js b/assets/js/0ece390c.89ee49b3.js deleted file mode 100644 index d6fb9e168..000000000 --- a/assets/js/0ece390c.89ee49b3.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[8125],{9561:(e,c,n)=>{n.r(c),n.d(c,{assets:()=>r,contentTitle:()=>s,default:()=>h,frontMatter:()=>o,metadata:()=>a,toc:()=>l});const a=JSON.parse('{"id":"java-client/client-overview","title":"Client SDK Overview","description":"- Samples//github.com/cadence-workflow/cadence-java-samples","source":"@site/docs/04-java-client/01-client-overview.md","sourceDirName":"04-java-client","slug":"/java-client/client-overview","permalink":"/docs/java-client/client-overview","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/04-java-client/01-client-overview.md","tags":[],"version":"current","sidebarPosition":1,"frontMatter":{"layout":"default","title":"Client SDK Overview","permalink":"/docs/java-client/client-overview"},"sidebar":"docsSidebar","previous":{"title":"Introduction","permalink":"/docs/java-client/"},"next":{"title":"Workflow interface","permalink":"/docs/java-client/workflow-interface"}}');var t=n(4848),i=n(8453);const o={layout:"default",title:"Client SDK Overview",permalink:"/docs/java-client/client-overview"},s="Client SDK Overview",r={},l=[{value:"JavaDoc Packages",id:"javadoc-packages",level:2},{value:"com.uber.cadence.activity",id:"comubercadenceactivity",level:3},{value:"com.uber.cadence.client",id:"comubercadenceclient",level:3},{value:"com.uber.cadence.workflow",id:"comubercadenceworkflow",level:3},{value:"com.uber.cadence.worker",id:"comubercadenceworker",level:3},{value:"com.uber.cadence.testing",id:"comubercadencetesting",level:3},{value:"Samples",id:"samples",level:2},{value:"com.uber.cadence.samples.hello",id:"comubercadencesampleshello",level:3},{value:"com.uber.cadence.samples.bookingsaga",id:"comubercadencesamplesbookingsaga",level:3},{value:"com.uber.cadence.samples.fileprocessing",id:"comubercadencesamplesfileprocessing",level:3}];function d(e){const c={a:"a",h1:"h1",h2:"h2",h3:"h3",header:"header",li:"li",p:"p",ul:"ul",...(0,i.R)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(c.header,{children:(0,t.jsx)(c.h1,{id:"client-sdk-overview",children:"Client SDK Overview"})}),"\n",(0,t.jsxs)(c.ul,{children:["\n",(0,t.jsxs)(c.li,{children:["Samples: ",(0,t.jsx)(c.a,{href:"https://github.com/cadence-workflow/cadence-java-samples",children:"https://github.com/cadence-workflow/cadence-java-samples"})]}),"\n",(0,t.jsxs)(c.li,{children:["JavaDoc documentation: ",(0,t.jsx)(c.a,{href:"https://www.javadoc.io/doc/com.uber.cadence/cadence-client",children:"https://www.javadoc.io/doc/com.uber.cadence/cadence-client"})]}),"\n"]}),"\n",(0,t.jsx)(c.h2,{id:"javadoc-packages",children:(0,t.jsx)(c.a,{href:"https://www.javadoc.io/doc/com.uber.cadence/cadence-client/latest/index.html",children:"JavaDoc Packages"})}),"\n",(0,t.jsx)(c.h3,{id:"comubercadenceactivity",children:"com.uber.cadence.activity"}),"\n",(0,t.jsx)(c.p,{children:"APIs to implement activity: accessing activity info, or sending heartbeat."}),"\n",(0,t.jsx)(c.h3,{id:"comubercadenceclient",children:"com.uber.cadence.client"}),"\n",(0,t.jsx)(c.p,{children:"APIs for external application code to interact with Cadence workflows: start workflows, send signals or query workflows."}),"\n",(0,t.jsx)(c.h3,{id:"comubercadenceworkflow",children:"com.uber.cadence.workflow"}),"\n",(0,t.jsx)(c.p,{children:"APIs to implement workflows."}),"\n",(0,t.jsx)(c.h3,{id:"comubercadenceworker",children:"com.uber.cadence.worker"}),"\n",(0,t.jsx)(c.p,{children:"APIs to configure and start workers."}),"\n",(0,t.jsx)(c.h3,{id:"comubercadencetesting",children:"com.uber.cadence.testing"}),"\n",(0,t.jsx)(c.p,{children:"APIs to write unit tests for workflows."}),"\n",(0,t.jsx)(c.h2,{id:"samples",children:(0,t.jsx)(c.a,{href:"https://github.com/cadence-workflow/cadence-java-samples/tree/master/src/main/java/com/uber/cadence/samples",children:"Samples"})}),"\n",(0,t.jsx)(c.h3,{id:"comubercadencesampleshello",children:"com.uber.cadence.samples.hello"}),"\n",(0,t.jsx)(c.p,{children:"Samples of how to use the basic feature: activity, local activity, ChildWorkflow, Query, etc.\nThis is the most important package you need to start with."}),"\n",(0,t.jsx)(c.h3,{id:"comubercadencesamplesbookingsaga",children:"com.uber.cadence.samples.bookingsaga"}),"\n",(0,t.jsx)(c.p,{children:"An end-to-end example to write workflow using SAGA APIs."}),"\n",(0,t.jsx)(c.h3,{id:"comubercadencesamplesfileprocessing",children:"com.uber.cadence.samples.fileprocessing"}),"\n",(0,t.jsx)(c.p,{children:"An end-to-end example to write workflows to download a file, zips it, and uploads it to a destination."}),"\n",(0,t.jsx)(c.p,{children:"An important requirement for such a workflow is that while a first activity can run\non any host, the second and third must run on the same host as the first one. This is achieved\nthrough use of a host specific task list. The first activity returns the name of the host\nspecific task list and all other activities are dispatched using the stub that is configured with\nit. This assumes that FileProcessingWorker has a worker running on the same task list."})]})}function h(e={}){const{wrapper:c}={...(0,i.R)(),...e.components};return c?(0,t.jsx)(c,{...e,children:(0,t.jsx)(d,{...e})}):d(e)}},8453:(e,c,n)=>{n.d(c,{R:()=>o,x:()=>s});var a=n(6540);const t={},i=a.createContext(t);function o(e){const c=a.useContext(i);return a.useMemo((function(){return"function"==typeof e?e(c):{...c,...e}}),[c,e])}function s(e){let c;return c=e.disableParentContext?"function"==typeof e.components?e.components(t):e.components||t:o(e.components),a.createElement(i.Provider,{value:c},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/0ece390c.9e4668ed.js b/assets/js/0ece390c.9e4668ed.js new file mode 100644 index 000000000..365a66ffc --- /dev/null +++ b/assets/js/0ece390c.9e4668ed.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[8125],{9561:(e,c,n)=>{n.r(c),n.d(c,{assets:()=>r,contentTitle:()=>s,default:()=>h,frontMatter:()=>o,metadata:()=>a,toc:()=>l});const a=JSON.parse('{"id":"java-client/client-overview","title":"Client SDK Overview","description":"- Samples//github.com/cadence-workflow/cadence-java-samples","source":"@site/docs/04-java-client/01-client-overview.md","sourceDirName":"04-java-client","slug":"/java-client/client-overview","permalink":"/Cadence-Docs/docs/java-client/client-overview","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/04-java-client/01-client-overview.md","tags":[],"version":"current","sidebarPosition":1,"frontMatter":{"layout":"default","title":"Client SDK Overview","permalink":"/docs/java-client/client-overview"},"sidebar":"docsSidebar","previous":{"title":"Introduction","permalink":"/Cadence-Docs/docs/java-client/"},"next":{"title":"Workflow interface","permalink":"/Cadence-Docs/docs/java-client/workflow-interface"}}');var t=n(4848),i=n(8453);const o={layout:"default",title:"Client SDK Overview",permalink:"/docs/java-client/client-overview"},s="Client SDK Overview",r={},l=[{value:"JavaDoc Packages",id:"javadoc-packages",level:2},{value:"com.uber.cadence.activity",id:"comubercadenceactivity",level:3},{value:"com.uber.cadence.client",id:"comubercadenceclient",level:3},{value:"com.uber.cadence.workflow",id:"comubercadenceworkflow",level:3},{value:"com.uber.cadence.worker",id:"comubercadenceworker",level:3},{value:"com.uber.cadence.testing",id:"comubercadencetesting",level:3},{value:"Samples",id:"samples",level:2},{value:"com.uber.cadence.samples.hello",id:"comubercadencesampleshello",level:3},{value:"com.uber.cadence.samples.bookingsaga",id:"comubercadencesamplesbookingsaga",level:3},{value:"com.uber.cadence.samples.fileprocessing",id:"comubercadencesamplesfileprocessing",level:3}];function d(e){const c={a:"a",h1:"h1",h2:"h2",h3:"h3",header:"header",li:"li",p:"p",ul:"ul",...(0,i.R)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(c.header,{children:(0,t.jsx)(c.h1,{id:"client-sdk-overview",children:"Client SDK Overview"})}),"\n",(0,t.jsxs)(c.ul,{children:["\n",(0,t.jsxs)(c.li,{children:["Samples: ",(0,t.jsx)(c.a,{href:"https://github.com/cadence-workflow/cadence-java-samples",children:"https://github.com/cadence-workflow/cadence-java-samples"})]}),"\n",(0,t.jsxs)(c.li,{children:["JavaDoc documentation: ",(0,t.jsx)(c.a,{href:"https://www.javadoc.io/doc/com.uber.cadence/cadence-client",children:"https://www.javadoc.io/doc/com.uber.cadence/cadence-client"})]}),"\n"]}),"\n",(0,t.jsx)(c.h2,{id:"javadoc-packages",children:(0,t.jsx)(c.a,{href:"https://www.javadoc.io/doc/com.uber.cadence/cadence-client/latest/index.html",children:"JavaDoc Packages"})}),"\n",(0,t.jsx)(c.h3,{id:"comubercadenceactivity",children:"com.uber.cadence.activity"}),"\n",(0,t.jsx)(c.p,{children:"APIs to implement activity: accessing activity info, or sending heartbeat."}),"\n",(0,t.jsx)(c.h3,{id:"comubercadenceclient",children:"com.uber.cadence.client"}),"\n",(0,t.jsx)(c.p,{children:"APIs for external application code to interact with Cadence workflows: start workflows, send signals or query workflows."}),"\n",(0,t.jsx)(c.h3,{id:"comubercadenceworkflow",children:"com.uber.cadence.workflow"}),"\n",(0,t.jsx)(c.p,{children:"APIs to implement workflows."}),"\n",(0,t.jsx)(c.h3,{id:"comubercadenceworker",children:"com.uber.cadence.worker"}),"\n",(0,t.jsx)(c.p,{children:"APIs to configure and start workers."}),"\n",(0,t.jsx)(c.h3,{id:"comubercadencetesting",children:"com.uber.cadence.testing"}),"\n",(0,t.jsx)(c.p,{children:"APIs to write unit tests for workflows."}),"\n",(0,t.jsx)(c.h2,{id:"samples",children:(0,t.jsx)(c.a,{href:"https://github.com/cadence-workflow/cadence-java-samples/tree/master/src/main/java/com/uber/cadence/samples",children:"Samples"})}),"\n",(0,t.jsx)(c.h3,{id:"comubercadencesampleshello",children:"com.uber.cadence.samples.hello"}),"\n",(0,t.jsx)(c.p,{children:"Samples of how to use the basic feature: activity, local activity, ChildWorkflow, Query, etc.\nThis is the most important package you need to start with."}),"\n",(0,t.jsx)(c.h3,{id:"comubercadencesamplesbookingsaga",children:"com.uber.cadence.samples.bookingsaga"}),"\n",(0,t.jsx)(c.p,{children:"An end-to-end example to write workflow using SAGA APIs."}),"\n",(0,t.jsx)(c.h3,{id:"comubercadencesamplesfileprocessing",children:"com.uber.cadence.samples.fileprocessing"}),"\n",(0,t.jsx)(c.p,{children:"An end-to-end example to write workflows to download a file, zips it, and uploads it to a destination."}),"\n",(0,t.jsx)(c.p,{children:"An important requirement for such a workflow is that while a first activity can run\non any host, the second and third must run on the same host as the first one. This is achieved\nthrough use of a host specific task list. The first activity returns the name of the host\nspecific task list and all other activities are dispatched using the stub that is configured with\nit. This assumes that FileProcessingWorker has a worker running on the same task list."})]})}function h(e={}){const{wrapper:c}={...(0,i.R)(),...e.components};return c?(0,t.jsx)(c,{...e,children:(0,t.jsx)(d,{...e})}):d(e)}},8453:(e,c,n)=>{n.d(c,{R:()=>o,x:()=>s});var a=n(6540);const t={},i=a.createContext(t);function o(e){const c=a.useContext(i);return a.useMemo((function(){return"function"==typeof e?e(c):{...c,...e}}),[c,e])}function s(e){let c;return c=e.disableParentContext?"function"==typeof e.components?e.components(t):e.components||t:o(e.components),a.createElement(i.Provider,{value:c},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/115ec24d.8b154ac8.js b/assets/js/115ec24d.85585615.js similarity index 65% rename from assets/js/115ec24d.8b154ac8.js rename to assets/js/115ec24d.85585615.js index 87a6a9dc6..89fe97568 100644 --- a/assets/js/115ec24d.8b154ac8.js +++ b/assets/js/115ec24d.85585615.js @@ -1 +1 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[5332],{2960:(e,o,n)=>{n.r(o),n.d(o,{assets:()=>s,contentTitle:()=>c,default:()=>h,frontMatter:()=>i,metadata:()=>t,toc:()=>d});var t=n(6850),r=n(4848),a=n(8453);const i={title:"Cadence Repositories Have Moved!",description:"Discover the latest update for Cadence Workflow! Our GitHub repositories have moved to the new cadence-workflow organization. Learn more about the migration, including updated links and how this change supports the growing Cadence community",authors:"ibarrajo",tags:["announcement"],date:"2024-11-18T14:00"},c=void 0,s={authorsImageUrls:[void 0]},d=[];function l(e){const o={a:"a",code:"code",p:"p",...(0,a.R)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsxs)(o.p,{children:["We\u2019re excited to announce that all Cadence GitHub repositories have been consolidated under the ",(0,r.jsx)(o.a,{href:"https://github.com/cadence-workflow",children:"cadence-workflow"})," organization! \ud83c\udf89"]}),"\n",(0,r.jsxs)(o.p,{children:["Previously, Cadence repositories were distributed across multiple organizations at Uber: ",(0,r.jsx)(o.a,{href:"https://github.com/uber",children:(0,r.jsx)(o.code,{children:"uber"})}),", ",(0,r.jsx)(o.a,{href:"https://github.com/uber-go",children:(0,r.jsx)(o.code,{children:"uber-go"})}),", ",(0,r.jsx)(o.a,{href:"https://github.com/uber-common",children:(0,r.jsx)(o.code,{children:"uber-common"})}),". To improve developer cohesiveness and simplify access, the Cadence Core team has migrated all open-source repositories to the ",(0,r.jsx)(o.a,{href:"https://github.com/cadence-workflow",children:(0,r.jsx)(o.code,{children:"cadence-workflow"})})," organization."]}),"\n",(0,r.jsx)(o.p,{children:"For example, our main repository has moved from:"}),"\n",(0,r.jsxs)(o.p,{children:["\ud83d\udc49 ",(0,r.jsx)(o.a,{href:"https://github.com/cadence-workflow/cadence",children:"uber/cadence"})]}),"\n",(0,r.jsx)(o.p,{children:"To its new home:"}),"\n",(0,r.jsxs)(o.p,{children:["\ud83d\udc49 ",(0,r.jsx)(o.a,{href:"https://github.com/cadence-workflow/cadence",children:"cadence-workflow/cadence"})]}),"\n",(0,r.jsxs)(o.p,{children:["You can find the full list of Cadence repositories here \ud83d\udc49 ",(0,r.jsx)(o.a,{href:"https://github.com/orgs/cadence-workflow/repositories",children:"orgs/cadence-workflow/repositories"})]}),"\n",(0,r.jsx)(o.p,{children:"This move reflects our continued commitment to growing the Cadence community and making the project even more accessible to contributors and users. Please update your bookmarks and links accordingly."}),"\n",(0,r.jsx)(o.p,{children:"Thank you for being part of the Cadence journey! \ud83d\ude80"})]})}function h(e={}){const{wrapper:o}={...(0,a.R)(),...e.components};return o?(0,r.jsx)(o,{...e,children:(0,r.jsx)(l,{...e})}):l(e)}},8453:(e,o,n)=>{n.d(o,{R:()=>i,x:()=>c});var t=n(6540);const r={},a=t.createContext(r);function i(e){const o=t.useContext(a);return t.useMemo((function(){return"function"==typeof e?e(o):{...o,...e}}),[o,e])}function c(e){let o;return o=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:i(e.components),t.createElement(a.Provider,{value:o},e.children)}},6850:e=>{e.exports=JSON.parse('{"permalink":"/blog/2024/11/18/cadence-workflows-github-organization","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2024-11-18-cadence-workflows-github-organization.md","source":"@site/blog/2024-11-18-cadence-workflows-github-organization.md","title":"Cadence Repositories Have Moved!","description":"Discover the latest update for Cadence Workflow! Our GitHub repositories have moved to the new cadence-workflow organization. Learn more about the migration, including updated links and how this change supports the growing Cadence community","date":"2024-11-18T14:00:00.000Z","tags":[{"inline":false,"label":"Announcement","permalink":"/blog/tags/announcements","description":"Announcement tag description"}],"readingTime":0.6,"hasTruncateMarker":true,"authors":[{"name":"Josu\xe9 Alexander Ibarra","title":"Developer Advocate @ Uber","url":"https://github.com/ibarrajo/","page":{"permalink":"/blog/authors/ibarrajo"},"socials":{"github":"https://github.com/ibarrajo","linkedin":"https://www.linkedin.com/in/elninja/"},"imageURL":"https://github.com/ibarrajo.png","key":"ibarrajo"}],"frontMatter":{"title":"Cadence Repositories Have Moved!","description":"Discover the latest update for Cadence Workflow! Our GitHub repositories have moved to the new cadence-workflow organization. Learn more about the migration, including updated links and how this change supports the growing Cadence community","authors":"ibarrajo","tags":["announcement"],"date":"2024-11-18T14:00"},"unlisted":false,"nextItem":{"title":"Zonal Isolation for Cadence Workflows","permalink":"/blog/zonal-isolation-v1/zonal-isolation-v1"}}')}}]); \ No newline at end of file +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[5332],{2960:(e,o,n)=>{n.r(o),n.d(o,{assets:()=>s,contentTitle:()=>c,default:()=>h,frontMatter:()=>i,metadata:()=>t,toc:()=>d});var t=n(6850),r=n(4848),a=n(8453);const i={title:"Cadence Repositories Have Moved!",description:"Discover the latest update for Cadence Workflow! Our GitHub repositories have moved to the new cadence-workflow organization. Learn more about the migration, including updated links and how this change supports the growing Cadence community",authors:"ibarrajo",tags:["announcement"],date:"2024-11-18T14:00"},c=void 0,s={authorsImageUrls:[void 0]},d=[];function l(e){const o={a:"a",code:"code",p:"p",...(0,a.R)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsxs)(o.p,{children:["We\u2019re excited to announce that all Cadence GitHub repositories have been consolidated under the ",(0,r.jsx)(o.a,{href:"https://github.com/cadence-workflow",children:"cadence-workflow"})," organization! \ud83c\udf89"]}),"\n",(0,r.jsxs)(o.p,{children:["Previously, Cadence repositories were distributed across multiple organizations at Uber: ",(0,r.jsx)(o.a,{href:"https://github.com/uber",children:(0,r.jsx)(o.code,{children:"uber"})}),", ",(0,r.jsx)(o.a,{href:"https://github.com/uber-go",children:(0,r.jsx)(o.code,{children:"uber-go"})}),", ",(0,r.jsx)(o.a,{href:"https://github.com/uber-common",children:(0,r.jsx)(o.code,{children:"uber-common"})}),". To improve developer cohesiveness and simplify access, the Cadence Core team has migrated all open-source repositories to the ",(0,r.jsx)(o.a,{href:"https://github.com/cadence-workflow",children:(0,r.jsx)(o.code,{children:"cadence-workflow"})})," organization."]}),"\n",(0,r.jsx)(o.p,{children:"For example, our main repository has moved from:"}),"\n",(0,r.jsxs)(o.p,{children:["\ud83d\udc49 ",(0,r.jsx)(o.a,{href:"https://github.com/cadence-workflow/cadence",children:"uber/cadence"})]}),"\n",(0,r.jsx)(o.p,{children:"To its new home:"}),"\n",(0,r.jsxs)(o.p,{children:["\ud83d\udc49 ",(0,r.jsx)(o.a,{href:"https://github.com/cadence-workflow/cadence",children:"cadence-workflow/cadence"})]}),"\n",(0,r.jsxs)(o.p,{children:["You can find the full list of Cadence repositories here \ud83d\udc49 ",(0,r.jsx)(o.a,{href:"https://github.com/orgs/cadence-workflow/repositories",children:"orgs/cadence-workflow/repositories"})]}),"\n",(0,r.jsx)(o.p,{children:"This move reflects our continued commitment to growing the Cadence community and making the project even more accessible to contributors and users. Please update your bookmarks and links accordingly."}),"\n",(0,r.jsx)(o.p,{children:"Thank you for being part of the Cadence journey! \ud83d\ude80"})]})}function h(e={}){const{wrapper:o}={...(0,a.R)(),...e.components};return o?(0,r.jsx)(o,{...e,children:(0,r.jsx)(l,{...e})}):l(e)}},8453:(e,o,n)=>{n.d(o,{R:()=>i,x:()=>c});var t=n(6540);const r={},a=t.createContext(r);function i(e){const o=t.useContext(a);return t.useMemo((function(){return"function"==typeof e?e(o):{...o,...e}}),[o,e])}function c(e){let o;return o=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:i(e.components),t.createElement(a.Provider,{value:o},e.children)}},6850:e=>{e.exports=JSON.parse('{"permalink":"/Cadence-Docs/blog/2024/11/18/cadence-workflows-github-organization","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2024-11-18-cadence-workflows-github-organization.md","source":"@site/blog/2024-11-18-cadence-workflows-github-organization.md","title":"Cadence Repositories Have Moved!","description":"Discover the latest update for Cadence Workflow! Our GitHub repositories have moved to the new cadence-workflow organization. Learn more about the migration, including updated links and how this change supports the growing Cadence community","date":"2024-11-18T14:00:00.000Z","tags":[{"inline":false,"label":"Announcement","permalink":"/Cadence-Docs/blog/tags/announcements","description":"Announcement tag description"}],"readingTime":0.6,"hasTruncateMarker":true,"authors":[{"name":"Josu\xe9 Alexander Ibarra","title":"Developer Advocate @ Uber","url":"https://github.com/ibarrajo/","page":{"permalink":"/Cadence-Docs/blog/authors/ibarrajo"},"socials":{"github":"https://github.com/ibarrajo","linkedin":"https://www.linkedin.com/in/elninja/"},"imageURL":"https://github.com/ibarrajo.png","key":"ibarrajo"}],"frontMatter":{"title":"Cadence Repositories Have Moved!","description":"Discover the latest update for Cadence Workflow! Our GitHub repositories have moved to the new cadence-workflow organization. Learn more about the migration, including updated links and how this change supports the growing Cadence community","authors":"ibarrajo","tags":["announcement"],"date":"2024-11-18T14:00"},"unlisted":false,"nextItem":{"title":"Zonal Isolation for Cadence Workflows","permalink":"/Cadence-Docs/blog/zonal-isolation-v1/zonal-isolation-v1"}}')}}]); \ No newline at end of file diff --git a/assets/js/144c3ace.60296059.js b/assets/js/144c3ace.60296059.js deleted file mode 100644 index 33a02276a..000000000 --- a/assets/js/144c3ace.60296059.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[8035],{2817:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>c,contentTitle:()=>r,default:()=>l,frontMatter:()=>s,metadata:()=>o,toc:()=>h});var o=n(7186),a=n(4848),i=n(8453);const s={title:"Cadence Community Spotlight Update - February 2022",date:new Date("2022-02-28T00:00:00.000Z"),authors:"sharanf",tags:["community-spotlight"]},r=void 0,c={authorsImageUrls:[void 0]},h=[{value:"Announcements",id:"announcements",level:2}];function u(e){const t={a:"a",h2:"h2",p:"p",...(0,i.R)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(t.p,{children:"Welcome to the Cadence Community Spotlight update!"}),"\n",(0,a.jsx)(t.p,{children:"This is the second in our series of monthly updates focused on the Cadence community and news about what you have been doing with Cadence. We hope that you enjoyed last month's update and are keen to find out what has been happening."}),"\n",(0,a.jsx)(t.p,{children:"Please see below for a short activity roundup of what has happened recently in the community."}),"\n",(0,a.jsx)(t.h2,{id:"announcements",children:"Announcements"}),"\n",(0,a.jsxs)(t.p,{children:["Just in case you missed it the alpha version of the Cadence notification service has been released. Details can be found at the following link:\n",(0,a.jsx)(t.a,{href:"https://github.com/cadence-oss/cadence-notification/releases/tag/v0.0.1",children:"Cadence Notification Service"})]}),"\n",(0,a.jsx)(t.p,{children:"Thanks very much to everyone that worked on this!"})]})}function l(e={}){const{wrapper:t}={...(0,i.R)(),...e.components};return t?(0,a.jsx)(t,{...e,children:(0,a.jsx)(u,{...e})}):u(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>s,x:()=>r});var o=n(6540);const a={},i=o.createContext(a);function s(e){const t=o.useContext(i);return o.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function r(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:s(e.components),o.createElement(i.Provider,{value:t},e.children)}},7186:e=>{e.exports=JSON.parse('{"permalink":"/blog/2022/02/28/community-spotlight-february-2022","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2022-02-28-community-spotlight-february-2022.md","source":"@site/blog/2022-02-28-community-spotlight-february-2022.md","title":"Cadence Community Spotlight Update - February 2022","description":"Welcome to the Cadence Community Spotlight update!","date":"2022-02-28T00:00:00.000Z","tags":[{"inline":false,"label":"Community Spotlight","permalink":"/blog/tags/community-spotlights","description":"Community Spotlight tag description"}],"readingTime":2.99,"hasTruncateMarker":true,"authors":[{"name":"Sharan Foga","title":"Director of Operations & Customer Success @ Encube Technologies","url":"https://www.linkedin.com/in/sfoga/","page":{"permalink":"/blog/authors/sharanf"},"socials":{"linkedin":"https://www.linkedin.com/in/sfoga/","github":"https://github.com/sharanf"},"imageURL":"https://github.com/sharanf.png","key":"sharanf"}],"frontMatter":{"title":"Cadence Community Spotlight Update - February 2022","date":"2022-02-28T00:00:00.000Z","authors":"sharanf","tags":["community-spotlight"]},"unlisted":false,"prevItem":{"title":"Cadence Community Spotlight Update - March 2022","permalink":"/blog/2022/03/31/community-spotlight-update-march-2022"},"nextItem":{"title":"Cadence Community Spotlight Update - January 2022","permalink":"/blog/2022/01/31/community-spotlight-january-2022"}}')}}]); \ No newline at end of file diff --git a/assets/js/144c3ace.9a12438b.js b/assets/js/144c3ace.9a12438b.js new file mode 100644 index 000000000..c044b0472 --- /dev/null +++ b/assets/js/144c3ace.9a12438b.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[8035],{2817:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>r,contentTitle:()=>c,default:()=>l,frontMatter:()=>s,metadata:()=>o,toc:()=>h});var o=n(7186),a=n(4848),i=n(8453);const s={title:"Cadence Community Spotlight Update - February 2022",date:new Date("2022-02-28T00:00:00.000Z"),authors:"sharanf",tags:["community-spotlight"]},c=void 0,r={authorsImageUrls:[void 0]},h=[{value:"Announcements",id:"announcements",level:2}];function u(e){const t={a:"a",h2:"h2",p:"p",...(0,i.R)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(t.p,{children:"Welcome to the Cadence Community Spotlight update!"}),"\n",(0,a.jsx)(t.p,{children:"This is the second in our series of monthly updates focused on the Cadence community and news about what you have been doing with Cadence. We hope that you enjoyed last month's update and are keen to find out what has been happening."}),"\n",(0,a.jsx)(t.p,{children:"Please see below for a short activity roundup of what has happened recently in the community."}),"\n",(0,a.jsx)(t.h2,{id:"announcements",children:"Announcements"}),"\n",(0,a.jsxs)(t.p,{children:["Just in case you missed it the alpha version of the Cadence notification service has been released. Details can be found at the following link:\n",(0,a.jsx)(t.a,{href:"https://github.com/cadence-oss/cadence-notification/releases/tag/v0.0.1",children:"Cadence Notification Service"})]}),"\n",(0,a.jsx)(t.p,{children:"Thanks very much to everyone that worked on this!"})]})}function l(e={}){const{wrapper:t}={...(0,i.R)(),...e.components};return t?(0,a.jsx)(t,{...e,children:(0,a.jsx)(u,{...e})}):u(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>s,x:()=>c});var o=n(6540);const a={},i=o.createContext(a);function s(e){const t=o.useContext(i);return o.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function c(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:s(e.components),o.createElement(i.Provider,{value:t},e.children)}},7186:e=>{e.exports=JSON.parse('{"permalink":"/Cadence-Docs/blog/2022/02/28/community-spotlight-february-2022","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2022-02-28-community-spotlight-february-2022.md","source":"@site/blog/2022-02-28-community-spotlight-february-2022.md","title":"Cadence Community Spotlight Update - February 2022","description":"Welcome to the Cadence Community Spotlight update!","date":"2022-02-28T00:00:00.000Z","tags":[{"inline":false,"label":"Community Spotlight","permalink":"/Cadence-Docs/blog/tags/community-spotlights","description":"Community Spotlight tag description"}],"readingTime":2.99,"hasTruncateMarker":true,"authors":[{"name":"Sharan Foga","title":"Director of Operations & Customer Success @ Encube Technologies","url":"https://www.linkedin.com/in/sfoga/","page":{"permalink":"/Cadence-Docs/blog/authors/sharanf"},"socials":{"linkedin":"https://www.linkedin.com/in/sfoga/","github":"https://github.com/sharanf"},"imageURL":"https://github.com/sharanf.png","key":"sharanf"}],"frontMatter":{"title":"Cadence Community Spotlight Update - February 2022","date":"2022-02-28T00:00:00.000Z","authors":"sharanf","tags":["community-spotlight"]},"unlisted":false,"prevItem":{"title":"Cadence Community Spotlight Update - March 2022","permalink":"/Cadence-Docs/blog/2022/03/31/community-spotlight-update-march-2022"},"nextItem":{"title":"Cadence Community Spotlight Update - January 2022","permalink":"/Cadence-Docs/blog/2022/01/31/community-spotlight-january-2022"}}')}}]); \ No newline at end of file diff --git a/assets/js/1685be14.a35fd5cd.js b/assets/js/1685be14.a35fd5cd.js deleted file mode 100644 index 99d18fdcc..000000000 --- a/assets/js/1685be14.a35fd5cd.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[1919],{7747:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>c,contentTitle:()=>i,default:()=>h,frontMatter:()=>s,metadata:()=>o,toc:()=>l});const o=JSON.parse('{"id":"java-client/workflow-interface","title":"Workflow interface","description":"Workflowactivity and childworkflows:.","source":"@site/docs/04-java-client/02-workflow-interface.md","sourceDirName":"04-java-client","slug":"/java-client/workflow-interface","permalink":"/docs/java-client/workflow-interface","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/04-java-client/02-workflow-interface.md","tags":[],"version":"current","sidebarPosition":2,"frontMatter":{"layout":"default","title":"Workflow interface","permalink":"/docs/java-client/workflow-interface"},"sidebar":"docsSidebar","previous":{"title":"Client SDK Overview","permalink":"/docs/java-client/client-overview"},"next":{"title":"Implementing workflows","permalink":"/docs/java-client/implementing-workflows"}}');var r=n(4848),a=n(8453);const s={layout:"default",title:"Workflow interface",permalink:"/docs/java-client/workflow-interface"},i="Workflow interface",c={},l=[];function d(e){const t={code:"code",h1:"h1",header:"header",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,a.R)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(t.header,{children:(0,r.jsx)(t.h1,{id:"workflow-interface",children:"Workflow interface"})}),"\n",(0,r.jsx)(t.p,{children:"Workflow encapsulates the orchestration of activities and child workflows.\nIt can also answer synchronous queries and receive external events (also known as signals)."}),"\n",(0,r.jsx)(t.p,{children:"A workflow must define an interface class. All of its methods must have one of the following annotations:"}),"\n",(0,r.jsxs)(t.ul,{children:["\n",(0,r.jsxs)(t.li,{children:[(0,r.jsx)(t.strong,{children:"@WorkflowMethod"})," indicates an entry point to a workflow. It contains parameters such as timeouts and a task_list.\nRequired parameters (such as ",(0,r.jsx)(t.code,{children:"executionStartToCloseTimeoutSeconds"}),") that are not specified through the annotation must be provided at runtime."]}),"\n",(0,r.jsxs)(t.li,{children:[(0,r.jsx)(t.strong,{children:"@SignalMethod"})," indicates a method that reacts to external signals. It must have a ",(0,r.jsx)(t.code,{children:"void"})," return type."]}),"\n",(0,r.jsxs)(t.li,{children:[(0,r.jsx)(t.strong,{children:"@QueryMethod"})," indicates a method that reacts to synchronous query requests."]}),"\n"]}),"\n",(0,r.jsx)(t.p,{children:"You can have more than one method with the same annotation (except @WorkflowMethod). For example:"}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{className:"language-java",children:'public interface FileProcessingWorkflow {\n\n @WorkflowMethod(executionStartToCloseTimeoutSeconds = 10, taskList = "file-processing")\n String processFile(Arguments args);\n\n @QueryMethod(name="history")\n List getHistory();\n\n @QueryMethod(name="status")\n String getStatus();\n\n @SignalMethod\n void retryNow();\n\n @SignalMethod\n void abandon();\n}\n'})}),"\n",(0,r.jsx)(t.p,{children:"We recommended that you use a single value type argument for workflow methods. In this way, adding new arguments as fields to the value type is a backwards-compatible change."})]})}function h(e={}){const{wrapper:t}={...(0,a.R)(),...e.components};return t?(0,r.jsx)(t,{...e,children:(0,r.jsx)(d,{...e})}):d(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>s,x:()=>i});var o=n(6540);const r={},a=o.createContext(r);function s(e){const t=o.useContext(a);return o.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function i(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:s(e.components),o.createElement(a.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/1685be14.b40f46bf.js b/assets/js/1685be14.b40f46bf.js new file mode 100644 index 000000000..1360aecbe --- /dev/null +++ b/assets/js/1685be14.b40f46bf.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[1919],{7747:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>c,contentTitle:()=>i,default:()=>h,frontMatter:()=>s,metadata:()=>o,toc:()=>l});const o=JSON.parse('{"id":"java-client/workflow-interface","title":"Workflow interface","description":"Workflowactivity and childworkflows:.","source":"@site/docs/04-java-client/02-workflow-interface.md","sourceDirName":"04-java-client","slug":"/java-client/workflow-interface","permalink":"/Cadence-Docs/docs/java-client/workflow-interface","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/04-java-client/02-workflow-interface.md","tags":[],"version":"current","sidebarPosition":2,"frontMatter":{"layout":"default","title":"Workflow interface","permalink":"/docs/java-client/workflow-interface"},"sidebar":"docsSidebar","previous":{"title":"Client SDK Overview","permalink":"/Cadence-Docs/docs/java-client/client-overview"},"next":{"title":"Implementing workflows","permalink":"/Cadence-Docs/docs/java-client/implementing-workflows"}}');var a=n(4848),r=n(8453);const s={layout:"default",title:"Workflow interface",permalink:"/docs/java-client/workflow-interface"},i="Workflow interface",c={},l=[];function d(e){const t={code:"code",h1:"h1",header:"header",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,r.R)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(t.header,{children:(0,a.jsx)(t.h1,{id:"workflow-interface",children:"Workflow interface"})}),"\n",(0,a.jsx)(t.p,{children:"Workflow encapsulates the orchestration of activities and child workflows.\nIt can also answer synchronous queries and receive external events (also known as signals)."}),"\n",(0,a.jsx)(t.p,{children:"A workflow must define an interface class. All of its methods must have one of the following annotations:"}),"\n",(0,a.jsxs)(t.ul,{children:["\n",(0,a.jsxs)(t.li,{children:[(0,a.jsx)(t.strong,{children:"@WorkflowMethod"})," indicates an entry point to a workflow. It contains parameters such as timeouts and a task_list.\nRequired parameters (such as ",(0,a.jsx)(t.code,{children:"executionStartToCloseTimeoutSeconds"}),") that are not specified through the annotation must be provided at runtime."]}),"\n",(0,a.jsxs)(t.li,{children:[(0,a.jsx)(t.strong,{children:"@SignalMethod"})," indicates a method that reacts to external signals. It must have a ",(0,a.jsx)(t.code,{children:"void"})," return type."]}),"\n",(0,a.jsxs)(t.li,{children:[(0,a.jsx)(t.strong,{children:"@QueryMethod"})," indicates a method that reacts to synchronous query requests."]}),"\n"]}),"\n",(0,a.jsx)(t.p,{children:"You can have more than one method with the same annotation (except @WorkflowMethod). For example:"}),"\n",(0,a.jsx)(t.pre,{children:(0,a.jsx)(t.code,{className:"language-java",children:'public interface FileProcessingWorkflow {\n\n @WorkflowMethod(executionStartToCloseTimeoutSeconds = 10, taskList = "file-processing")\n String processFile(Arguments args);\n\n @QueryMethod(name="history")\n List getHistory();\n\n @QueryMethod(name="status")\n String getStatus();\n\n @SignalMethod\n void retryNow();\n\n @SignalMethod\n void abandon();\n}\n'})}),"\n",(0,a.jsx)(t.p,{children:"We recommended that you use a single value type argument for workflow methods. In this way, adding new arguments as fields to the value type is a backwards-compatible change."})]})}function h(e={}){const{wrapper:t}={...(0,r.R)(),...e.components};return t?(0,a.jsx)(t,{...e,children:(0,a.jsx)(d,{...e})}):d(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>s,x:()=>i});var o=n(6540);const a={},r=o.createContext(a);function s(e){const t=o.useContext(r);return o.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function i(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:s(e.components),o.createElement(r.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/177ff540.a2742758.js b/assets/js/177ff540.8328b22b.js similarity index 83% rename from assets/js/177ff540.a2742758.js rename to assets/js/177ff540.8328b22b.js index 9921af7b2..d35b50be3 100644 --- a/assets/js/177ff540.a2742758.js +++ b/assets/js/177ff540.8328b22b.js @@ -1 +1 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[647],{4329:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>c,contentTitle:()=>s,default:()=>h,frontMatter:()=>o,metadata:()=>i,toc:()=>l});var i=n(8853),a=n(4848),r=n(8453);const o={title:"Moving to gRPC",date:new Date("2021-10-19T00:00:00.000Z"),authors:"vytautas-karpavicius",tags:["deep-dive","cadence-operations"]},s=void 0,c={authorsImageUrls:[void 0]},l=[{value:"Background",id:"background",level:2},{value:"Our Approach",id:"our-approach",level:2},{value:"System overview",id:"system-overview",level:2},{value:"Migration steps",id:"migration-steps",level:2},{value:"Upgrading Cadence server",id:"upgrading-cadence-server",level:3},{value:"Upgrading clients",id:"upgrading-clients",level:3},{value:"Status at Uber",id:"status-at-uber",level:3}];function d(e){const t={a:"a",h2:"h2",h3:"h3",hr:"hr",img:"img",li:"li",ol:"ol",p:"p",strong:"strong",ul:"ul",...(0,r.R)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(t.h2,{id:"background",children:"Background"}),"\n",(0,a.jsx)(t.p,{children:"Cadence historically has been using TChannel transport with Thrift encoding for both internal RPC calls and communication with client SDKs. gRPC is becoming a de-facto industry standard with much better adoption and community support. It offers features such as authentication and streaming that are very relevant for Cadence. Moreover, TChannel is being deprecated within Uber itself, pushing an effort for this migration. During the last year we\u2019ve implemented multiple changes in server and SDK that allows users to use gRPC in Cadence, as well as to upgrade their existing Cadence cluster in a backward compatible way. This post tracks the completed work items and our future plans."}),"\n",(0,a.jsx)(t.h2,{id:"our-approach",children:"Our Approach"}),"\n",(0,a.jsx)(t.p,{children:"With ~500 services using Cadence at Uber and many more open source customers around the world, we had to think about the gRPC transition in a backwards compatible way. We couldn\u2019t simply flip transport and encoding everywhere. Instead we needed to support both protocols as an intermediate step to ensure a smooth transition for our users."}),"\n",(0,a.jsx)(t.p,{children:"Cadence was using Thrift/TChannel not just for the API with client SDKs. They were also used for RPC calls between internal Cadence server components and also between different data centers. When starting this migration we had a choice of either starting with public APIs first or all the internal things within the server. We chose the latter one, so that we could gain experience and iterate faster within the server without disruption to the clients. With server side done and listening for both protocols, dynamic config flag was exposed to switch traffic internally. It allowed gradual deployment and provided an option to rollback if needed."}),"\n",(0,a.jsxs)(t.p,{children:["The next step - client migration. We have more users for the Go SDK at Uber, that is why we started with it. Current version of SDK exposes Thrift types via public API, therefore we can not remove them without breaking changes. While we have plans for revamped v2 SDK, current users are able to use gRPC as well - with the help of a ",(0,a.jsx)(t.a,{href:"https://github.com/cadence-workflow/cadence-go-client/blob/v0.18.2/compatibility/thrift2proto.go",children:"translation adapter"}),". Migration is underway starting with ",(0,a.jsx)(t.a,{href:"https://github.com/cadence-workflow/cadence/tree/master/canary",children:"cadence canary service"}),", and then onboarding user services one by one."]}),"\n",(0,a.jsx)(t.p,{children:"We plan to support TChannel for a few more releases and then eventually drop it in a future."}),"\n",(0,a.jsx)(t.h2,{id:"system-overview",children:"System overview"}),"\n",(0,a.jsx)(t.p,{children:(0,a.jsx)(t.img,{alt:"gRPC migration overview",src:n(2073).A+"",width:"1620",height:"763"})}),"\n",(0,a.jsxs)(t.ol,{children:["\n",(0,a.jsxs)(t.li,{children:["The frontend of ",(0,a.jsx)(t.a,{href:"https://github.com/cadence-workflow/cadence",children:"Cadence Server"})," exposes two inbounds for both gRPC and TChannel starting ",(0,a.jsx)(t.a,{href:"https://github.com/cadence-workflow/cadence/releases/tag/v0.21.0",children:"v0.21.0 release"}),". gRPC traffic is being served on a different port that can be configured ",(0,a.jsx)(t.a,{href:"https://github.com/cadence-workflow/cadence/blob/v0.21.0/config/development.yaml#L25",children:"here"}),". For gRPC API we introduced ",(0,a.jsx)(t.a,{href:"https://github.com/cadence-workflow/cadence-idl/tree/master/proto/cadence-workflow/cadence/api/v1",children:"proto IDL"})," definitions. We will keep TChannel open on frontend for some time to allow gradual client migration."]}),"\n",(0,a.jsxs)(t.li,{children:["Starting with ",(0,a.jsx)(t.a,{href:"https://github.com/cadence-workflow/cadence/releases/tag/v0.21.0",children:"v0.21.0"})," internal components of Cadence Server (history & matching) also started accepting gRPC traffic. Sending traffic via gRPC is off by default and could be enabled with a flag in ",(0,a.jsx)(t.a,{href:"https://github.com/cadence-workflow/cadence/blob/v0.21.0/config/dynamicconfig/development.yaml#L10",children:"dynamic config"}),". Planned for v0.24.0 it will be enabled by default, with an option to opt-out."]}),"\n",(0,a.jsxs)(t.li,{children:["Starting with v0.23.0 communication between different Cadence clusters can be switched to gRPC via this ",(0,a.jsx)(t.a,{href:"https://github.com/cadence-workflow/cadence/blob/0.23.x/config/development_active.yaml#L82",children:"configuration"}),". It is used for replication and request redirection to different DC."]}),"\n",(0,a.jsxs)(t.li,{children:[(0,a.jsx)(t.a,{href:"https://github.com/cadence-workflow/cadence-go-client",children:"Go SDK"})," has exposed generated Thrift types via its public API. This complicated migration, because switching them to proto types (or rpc agnostic types) means breaking changes. Because of this we are pursuing two alternatives:","\n",(0,a.jsxs)(t.ol,{children:["\n",(0,a.jsxs)(t.li,{children:["(A) Short term: starting with ",(0,a.jsx)(t.a,{href:"https://github.com/cadence-workflow/cadence-go-client/releases/tag/v0.18.2",children:"v0.18.2"})," a ",(0,a.jsx)(t.a,{href:"https://github.com/cadence-workflow/cadence-go-client/blob/v0.18.2/compatibility/thrift2proto.go",children:"compatibility layer"})," is available which makes translation between thrift-proto types underneath. It allows using gRPC communication while still using Thrift based API. ",(0,a.jsx)(t.a,{href:"https://github.com/cadence-workflow/cadence-samples/pull/52",children:"Usage example"}),"."]}),"\n",(0,a.jsxs)(t.li,{children:["(B) Long term: we are currently designing v2 SDK that will support gRPC directly. Its API will be RPC agnostic and will include other usability improvements. You can check some ideas that are being considered ",(0,a.jsx)(t.a,{href:"https://github.com/cadence-workflow/cadence-go-client/issues/1133",children:"here"}),"."]}),"\n"]}),"\n"]}),"\n",(0,a.jsxs)(t.li,{children:[(0,a.jsx)(t.a,{href:"https://github.com/cadence-workflow/cadence-java-client",children:"Java SDK"})," is currently on TChannel only. Move to gRPC is planned for 2022 H1."]}),"\n",(0,a.jsxs)(t.li,{children:["It is now possible to communicate with gRPC from other languages as well. Use ",(0,a.jsx)(t.a,{href:"https://github.com/cadence-workflow/cadence-idl/tree/master/proto/cadence-workflow/cadence/api/v1",children:"proto IDLs"})," to generate bindings for your preferred language. ",(0,a.jsx)(t.a,{href:"https://github.com/vytautas-karpavicius/cadence-python",children:"Minimal example"})," for doing it in python."]}),"\n",(0,a.jsx)(t.li,{children:"WebUI and CLI are currently on TChannel. They are planned to be switched to gRPC for 2022 H1."}),"\n"]}),"\n",(0,a.jsx)(t.h2,{id:"migration-steps",children:"Migration steps"}),"\n",(0,a.jsx)(t.h3,{id:"upgrading-cadence-server",children:"Upgrading Cadence server"}),"\n",(0,a.jsxs)(t.p,{children:["In order to start using gRPC please upgrade Cadence server to ",(0,a.jsxs)(t.strong,{children:[(0,a.jsx)(t.a,{href:"https://github.com/cadence-workflow/cadence/releases/tag/v0.22.0",children:"v0.22.0"})," or later"]}),"."]}),"\n",(0,a.jsxs)(t.ol,{children:["\n",(0,a.jsxs)(t.li,{children:["If you are using an older version (before v0.21.0), make sure to disable internal gRPC communication at first. Needed to ensure that all nodes in the cluster are ready to accept gRPC traffic, before switching it on. This is controlled by the ",(0,a.jsx)(t.a,{href:"https://github.com/cadence-workflow/cadence/blob/v0.21.0/config/dynamicconfig/development.yaml#L10",children:"system.enableGRPCOutbound"})," flag in dynamic config."]}),"\n",(0,a.jsx)(t.li,{children:"Once deployed, flip system.enableGRPCOutbound to true. It will require a cluster restart for setting to take effect."}),"\n",(0,a.jsxs)(t.li,{children:["If you are operating in more than one DC - recommended server version to upgrade to is v0.23.0 or newer. Once individual clusters with gRPC support are deployed, please update ",(0,a.jsx)(t.a,{href:"https://github.com/cadence-workflow/cadence/blob/0.23.x/config/development_active.yaml#L82",children:"config"})," to switch cross DC traffic to gRPC. Don\u2019t forget to update ports as well. We also recommend increasing ",(0,a.jsx)(t.a,{href:"https://github.com/cadence-workflow/cadence/blob/0.23.x/config/development.yaml#L29",children:"grpcMaxMsgSize"})," to 32MB which is needed to ensure smooth replication. After config change you will need a restart for setting to take effect."]}),"\n",(0,a.jsx)(t.li,{children:"Do not forget that gRPC runs on a different port, therefore you might need to open it on docker containers, firewalls, etc."}),"\n"]}),"\n",(0,a.jsx)(t.h3,{id:"upgrading-clients",children:"Upgrading clients"}),"\n",(0,a.jsxs)(t.ol,{children:["\n",(0,a.jsxs)(t.li,{children:["GoSDK - Follow an ",(0,a.jsx)(t.a,{href:"https://github.com/cadence-workflow/cadence-samples/pull/52",children:"example"})," to inject Thrift-to-proto adapter during client initialization and update your config to use the gRPC port."]}),"\n"]}),"\n",(0,a.jsx)(t.h3,{id:"status-at-uber",children:"Status at Uber"}),"\n",(0,a.jsxs)(t.ul,{children:["\n",(0,a.jsx)(t.li,{children:"All clusters run gRPC traffic internally for 4 months without any issues."}),"\n",(0,a.jsx)(t.li,{children:"Cross DC traffic has been switched to gRPC this month."}),"\n",(0,a.jsx)(t.li,{children:"With internal tooling updated, we are starting to onboard services to use the Go SDK gRPC compatibility layer."}),"\n"]}),"\n",(0,a.jsx)(t.hr,{}),"\n",(0,a.jsxs)(t.p,{children:["Do not hesitate to reach out to us (",(0,a.jsx)(t.a,{href:"mailto:cadence-oss@googlegroups.com",children:"cadence-oss@googlegroups.com"}),"\xa0or\xa0",(0,a.jsx)(t.a,{href:"http://t.uber.com/cadence-slack",children:"slack"}),") if you have any questions."]}),"\n",(0,a.jsx)(t.p,{children:"The Uber Cadence team"})]})}function h(e={}){const{wrapper:t}={...(0,r.R)(),...e.components};return t?(0,a.jsx)(t,{...e,children:(0,a.jsx)(d,{...e})}):d(e)}},2073:(e,t,n)=>{n.d(t,{A:()=>i});const i=n.p+"assets/images/grpc-migration-37a72dbf7fccdebbb79ce21a53987bfc.svg"},8453:(e,t,n)=>{n.d(t,{R:()=>o,x:()=>s});var i=n(6540);const a={},r=i.createContext(a);function o(e){const t=i.useContext(r);return i.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function s(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:o(e.components),i.createElement(r.Provider,{value:t},e.children)}},8853:e=>{e.exports=JSON.parse('{"permalink":"/blog/2021/10/19/2021-10-19-moving-to-grpc/moving-to-grpc","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2021-10-19-moving-to-grpc/2021-10-19-moving-to-grpc.md","source":"@site/blog/2021-10-19-moving-to-grpc/2021-10-19-moving-to-grpc.md","title":"Moving to gRPC","description":"Background","date":"2021-10-19T00:00:00.000Z","tags":[{"inline":false,"label":"Deep Dives","permalink":"/blog/tags/deep-dives","description":"Deep Dives tag description"},{"inline":false,"label":"Cadence Operations","permalink":"/blog/tags/cadence-operations","description":"Cadence Operations tag description"}],"readingTime":4.795,"hasTruncateMarker":true,"authors":[{"name":"Vytautas Karpavicius","title":"Software Engineer @ Uber","url":"https://www.linkedin.com/in/vytautas-karpavicius","page":{"permalink":"/blog/authors/vytautas-karpavicius"},"socials":{"linkedin":"https://www.linkedin.com/in/vytautas-karpavicius","github":"https://github.com/vytautas-karpavicius"},"imageURL":"https://github.com/vytautas-karpavicius.png","key":"vytautas-karpavicius"}],"frontMatter":{"title":"Moving to gRPC","date":"2021-10-19T00:00:00.000Z","authors":"vytautas-karpavicius","tags":["deep-dive","cadence-operations"]},"unlisted":false,"prevItem":{"title":"Cadence Community Spotlight Update - January 2022","permalink":"/blog/2022/01/31/community-spotlight-january-2022"},"nextItem":{"title":"Announcing Cadence OSS office hours and community sync up","permalink":"/blog/2021/10/13/announcing-cadence-oss-office-hours-and-community-sync-up"}}')}}]); \ No newline at end of file +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[647],{4329:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>c,contentTitle:()=>s,default:()=>h,frontMatter:()=>r,metadata:()=>i,toc:()=>l});var i=n(8853),a=n(4848),o=n(8453);const r={title:"Moving to gRPC",date:new Date("2021-10-19T00:00:00.000Z"),authors:"vytautas-karpavicius",tags:["deep-dive","cadence-operations"]},s=void 0,c={authorsImageUrls:[void 0]},l=[{value:"Background",id:"background",level:2},{value:"Our Approach",id:"our-approach",level:2},{value:"System overview",id:"system-overview",level:2},{value:"Migration steps",id:"migration-steps",level:2},{value:"Upgrading Cadence server",id:"upgrading-cadence-server",level:3},{value:"Upgrading clients",id:"upgrading-clients",level:3},{value:"Status at Uber",id:"status-at-uber",level:3}];function d(e){const t={a:"a",h2:"h2",h3:"h3",hr:"hr",img:"img",li:"li",ol:"ol",p:"p",strong:"strong",ul:"ul",...(0,o.R)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(t.h2,{id:"background",children:"Background"}),"\n",(0,a.jsx)(t.p,{children:"Cadence historically has been using TChannel transport with Thrift encoding for both internal RPC calls and communication with client SDKs. gRPC is becoming a de-facto industry standard with much better adoption and community support. It offers features such as authentication and streaming that are very relevant for Cadence. Moreover, TChannel is being deprecated within Uber itself, pushing an effort for this migration. During the last year we\u2019ve implemented multiple changes in server and SDK that allows users to use gRPC in Cadence, as well as to upgrade their existing Cadence cluster in a backward compatible way. This post tracks the completed work items and our future plans."}),"\n",(0,a.jsx)(t.h2,{id:"our-approach",children:"Our Approach"}),"\n",(0,a.jsx)(t.p,{children:"With ~500 services using Cadence at Uber and many more open source customers around the world, we had to think about the gRPC transition in a backwards compatible way. We couldn\u2019t simply flip transport and encoding everywhere. Instead we needed to support both protocols as an intermediate step to ensure a smooth transition for our users."}),"\n",(0,a.jsx)(t.p,{children:"Cadence was using Thrift/TChannel not just for the API with client SDKs. They were also used for RPC calls between internal Cadence server components and also between different data centers. When starting this migration we had a choice of either starting with public APIs first or all the internal things within the server. We chose the latter one, so that we could gain experience and iterate faster within the server without disruption to the clients. With server side done and listening for both protocols, dynamic config flag was exposed to switch traffic internally. It allowed gradual deployment and provided an option to rollback if needed."}),"\n",(0,a.jsxs)(t.p,{children:["The next step - client migration. We have more users for the Go SDK at Uber, that is why we started with it. Current version of SDK exposes Thrift types via public API, therefore we can not remove them without breaking changes. While we have plans for revamped v2 SDK, current users are able to use gRPC as well - with the help of a ",(0,a.jsx)(t.a,{href:"https://github.com/cadence-workflow/cadence-go-client/blob/v0.18.2/compatibility/thrift2proto.go",children:"translation adapter"}),". Migration is underway starting with ",(0,a.jsx)(t.a,{href:"https://github.com/cadence-workflow/cadence/tree/master/canary",children:"cadence canary service"}),", and then onboarding user services one by one."]}),"\n",(0,a.jsx)(t.p,{children:"We plan to support TChannel for a few more releases and then eventually drop it in a future."}),"\n",(0,a.jsx)(t.h2,{id:"system-overview",children:"System overview"}),"\n",(0,a.jsx)(t.p,{children:(0,a.jsx)(t.img,{alt:"gRPC migration overview",src:n(2073).A+"",width:"1620",height:"763"})}),"\n",(0,a.jsxs)(t.ol,{children:["\n",(0,a.jsxs)(t.li,{children:["The frontend of ",(0,a.jsx)(t.a,{href:"https://github.com/cadence-workflow/cadence",children:"Cadence Server"})," exposes two inbounds for both gRPC and TChannel starting ",(0,a.jsx)(t.a,{href:"https://github.com/cadence-workflow/cadence/releases/tag/v0.21.0",children:"v0.21.0 release"}),". gRPC traffic is being served on a different port that can be configured ",(0,a.jsx)(t.a,{href:"https://github.com/cadence-workflow/cadence/blob/v0.21.0/config/development.yaml#L25",children:"here"}),". For gRPC API we introduced ",(0,a.jsx)(t.a,{href:"https://github.com/cadence-workflow/cadence-idl/tree/master/proto/cadence-workflow/cadence/api/v1",children:"proto IDL"})," definitions. We will keep TChannel open on frontend for some time to allow gradual client migration."]}),"\n",(0,a.jsxs)(t.li,{children:["Starting with ",(0,a.jsx)(t.a,{href:"https://github.com/cadence-workflow/cadence/releases/tag/v0.21.0",children:"v0.21.0"})," internal components of Cadence Server (history & matching) also started accepting gRPC traffic. Sending traffic via gRPC is off by default and could be enabled with a flag in ",(0,a.jsx)(t.a,{href:"https://github.com/cadence-workflow/cadence/blob/v0.21.0/config/dynamicconfig/development.yaml#L10",children:"dynamic config"}),". Planned for v0.24.0 it will be enabled by default, with an option to opt-out."]}),"\n",(0,a.jsxs)(t.li,{children:["Starting with v0.23.0 communication between different Cadence clusters can be switched to gRPC via this ",(0,a.jsx)(t.a,{href:"https://github.com/cadence-workflow/cadence/blob/0.23.x/config/development_active.yaml#L82",children:"configuration"}),". It is used for replication and request redirection to different DC."]}),"\n",(0,a.jsxs)(t.li,{children:[(0,a.jsx)(t.a,{href:"https://github.com/cadence-workflow/cadence-go-client",children:"Go SDK"})," has exposed generated Thrift types via its public API. This complicated migration, because switching them to proto types (or rpc agnostic types) means breaking changes. Because of this we are pursuing two alternatives:","\n",(0,a.jsxs)(t.ol,{children:["\n",(0,a.jsxs)(t.li,{children:["(A) Short term: starting with ",(0,a.jsx)(t.a,{href:"https://github.com/cadence-workflow/cadence-go-client/releases/tag/v0.18.2",children:"v0.18.2"})," a ",(0,a.jsx)(t.a,{href:"https://github.com/cadence-workflow/cadence-go-client/blob/v0.18.2/compatibility/thrift2proto.go",children:"compatibility layer"})," is available which makes translation between thrift-proto types underneath. It allows using gRPC communication while still using Thrift based API. ",(0,a.jsx)(t.a,{href:"https://github.com/cadence-workflow/cadence-samples/pull/52",children:"Usage example"}),"."]}),"\n",(0,a.jsxs)(t.li,{children:["(B) Long term: we are currently designing v2 SDK that will support gRPC directly. Its API will be RPC agnostic and will include other usability improvements. You can check some ideas that are being considered ",(0,a.jsx)(t.a,{href:"https://github.com/cadence-workflow/cadence-go-client/issues/1133",children:"here"}),"."]}),"\n"]}),"\n"]}),"\n",(0,a.jsxs)(t.li,{children:[(0,a.jsx)(t.a,{href:"https://github.com/cadence-workflow/cadence-java-client",children:"Java SDK"})," is currently on TChannel only. Move to gRPC is planned for 2022 H1."]}),"\n",(0,a.jsxs)(t.li,{children:["It is now possible to communicate with gRPC from other languages as well. Use ",(0,a.jsx)(t.a,{href:"https://github.com/cadence-workflow/cadence-idl/tree/master/proto/cadence-workflow/cadence/api/v1",children:"proto IDLs"})," to generate bindings for your preferred language. ",(0,a.jsx)(t.a,{href:"https://github.com/vytautas-karpavicius/cadence-python",children:"Minimal example"})," for doing it in python."]}),"\n",(0,a.jsx)(t.li,{children:"WebUI and CLI are currently on TChannel. They are planned to be switched to gRPC for 2022 H1."}),"\n"]}),"\n",(0,a.jsx)(t.h2,{id:"migration-steps",children:"Migration steps"}),"\n",(0,a.jsx)(t.h3,{id:"upgrading-cadence-server",children:"Upgrading Cadence server"}),"\n",(0,a.jsxs)(t.p,{children:["In order to start using gRPC please upgrade Cadence server to ",(0,a.jsxs)(t.strong,{children:[(0,a.jsx)(t.a,{href:"https://github.com/cadence-workflow/cadence/releases/tag/v0.22.0",children:"v0.22.0"})," or later"]}),"."]}),"\n",(0,a.jsxs)(t.ol,{children:["\n",(0,a.jsxs)(t.li,{children:["If you are using an older version (before v0.21.0), make sure to disable internal gRPC communication at first. Needed to ensure that all nodes in the cluster are ready to accept gRPC traffic, before switching it on. This is controlled by the ",(0,a.jsx)(t.a,{href:"https://github.com/cadence-workflow/cadence/blob/v0.21.0/config/dynamicconfig/development.yaml#L10",children:"system.enableGRPCOutbound"})," flag in dynamic config."]}),"\n",(0,a.jsx)(t.li,{children:"Once deployed, flip system.enableGRPCOutbound to true. It will require a cluster restart for setting to take effect."}),"\n",(0,a.jsxs)(t.li,{children:["If you are operating in more than one DC - recommended server version to upgrade to is v0.23.0 or newer. Once individual clusters with gRPC support are deployed, please update ",(0,a.jsx)(t.a,{href:"https://github.com/cadence-workflow/cadence/blob/0.23.x/config/development_active.yaml#L82",children:"config"})," to switch cross DC traffic to gRPC. Don\u2019t forget to update ports as well. We also recommend increasing ",(0,a.jsx)(t.a,{href:"https://github.com/cadence-workflow/cadence/blob/0.23.x/config/development.yaml#L29",children:"grpcMaxMsgSize"})," to 32MB which is needed to ensure smooth replication. After config change you will need a restart for setting to take effect."]}),"\n",(0,a.jsx)(t.li,{children:"Do not forget that gRPC runs on a different port, therefore you might need to open it on docker containers, firewalls, etc."}),"\n"]}),"\n",(0,a.jsx)(t.h3,{id:"upgrading-clients",children:"Upgrading clients"}),"\n",(0,a.jsxs)(t.ol,{children:["\n",(0,a.jsxs)(t.li,{children:["GoSDK - Follow an ",(0,a.jsx)(t.a,{href:"https://github.com/cadence-workflow/cadence-samples/pull/52",children:"example"})," to inject Thrift-to-proto adapter during client initialization and update your config to use the gRPC port."]}),"\n"]}),"\n",(0,a.jsx)(t.h3,{id:"status-at-uber",children:"Status at Uber"}),"\n",(0,a.jsxs)(t.ul,{children:["\n",(0,a.jsx)(t.li,{children:"All clusters run gRPC traffic internally for 4 months without any issues."}),"\n",(0,a.jsx)(t.li,{children:"Cross DC traffic has been switched to gRPC this month."}),"\n",(0,a.jsx)(t.li,{children:"With internal tooling updated, we are starting to onboard services to use the Go SDK gRPC compatibility layer."}),"\n"]}),"\n",(0,a.jsx)(t.hr,{}),"\n",(0,a.jsxs)(t.p,{children:["Do not hesitate to reach out to us (",(0,a.jsx)(t.a,{href:"mailto:cadence-oss@googlegroups.com",children:"cadence-oss@googlegroups.com"}),"\xa0or\xa0",(0,a.jsx)(t.a,{href:"http://t.uber.com/cadence-slack",children:"slack"}),") if you have any questions."]}),"\n",(0,a.jsx)(t.p,{children:"The Uber Cadence team"})]})}function h(e={}){const{wrapper:t}={...(0,o.R)(),...e.components};return t?(0,a.jsx)(t,{...e,children:(0,a.jsx)(d,{...e})}):d(e)}},2073:(e,t,n)=>{n.d(t,{A:()=>i});const i=n.p+"assets/images/grpc-migration-37a72dbf7fccdebbb79ce21a53987bfc.svg"},8453:(e,t,n)=>{n.d(t,{R:()=>r,x:()=>s});var i=n(6540);const a={},o=i.createContext(a);function r(e){const t=i.useContext(o);return i.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function s(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:r(e.components),i.createElement(o.Provider,{value:t},e.children)}},8853:e=>{e.exports=JSON.parse('{"permalink":"/Cadence-Docs/blog/2021/10/19/2021-10-19-moving-to-grpc/moving-to-grpc","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2021-10-19-moving-to-grpc/2021-10-19-moving-to-grpc.md","source":"@site/blog/2021-10-19-moving-to-grpc/2021-10-19-moving-to-grpc.md","title":"Moving to gRPC","description":"Background","date":"2021-10-19T00:00:00.000Z","tags":[{"inline":false,"label":"Deep Dives","permalink":"/Cadence-Docs/blog/tags/deep-dives","description":"Deep Dives tag description"},{"inline":false,"label":"Cadence Operations","permalink":"/Cadence-Docs/blog/tags/cadence-operations","description":"Cadence Operations tag description"}],"readingTime":4.795,"hasTruncateMarker":true,"authors":[{"name":"Vytautas Karpavicius","title":"Software Engineer @ Uber","url":"https://www.linkedin.com/in/vytautas-karpavicius","page":{"permalink":"/Cadence-Docs/blog/authors/vytautas-karpavicius"},"socials":{"linkedin":"https://www.linkedin.com/in/vytautas-karpavicius","github":"https://github.com/vytautas-karpavicius"},"imageURL":"https://github.com/vytautas-karpavicius.png","key":"vytautas-karpavicius"}],"frontMatter":{"title":"Moving to gRPC","date":"2021-10-19T00:00:00.000Z","authors":"vytautas-karpavicius","tags":["deep-dive","cadence-operations"]},"unlisted":false,"prevItem":{"title":"Cadence Community Spotlight Update - January 2022","permalink":"/Cadence-Docs/blog/2022/01/31/community-spotlight-january-2022"},"nextItem":{"title":"Announcing Cadence OSS office hours and community sync up","permalink":"/Cadence-Docs/blog/2021/10/13/announcing-cadence-oss-office-hours-and-community-sync-up"}}')}}]); \ No newline at end of file diff --git a/assets/js/17896883.680e0e06.js b/assets/js/17896883.680e0e06.js deleted file mode 100644 index 629b274bc..000000000 --- a/assets/js/17896883.680e0e06.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[1643],{9379:t=>{t.exports=JSON.parse('{"author":{"name":"Kevin Corbett","title":"Open Source Community Manager | @instaclustr @NetApp","url":"https://github.com/kcorbett-netapp","page":{"permalink":"/blog/authors/kcorbett-netapp"},"socials":{"linkedin":"https://www.linkedin.com/in/kcorb95/","github":"https://github.com/kcorbett-netapp"},"imageURL":"https://github.com/kcorbett-netapp.png","key":"kcorbett-netapp","count":1},"listMetadata":{"permalink":"/blog/authors/kcorbett-netapp","page":1,"postsPerPage":10,"totalPages":1,"totalCount":1,"blogDescription":"The latest news and updates from the Cadence team","blogTitle":"Cadence Blog"}}')}}]); \ No newline at end of file diff --git a/assets/js/18e1ae2c.3dde30da.js b/assets/js/18e1ae2c.185d36d3.js similarity index 82% rename from assets/js/18e1ae2c.3dde30da.js rename to assets/js/18e1ae2c.185d36d3.js index bb8d0f841..235bd36e6 100644 --- a/assets/js/18e1ae2c.3dde30da.js +++ b/assets/js/18e1ae2c.185d36d3.js @@ -1 +1 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[3029],{3198:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>s,contentTitle:()=>c,default:()=>p,frontMatter:()=>a,metadata:()=>r,toc:()=>l});var r=t(3865),o=t(4848),i=t(8453);const a={title:"Implement a Cadence worker service from scratch",date:new Date("2023-07-05T00:00:00.000Z"),authors:"chopincode",tags:["deep-dive","introduction-to-cadence"]},c=void 0,s={authorsImageUrls:[void 0]},l=[];function d(e){const n={a:"a",code:"code",li:"li",ol:"ol",p:"p",pre:"pre",...(0,i.R)(),...e.components};return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsxs)(n.p,{children:["In the previous ",(0,o.jsx)(n.a,{href:"/blog/2023/06/28/components-of-cadence-application-setup",children:"blog"}),", we have introduced three critical components for a Cadence application: the Cadence backend, domain, and worker. Among these, the worker service is the most crucial focus for developers as it hosts the activities and workflows of a Cadence application. In this blog, I will provide a short tutorial on how to implement a simple worker service from scratch in Go."]}),"\n",(0,o.jsx)(n.p,{children:"To finish this tutorial, there are two prerequisites you need to finish first"}),"\n",(0,o.jsxs)(n.ol,{children:["\n",(0,o.jsxs)(n.li,{children:["Register a Cadence domain for your worker. For this tutorial, I've already registered a domain named ",(0,o.jsx)(n.code,{children:"test-domain"})]}),"\n",(0,o.jsx)(n.li,{children:"Start the Cadence backend server in background."}),"\n"]}),"\n",(0,o.jsx)(n.p,{children:"To get started, let's simply use the native HTTP package built in Go to start a process listening to port 3000. You may customize the port for your worker, but the port you choose should not conflict with existing port for your Cadence backend."}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-go",children:'package main\n\nimport (\n\t"fmt"\n\t"net/http"\n)\n\nfunc main(){\n\tfmt.Println("Cadence worker started at port 3000")\n\thttp.ListenAndServe(":3000", nil)\n}\n'})}),"\n",(0,o.jsx)(n.p,{children:"Next, let's define some basic configurations for the worker. In real production environment, you may need to implement them in configurational languages, but in this tutorial, let's just hard code them for now."}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-go",children:'var HostPort = "127.0.0.1:7933"\nvar Domain = "test-domain"\nvar TaskListName = "test-worker"\nvar ClientName = "test-worker"\nvar CadenceService = "cadence-frontend"\n'})}),"\n",(0,o.jsx)(n.p,{children:"Note that the domain is what we've already registered in advance. We will need to use this domain to interact with Cadence CLI tool."}),"\n",(0,o.jsx)(n.p,{children:"Then let's write a simple function to build a Cadence client on gRPC in your worker, which will communicate with the Cadence backend continuously."}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-go",children:'func buildCadenceClient() workflowserviceclient.Interface {\n dispatcher := yarpc.NewDispatcher(yarpc.Config{\n\t\tName: ClientName,\n\t\tOutbounds: yarpc.Outbounds{\n\t\t CadenceService: {Unary: grpc.NewTransport().NewSingleOutbound(HostPort)},\n\t\t},\n\t })\n\t if err := dispatcher.Start(); err != nil {\n\t\tpanic("Failed to start dispatcher")\n\t }\n\n\t clientConfig := dispatcher.ClientConfig(CadenceService)\n\n\t return compatibility.NewThrift2ProtoAdapter(\n\t\tapiv1.NewDomainAPIYARPCClient(clientConfig),\n\t\tapiv1.NewWorkflowAPIYARPCClient(clientConfig),\n\t\tapiv1.NewWorkerAPIYARPCClient(clientConfig),\n\t\tapiv1.NewVisibilityAPIYARPCClient(clientConfig),\n\t )\n}\n'})}),"\n",(0,o.jsx)(n.p,{children:"Let's also build a logger to help us debug our application"}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-go",children:'func buildLogger() *zap.Logger {\n config := zap.NewDevelopmentConfig()\n config.Level.SetLevel(zapcore.InfoLevel)\n\n var err error\n logger, err := config.Build()\n if err != nil {\n panic("Failed to setup logger")\n }\n\n return logger\n}\n'})}),"\n",(0,o.jsx)(n.p,{children:"With both client and logger helper function ready, let's write the function that starts our worker."}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-go",children:'func startWorker(logger *zap.Logger, service workflowserviceclient.Interface) {\n // TaskListName identifies set of client workflows, activities, and workers.\n // It could be your group or client or application name.\n workerOptions := worker.Options{\n Logger: logger,\n MetricsScope: tally.NewTestScope(TaskListName, map[string]string{}),\n }\n\n worker := worker.New(\n service,\n Domain,\n TaskListName,\n workerOptions)\n err := worker.Start()\n if err != nil {\n panic("Failed to start worker")\n }\n\n logger.Info("Started Worker.", zap.String("worker", TaskListName))\n}\n'})}),"\n",(0,o.jsx)(n.p,{children:"Now we have all components ready for the worker, let's put them together."}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-Go",children:'import (\n "net/http"\n "go.uber.org/cadence/.gen/go/cadence/workflowserviceclient"\n "go.uber.org/cadence/compatibility"\n "go.uber.org/cadence/worker"\n\n apiv1 "github.com/cadence-workflow/cadence-idl/go/proto/api/v1"\n "github.com/uber-go/tally"\n "go.uber.org/zap"\n "go.uber.org/zap/zapcore"\n "go.uber.org/yarpc"\n "go.uber.org/yarpc/transport/grpc"\n)\n\nvar HostPort = "127.0.0.1:7933"\nvar Domain = "test-domain"\nvar TaskListName = "test-worker"\nvar ClientName = "test-worker"\nvar CadenceService = "cadence-frontend"\n\nfunc main() {\n startWorker(buildLogger(), buildCadenceClient())\n http.ListenAndServe(":3000", nil)\n}\n\nfunc buildLogger() *zap.Logger {\n config := zap.NewDevelopmentConfig()\n config.Level.SetLevel(zapcore.InfoLevel)\n\n var err error\n logger, err := config.Build()\n if err != nil {\n panic("Failed to setup logger")\n }\n\n return logger\n}\n\nfunc buildCadenceClient() workflowserviceclient.Interface {\n dispatcher := yarpc.NewDispatcher(yarpc.Config{\n\t\tName: ClientName,\n\t\tOutbounds: yarpc.Outbounds{\n\t\t CadenceService: {Unary: grpc.NewTransport().NewSingleOutbound(HostPort)},\n\t\t},\n\t })\n\t if err := dispatcher.Start(); err != nil {\n\t\tpanic("Failed to start dispatcher")\n\t }\n\n\t clientConfig := dispatcher.ClientConfig(CadenceService)\n\n\t return compatibility.NewThrift2ProtoAdapter(\n\t\tapiv1.NewDomainAPIYARPCClient(clientConfig),\n\t\tapiv1.NewWorkflowAPIYARPCClient(clientConfig),\n\t\tapiv1.NewWorkerAPIYARPCClient(clientConfig),\n\t\tapiv1.NewVisibilityAPIYARPCClient(clientConfig),\n\t )\n}\n\nfunc startWorker(logger *zap.Logger, service workflowserviceclient.Interface) {\n // TaskListName identifies set of client workflows, activities, and workers.\n // It could be your group or client or application name.\n workerOptions := worker.Options{\n Logger: logger,\n MetricsScope: tally.NewTestScope(TaskListName, map[string]string{}),\n }\n\n worker := worker.New(\n service,\n Domain,\n TaskListName,\n workerOptions)\n err := worker.Start()\n if err != nil {\n panic("Failed to start worker")\n }\n\n logger.Info("Started Worker.", zap.String("worker", TaskListName))\n}\n'})}),"\n",(0,o.jsx)(n.p,{children:"Open a new terminal and start this server, you should see logs like"}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-shell",children:'2023-07-03T11:46:46.266-0700 INFO internal/internal_worker.go:826 Worker has no workflows registered, so workflow worker will not be started. {"Domain": "test-domain", "TaskList": "test-worker", "WorkerID": "35987@uber-C02F18EQMD6R@test-worker@90c0260e-ba5c-4652-9f10-c6d1f9e29c1d"}\n2023-07-03T11:46:46.267-0700 INFO internal/internal_worker.go:834 Started Workflow Worker {"Domain": "test-domain", "TaskList": "test-worker", "WorkerID": "35987@uber-C02F18EQMD6R@test-worker@90c0260e-ba5c-4652-9f10-c6d1f9e29c1d"}\n2023-07-03T11:46:46.267-0700 INFO internal/internal_worker.go:838 Worker has no activities registered, so activity worker will not be started. {"Domain": "test-domain", "TaskList": "test-worker", "WorkerID": "35987@uber-C02F18EQMD6R@test-worker@90c0260e-ba5c-4652-9f10-c6d1f9e29c1d"}\n2023-07-03T11:46:46.267-0700 INFO cadence-worker/main.go:75 Started Worker. {"worker": "test-worker"}\n'})}),"\n",(0,o.jsx)(n.p,{children:"You may see these logs because your worker is successfully running but we haven't registered any workflows or activities to the worker. In the next tutorial, we will learn how to write a simple hello world workflow for your Cadence application."})]})}function p(e={}){const{wrapper:n}={...(0,i.R)(),...e.components};return n?(0,o.jsx)(n,{...e,children:(0,o.jsx)(d,{...e})}):d(e)}},8453:(e,n,t)=>{t.d(n,{R:()=>a,x:()=>c});var r=t(6540);const o={},i=r.createContext(o);function a(e){const n=r.useContext(i);return r.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function c(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:a(e.components),r.createElement(i.Provider,{value:n},e.children)}},3865:e=>{e.exports=JSON.parse('{"permalink":"/blog/2023/07/05/implement-cadence-worker-from-scratch","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2023-07-05-implement-cadence-worker-from-scratch.md","source":"@site/blog/2023-07-05-implement-cadence-worker-from-scratch.md","title":"Implement a Cadence worker service from scratch","description":"In the previous blog, we have introduced three critical components for a Cadence application: the Cadence backend, domain, and worker. Among these, the worker service is the most crucial focus for developers as it hosts the activities and workflows of a Cadence application. In this blog, I will provide a short tutorial on how to implement a simple worker service from scratch in Go.","date":"2023-07-05T00:00:00.000Z","tags":[{"inline":false,"label":"Deep Dives","permalink":"/blog/tags/deep-dives","description":"Deep Dives tag description"},{"inline":false,"label":"Introduction to Cadence","permalink":"/blog/tags/introduction-to-cadence","description":"Introduction to Cadence tag description"}],"readingTime":3.69,"hasTruncateMarker":true,"authors":[{"name":"Chris Qin","title":"Applications Developer @ Uber","url":"https://www.linkedin.com/in/chrisqin0610/","page":{"permalink":"/blog/authors/chopincode"},"socials":{"linkedin":"https://www.linkedin.com/in/chrisqin0610/","github":"https://github.com/chopincode"},"imageURL":"https://github.com/chopincode.png","key":"chopincode"}],"frontMatter":{"title":"Implement a Cadence worker service from scratch","date":"2023-07-05T00:00:00.000Z","authors":"chopincode","tags":["deep-dive","introduction-to-cadence"]},"unlisted":false,"prevItem":{"title":"Bad practices and Anti-patterns with Cadence (Part 1)","permalink":"/blog/2023/07/10/cadence-bad-practices-part-1"},"nextItem":{"title":"Understanding components of Cadence application","permalink":"/blog/2023/06/28/components-of-cadence-application-setup"}}')}}]); \ No newline at end of file +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[3029],{3198:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>s,contentTitle:()=>c,default:()=>p,frontMatter:()=>a,metadata:()=>r,toc:()=>l});var r=t(3865),o=t(4848),i=t(8453);const a={title:"Implement a Cadence worker service from scratch",date:new Date("2023-07-05T00:00:00.000Z"),authors:"chopincode",tags:["deep-dive","introduction-to-cadence"]},c=void 0,s={authorsImageUrls:[void 0]},l=[];function d(e){const n={a:"a",code:"code",li:"li",ol:"ol",p:"p",pre:"pre",...(0,i.R)(),...e.components};return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsxs)(n.p,{children:["In the previous ",(0,o.jsx)(n.a,{href:"/blog/2023/06/28/components-of-cadence-application-setup",children:"blog"}),", we have introduced three critical components for a Cadence application: the Cadence backend, domain, and worker. Among these, the worker service is the most crucial focus for developers as it hosts the activities and workflows of a Cadence application. In this blog, I will provide a short tutorial on how to implement a simple worker service from scratch in Go."]}),"\n",(0,o.jsx)(n.p,{children:"To finish this tutorial, there are two prerequisites you need to finish first"}),"\n",(0,o.jsxs)(n.ol,{children:["\n",(0,o.jsxs)(n.li,{children:["Register a Cadence domain for your worker. For this tutorial, I've already registered a domain named ",(0,o.jsx)(n.code,{children:"test-domain"})]}),"\n",(0,o.jsx)(n.li,{children:"Start the Cadence backend server in background."}),"\n"]}),"\n",(0,o.jsx)(n.p,{children:"To get started, let's simply use the native HTTP package built in Go to start a process listening to port 3000. You may customize the port for your worker, but the port you choose should not conflict with existing port for your Cadence backend."}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-go",children:'package main\n\nimport (\n\t"fmt"\n\t"net/http"\n)\n\nfunc main(){\n\tfmt.Println("Cadence worker started at port 3000")\n\thttp.ListenAndServe(":3000", nil)\n}\n'})}),"\n",(0,o.jsx)(n.p,{children:"Next, let's define some basic configurations for the worker. In real production environment, you may need to implement them in configurational languages, but in this tutorial, let's just hard code them for now."}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-go",children:'var HostPort = "127.0.0.1:7933"\nvar Domain = "test-domain"\nvar TaskListName = "test-worker"\nvar ClientName = "test-worker"\nvar CadenceService = "cadence-frontend"\n'})}),"\n",(0,o.jsx)(n.p,{children:"Note that the domain is what we've already registered in advance. We will need to use this domain to interact with Cadence CLI tool."}),"\n",(0,o.jsx)(n.p,{children:"Then let's write a simple function to build a Cadence client on gRPC in your worker, which will communicate with the Cadence backend continuously."}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-go",children:'func buildCadenceClient() workflowserviceclient.Interface {\n dispatcher := yarpc.NewDispatcher(yarpc.Config{\n\t\tName: ClientName,\n\t\tOutbounds: yarpc.Outbounds{\n\t\t CadenceService: {Unary: grpc.NewTransport().NewSingleOutbound(HostPort)},\n\t\t},\n\t })\n\t if err := dispatcher.Start(); err != nil {\n\t\tpanic("Failed to start dispatcher")\n\t }\n\n\t clientConfig := dispatcher.ClientConfig(CadenceService)\n\n\t return compatibility.NewThrift2ProtoAdapter(\n\t\tapiv1.NewDomainAPIYARPCClient(clientConfig),\n\t\tapiv1.NewWorkflowAPIYARPCClient(clientConfig),\n\t\tapiv1.NewWorkerAPIYARPCClient(clientConfig),\n\t\tapiv1.NewVisibilityAPIYARPCClient(clientConfig),\n\t )\n}\n'})}),"\n",(0,o.jsx)(n.p,{children:"Let's also build a logger to help us debug our application"}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-go",children:'func buildLogger() *zap.Logger {\n config := zap.NewDevelopmentConfig()\n config.Level.SetLevel(zapcore.InfoLevel)\n\n var err error\n logger, err := config.Build()\n if err != nil {\n panic("Failed to setup logger")\n }\n\n return logger\n}\n'})}),"\n",(0,o.jsx)(n.p,{children:"With both client and logger helper function ready, let's write the function that starts our worker."}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-go",children:'func startWorker(logger *zap.Logger, service workflowserviceclient.Interface) {\n // TaskListName identifies set of client workflows, activities, and workers.\n // It could be your group or client or application name.\n workerOptions := worker.Options{\n Logger: logger,\n MetricsScope: tally.NewTestScope(TaskListName, map[string]string{}),\n }\n\n worker := worker.New(\n service,\n Domain,\n TaskListName,\n workerOptions)\n err := worker.Start()\n if err != nil {\n panic("Failed to start worker")\n }\n\n logger.Info("Started Worker.", zap.String("worker", TaskListName))\n}\n'})}),"\n",(0,o.jsx)(n.p,{children:"Now we have all components ready for the worker, let's put them together."}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-Go",children:'import (\n "net/http"\n "go.uber.org/cadence/.gen/go/cadence/workflowserviceclient"\n "go.uber.org/cadence/compatibility"\n "go.uber.org/cadence/worker"\n\n apiv1 "github.com/cadence-workflow/cadence-idl/go/proto/api/v1"\n "github.com/uber-go/tally"\n "go.uber.org/zap"\n "go.uber.org/zap/zapcore"\n "go.uber.org/yarpc"\n "go.uber.org/yarpc/transport/grpc"\n)\n\nvar HostPort = "127.0.0.1:7933"\nvar Domain = "test-domain"\nvar TaskListName = "test-worker"\nvar ClientName = "test-worker"\nvar CadenceService = "cadence-frontend"\n\nfunc main() {\n startWorker(buildLogger(), buildCadenceClient())\n http.ListenAndServe(":3000", nil)\n}\n\nfunc buildLogger() *zap.Logger {\n config := zap.NewDevelopmentConfig()\n config.Level.SetLevel(zapcore.InfoLevel)\n\n var err error\n logger, err := config.Build()\n if err != nil {\n panic("Failed to setup logger")\n }\n\n return logger\n}\n\nfunc buildCadenceClient() workflowserviceclient.Interface {\n dispatcher := yarpc.NewDispatcher(yarpc.Config{\n\t\tName: ClientName,\n\t\tOutbounds: yarpc.Outbounds{\n\t\t CadenceService: {Unary: grpc.NewTransport().NewSingleOutbound(HostPort)},\n\t\t},\n\t })\n\t if err := dispatcher.Start(); err != nil {\n\t\tpanic("Failed to start dispatcher")\n\t }\n\n\t clientConfig := dispatcher.ClientConfig(CadenceService)\n\n\t return compatibility.NewThrift2ProtoAdapter(\n\t\tapiv1.NewDomainAPIYARPCClient(clientConfig),\n\t\tapiv1.NewWorkflowAPIYARPCClient(clientConfig),\n\t\tapiv1.NewWorkerAPIYARPCClient(clientConfig),\n\t\tapiv1.NewVisibilityAPIYARPCClient(clientConfig),\n\t )\n}\n\nfunc startWorker(logger *zap.Logger, service workflowserviceclient.Interface) {\n // TaskListName identifies set of client workflows, activities, and workers.\n // It could be your group or client or application name.\n workerOptions := worker.Options{\n Logger: logger,\n MetricsScope: tally.NewTestScope(TaskListName, map[string]string{}),\n }\n\n worker := worker.New(\n service,\n Domain,\n TaskListName,\n workerOptions)\n err := worker.Start()\n if err != nil {\n panic("Failed to start worker")\n }\n\n logger.Info("Started Worker.", zap.String("worker", TaskListName))\n}\n'})}),"\n",(0,o.jsx)(n.p,{children:"Open a new terminal and start this server, you should see logs like"}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-shell",children:'2023-07-03T11:46:46.266-0700 INFO internal/internal_worker.go:826 Worker has no workflows registered, so workflow worker will not be started. {"Domain": "test-domain", "TaskList": "test-worker", "WorkerID": "35987@uber-C02F18EQMD6R@test-worker@90c0260e-ba5c-4652-9f10-c6d1f9e29c1d"}\n2023-07-03T11:46:46.267-0700 INFO internal/internal_worker.go:834 Started Workflow Worker {"Domain": "test-domain", "TaskList": "test-worker", "WorkerID": "35987@uber-C02F18EQMD6R@test-worker@90c0260e-ba5c-4652-9f10-c6d1f9e29c1d"}\n2023-07-03T11:46:46.267-0700 INFO internal/internal_worker.go:838 Worker has no activities registered, so activity worker will not be started. {"Domain": "test-domain", "TaskList": "test-worker", "WorkerID": "35987@uber-C02F18EQMD6R@test-worker@90c0260e-ba5c-4652-9f10-c6d1f9e29c1d"}\n2023-07-03T11:46:46.267-0700 INFO cadence-worker/main.go:75 Started Worker. {"worker": "test-worker"}\n'})}),"\n",(0,o.jsx)(n.p,{children:"You may see these logs because your worker is successfully running but we haven't registered any workflows or activities to the worker. In the next tutorial, we will learn how to write a simple hello world workflow for your Cadence application."})]})}function p(e={}){const{wrapper:n}={...(0,i.R)(),...e.components};return n?(0,o.jsx)(n,{...e,children:(0,o.jsx)(d,{...e})}):d(e)}},8453:(e,n,t)=>{t.d(n,{R:()=>a,x:()=>c});var r=t(6540);const o={},i=r.createContext(o);function a(e){const n=r.useContext(i);return r.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function c(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:a(e.components),r.createElement(i.Provider,{value:n},e.children)}},3865:e=>{e.exports=JSON.parse('{"permalink":"/Cadence-Docs/blog/2023/07/05/implement-cadence-worker-from-scratch","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2023-07-05-implement-cadence-worker-from-scratch.md","source":"@site/blog/2023-07-05-implement-cadence-worker-from-scratch.md","title":"Implement a Cadence worker service from scratch","description":"In the previous blog, we have introduced three critical components for a Cadence application: the Cadence backend, domain, and worker. Among these, the worker service is the most crucial focus for developers as it hosts the activities and workflows of a Cadence application. In this blog, I will provide a short tutorial on how to implement a simple worker service from scratch in Go.","date":"2023-07-05T00:00:00.000Z","tags":[{"inline":false,"label":"Deep Dives","permalink":"/Cadence-Docs/blog/tags/deep-dives","description":"Deep Dives tag description"},{"inline":false,"label":"Introduction to Cadence","permalink":"/Cadence-Docs/blog/tags/introduction-to-cadence","description":"Introduction to Cadence tag description"}],"readingTime":3.69,"hasTruncateMarker":true,"authors":[{"name":"Chris Qin","title":"Applications Developer @ Uber","url":"https://www.linkedin.com/in/chrisqin0610/","page":{"permalink":"/Cadence-Docs/blog/authors/chopincode"},"socials":{"linkedin":"https://www.linkedin.com/in/chrisqin0610/","github":"https://github.com/chopincode"},"imageURL":"https://github.com/chopincode.png","key":"chopincode"}],"frontMatter":{"title":"Implement a Cadence worker service from scratch","date":"2023-07-05T00:00:00.000Z","authors":"chopincode","tags":["deep-dive","introduction-to-cadence"]},"unlisted":false,"prevItem":{"title":"Bad practices and Anti-patterns with Cadence (Part 1)","permalink":"/Cadence-Docs/blog/2023/07/10/cadence-bad-practices-part-1"},"nextItem":{"title":"Understanding components of Cadence application","permalink":"/Cadence-Docs/blog/2023/06/28/components-of-cadence-application-setup"}}')}}]); \ No newline at end of file diff --git a/assets/js/18ffe98c.de26ef7e.js b/assets/js/18ffe98c.de26ef7e.js deleted file mode 100644 index e3e0fb1c3..000000000 --- a/assets/js/18ffe98c.de26ef7e.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[4269],{5363:e=>{e.exports=JSON.parse('{"metadata":{"permalink":"/blog/page/3","page":3,"postsPerPage":10,"totalPages":4,"totalCount":35,"previousPage":"/blog/page/2","nextPage":"/blog/page/4","blogDescription":"The latest news and updates from the Cadence team","blogTitle":"Cadence Blog"}}')}}]); \ No newline at end of file diff --git a/assets/js/1c90ed0c.09b814ea.js b/assets/js/1c90ed0c.4a6c3b6a.js similarity index 51% rename from assets/js/1c90ed0c.09b814ea.js rename to assets/js/1c90ed0c.4a6c3b6a.js index 8aa4b48f5..1ee270a3d 100644 --- a/assets/js/1c90ed0c.09b814ea.js +++ b/assets/js/1c90ed0c.4a6c3b6a.js @@ -1 +1 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[4860],{6553:(e,t,o)=>{o.r(t),o.d(t,{assets:()=>r,contentTitle:()=>c,default:()=>d,frontMatter:()=>s,metadata:()=>n,toc:()=>l});var n=o(6109),a=o(4848),i=o(8453);const s={title:"Cadence Community Spotlight Update - May 2022",date:new Date("2022-05-31T00:00:00.000Z"),authors:"sharanf",tags:["community-spotlight"]},c=void 0,r={authorsImageUrls:[void 0]},l=[{value:"Cadence Polling Cookbook",id:"cadence-polling-cookbook",level:2}];function h(e){const t={a:"a",em:"em",h2:"h2",p:"p",...(0,i.R)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(t.p,{children:"Welcome to our regular Cadence Community Spotlight update!"}),"\n",(0,a.jsx)(t.p,{children:"This is our monthly blog post series focused on news from in and around the Cadence community."}),"\n",(0,a.jsx)(t.p,{children:"Please see below for a short activity roundup of what has happened recently in the community."}),"\n",(0,a.jsx)(t.h2,{id:"cadence-polling-cookbook",children:"Cadence Polling Cookbook"}),"\n",(0,a.jsxs)(t.p,{children:["Do you want to understand polling work and have an example of how to set it up in Cadence? Well a brand new ",(0,a.jsx)(t.a,{href:"https://info.instaclustr.com/rs/620-JHM-287/images/Cadence_Cookbook.pdf",children:"Cadence Polling cookbook"})," is now available that gives you all the details you need. The cookbook was created by several members of the ",(0,a.jsx)(t.a,{href:"https://www.instaclustr.com/",children:"Instaclustr"})," team and they are keen to share it with the community. The pdf version of the cookbook can found on the Cadence website under the ",(0,a.jsx)(t.em,{children:"Polling an external API for a specific resource to become available"})," section of the ",(0,a.jsx)(t.a,{href:"https://cadenceworkflow.io/docs/use-cases/polling/",children:"Polling Use cases"}),"."]}),"\n",(0,a.jsxs)(t.p,{children:["A ",(0,a.jsx)(t.a,{href:"https://github.com/instaclustr/cadence-cookbooks-instafood",children:"Github repository"})," has also been created with the sample cookbook code for you to try out for yourself."]}),"\n",(0,a.jsx)(t.p,{children:"So please go ahead and try out the cookbook and don\u2019t forget to let us have your feedback."})]})}function d(e={}){const{wrapper:t}={...(0,i.R)(),...e.components};return t?(0,a.jsx)(t,{...e,children:(0,a.jsx)(h,{...e})}):h(e)}},8453:(e,t,o)=>{o.d(t,{R:()=>s,x:()=>c});var n=o(6540);const a={},i=n.createContext(a);function s(e){const t=n.useContext(i);return n.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function c(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:s(e.components),n.createElement(i.Provider,{value:t},e.children)}},6109:e=>{e.exports=JSON.parse('{"permalink":"/blog/2022/05/31/community-spotlight-update-may-2022","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2022-05-31-community-spotlight-update-may-2022.md","source":"@site/blog/2022-05-31-community-spotlight-update-may-2022.md","title":"Cadence Community Spotlight Update - May 2022","description":"Welcome to our regular Cadence Community Spotlight update!","date":"2022-05-31T00:00:00.000Z","tags":[{"inline":false,"label":"Community Spotlight","permalink":"/blog/tags/community-spotlights","description":"Community Spotlight tag description"}],"readingTime":2.905,"hasTruncateMarker":true,"authors":[{"name":"Sharan Foga","title":"Director of Operations & Customer Success @ Encube Technologies","url":"https://www.linkedin.com/in/sfoga/","page":{"permalink":"/blog/authors/sharanf"},"socials":{"linkedin":"https://www.linkedin.com/in/sfoga/","github":"https://github.com/sharanf"},"imageURL":"https://github.com/sharanf.png","key":"sharanf"}],"frontMatter":{"title":"Cadence Community Spotlight Update - May 2022","date":"2022-05-31T00:00:00.000Z","authors":"sharanf","tags":["community-spotlight"]},"unlisted":false,"prevItem":{"title":"Cadence Community Spotlight Update - June 2022","permalink":"/blog/2022/06/30/community-spotlight-update-june-2022"},"nextItem":{"title":"Cadence Community Spotlight Update - April 2022","permalink":"/blog/2022/04/30/community-spotlight-update-april-2022"}}')}}]); \ No newline at end of file +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[4860],{6553:(e,t,o)=>{o.r(t),o.d(t,{assets:()=>r,contentTitle:()=>c,default:()=>h,frontMatter:()=>i,metadata:()=>n,toc:()=>l});var n=o(6109),a=o(4848),s=o(8453);const i={title:"Cadence Community Spotlight Update - May 2022",date:new Date("2022-05-31T00:00:00.000Z"),authors:"sharanf",tags:["community-spotlight"]},c=void 0,r={authorsImageUrls:[void 0]},l=[{value:"Cadence Polling Cookbook",id:"cadence-polling-cookbook",level:2}];function d(e){const t={a:"a",em:"em",h2:"h2",p:"p",...(0,s.R)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(t.p,{children:"Welcome to our regular Cadence Community Spotlight update!"}),"\n",(0,a.jsx)(t.p,{children:"This is our monthly blog post series focused on news from in and around the Cadence community."}),"\n",(0,a.jsx)(t.p,{children:"Please see below for a short activity roundup of what has happened recently in the community."}),"\n",(0,a.jsx)(t.h2,{id:"cadence-polling-cookbook",children:"Cadence Polling Cookbook"}),"\n",(0,a.jsxs)(t.p,{children:["Do you want to understand polling work and have an example of how to set it up in Cadence? Well a brand new ",(0,a.jsx)(t.a,{href:"https://info.instaclustr.com/rs/620-JHM-287/images/Cadence_Cookbook.pdf",children:"Cadence Polling cookbook"})," is now available that gives you all the details you need. The cookbook was created by several members of the ",(0,a.jsx)(t.a,{href:"https://www.instaclustr.com/",children:"Instaclustr"})," team and they are keen to share it with the community. The pdf version of the cookbook can found on the Cadence website under the ",(0,a.jsx)(t.em,{children:"Polling an external API for a specific resource to become available"})," section of the ",(0,a.jsx)(t.a,{href:"https://cadenceworkflow.io/docs/use-cases/polling/",children:"Polling Use cases"}),"."]}),"\n",(0,a.jsxs)(t.p,{children:["A ",(0,a.jsx)(t.a,{href:"https://github.com/instaclustr/cadence-cookbooks-instafood",children:"Github repository"})," has also been created with the sample cookbook code for you to try out for yourself."]}),"\n",(0,a.jsx)(t.p,{children:"So please go ahead and try out the cookbook and don\u2019t forget to let us have your feedback."})]})}function h(e={}){const{wrapper:t}={...(0,s.R)(),...e.components};return t?(0,a.jsx)(t,{...e,children:(0,a.jsx)(d,{...e})}):d(e)}},8453:(e,t,o)=>{o.d(t,{R:()=>i,x:()=>c});var n=o(6540);const a={},s=n.createContext(a);function i(e){const t=n.useContext(s);return n.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function c(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:i(e.components),n.createElement(s.Provider,{value:t},e.children)}},6109:e=>{e.exports=JSON.parse('{"permalink":"/Cadence-Docs/blog/2022/05/31/community-spotlight-update-may-2022","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2022-05-31-community-spotlight-update-may-2022.md","source":"@site/blog/2022-05-31-community-spotlight-update-may-2022.md","title":"Cadence Community Spotlight Update - May 2022","description":"Welcome to our regular Cadence Community Spotlight update!","date":"2022-05-31T00:00:00.000Z","tags":[{"inline":false,"label":"Community Spotlight","permalink":"/Cadence-Docs/blog/tags/community-spotlights","description":"Community Spotlight tag description"}],"readingTime":2.905,"hasTruncateMarker":true,"authors":[{"name":"Sharan Foga","title":"Director of Operations & Customer Success @ Encube Technologies","url":"https://www.linkedin.com/in/sfoga/","page":{"permalink":"/Cadence-Docs/blog/authors/sharanf"},"socials":{"linkedin":"https://www.linkedin.com/in/sfoga/","github":"https://github.com/sharanf"},"imageURL":"https://github.com/sharanf.png","key":"sharanf"}],"frontMatter":{"title":"Cadence Community Spotlight Update - May 2022","date":"2022-05-31T00:00:00.000Z","authors":"sharanf","tags":["community-spotlight"]},"unlisted":false,"prevItem":{"title":"Cadence Community Spotlight Update - June 2022","permalink":"/Cadence-Docs/blog/2022/06/30/community-spotlight-update-june-2022"},"nextItem":{"title":"Cadence Community Spotlight Update - April 2022","permalink":"/Cadence-Docs/blog/2022/04/30/community-spotlight-update-april-2022"}}')}}]); \ No newline at end of file diff --git a/assets/js/1dec29fa.27d7aff3.js b/assets/js/1dec29fa.27d7aff3.js new file mode 100644 index 000000000..ccb55cdc5 --- /dev/null +++ b/assets/js/1dec29fa.27d7aff3.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[9612],{3209:(e,t,i)=>{i.r(t),i.d(t,{assets:()=>c,contentTitle:()=>s,default:()=>d,frontMatter:()=>a,metadata:()=>o,toc:()=>l});const o=JSON.parse('{"id":"workflow-troubleshooting/timeouts","title":"Timeouts","description":"A workflow could fail if an activity times out and will timeout when the entire workflow execution times out. Workflows or activities time out when their time to execute or time to start has been longer than their configured timeout. Some of the common causes for timeouts have been listed here.","source":"@site/docs/08-workflow-troubleshooting/01-timeouts.md","sourceDirName":"08-workflow-troubleshooting","slug":"/workflow-troubleshooting/timeouts","permalink":"/Cadence-Docs/docs/workflow-troubleshooting/timeouts","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/08-workflow-troubleshooting/01-timeouts.md","tags":[],"version":"current","sidebarPosition":1,"frontMatter":{"layout":"default","title":"Timeouts","permalink":"/docs/workflow-troubleshooting/timeouts"},"sidebar":"docsSidebar","previous":{"title":"Overview","permalink":"/Cadence-Docs/docs/workflow-troubleshooting/"},"next":{"title":"Activity Failures","permalink":"/Cadence-Docs/docs/workflow-troubleshooting/activity-failures"}}');var r=i(4848),n=i(8453);const a={layout:"default",title:"Timeouts",permalink:"/docs/workflow-troubleshooting/timeouts"},s="Timeouts",c={},l=[{value:"Missing Pollers",id:"missing-pollers",level:2},{value:"Tasklist backlog despite having pollers",id:"tasklist-backlog-despite-having-pollers",level:2},{value:"No heartbeat timeout or retry policy configured",id:"no-heartbeat-timeout-or-retry-policy-configured",level:2},{value:"Retry policy configured without setting heartbeat timeout",id:"retry-policy-configured-without-setting-heartbeat-timeout",level:2},{value:"Heartbeat timeout configured without a retry policy",id:"heartbeat-timeout-configured-without-a-retry-policy",level:2},{value:"Heartbeat timeout seen after configuring heartbeat timeout",id:"heartbeat-timeout-seen-after-configuring-heartbeat-timeout",level:2}];function h(e){const t={a:"a",h1:"h1",h2:"h2",header:"header",p:"p",...(0,n.R)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(t.header,{children:(0,r.jsx)(t.h1,{id:"timeouts",children:"Timeouts"})}),"\n",(0,r.jsx)(t.p,{children:"A workflow could fail if an activity times out and will timeout when the entire workflow execution times out. Workflows or activities time out when their time to execute or time to start has been longer than their configured timeout. Some of the common causes for timeouts have been listed here."}),"\n",(0,r.jsx)(t.h2,{id:"missing-pollers",children:"Missing Pollers"}),"\n",(0,r.jsx)(t.p,{children:"Cadence workers are part of the service that hosts and executes the workflow. They are of two types: activity worker and workflow worker. Each of these workers are responsible for having pollers which are go-routines that poll for activity tasks and decision tasks respectively from the Cadence server. Without pollers, the workflow cannot proceed with the execution."}),"\n",(0,r.jsx)(t.p,{children:"Mitigation: Make sure these workers are configured with the task lists that are used in the workflow and activities so the server can dispatch tasks to the cadence workers."}),"\n",(0,r.jsx)(t.p,{children:(0,r.jsx)(t.a,{href:"https://github.com/cadence-workflow/cadence-samples/blob/master/cmd/samples/pageflow/main.go#L18",children:"Worker setup example"})}),"\n",(0,r.jsx)(t.h2,{id:"tasklist-backlog-despite-having-pollers",children:"Tasklist backlog despite having pollers"}),"\n",(0,r.jsx)(t.p,{children:"If a tasklist has pollers but the backlog continues to grow then it is a supply-demand issue. The workflow is growing faster than what the workers can handle. The server wants to dispatch more tasks to the workers but they are not able to keep up."}),"\n",(0,r.jsx)(t.p,{children:"Mitigation: Increase the number of cadence workers by horizontally scaling up the instances where the workflow is running."}),"\n",(0,r.jsx)(t.p,{children:"Optionally you can also increase the number of pollers per worker by providing this via worker options."}),"\n",(0,r.jsxs)(t.p,{children:[(0,r.jsx)(t.a,{href:"https://pkg.go.dev/go.uber.org/cadence@v1.2.9/internal#WorkerOptions",children:"Link to options in go client"}),"\n",(0,r.jsx)(t.a,{href:"https://github.com/cadence-workflow/cadence-java-client/blob/master/src/main/java/com/uber/cadence/internal/worker/PollerOptions.java#L124",children:"Link to options in java client"})]}),"\n",(0,r.jsx)(t.h2,{id:"no-heartbeat-timeout-or-retry-policy-configured",children:"No heartbeat timeout or retry policy configured"}),"\n",(0,r.jsx)(t.p,{children:"Activities time out StartToClose or ScheduleToClose if the activity took longer than the configured timeout."}),"\n",(0,r.jsx)(t.p,{children:(0,r.jsx)(t.a,{href:"https://cadenceworkflow.io/docs/concepts/activities/#timeouts",children:"Link to description of timeouts"})}),"\n",(0,r.jsx)(t.p,{children:"For long running activities, while the activity is executing, the worker can die due to regular deployments or host restarts or failures. Cadence doesn't know about this and will wait for StartToClose or ScheduleToClose timeouts to kick in."}),"\n",(0,r.jsx)(t.p,{children:"Mitigation: Consider configuring heartbeat timeout and a retry policy"}),"\n",(0,r.jsxs)(t.p,{children:[(0,r.jsx)(t.a,{href:"https://github.com/cadence-workflow/cadence-samples/blob/df6f7bdba978d6565ad78e9f86d9cd31dfac9f78/cmd/samples/expense/workflow.go#L23",children:"Example"}),"\n",(0,r.jsx)(t.a,{href:"https://cadenceworkflow.io/docs/concepts/activities/#retries",children:"Check retry policy for activity"})]}),"\n",(0,r.jsx)(t.p,{children:"For short running activities, heart beating is not required but maybe consider increasing the timeout value to suit the actual activity execution time."}),"\n",(0,r.jsx)(t.h2,{id:"retry-policy-configured-without-setting-heartbeat-timeout",children:"Retry policy configured without setting heartbeat timeout"}),"\n",(0,r.jsx)(t.p,{children:"Retry policies are configured so activities can be retried after timeouts or failures. For long-running activities, the worker can die while the activity is executing, e.g. due to regular deployments or host restarts or failures. Cadence doesn't know about this and will wait for StartToClose or ScheduleToClose timeouts to kick in. The retry is attempted only after this timeout. Configuring heartbeat timeout would cause the activity to timeout earlier so it can be retried on another worker."}),"\n",(0,r.jsx)(t.p,{children:"Mitigation: Consider configuring heartbeat timeout"}),"\n",(0,r.jsx)(t.p,{children:(0,r.jsx)(t.a,{href:"https://github.com/cadence-workflow/cadence-samples/blob/df6f7bdba978d6565ad78e9f86d9cd31dfac9f78/cmd/samples/expense/workflow.go#L23",children:"Example"})}),"\n",(0,r.jsx)(t.h2,{id:"heartbeat-timeout-configured-without-a-retry-policy",children:"Heartbeat timeout configured without a retry policy"}),"\n",(0,r.jsx)(t.p,{children:"Heartbeat timeouts are used to detect when a worker died or restarted. With heartbeat timeout configured, the activity will timeout faster. But without a retry policy, it will not be scheduled again on a healthy worker."}),"\n",(0,r.jsx)(t.p,{children:"Mitigation: Consider adding retry policy to an activity"}),"\n",(0,r.jsx)(t.p,{children:(0,r.jsx)(t.a,{href:"https://cadenceworkflow.io/docs/concepts/activities/#retries",children:"Check retry policy for activity"})}),"\n",(0,r.jsx)(t.h2,{id:"heartbeat-timeout-seen-after-configuring-heartbeat-timeout",children:"Heartbeat timeout seen after configuring heartbeat timeout"}),"\n",(0,r.jsx)(t.p,{children:"Activity has configured heartbeat timeout and the activity timed out with heart beat timeout. This is because the server did not receive a heart beat in the time interval configured as the heart beat timeout. This could happen if the activity is actually not executing or the activity is not sending periodic heartbeats. The first case is good since the activity now times out instead of being stuck until startToClose or scheduleToClose kicks in. The second case needs a fix."}),"\n",(0,r.jsx)(t.p,{children:"Mitigation: Once heartbeat timeout is configured in activity options, you need to make sure the activity periodically sends a heart beat to the server to make sure the server is aware of the activity being alive."}),"\n",(0,r.jsx)(t.p,{children:(0,r.jsx)(t.a,{href:"https://github.com/cadence-workflow/cadence-samples/blob/df6f7bdba978d6565ad78e9f86d9cd31dfac9f78/cmd/samples/fileprocessing/activities.go#L111",children:"Example to send periodic heart beat"})}),"\n",(0,r.jsx)(t.p,{children:"In go client, there is an option to register the activity with auto heart beating so that it is done automatically"}),"\n",(0,r.jsx)(t.p,{children:(0,r.jsx)(t.a,{href:"https://pkg.go.dev/go.uber.org/cadence@v1.2.9/internal#WorkerOptions",children:"Configuring auto heart beat during activity registration example"})})]})}function d(e={}){const{wrapper:t}={...(0,n.R)(),...e.components};return t?(0,r.jsx)(t,{...e,children:(0,r.jsx)(h,{...e})}):h(e)}},8453:(e,t,i)=>{i.d(t,{R:()=>a,x:()=>s});var o=i(6540);const r={},n=o.createContext(r);function a(e){const t=o.useContext(n);return o.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function s(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:a(e.components),o.createElement(n.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/1dec29fa.c54d4098.js b/assets/js/1dec29fa.c54d4098.js deleted file mode 100644 index 878ba50c5..000000000 --- a/assets/js/1dec29fa.c54d4098.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[9612],{3209:(e,t,i)=>{i.r(t),i.d(t,{assets:()=>c,contentTitle:()=>s,default:()=>d,frontMatter:()=>a,metadata:()=>o,toc:()=>l});const o=JSON.parse('{"id":"workflow-troubleshooting/timeouts","title":"Timeouts","description":"A workflow could fail if an activity times out and will timeout when the entire workflow execution times out. Workflows or activities time out when their time to execute or time to start has been longer than their configured timeout. Some of the common causes for timeouts have been listed here.","source":"@site/docs/08-workflow-troubleshooting/01-timeouts.md","sourceDirName":"08-workflow-troubleshooting","slug":"/workflow-troubleshooting/timeouts","permalink":"/docs/workflow-troubleshooting/timeouts","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/08-workflow-troubleshooting/01-timeouts.md","tags":[],"version":"current","sidebarPosition":1,"frontMatter":{"layout":"default","title":"Timeouts","permalink":"/docs/workflow-troubleshooting/timeouts"},"sidebar":"docsSidebar","previous":{"title":"Overview","permalink":"/docs/workflow-troubleshooting/"},"next":{"title":"Activity Failures","permalink":"/docs/workflow-troubleshooting/activity-failures"}}');var r=i(4848),n=i(8453);const a={layout:"default",title:"Timeouts",permalink:"/docs/workflow-troubleshooting/timeouts"},s="Timeouts",c={},l=[{value:"Missing Pollers",id:"missing-pollers",level:2},{value:"Tasklist backlog despite having pollers",id:"tasklist-backlog-despite-having-pollers",level:2},{value:"No heartbeat timeout or retry policy configured",id:"no-heartbeat-timeout-or-retry-policy-configured",level:2},{value:"Retry policy configured without setting heartbeat timeout",id:"retry-policy-configured-without-setting-heartbeat-timeout",level:2},{value:"Heartbeat timeout configured without a retry policy",id:"heartbeat-timeout-configured-without-a-retry-policy",level:2},{value:"Heartbeat timeout seen after configuring heartbeat timeout",id:"heartbeat-timeout-seen-after-configuring-heartbeat-timeout",level:2}];function h(e){const t={a:"a",h1:"h1",h2:"h2",header:"header",p:"p",...(0,n.R)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(t.header,{children:(0,r.jsx)(t.h1,{id:"timeouts",children:"Timeouts"})}),"\n",(0,r.jsx)(t.p,{children:"A workflow could fail if an activity times out and will timeout when the entire workflow execution times out. Workflows or activities time out when their time to execute or time to start has been longer than their configured timeout. Some of the common causes for timeouts have been listed here."}),"\n",(0,r.jsx)(t.h2,{id:"missing-pollers",children:"Missing Pollers"}),"\n",(0,r.jsx)(t.p,{children:"Cadence workers are part of the service that hosts and executes the workflow. They are of two types: activity worker and workflow worker. Each of these workers are responsible for having pollers which are go-routines that poll for activity tasks and decision tasks respectively from the Cadence server. Without pollers, the workflow cannot proceed with the execution."}),"\n",(0,r.jsx)(t.p,{children:"Mitigation: Make sure these workers are configured with the task lists that are used in the workflow and activities so the server can dispatch tasks to the cadence workers."}),"\n",(0,r.jsx)(t.p,{children:(0,r.jsx)(t.a,{href:"https://github.com/cadence-workflow/cadence-samples/blob/master/cmd/samples/pageflow/main.go#L18",children:"Worker setup example"})}),"\n",(0,r.jsx)(t.h2,{id:"tasklist-backlog-despite-having-pollers",children:"Tasklist backlog despite having pollers"}),"\n",(0,r.jsx)(t.p,{children:"If a tasklist has pollers but the backlog continues to grow then it is a supply-demand issue. The workflow is growing faster than what the workers can handle. The server wants to dispatch more tasks to the workers but they are not able to keep up."}),"\n",(0,r.jsx)(t.p,{children:"Mitigation: Increase the number of cadence workers by horizontally scaling up the instances where the workflow is running."}),"\n",(0,r.jsx)(t.p,{children:"Optionally you can also increase the number of pollers per worker by providing this via worker options."}),"\n",(0,r.jsxs)(t.p,{children:[(0,r.jsx)(t.a,{href:"https://pkg.go.dev/go.uber.org/cadence@v1.2.9/internal#WorkerOptions",children:"Link to options in go client"}),"\n",(0,r.jsx)(t.a,{href:"https://github.com/cadence-workflow/cadence-java-client/blob/master/src/main/java/com/uber/cadence/internal/worker/PollerOptions.java#L124",children:"Link to options in java client"})]}),"\n",(0,r.jsx)(t.h2,{id:"no-heartbeat-timeout-or-retry-policy-configured",children:"No heartbeat timeout or retry policy configured"}),"\n",(0,r.jsx)(t.p,{children:"Activities time out StartToClose or ScheduleToClose if the activity took longer than the configured timeout."}),"\n",(0,r.jsx)(t.p,{children:(0,r.jsx)(t.a,{href:"https://cadenceworkflow.io/docs/concepts/activities/#timeouts",children:"Link to description of timeouts"})}),"\n",(0,r.jsx)(t.p,{children:"For long running activities, while the activity is executing, the worker can die due to regular deployments or host restarts or failures. Cadence doesn't know about this and will wait for StartToClose or ScheduleToClose timeouts to kick in."}),"\n",(0,r.jsx)(t.p,{children:"Mitigation: Consider configuring heartbeat timeout and a retry policy"}),"\n",(0,r.jsxs)(t.p,{children:[(0,r.jsx)(t.a,{href:"https://github.com/cadence-workflow/cadence-samples/blob/df6f7bdba978d6565ad78e9f86d9cd31dfac9f78/cmd/samples/expense/workflow.go#L23",children:"Example"}),"\n",(0,r.jsx)(t.a,{href:"https://cadenceworkflow.io/docs/concepts/activities/#retries",children:"Check retry policy for activity"})]}),"\n",(0,r.jsx)(t.p,{children:"For short running activities, heart beating is not required but maybe consider increasing the timeout value to suit the actual activity execution time."}),"\n",(0,r.jsx)(t.h2,{id:"retry-policy-configured-without-setting-heartbeat-timeout",children:"Retry policy configured without setting heartbeat timeout"}),"\n",(0,r.jsx)(t.p,{children:"Retry policies are configured so activities can be retried after timeouts or failures. For long-running activities, the worker can die while the activity is executing, e.g. due to regular deployments or host restarts or failures. Cadence doesn't know about this and will wait for StartToClose or ScheduleToClose timeouts to kick in. The retry is attempted only after this timeout. Configuring heartbeat timeout would cause the activity to timeout earlier so it can be retried on another worker."}),"\n",(0,r.jsx)(t.p,{children:"Mitigation: Consider configuring heartbeat timeout"}),"\n",(0,r.jsx)(t.p,{children:(0,r.jsx)(t.a,{href:"https://github.com/cadence-workflow/cadence-samples/blob/df6f7bdba978d6565ad78e9f86d9cd31dfac9f78/cmd/samples/expense/workflow.go#L23",children:"Example"})}),"\n",(0,r.jsx)(t.h2,{id:"heartbeat-timeout-configured-without-a-retry-policy",children:"Heartbeat timeout configured without a retry policy"}),"\n",(0,r.jsx)(t.p,{children:"Heartbeat timeouts are used to detect when a worker died or restarted. With heartbeat timeout configured, the activity will timeout faster. But without a retry policy, it will not be scheduled again on a healthy worker."}),"\n",(0,r.jsx)(t.p,{children:"Mitigation: Consider adding retry policy to an activity"}),"\n",(0,r.jsx)(t.p,{children:(0,r.jsx)(t.a,{href:"https://cadenceworkflow.io/docs/concepts/activities/#retries",children:"Check retry policy for activity"})}),"\n",(0,r.jsx)(t.h2,{id:"heartbeat-timeout-seen-after-configuring-heartbeat-timeout",children:"Heartbeat timeout seen after configuring heartbeat timeout"}),"\n",(0,r.jsx)(t.p,{children:"Activity has configured heartbeat timeout and the activity timed out with heart beat timeout. This is because the server did not receive a heart beat in the time interval configured as the heart beat timeout. This could happen if the activity is actually not executing or the activity is not sending periodic heartbeats. The first case is good since the activity now times out instead of being stuck until startToClose or scheduleToClose kicks in. The second case needs a fix."}),"\n",(0,r.jsx)(t.p,{children:"Mitigation: Once heartbeat timeout is configured in activity options, you need to make sure the activity periodically sends a heart beat to the server to make sure the server is aware of the activity being alive."}),"\n",(0,r.jsx)(t.p,{children:(0,r.jsx)(t.a,{href:"https://github.com/cadence-workflow/cadence-samples/blob/df6f7bdba978d6565ad78e9f86d9cd31dfac9f78/cmd/samples/fileprocessing/activities.go#L111",children:"Example to send periodic heart beat"})}),"\n",(0,r.jsx)(t.p,{children:"In go client, there is an option to register the activity with auto heart beating so that it is done automatically"}),"\n",(0,r.jsx)(t.p,{children:(0,r.jsx)(t.a,{href:"https://pkg.go.dev/go.uber.org/cadence@v1.2.9/internal#WorkerOptions",children:"Configuring auto heart beat during activity registration example"})})]})}function d(e={}){const{wrapper:t}={...(0,n.R)(),...e.components};return t?(0,r.jsx)(t,{...e,children:(0,r.jsx)(h,{...e})}):h(e)}},8453:(e,t,i)=>{i.d(t,{R:()=>a,x:()=>s});var o=i(6540);const r={},n=o.createContext(r);function a(e){const t=o.useContext(n);return o.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function s(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:a(e.components),o.createElement(n.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/20139c40.44ed83b8.js b/assets/js/20139c40.44ed83b8.js deleted file mode 100644 index cecd811dd..000000000 --- a/assets/js/20139c40.44ed83b8.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[9369],{8281:(t,n,e)=>{e.r(n),e.d(n,{assets:()=>d,contentTitle:()=>a,default:()=>p,frontMatter:()=>u,metadata:()=>r,toc:()=>l});const r=JSON.parse('{"id":"contributing","title":"Contributing","description":"","source":"@site/community/3-contributing.mdx","sourceDirName":".","slug":"/contributing","permalink":"/community/contributing","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/edit/master/community/3-contributing.mdx","tags":[],"version":"current","lastUpdatedBy":"Josue Ibarra","lastUpdatedAt":1733775428000,"sidebarPosition":3,"frontMatter":{"title":"Contributing","hide_title":true,"sidebar_label":"Contributing"}}');var i=e(4848),o=e(8453);function c(t){return(0,i.jsx)(i.Fragment,{})}function s(t={}){const{wrapper:n}={...(0,o.R)(),...t.components};return n?(0,i.jsx)(n,{...t,children:(0,i.jsx)(c,{...t})}):c()}const u={title:"Contributing",hide_title:!0,sidebar_label:"Contributing"},a=void 0,d={},l=[];function m(t){return(0,i.jsx)(s,{})}function p(t={}){const{wrapper:n}={...(0,o.R)(),...t.components};return n?(0,i.jsx)(n,{...t,children:(0,i.jsx)(m,{...t})}):m()}},8453:(t,n,e)=>{e.d(n,{R:()=>c,x:()=>s});var r=e(6540);const i={},o=r.createContext(i);function c(t){const n=r.useContext(o);return r.useMemo((function(){return"function"==typeof t?t(n):{...n,...t}}),[n,t])}function s(t){let n;return n=t.disableParentContext?"function"==typeof t.components?t.components(i):t.components||i:c(t.components),r.createElement(o.Provider,{value:n},t.children)}}}]); \ No newline at end of file diff --git a/assets/js/20139c40.4fc9927f.js b/assets/js/20139c40.4fc9927f.js new file mode 100644 index 000000000..0b0bbd3bf --- /dev/null +++ b/assets/js/20139c40.4fc9927f.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[9369],{8281:(t,n,e)=>{e.r(n),e.d(n,{assets:()=>d,contentTitle:()=>a,default:()=>p,frontMatter:()=>u,metadata:()=>o,toc:()=>l});const o=JSON.parse('{"id":"contributing","title":"Contributing","description":"","source":"@site/community/3-contributing.mdx","sourceDirName":".","slug":"/contributing","permalink":"/Cadence-Docs/community/contributing","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/edit/master/community/3-contributing.mdx","tags":[],"version":"current","lastUpdatedBy":"Josue Ibarra","lastUpdatedAt":1733775428000,"sidebarPosition":3,"frontMatter":{"title":"Contributing","hide_title":true,"sidebar_label":"Contributing"}}');var r=e(4848),i=e(8453);function c(t){return(0,r.jsx)(r.Fragment,{})}function s(t={}){const{wrapper:n}={...(0,i.R)(),...t.components};return n?(0,r.jsx)(n,{...t,children:(0,r.jsx)(c,{...t})}):c()}const u={title:"Contributing",hide_title:!0,sidebar_label:"Contributing"},a=void 0,d={},l=[];function m(t){return(0,r.jsx)(s,{})}function p(t={}){const{wrapper:n}={...(0,i.R)(),...t.components};return n?(0,r.jsx)(n,{...t,children:(0,r.jsx)(m,{...t})}):m()}},8453:(t,n,e)=>{e.d(n,{R:()=>c,x:()=>s});var o=e(6540);const r={},i=o.createContext(r);function c(t){const n=o.useContext(i);return o.useMemo((function(){return"function"==typeof t?t(n):{...n,...t}}),[n,t])}function s(t){let n;return n=t.disableParentContext?"function"==typeof t.components?t.components(r):t.components||r:c(t.components),o.createElement(i.Provider,{value:n},t.children)}}}]); \ No newline at end of file diff --git a/assets/js/23beb9a4.148a9a8e.js b/assets/js/23beb9a4.148a9a8e.js new file mode 100644 index 000000000..dc258e2eb --- /dev/null +++ b/assets/js/23beb9a4.148a9a8e.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[2093],{2074:t=>{t.exports=JSON.parse('{"author":{"name":"Kevin Corbett","title":"Open Source Community Manager | @instaclustr @NetApp","url":"https://github.com/kcorbett-netapp","page":{"permalink":"/Cadence-Docs/blog/authors/kcorbett-netapp"},"socials":{"linkedin":"https://www.linkedin.com/in/kcorb95/","github":"https://github.com/kcorbett-netapp"},"imageURL":"https://github.com/kcorbett-netapp.png","key":"kcorbett-netapp","count":1},"listMetadata":{"permalink":"/Cadence-Docs/blog/authors/kcorbett-netapp","page":1,"postsPerPage":10,"totalPages":1,"totalCount":1,"blogDescription":"The latest news and updates from the Cadence team","blogTitle":"Cadence Blog"}}')}}]); \ No newline at end of file diff --git a/assets/js/278bd730.87fa8dfd.js b/assets/js/278bd730.81ac964c.js similarity index 79% rename from assets/js/278bd730.87fa8dfd.js rename to assets/js/278bd730.81ac964c.js index 2b8723927..fb4bdd382 100644 --- a/assets/js/278bd730.87fa8dfd.js +++ b/assets/js/278bd730.81ac964c.js @@ -1 +1 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[1198],{9328:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>c,contentTitle:()=>i,default:()=>h,frontMatter:()=>s,metadata:()=>o,toc:()=>l});var o=t(5432),a=t(4848),r=t(8453);const s={title:"Long-term commitment and support for the Cadence project, and its community",date:new Date("2021-09-30T00:00:00.000Z"),authors:"meiliang86",tags:["announcement"]},i=void 0,c={authorsImageUrls:[void 0]},l=[];function d(e){const n={a:"a",p:"p",strong:"strong",...(0,r.R)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(n.p,{children:"Dear valued Cadence users and developers,"}),"\n",(0,a.jsx)(n.p,{children:"Some of you might have read Temporal\u2019s recent announcement about their decision to drop the support for the Cadence project. This message caused some confusion in the community, so we would like to take this opportunity to clear things out."}),"\n",(0,a.jsxs)(n.p,{children:["First of all, ",(0,a.jsx)(n.strong,{children:"Uber is committed to the long-term success of the Cadence project"}),". Since its inception 5 years ago, use cases built on Cadence and their scale have grown significantly at Uber. Today, Cadence powers a variety of our most business-critical use cases (some public stories are available ",(0,a.jsx)(n.a,{href:"https://eng.uber.com/hadoop-container-blog/",children:"here"})," and ",(0,a.jsx)(n.a,{href:"https://eng.uber.com/meet-sao-paulo-tech/",children:"here"}),"). At the same time, the Cadence development team at Uber has enjoyed rapid growth with the product and has been driving innovations of workflow technology across the board, from new features (e.g. ",(0,a.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence/pulls?q=is%3Apr+graceful+failover",children:"graceful failover"}),", ",(0,a.jsx)(n.a,{href:"https://cadenceworkflow.io/docs/java-client/workflow-replay-shadowing/#workflow-replayer",children:"workflow shadowing"}),", ",(0,a.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence-web/commits/master",children:"UI improvements"}),") to better engineering foundations (e.g. ",(0,a.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence/pulls?q=is%3Apr+grpc",children:"gRPC support"}),", ",(0,a.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence/pulls?q=is%3Apr+label%3A%22cadence+multi-tenancy%22+",children:"multi-tenancy support"}),"), all in a backwards compatible manner. Neither Uber\u2019s use nor support of Cadence is going to change with Temporal\u2019s announcement. We have a long list of features and exciting roadmaps ahead of us, and we will share more details in our next meetup in November \u201821. As always we will continue to push the boundaries of scale and reliability as our usage within Uber grows."]}),"\n",(0,a.jsxs)(n.p,{children:["Secondly, ",(0,a.jsx)(n.strong,{children:"we are committed to maintaining and growing a healthy and collaborative community"}),". Cadence continues to attract attention as a ",(0,a.jsx)(n.a,{href:"https://star-history.t9t.io/#cadence-workflow/cadence",children:"popular open source platform"}),", with more than 100 contributors to our project, and more than 1500 developers in our ",(0,a.jsx)(n.a,{href:"https://t.uber.com/cadence-slack",children:"open source Slack support channel"}),". The Uber Cadence team, along with our open source partners like ",(0,a.jsx)(n.a,{href:"https://www.linkedin.com/in/prclqz/",children:"Long"})," from Indeed, have been behind the management and support of the Cadence open source community for the past 2 years. Moving forward, we are going to work even more closely with our community, through a series of online and offline channels including meetups, office hours, tech deep dives, and design consultations. We would also like to scale the way we operate, by creating a ",(0,a.jsx)(n.strong,{children:"Cadence OSS Committee"})," that allows us to maintain a closer relationship with its members, so that we can learn from each other's Cadence experiences and grow together. Please definitely let us know your suggestions on the type of engagements that you would like to see with the core team."]}),"\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.strong,{children:"About Temporal and its \u201cEOL announcement\u201d"})}),"\n",(0,a.jsx)(n.p,{children:"Temporal is a startup that was started 2 years ago based on a Cadence fork by some of the original Cadence team members. We are always grateful for their original contribution to the Cadence project and wish them the best of luck in their future endeavours. That said the announcement from Temporal only means that their team will focus on Temporal (which has always been the case for the last 2 years), and not an official stance on Cadence since they have not been involved with the project for quite some time now."}),"\n",(0,a.jsxs)(n.p,{children:["Feel free to reach out to us (",(0,a.jsx)(n.a,{href:"mailto:cadence-oss@googlegroups.com",children:"cadence-oss@googlegroups.com"})," or ",(0,a.jsx)(n.a,{href:"http://t.uber.com/cadence-slack",children:"slack"}),") if you have any questions. And we look forward to your contribution and collaboration."]}),"\n",(0,a.jsx)(n.p,{children:"The Uber Cadence team"})]})}function h(e={}){const{wrapper:n}={...(0,r.R)(),...e.components};return n?(0,a.jsx)(n,{...e,children:(0,a.jsx)(d,{...e})}):d(e)}},8453:(e,n,t)=>{t.d(n,{R:()=>s,x:()=>i});var o=t(6540);const a={},r=o.createContext(a);function s(e){const n=o.useContext(r);return o.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function i(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:s(e.components),o.createElement(r.Provider,{value:n},e.children)}},5432:e=>{e.exports=JSON.parse('{"permalink":"/blog/2021/09/30/long-term-commitment-and-support-for-the-cadence-project-and-its-community","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2021-09-30-long-term-commitment-and-support-for-the-cadence-project-and-its-community.md","source":"@site/blog/2021-09-30-long-term-commitment-and-support-for-the-cadence-project-and-its-community.md","title":"Long-term commitment and support for the Cadence project, and its community","description":"Dear valued Cadence users and developers,","date":"2021-09-30T00:00:00.000Z","tags":[{"inline":false,"label":"Announcement","permalink":"/blog/tags/announcements","description":"Announcement tag description"}],"readingTime":2.545,"hasTruncateMarker":true,"authors":[{"name":"Liang Mei","title":"Engineering Manager @ Uber","url":"https://www.linkedin.com/in/meiliang86/","page":{"permalink":"/blog/authors/meiliang-86"},"socials":{"linkedin":"https://www.linkedin.com/in/meiliang86/","github":"https://github.com/meiliang86"},"imageURL":"https://github.com/meiliang86.png","key":"meiliang86"}],"frontMatter":{"title":"Long-term commitment and support for the Cadence project, and its community","date":"2021-09-30T00:00:00.000Z","authors":"meiliang86","tags":["announcement"]},"unlisted":false,"prevItem":{"title":"Announcing Cadence OSS office hours and community sync up","permalink":"/blog/2021/10/13/announcing-cadence-oss-office-hours-and-community-sync-up"}}')}}]); \ No newline at end of file +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[1198],{9328:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>c,contentTitle:()=>i,default:()=>h,frontMatter:()=>s,metadata:()=>o,toc:()=>l});var o=t(5432),a=t(4848),r=t(8453);const s={title:"Long-term commitment and support for the Cadence project, and its community",date:new Date("2021-09-30T00:00:00.000Z"),authors:"meiliang86",tags:["announcement"]},i=void 0,c={authorsImageUrls:[void 0]},l=[];function d(e){const n={a:"a",p:"p",strong:"strong",...(0,r.R)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(n.p,{children:"Dear valued Cadence users and developers,"}),"\n",(0,a.jsx)(n.p,{children:"Some of you might have read Temporal\u2019s recent announcement about their decision to drop the support for the Cadence project. This message caused some confusion in the community, so we would like to take this opportunity to clear things out."}),"\n",(0,a.jsxs)(n.p,{children:["First of all, ",(0,a.jsx)(n.strong,{children:"Uber is committed to the long-term success of the Cadence project"}),". Since its inception 5 years ago, use cases built on Cadence and their scale have grown significantly at Uber. Today, Cadence powers a variety of our most business-critical use cases (some public stories are available ",(0,a.jsx)(n.a,{href:"https://eng.uber.com/hadoop-container-blog/",children:"here"})," and ",(0,a.jsx)(n.a,{href:"https://eng.uber.com/meet-sao-paulo-tech/",children:"here"}),"). At the same time, the Cadence development team at Uber has enjoyed rapid growth with the product and has been driving innovations of workflow technology across the board, from new features (e.g. ",(0,a.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence/pulls?q=is%3Apr+graceful+failover",children:"graceful failover"}),", ",(0,a.jsx)(n.a,{href:"https://cadenceworkflow.io/docs/java-client/workflow-replay-shadowing/#workflow-replayer",children:"workflow shadowing"}),", ",(0,a.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence-web/commits/master",children:"UI improvements"}),") to better engineering foundations (e.g. ",(0,a.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence/pulls?q=is%3Apr+grpc",children:"gRPC support"}),", ",(0,a.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence/pulls?q=is%3Apr+label%3A%22cadence+multi-tenancy%22+",children:"multi-tenancy support"}),"), all in a backwards compatible manner. Neither Uber\u2019s use nor support of Cadence is going to change with Temporal\u2019s announcement. We have a long list of features and exciting roadmaps ahead of us, and we will share more details in our next meetup in November \u201821. As always we will continue to push the boundaries of scale and reliability as our usage within Uber grows."]}),"\n",(0,a.jsxs)(n.p,{children:["Secondly, ",(0,a.jsx)(n.strong,{children:"we are committed to maintaining and growing a healthy and collaborative community"}),". Cadence continues to attract attention as a ",(0,a.jsx)(n.a,{href:"https://star-history.t9t.io/#cadence-workflow/cadence",children:"popular open source platform"}),", with more than 100 contributors to our project, and more than 1500 developers in our ",(0,a.jsx)(n.a,{href:"https://t.uber.com/cadence-slack",children:"open source Slack support channel"}),". The Uber Cadence team, along with our open source partners like ",(0,a.jsx)(n.a,{href:"https://www.linkedin.com/in/prclqz/",children:"Long"})," from Indeed, have been behind the management and support of the Cadence open source community for the past 2 years. Moving forward, we are going to work even more closely with our community, through a series of online and offline channels including meetups, office hours, tech deep dives, and design consultations. We would also like to scale the way we operate, by creating a ",(0,a.jsx)(n.strong,{children:"Cadence OSS Committee"})," that allows us to maintain a closer relationship with its members, so that we can learn from each other's Cadence experiences and grow together. Please definitely let us know your suggestions on the type of engagements that you would like to see with the core team."]}),"\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.strong,{children:"About Temporal and its \u201cEOL announcement\u201d"})}),"\n",(0,a.jsx)(n.p,{children:"Temporal is a startup that was started 2 years ago based on a Cadence fork by some of the original Cadence team members. We are always grateful for their original contribution to the Cadence project and wish them the best of luck in their future endeavours. That said the announcement from Temporal only means that their team will focus on Temporal (which has always been the case for the last 2 years), and not an official stance on Cadence since they have not been involved with the project for quite some time now."}),"\n",(0,a.jsxs)(n.p,{children:["Feel free to reach out to us (",(0,a.jsx)(n.a,{href:"mailto:cadence-oss@googlegroups.com",children:"cadence-oss@googlegroups.com"})," or ",(0,a.jsx)(n.a,{href:"http://t.uber.com/cadence-slack",children:"slack"}),") if you have any questions. And we look forward to your contribution and collaboration."]}),"\n",(0,a.jsx)(n.p,{children:"The Uber Cadence team"})]})}function h(e={}){const{wrapper:n}={...(0,r.R)(),...e.components};return n?(0,a.jsx)(n,{...e,children:(0,a.jsx)(d,{...e})}):d(e)}},8453:(e,n,t)=>{t.d(n,{R:()=>s,x:()=>i});var o=t(6540);const a={},r=o.createContext(a);function s(e){const n=o.useContext(r);return o.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function i(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:s(e.components),o.createElement(r.Provider,{value:n},e.children)}},5432:e=>{e.exports=JSON.parse('{"permalink":"/Cadence-Docs/blog/2021/09/30/long-term-commitment-and-support-for-the-cadence-project-and-its-community","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2021-09-30-long-term-commitment-and-support-for-the-cadence-project-and-its-community.md","source":"@site/blog/2021-09-30-long-term-commitment-and-support-for-the-cadence-project-and-its-community.md","title":"Long-term commitment and support for the Cadence project, and its community","description":"Dear valued Cadence users and developers,","date":"2021-09-30T00:00:00.000Z","tags":[{"inline":false,"label":"Announcement","permalink":"/Cadence-Docs/blog/tags/announcements","description":"Announcement tag description"}],"readingTime":2.545,"hasTruncateMarker":true,"authors":[{"name":"Liang Mei","title":"Engineering Manager @ Uber","url":"https://www.linkedin.com/in/meiliang86/","page":{"permalink":"/Cadence-Docs/blog/authors/meiliang-86"},"socials":{"linkedin":"https://www.linkedin.com/in/meiliang86/","github":"https://github.com/meiliang86"},"imageURL":"https://github.com/meiliang86.png","key":"meiliang86"}],"frontMatter":{"title":"Long-term commitment and support for the Cadence project, and its community","date":"2021-09-30T00:00:00.000Z","authors":"meiliang86","tags":["announcement"]},"unlisted":false,"prevItem":{"title":"Announcing Cadence OSS office hours and community sync up","permalink":"/Cadence-Docs/blog/2021/10/13/announcing-cadence-oss-office-hours-and-community-sync-up"}}')}}]); \ No newline at end of file diff --git a/assets/js/27f46eca.4d1ff655.js b/assets/js/27f46eca.4d1ff655.js deleted file mode 100644 index 1016a534b..000000000 --- a/assets/js/27f46eca.4d1ff655.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[447],{9303:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>a,contentTitle:()=>r,default:()=>u,frontMatter:()=>c,metadata:()=>o,toc:()=>l});const o=JSON.parse('{"id":"about/license","title":"MIT License","description":"","source":"@site/docs/09-about/01-license.md","sourceDirName":"09-about","slug":"/about/license","permalink":"/docs/about/license","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/09-about/01-license.md","tags":[],"version":"current","sidebarPosition":1,"frontMatter":{"layout":"default","title":"MIT License","permalink":"/docs/about/license"},"sidebar":"docsSidebar","previous":{"title":"Contact us","permalink":"/docs/about/"}}');var s=n(4848),i=n(8453);const c={layout:"default",title:"MIT License",permalink:"/docs/about/license"},r="MIT License",a={},l=[];function d(e){const t={code:"code",h1:"h1",header:"header",pre:"pre",...(0,i.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(t.header,{children:(0,s.jsx)(t.h1,{id:"mit-license",children:"MIT License"})}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-text",children:'Copyright (c) 2017 Uber Technologies, Inc.\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the "Software"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n'})})]})}function u(e={}){const{wrapper:t}={...(0,i.R)(),...e.components};return t?(0,s.jsx)(t,{...e,children:(0,s.jsx)(d,{...e})}):d(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>c,x:()=>r});var o=n(6540);const s={},i=o.createContext(s);function c(e){const t=o.useContext(i);return o.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function r(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:c(e.components),o.createElement(i.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/27f46eca.bf4e8268.js b/assets/js/27f46eca.bf4e8268.js new file mode 100644 index 000000000..27216a646 --- /dev/null +++ b/assets/js/27f46eca.bf4e8268.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[447],{9303:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>a,contentTitle:()=>r,default:()=>u,frontMatter:()=>c,metadata:()=>o,toc:()=>d});const o=JSON.parse('{"id":"about/license","title":"MIT License","description":"","source":"@site/docs/09-about/01-license.md","sourceDirName":"09-about","slug":"/about/license","permalink":"/Cadence-Docs/docs/about/license","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/09-about/01-license.md","tags":[],"version":"current","sidebarPosition":1,"frontMatter":{"layout":"default","title":"MIT License","permalink":"/docs/about/license"},"sidebar":"docsSidebar","previous":{"title":"Contact us","permalink":"/Cadence-Docs/docs/about/"}}');var s=n(4848),i=n(8453);const c={layout:"default",title:"MIT License",permalink:"/docs/about/license"},r="MIT License",a={},d=[];function l(e){const t={code:"code",h1:"h1",header:"header",pre:"pre",...(0,i.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(t.header,{children:(0,s.jsx)(t.h1,{id:"mit-license",children:"MIT License"})}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-text",children:'Copyright (c) 2017 Uber Technologies, Inc.\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the "Software"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n'})})]})}function u(e={}){const{wrapper:t}={...(0,i.R)(),...e.components};return t?(0,s.jsx)(t,{...e,children:(0,s.jsx)(l,{...e})}):l(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>c,x:()=>r});var o=n(6540);const s={},i=o.createContext(s);function c(e){const t=o.useContext(i);return o.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function r(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:c(e.components),o.createElement(i.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/28839895.0d8c1b0d.js b/assets/js/28839895.0d8c1b0d.js new file mode 100644 index 000000000..d326fc9ca --- /dev/null +++ b/assets/js/28839895.0d8c1b0d.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[9171],{649:(e,t,o)=>{o.r(t),o.d(t,{assets:()=>c,contentTitle:()=>a,default:()=>w,frontMatter:()=>l,metadata:()=>n,toc:()=>s});const n=JSON.parse('{"id":"get-started/golang-hello-world","title":"Golang hello world","description":"This section provides step-by-step instructions on how to write and run a HelloWorld workflow in Cadence with Golang. You will learn two critical building blocks of Cadence: activities and workflows. First, you will write an activity function that prints a \\"Hello World!\\" message in the log. Then, you will write a workflow function that executes this activity.","source":"@site/docs/01-get-started/03-golang-hello-world.md","sourceDirName":"01-get-started","slug":"/get-started/golang-hello-world","permalink":"/Cadence-Docs/docs/get-started/golang-hello-world","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/01-get-started/03-golang-hello-world.md","tags":[],"version":"current","sidebarPosition":3,"frontMatter":{"layout":"default","title":"Golang hello world","permalink":"/docs/get-started/golang-hello-world"},"sidebar":"docsSidebar","previous":{"title":"Java hello world","permalink":"/Cadence-Docs/docs/get-started/java-hello-world"},"next":{"title":"Video Tutorials","permalink":"/Cadence-Docs/docs/get-started/video-tutorials"}}');var r=o(4848),i=o(8453);const l={layout:"default",title:"Golang hello world",permalink:"/docs/get-started/golang-hello-world"},a="Golang Hello World",c={},s=[{value:"Prerequisite",id:"prerequisite",level:2},{value:"Step 1. Implement A Cadence Worker Service",id:"step-1-implement-a-cadence-worker-service",level:2},{value:"Step 2. Write a simple Cadence hello world activity and workflow",id:"step-2-write-a-simple-cadence-hello-world-activity-and-workflow",level:2},{value:"Step 3. Run the workflow with Cadence CLI",id:"step-3-run-the-workflow-with-cadence-cli",level:2},{value:"(Optional) Step 4. Monitor Cadence workflow with Cadence web UI",id:"optional-step-4-monitor-cadence-workflow-with-cadence-web-ui",level:2},{value:"What is Next",id:"what-is-next",level:2}];function d(e){const t={a:"a",code:"code",h1:"h1",h2:"h2",header:"header",img:"img",li:"li",ol:"ol",p:"p",pre:"pre",...(0,i.R)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(t.header,{children:(0,r.jsx)(t.h1,{id:"golang-hello-world",children:"Golang Hello World"})}),"\n",(0,r.jsx)(t.p,{children:'This section provides step-by-step instructions on how to write and run a HelloWorld workflow in Cadence with Golang. You will learn two critical building blocks of Cadence: activities and workflows. First, you will write an activity function that prints a "Hello World!" message in the log. Then, you will write a workflow function that executes this activity.'}),"\n",(0,r.jsx)(t.h2,{id:"prerequisite",children:"Prerequisite"}),"\n",(0,r.jsx)(t.p,{children:"To successfully run this hello world sample, follow this checklist of setting up Cadence environment"}),"\n",(0,r.jsxs)(t.ol,{children:["\n",(0,r.jsx)(t.li,{children:"Your worker is running properly and you have registered the hello world activity and workflow to the worker"}),"\n",(0,r.jsx)(t.li,{children:"Your Cadence server is running (check your background docker container process)"}),"\n",(0,r.jsx)(t.li,{children:"You have successfully registered a domain for this workflow"}),"\n"]}),"\n",(0,r.jsxs)(t.p,{children:["You must finish part 2 and 3 by following the ",(0,r.jsx)(t.a,{href:"/docs/get-started/server-installation",children:"first section"})," to proceed the next steps.\nWe are using domain called ",(0,r.jsx)(t.code,{children:"test-domain"})," for this tutorial project."]}),"\n",(0,r.jsx)(t.h2,{id:"step-1-implement-a-cadence-worker-service",children:"Step 1. Implement A Cadence Worker Service"}),"\n",(0,r.jsxs)(t.p,{children:["Create a new ",(0,r.jsx)(t.code,{children:"main.go"})," file in your local directory and paste the basic worker service layout."]}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{className:"language-go",children:'package main\n\nimport (\n "net/http"\n "go.uber.org/cadence/.gen/go/cadence/workflowserviceclient"\n "go.uber.org/cadence/compatibility"\n "go.uber.org/cadence/worker"\n\n apiv1 "github.com/cadence-workflow/cadence-idl/go/proto/api/v1"\n "github.com/uber-go/tally"\n "go.uber.org/zap"\n "go.uber.org/zap/zapcore"\n "go.uber.org/yarpc"\n "go.uber.org/yarpc/transport/grpc"\n)\n\nvar HostPort = "127.0.0.1:7833"\nvar Domain = "test-domain"\nvar TaskListName = "test-worker"\nvar ClientName = "test-worker"\nvar CadenceService = "cadence-frontend"\n\nfunc main() {\n startWorker(buildLogger(), buildCadenceClient())\n err := http.ListenAndServe(":8080", nil)\n if err != nil {\n panic(err)\n }\n}\n\nfunc buildLogger() *zap.Logger {\n config := zap.NewDevelopmentConfig()\n config.Level.SetLevel(zapcore.InfoLevel)\n\n var err error\n logger, err := config.Build()\n if err != nil {\n panic("Failed to setup logger")\n }\n\n return logger\n}\n\nfunc buildCadenceClient() workflowserviceclient.Interface {\n dispatcher := yarpc.NewDispatcher(yarpc.Config{\n\t\tName: ClientName,\n\t\tOutbounds: yarpc.Outbounds{\n\t\t CadenceService: {Unary: grpc.NewTransport().NewSingleOutbound(HostPort)},\n\t\t},\n\t })\n\t if err := dispatcher.Start(); err != nil {\n\t\tpanic("Failed to start dispatcher")\n\t }\n\n\t clientConfig := dispatcher.ClientConfig(CadenceService)\n\n\t return compatibility.NewThrift2ProtoAdapter(\n\t\tapiv1.NewDomainAPIYARPCClient(clientConfig),\n\t\tapiv1.NewWorkflowAPIYARPCClient(clientConfig),\n\t\tapiv1.NewWorkerAPIYARPCClient(clientConfig),\n\t\tapiv1.NewVisibilityAPIYARPCClient(clientConfig),\n\t )\n}\n\nfunc startWorker(logger *zap.Logger, service workflowserviceclient.Interface) {\n // TaskListName identifies set of client workflows, activities, and workers.\n // It could be your group or client or application name.\n workerOptions := worker.Options{\n Logger: logger,\n MetricsScope: tally.NewTestScope(TaskListName, map[string]string{}),\n }\n\n worker := worker.New(\n service,\n Domain,\n TaskListName,\n workerOptions)\n err := worker.Start()\n if err != nil {\n panic("Failed to start worker")\n }\n\n logger.Info("Started Worker.", zap.String("worker", TaskListName))\n}\n'})}),"\n",(0,r.jsx)(t.p,{children:"In this worker service, we start a HTTP server and create a new Cadence client running continuously at the background. Then start the server on your local, you may see logs such like"}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{className:"language-log",children:'2023-07-03T11:46:46.266-0700 INFO internal/internal_worker.go:826 Worker has no workflows registered, so workflow worker will not be started. {"Domain": "test-domain", "TaskList": "test-worker", "WorkerID": "35987@uber-C02F18EQMD6R@test-worker@90c0260e-ba5c-4652-9f10-c6d1f9e29c1d"}\n2023-07-03T11:46:46.267-0700 INFO internal/internal_worker.go:834 Started Workflow Worker {"Domain": "test-domain", "TaskList": "test-worker", "WorkerID": "35987@uber-C02F18EQMD6R@test-worker@90c0260e-ba5c-4652-9f10-c6d1f9e29c1d"}\n2023-07-03T11:46:46.267-0700 INFO internal/internal_worker.go:838 Worker has no activities registered, so activity worker will not be started. {"Domain": "test-domain", "TaskList": "test-worker", "WorkerID": "35987@uber-C02F18EQMD6R@test-worker@90c0260e-ba5c-4652-9f10-c6d1f9e29c1d"}\n2023-07-03T11:46:46.267-0700 INFO cadence-worker/main.go:75 Started Worker. {"worker": "test-worker"}\n'})}),"\n",(0,r.jsx)(t.p,{children:"You may see this because there are no activities and workflows registered to the worker. Let's proceed to next steps to write a hello world activity and workflow."}),"\n",(0,r.jsx)(t.h2,{id:"step-2-write-a-simple-cadence-hello-world-activity-and-workflow",children:"Step 2. Write a simple Cadence hello world activity and workflow"}),"\n",(0,r.jsxs)(t.p,{children:["Let's write a hello world activity, which take a single input called ",(0,r.jsx)(t.code,{children:"name"})," and greet us after the workflow is finished."]}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{className:"language-go",children:'func helloWorldWorkflow(ctx workflow.Context, name string) error {\n\tao := workflow.ActivityOptions{\n\t\tScheduleToStartTimeout: time.Minute,\n\t\tStartToCloseTimeout: time.Minute,\n\t\tHeartbeatTimeout: time.Second * 20,\n\t}\n\tctx = workflow.WithActivityOptions(ctx, ao)\n\n\tlogger := workflow.GetLogger(ctx)\n\tlogger.Info("helloworld workflow started")\n\tvar helloworldResult string\n\terr := workflow.ExecuteActivity(ctx, helloWorldActivity, name).Get(ctx, &helloworldResult)\n\tif err != nil {\n\t\tlogger.Error("Activity failed.", zap.Error(err))\n\t\treturn err\n\t}\n\n\tlogger.Info("Workflow completed.", zap.String("Result", helloworldResult))\n\n\treturn nil\n}\n\nfunc helloWorldActivity(ctx context.Context, name string) (string, error) {\n\tlogger := activity.GetLogger(ctx)\n\tlogger.Info("helloworld activity started")\n\treturn "Hello " + name + "!", nil\n}\n'})}),"\n",(0,r.jsx)(t.p,{children:"Don't forget to register the workflow and activity to the worker."}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{className:"language-go",children:"func init() {\n workflow.Register(helloWorldWorkflow)\n activity.Register(helloWorldActivity)\n}\n"})}),"\n",(0,r.jsxs)(t.p,{children:["Import the ",(0,r.jsx)(t.code,{children:"context"})," module if it was not automatically added."]}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{className:"language-go",children:'import (\n "context"\n)\n'})}),"\n",(0,r.jsx)(t.h2,{id:"step-3-run-the-workflow-with-cadence-cli",children:"Step 3. Run the workflow with Cadence CLI"}),"\n",(0,r.jsx)(t.p,{children:"Restart your worker and run the following command to interact with your workflow."}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{className:"language-bash",children:"cadence --domain test-domain workflow start --et 60 --tl test-worker --workflow_type main.helloWorldWorkflow --input '\"World\"'\n"})}),"\n",(0,r.jsx)(t.p,{children:"You should see logs in your worker terminal like"}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{className:"language-log",children:'2023-07-16T11:30:02.717-0700 INFO cadence-worker/code.go:104 Workflow completed. {"Domain": "test-domain", "TaskList": "test-worker", "WorkerID": "11294@uber-C02F18EQMD6R@test-worker@5829c68e-ace0-472f-b5f3-6ccfc7903dd5", "WorkflowType": "main.helloWorldWorkflow", "WorkflowID": "8acbda3c-d240-4f27-8388-97c866b8bfb5", "RunID": "4b91341f-056f-4f0b-ab64-83bcc3a53e5a", "Result": "Hello World!"}\n'})}),"\n",(0,r.jsx)(t.p,{children:"Congratulations! You just launched your very first Cadence workflow from scratch"}),"\n",(0,r.jsx)(t.h2,{id:"optional-step-4-monitor-cadence-workflow-with-cadence-web-ui",children:"(Optional) Step 4. Monitor Cadence workflow with Cadence web UI"}),"\n",(0,r.jsx)(t.p,{children:"When you start the Cadence backend server, it also automatically starts a front end portal for your workflow. Open you browser and go to"}),"\n",(0,r.jsx)(t.p,{children:(0,r.jsx)(t.a,{href:"http://localhost:8088",children:"http://localhost:8088"})}),"\n",(0,r.jsxs)(t.p,{children:["You may see a dashboard below\n",(0,r.jsx)(t.img,{alt:"cadence-ui",src:o(2954).A+"",width:"3790",height:"674"})]}),"\n",(0,r.jsxs)(t.p,{children:["Type the domain you used for the tutorial, in this case, we type ",(0,r.jsx)(t.code,{children:"test-domain"})," and hit enter. Then you can see a complete history of the workflows you have triggered associated to this domain.\n",(0,r.jsx)(t.img,{alt:"cadence-ui-detailed",src:o(8255).A+"",width:"3790",height:"764"})]}),"\n",(0,r.jsx)(t.h2,{id:"what-is-next",children:"What is Next"}),"\n",(0,r.jsxs)(t.p,{children:["Now you have completed the tutorials. You can continue to explore the key ",(0,r.jsx)(t.a,{href:"/docs/concepts",children:"concepts"})," in Cadence, and also how to use them with ",(0,r.jsx)(t.a,{href:"/docs/go-client",children:"Go Client"})]}),"\n",(0,r.jsxs)(t.p,{children:["For complete, ready to build samples covering all the key Cadence concepts go to ",(0,r.jsx)(t.a,{href:"https://github.com/cadence-workflow/cadence-samples",children:"Cadence-Samples"})," for more examples."]}),"\n",(0,r.jsxs)(t.p,{children:["You can also review ",(0,r.jsx)(t.a,{href:"https://github.com/cadence-workflow/cadence-go-client/",children:"Cadence-Client"})," and ",(0,r.jsx)(t.a,{href:"https://pkg.go.dev/go.uber.org/cadence",children:"go-docs"})," for more documentation."]})]})}function w(e={}){const{wrapper:t}={...(0,i.R)(),...e.components};return t?(0,r.jsx)(t,{...e,children:(0,r.jsx)(d,{...e})}):d(e)}},2954:(e,t,o)=>{o.d(t,{A:()=>n});const n=o.p+"assets/images/cadence_ui-7a1200a6a9f9d11aa28452f0cd539b71.png"},8255:(e,t,o)=>{o.d(t,{A:()=>n});const n=o.p+"assets/images/cadence_ui_detailed-786dba0e7aa1f9048af4f0c1420c3ccf.png"},8453:(e,t,o)=>{o.d(t,{R:()=>l,x:()=>a});var n=o(6540);const r={},i=n.createContext(r);function l(e){const t=n.useContext(i);return n.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function a(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:l(e.components),n.createElement(i.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/28839895.be9e60a7.js b/assets/js/28839895.be9e60a7.js deleted file mode 100644 index f571cdb89..000000000 --- a/assets/js/28839895.be9e60a7.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[9171],{649:(e,t,o)=>{o.r(t),o.d(t,{assets:()=>c,contentTitle:()=>a,default:()=>w,frontMatter:()=>l,metadata:()=>r,toc:()=>s});const r=JSON.parse('{"id":"get-started/golang-hello-world","title":"Golang hello world","description":"This section provides step-by-step instructions on how to write and run a HelloWorld workflow in Cadence with Golang. You will learn two critical building blocks of Cadence: activities and workflows. First, you will write an activity function that prints a \\"Hello World!\\" message in the log. Then, you will write a workflow function that executes this activity.","source":"@site/docs/01-get-started/03-golang-hello-world.md","sourceDirName":"01-get-started","slug":"/get-started/golang-hello-world","permalink":"/docs/get-started/golang-hello-world","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/01-get-started/03-golang-hello-world.md","tags":[],"version":"current","sidebarPosition":3,"frontMatter":{"layout":"default","title":"Golang hello world","permalink":"/docs/get-started/golang-hello-world"},"sidebar":"docsSidebar","previous":{"title":"Java hello world","permalink":"/docs/get-started/java-hello-world"},"next":{"title":"Video Tutorials","permalink":"/docs/get-started/video-tutorials"}}');var n=o(4848),i=o(8453);const l={layout:"default",title:"Golang hello world",permalink:"/docs/get-started/golang-hello-world"},a="Golang Hello World",c={},s=[{value:"Prerequisite",id:"prerequisite",level:2},{value:"Step 1. Implement A Cadence Worker Service",id:"step-1-implement-a-cadence-worker-service",level:2},{value:"Step 2. Write a simple Cadence hello world activity and workflow",id:"step-2-write-a-simple-cadence-hello-world-activity-and-workflow",level:2},{value:"Step 3. Run the workflow with Cadence CLI",id:"step-3-run-the-workflow-with-cadence-cli",level:2},{value:"(Optional) Step 4. Monitor Cadence workflow with Cadence web UI",id:"optional-step-4-monitor-cadence-workflow-with-cadence-web-ui",level:2},{value:"What is Next",id:"what-is-next",level:2}];function d(e){const t={a:"a",code:"code",h1:"h1",h2:"h2",header:"header",img:"img",li:"li",ol:"ol",p:"p",pre:"pre",...(0,i.R)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(t.header,{children:(0,n.jsx)(t.h1,{id:"golang-hello-world",children:"Golang Hello World"})}),"\n",(0,n.jsx)(t.p,{children:'This section provides step-by-step instructions on how to write and run a HelloWorld workflow in Cadence with Golang. You will learn two critical building blocks of Cadence: activities and workflows. First, you will write an activity function that prints a "Hello World!" message in the log. Then, you will write a workflow function that executes this activity.'}),"\n",(0,n.jsx)(t.h2,{id:"prerequisite",children:"Prerequisite"}),"\n",(0,n.jsx)(t.p,{children:"To successfully run this hello world sample, follow this checklist of setting up Cadence environment"}),"\n",(0,n.jsxs)(t.ol,{children:["\n",(0,n.jsx)(t.li,{children:"Your worker is running properly and you have registered the hello world activity and workflow to the worker"}),"\n",(0,n.jsx)(t.li,{children:"Your Cadence server is running (check your background docker container process)"}),"\n",(0,n.jsx)(t.li,{children:"You have successfully registered a domain for this workflow"}),"\n"]}),"\n",(0,n.jsxs)(t.p,{children:["You must finish part 2 and 3 by following the ",(0,n.jsx)(t.a,{href:"/docs/get-started/server-installation",children:"first section"})," to proceed the next steps.\nWe are using domain called ",(0,n.jsx)(t.code,{children:"test-domain"})," for this tutorial project."]}),"\n",(0,n.jsx)(t.h2,{id:"step-1-implement-a-cadence-worker-service",children:"Step 1. Implement A Cadence Worker Service"}),"\n",(0,n.jsxs)(t.p,{children:["Create a new ",(0,n.jsx)(t.code,{children:"main.go"})," file in your local directory and paste the basic worker service layout."]}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{className:"language-go",children:'package main\n\nimport (\n "net/http"\n "go.uber.org/cadence/.gen/go/cadence/workflowserviceclient"\n "go.uber.org/cadence/compatibility"\n "go.uber.org/cadence/worker"\n\n apiv1 "github.com/cadence-workflow/cadence-idl/go/proto/api/v1"\n "github.com/uber-go/tally"\n "go.uber.org/zap"\n "go.uber.org/zap/zapcore"\n "go.uber.org/yarpc"\n "go.uber.org/yarpc/transport/grpc"\n)\n\nvar HostPort = "127.0.0.1:7833"\nvar Domain = "test-domain"\nvar TaskListName = "test-worker"\nvar ClientName = "test-worker"\nvar CadenceService = "cadence-frontend"\n\nfunc main() {\n startWorker(buildLogger(), buildCadenceClient())\n err := http.ListenAndServe(":8080", nil)\n if err != nil {\n panic(err)\n }\n}\n\nfunc buildLogger() *zap.Logger {\n config := zap.NewDevelopmentConfig()\n config.Level.SetLevel(zapcore.InfoLevel)\n\n var err error\n logger, err := config.Build()\n if err != nil {\n panic("Failed to setup logger")\n }\n\n return logger\n}\n\nfunc buildCadenceClient() workflowserviceclient.Interface {\n dispatcher := yarpc.NewDispatcher(yarpc.Config{\n\t\tName: ClientName,\n\t\tOutbounds: yarpc.Outbounds{\n\t\t CadenceService: {Unary: grpc.NewTransport().NewSingleOutbound(HostPort)},\n\t\t},\n\t })\n\t if err := dispatcher.Start(); err != nil {\n\t\tpanic("Failed to start dispatcher")\n\t }\n\n\t clientConfig := dispatcher.ClientConfig(CadenceService)\n\n\t return compatibility.NewThrift2ProtoAdapter(\n\t\tapiv1.NewDomainAPIYARPCClient(clientConfig),\n\t\tapiv1.NewWorkflowAPIYARPCClient(clientConfig),\n\t\tapiv1.NewWorkerAPIYARPCClient(clientConfig),\n\t\tapiv1.NewVisibilityAPIYARPCClient(clientConfig),\n\t )\n}\n\nfunc startWorker(logger *zap.Logger, service workflowserviceclient.Interface) {\n // TaskListName identifies set of client workflows, activities, and workers.\n // It could be your group or client or application name.\n workerOptions := worker.Options{\n Logger: logger,\n MetricsScope: tally.NewTestScope(TaskListName, map[string]string{}),\n }\n\n worker := worker.New(\n service,\n Domain,\n TaskListName,\n workerOptions)\n err := worker.Start()\n if err != nil {\n panic("Failed to start worker")\n }\n\n logger.Info("Started Worker.", zap.String("worker", TaskListName))\n}\n'})}),"\n",(0,n.jsx)(t.p,{children:"In this worker service, we start a HTTP server and create a new Cadence client running continuously at the background. Then start the server on your local, you may see logs such like"}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{className:"language-log",children:'2023-07-03T11:46:46.266-0700 INFO internal/internal_worker.go:826 Worker has no workflows registered, so workflow worker will not be started. {"Domain": "test-domain", "TaskList": "test-worker", "WorkerID": "35987@uber-C02F18EQMD6R@test-worker@90c0260e-ba5c-4652-9f10-c6d1f9e29c1d"}\n2023-07-03T11:46:46.267-0700 INFO internal/internal_worker.go:834 Started Workflow Worker {"Domain": "test-domain", "TaskList": "test-worker", "WorkerID": "35987@uber-C02F18EQMD6R@test-worker@90c0260e-ba5c-4652-9f10-c6d1f9e29c1d"}\n2023-07-03T11:46:46.267-0700 INFO internal/internal_worker.go:838 Worker has no activities registered, so activity worker will not be started. {"Domain": "test-domain", "TaskList": "test-worker", "WorkerID": "35987@uber-C02F18EQMD6R@test-worker@90c0260e-ba5c-4652-9f10-c6d1f9e29c1d"}\n2023-07-03T11:46:46.267-0700 INFO cadence-worker/main.go:75 Started Worker. {"worker": "test-worker"}\n'})}),"\n",(0,n.jsx)(t.p,{children:"You may see this because there are no activities and workflows registered to the worker. Let's proceed to next steps to write a hello world activity and workflow."}),"\n",(0,n.jsx)(t.h2,{id:"step-2-write-a-simple-cadence-hello-world-activity-and-workflow",children:"Step 2. Write a simple Cadence hello world activity and workflow"}),"\n",(0,n.jsxs)(t.p,{children:["Let's write a hello world activity, which take a single input called ",(0,n.jsx)(t.code,{children:"name"})," and greet us after the workflow is finished."]}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{className:"language-go",children:'func helloWorldWorkflow(ctx workflow.Context, name string) error {\n\tao := workflow.ActivityOptions{\n\t\tScheduleToStartTimeout: time.Minute,\n\t\tStartToCloseTimeout: time.Minute,\n\t\tHeartbeatTimeout: time.Second * 20,\n\t}\n\tctx = workflow.WithActivityOptions(ctx, ao)\n\n\tlogger := workflow.GetLogger(ctx)\n\tlogger.Info("helloworld workflow started")\n\tvar helloworldResult string\n\terr := workflow.ExecuteActivity(ctx, helloWorldActivity, name).Get(ctx, &helloworldResult)\n\tif err != nil {\n\t\tlogger.Error("Activity failed.", zap.Error(err))\n\t\treturn err\n\t}\n\n\tlogger.Info("Workflow completed.", zap.String("Result", helloworldResult))\n\n\treturn nil\n}\n\nfunc helloWorldActivity(ctx context.Context, name string) (string, error) {\n\tlogger := activity.GetLogger(ctx)\n\tlogger.Info("helloworld activity started")\n\treturn "Hello " + name + "!", nil\n}\n'})}),"\n",(0,n.jsx)(t.p,{children:"Don't forget to register the workflow and activity to the worker."}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{className:"language-go",children:"func init() {\n workflow.Register(helloWorldWorkflow)\n activity.Register(helloWorldActivity)\n}\n"})}),"\n",(0,n.jsxs)(t.p,{children:["Import the ",(0,n.jsx)(t.code,{children:"context"})," module if it was not automatically added."]}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{className:"language-go",children:'import (\n "context"\n)\n'})}),"\n",(0,n.jsx)(t.h2,{id:"step-3-run-the-workflow-with-cadence-cli",children:"Step 3. Run the workflow with Cadence CLI"}),"\n",(0,n.jsx)(t.p,{children:"Restart your worker and run the following command to interact with your workflow."}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{className:"language-bash",children:"cadence --domain test-domain workflow start --et 60 --tl test-worker --workflow_type main.helloWorldWorkflow --input '\"World\"'\n"})}),"\n",(0,n.jsx)(t.p,{children:"You should see logs in your worker terminal like"}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{className:"language-log",children:'2023-07-16T11:30:02.717-0700 INFO cadence-worker/code.go:104 Workflow completed. {"Domain": "test-domain", "TaskList": "test-worker", "WorkerID": "11294@uber-C02F18EQMD6R@test-worker@5829c68e-ace0-472f-b5f3-6ccfc7903dd5", "WorkflowType": "main.helloWorldWorkflow", "WorkflowID": "8acbda3c-d240-4f27-8388-97c866b8bfb5", "RunID": "4b91341f-056f-4f0b-ab64-83bcc3a53e5a", "Result": "Hello World!"}\n'})}),"\n",(0,n.jsx)(t.p,{children:"Congratulations! You just launched your very first Cadence workflow from scratch"}),"\n",(0,n.jsx)(t.h2,{id:"optional-step-4-monitor-cadence-workflow-with-cadence-web-ui",children:"(Optional) Step 4. Monitor Cadence workflow with Cadence web UI"}),"\n",(0,n.jsx)(t.p,{children:"When you start the Cadence backend server, it also automatically starts a front end portal for your workflow. Open you browser and go to"}),"\n",(0,n.jsx)(t.p,{children:(0,n.jsx)(t.a,{href:"http://localhost:8088",children:"http://localhost:8088"})}),"\n",(0,n.jsxs)(t.p,{children:["You may see a dashboard below\n",(0,n.jsx)(t.img,{alt:"cadence-ui",src:o(2954).A+"",width:"3790",height:"674"})]}),"\n",(0,n.jsxs)(t.p,{children:["Type the domain you used for the tutorial, in this case, we type ",(0,n.jsx)(t.code,{children:"test-domain"})," and hit enter. Then you can see a complete history of the workflows you have triggered associated to this domain.\n",(0,n.jsx)(t.img,{alt:"cadence-ui-detailed",src:o(8255).A+"",width:"3790",height:"764"})]}),"\n",(0,n.jsx)(t.h2,{id:"what-is-next",children:"What is Next"}),"\n",(0,n.jsxs)(t.p,{children:["Now you have completed the tutorials. You can continue to explore the key ",(0,n.jsx)(t.a,{href:"/docs/concepts",children:"concepts"})," in Cadence, and also how to use them with ",(0,n.jsx)(t.a,{href:"/docs/go-client",children:"Go Client"})]}),"\n",(0,n.jsxs)(t.p,{children:["For complete, ready to build samples covering all the key Cadence concepts go to ",(0,n.jsx)(t.a,{href:"https://github.com/cadence-workflow/cadence-samples",children:"Cadence-Samples"})," for more examples."]}),"\n",(0,n.jsxs)(t.p,{children:["You can also review ",(0,n.jsx)(t.a,{href:"https://github.com/cadence-workflow/cadence-go-client/",children:"Cadence-Client"})," and ",(0,n.jsx)(t.a,{href:"https://pkg.go.dev/go.uber.org/cadence",children:"go-docs"})," for more documentation."]})]})}function w(e={}){const{wrapper:t}={...(0,i.R)(),...e.components};return t?(0,n.jsx)(t,{...e,children:(0,n.jsx)(d,{...e})}):d(e)}},2954:(e,t,o)=>{o.d(t,{A:()=>r});const r=o.p+"assets/images/cadence_ui-7a1200a6a9f9d11aa28452f0cd539b71.png"},8255:(e,t,o)=>{o.d(t,{A:()=>r});const r=o.p+"assets/images/cadence_ui_detailed-786dba0e7aa1f9048af4f0c1420c3ccf.png"},8453:(e,t,o)=>{o.d(t,{R:()=>l,x:()=>a});var r=o(6540);const n={},i=r.createContext(n);function l(e){const t=r.useContext(i);return r.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function a(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(n):e.components||n:l(e.components),r.createElement(i.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/28f6f2b5.92a656e2.js b/assets/js/28f6f2b5.00cf4faf.js similarity index 64% rename from assets/js/28f6f2b5.92a656e2.js rename to assets/js/28f6f2b5.00cf4faf.js index 871fd8669..bb828124b 100644 --- a/assets/js/28f6f2b5.92a656e2.js +++ b/assets/js/28f6f2b5.00cf4faf.js @@ -1 +1 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[4830],{3947:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>c,contentTitle:()=>s,default:()=>u,frontMatter:()=>r,metadata:()=>a,toc:()=>d});var a=n(8853),i=n(4848),o=n(8453);const r={title:"Moving to gRPC",date:new Date("2021-10-19T00:00:00.000Z"),authors:"vytautas-karpavicius",tags:["deep-dive","cadence-operations"]},s=void 0,c={authorsImageUrls:[void 0]},d=[{value:"Background",id:"background",level:2},{value:"Our Approach",id:"our-approach",level:2}];function l(e){const t={h2:"h2",p:"p",...(0,o.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(t.h2,{id:"background",children:"Background"}),"\n",(0,i.jsx)(t.p,{children:"Cadence historically has been using TChannel transport with Thrift encoding for both internal RPC calls and communication with client SDKs. gRPC is becoming a de-facto industry standard with much better adoption and community support. It offers features such as authentication and streaming that are very relevant for Cadence. Moreover, TChannel is being deprecated within Uber itself, pushing an effort for this migration. During the last year we\u2019ve implemented multiple changes in server and SDK that allows users to use gRPC in Cadence, as well as to upgrade their existing Cadence cluster in a backward compatible way. This post tracks the completed work items and our future plans."}),"\n",(0,i.jsx)(t.h2,{id:"our-approach",children:"Our Approach"}),"\n",(0,i.jsx)(t.p,{children:"With ~500 services using Cadence at Uber and many more open source customers around the world, we had to think about the gRPC transition in a backwards compatible way. We couldn\u2019t simply flip transport and encoding everywhere. Instead we needed to support both protocols as an intermediate step to ensure a smooth transition for our users."}),"\n",(0,i.jsx)(t.p,{children:"Cadence was using Thrift/TChannel not just for the API with client SDKs. They were also used for RPC calls between internal Cadence server components and also between different data centers. When starting this migration we had a choice of either starting with public APIs first or all the internal things within the server. We chose the latter one, so that we could gain experience and iterate faster within the server without disruption to the clients. With server side done and listening for both protocols, dynamic config flag was exposed to switch traffic internally. It allowed gradual deployment and provided an option to rollback if needed."})]})}function u(e={}){const{wrapper:t}={...(0,o.R)(),...e.components};return t?(0,i.jsx)(t,{...e,children:(0,i.jsx)(l,{...e})}):l(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>r,x:()=>s});var a=n(6540);const i={},o=a.createContext(i);function r(e){const t=a.useContext(o);return a.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function s(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:r(e.components),a.createElement(o.Provider,{value:t},e.children)}},8853:e=>{e.exports=JSON.parse('{"permalink":"/blog/2021/10/19/2021-10-19-moving-to-grpc/moving-to-grpc","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2021-10-19-moving-to-grpc/2021-10-19-moving-to-grpc.md","source":"@site/blog/2021-10-19-moving-to-grpc/2021-10-19-moving-to-grpc.md","title":"Moving to gRPC","description":"Background","date":"2021-10-19T00:00:00.000Z","tags":[{"inline":false,"label":"Deep Dives","permalink":"/blog/tags/deep-dives","description":"Deep Dives tag description"},{"inline":false,"label":"Cadence Operations","permalink":"/blog/tags/cadence-operations","description":"Cadence Operations tag description"}],"readingTime":4.795,"hasTruncateMarker":true,"authors":[{"name":"Vytautas Karpavicius","title":"Software Engineer @ Uber","url":"https://www.linkedin.com/in/vytautas-karpavicius","page":{"permalink":"/blog/authors/vytautas-karpavicius"},"socials":{"linkedin":"https://www.linkedin.com/in/vytautas-karpavicius","github":"https://github.com/vytautas-karpavicius"},"imageURL":"https://github.com/vytautas-karpavicius.png","key":"vytautas-karpavicius"}],"frontMatter":{"title":"Moving to gRPC","date":"2021-10-19T00:00:00.000Z","authors":"vytautas-karpavicius","tags":["deep-dive","cadence-operations"]},"unlisted":false,"prevItem":{"title":"Cadence Community Spotlight Update - January 2022","permalink":"/blog/2022/01/31/community-spotlight-january-2022"},"nextItem":{"title":"Announcing Cadence OSS office hours and community sync up","permalink":"/blog/2021/10/13/announcing-cadence-oss-office-hours-and-community-sync-up"}}')}}]); \ No newline at end of file +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[4830],{3947:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>c,contentTitle:()=>s,default:()=>u,frontMatter:()=>r,metadata:()=>a,toc:()=>d});var a=n(8853),i=n(4848),o=n(8453);const r={title:"Moving to gRPC",date:new Date("2021-10-19T00:00:00.000Z"),authors:"vytautas-karpavicius",tags:["deep-dive","cadence-operations"]},s=void 0,c={authorsImageUrls:[void 0]},d=[{value:"Background",id:"background",level:2},{value:"Our Approach",id:"our-approach",level:2}];function l(e){const t={h2:"h2",p:"p",...(0,o.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(t.h2,{id:"background",children:"Background"}),"\n",(0,i.jsx)(t.p,{children:"Cadence historically has been using TChannel transport with Thrift encoding for both internal RPC calls and communication with client SDKs. gRPC is becoming a de-facto industry standard with much better adoption and community support. It offers features such as authentication and streaming that are very relevant for Cadence. Moreover, TChannel is being deprecated within Uber itself, pushing an effort for this migration. During the last year we\u2019ve implemented multiple changes in server and SDK that allows users to use gRPC in Cadence, as well as to upgrade their existing Cadence cluster in a backward compatible way. This post tracks the completed work items and our future plans."}),"\n",(0,i.jsx)(t.h2,{id:"our-approach",children:"Our Approach"}),"\n",(0,i.jsx)(t.p,{children:"With ~500 services using Cadence at Uber and many more open source customers around the world, we had to think about the gRPC transition in a backwards compatible way. We couldn\u2019t simply flip transport and encoding everywhere. Instead we needed to support both protocols as an intermediate step to ensure a smooth transition for our users."}),"\n",(0,i.jsx)(t.p,{children:"Cadence was using Thrift/TChannel not just for the API with client SDKs. They were also used for RPC calls between internal Cadence server components and also between different data centers. When starting this migration we had a choice of either starting with public APIs first or all the internal things within the server. We chose the latter one, so that we could gain experience and iterate faster within the server without disruption to the clients. With server side done and listening for both protocols, dynamic config flag was exposed to switch traffic internally. It allowed gradual deployment and provided an option to rollback if needed."})]})}function u(e={}){const{wrapper:t}={...(0,o.R)(),...e.components};return t?(0,i.jsx)(t,{...e,children:(0,i.jsx)(l,{...e})}):l(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>r,x:()=>s});var a=n(6540);const i={},o=a.createContext(i);function r(e){const t=a.useContext(o);return a.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function s(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:r(e.components),a.createElement(o.Provider,{value:t},e.children)}},8853:e=>{e.exports=JSON.parse('{"permalink":"/Cadence-Docs/blog/2021/10/19/2021-10-19-moving-to-grpc/moving-to-grpc","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2021-10-19-moving-to-grpc/2021-10-19-moving-to-grpc.md","source":"@site/blog/2021-10-19-moving-to-grpc/2021-10-19-moving-to-grpc.md","title":"Moving to gRPC","description":"Background","date":"2021-10-19T00:00:00.000Z","tags":[{"inline":false,"label":"Deep Dives","permalink":"/Cadence-Docs/blog/tags/deep-dives","description":"Deep Dives tag description"},{"inline":false,"label":"Cadence Operations","permalink":"/Cadence-Docs/blog/tags/cadence-operations","description":"Cadence Operations tag description"}],"readingTime":4.795,"hasTruncateMarker":true,"authors":[{"name":"Vytautas Karpavicius","title":"Software Engineer @ Uber","url":"https://www.linkedin.com/in/vytautas-karpavicius","page":{"permalink":"/Cadence-Docs/blog/authors/vytautas-karpavicius"},"socials":{"linkedin":"https://www.linkedin.com/in/vytautas-karpavicius","github":"https://github.com/vytautas-karpavicius"},"imageURL":"https://github.com/vytautas-karpavicius.png","key":"vytautas-karpavicius"}],"frontMatter":{"title":"Moving to gRPC","date":"2021-10-19T00:00:00.000Z","authors":"vytautas-karpavicius","tags":["deep-dive","cadence-operations"]},"unlisted":false,"prevItem":{"title":"Cadence Community Spotlight Update - January 2022","permalink":"/Cadence-Docs/blog/2022/01/31/community-spotlight-january-2022"},"nextItem":{"title":"Announcing Cadence OSS office hours and community sync up","permalink":"/Cadence-Docs/blog/2021/10/13/announcing-cadence-oss-office-hours-and-community-sync-up"}}')}}]); \ No newline at end of file diff --git a/assets/js/2955167d.7691892b.js b/assets/js/2955167d.0094316b.js similarity index 57% rename from assets/js/2955167d.7691892b.js rename to assets/js/2955167d.0094316b.js index 06a32c2e8..8ca328169 100644 --- a/assets/js/2955167d.7691892b.js +++ b/assets/js/2955167d.0094316b.js @@ -1 +1 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[8202],{5372:(e,t,o)=>{o.r(t),o.d(t,{assets:()=>l,contentTitle:()=>a,default:()=>h,frontMatter:()=>s,metadata:()=>i,toc:()=>c});var i=o(3315),n=o(4848),r=o(8453);const s={title:"Non-deterministic errors, replayers and shadowers",date:new Date("2023-08-27T00:00:00.000Z"),authors:"chopincode",tags:["deep-dive","testing"]},a=void 0,l={authorsImageUrls:[void 0]},c=[];function d(e){const t={a:"a",code:"code",p:"p",pre:"pre",...(0,r.R)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(t.p,{children:"It is conceivable that developers constantly update their Cadence workflow code based upon new business use cases and needs. However,\nthe definition of a Cadence workflow must be deterministic because behind the scenes cadence uses event sourcing to construct\nthe workflow state by replaying the historical events stored for this specific workflow. Introducing components that are not compatible\nwith an existing running workflow will yield to non-deterministic errors and sometimes developers find it tricky to debug. Consider the\nfollowing workflow that executes two activities."}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{className:"language-go",children:'func SampleWorkflow(ctx workflow.Context, data string) (string, error) {\n ao := workflow.ActivityOptions{\n ScheduleToStartTimeout: time.Minute,\n StartToCloseTimeout: time.Minute,\n }\n ctx = workflow.WithActivityOptions(ctx, ao)\n var result1 string\n err := workflow.ExecuteActivity(ctx, ActivityA, data).Get(ctx, &result1)\n if err != nil {\n return "", err\n }\n var result2 string\n err = workflow.ExecuteActivity(ctx, ActivityB, result1).Get(ctx, &result2)\n return result2, err\n}\n\n'})}),"\n",(0,n.jsx)(t.p,{children:"In this example, the workflow will execute ActivityA and Activity B in sequence. These activities may have other logics in background, such as polling long running operations or manipulate database reads or writes. Now if the developer replaces ActivityA with another activity ActivityC, a non-deterministic error could happen for an existing workflow. It is because the workflow expects results from ActivityA but since the definition of the workflow has been changed to use results from ActivityC, the workflow will fail due to failure of identifying history data of ActivityA. Such issues can be detected by introducing replayers and shadowers to the workflow unit tests."}),"\n",(0,n.jsx)(t.p,{children:"Cadence workflow replayer is a testing component for replaying existing workflow histories against a workflow definition. You may think of replayer as a mock which will rerun your workflow with exactly the same history as your real workflow. The replaying logic is the same as the one used for processing workflow tasks. If it detects any incompatible changes, the replay test will fail.\nWorkflow Replayer works well when verifying the compatibility against a small number of workflow histories. If there are lots of workflows in production that need to be verified, dumping all histories manually clearly won't work. Directly fetching histories from the cadence server might be a solution, but the time to replay all workflow histories might be too long for a test."}),"\n",(0,n.jsx)(t.p,{children:"Workflow Shadower is built on top of Workflow Replayer to address this problem. The basic idea of shadowing is: scan workflows based on the filters you defined, fetch history for each workflow in the scan result from Cadence server and run the replay test. It can be run either as a test to serve local development purposes or as a workflow in your worker to continuously replay production workflows."}),"\n",(0,n.jsxs)(t.p,{children:["You may find detailed instructions on how to use replayers and shadowers on ",(0,n.jsx)(t.a,{href:"https://cadenceworkflow.io/docs/go-client/workflow-replay-shadowing/",children:"our website"}),". We will introduce versioning in the next coming blogs."]})]})}function h(e={}){const{wrapper:t}={...(0,r.R)(),...e.components};return t?(0,n.jsx)(t,{...e,children:(0,n.jsx)(d,{...e})}):d(e)}},8453:(e,t,o)=>{o.d(t,{R:()=>s,x:()=>a});var i=o(6540);const n={},r=i.createContext(n);function s(e){const t=i.useContext(r);return i.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function a(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(n):e.components||n:s(e.components),i.createElement(r.Provider,{value:t},e.children)}},3315:e=>{e.exports=JSON.parse('{"permalink":"/blog/2023/08/28/nondeterministic-errors-replayers-shadowers","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2023-08-28-nondeterministic-errors-replayers-shadowers.md","source":"@site/blog/2023-08-28-nondeterministic-errors-replayers-shadowers.md","title":"Non-deterministic errors, replayers and shadowers","description":"It is conceivable that developers constantly update their Cadence workflow code based upon new business use cases and needs. However,","date":"2023-08-27T00:00:00.000Z","tags":[{"inline":false,"label":"Deep Dives","permalink":"/blog/tags/deep-dives","description":"Deep Dives tag description"},{"inline":false,"label":"Testing","permalink":"/blog/tags/testing","description":"Testing tag description"}],"readingTime":2.305,"hasTruncateMarker":true,"authors":[{"name":"Chris Qin","title":"Applications Developer @ Uber","url":"https://www.linkedin.com/in/chrisqin0610/","page":{"permalink":"/blog/authors/chopincode"},"socials":{"linkedin":"https://www.linkedin.com/in/chrisqin0610/","github":"https://github.com/chopincode"},"imageURL":"https://github.com/chopincode.png","key":"chopincode"}],"frontMatter":{"title":"Non-deterministic errors, replayers and shadowers","date":"2023-08-27T00:00:00.000Z","authors":"chopincode","tags":["deep-dive","testing"]},"unlisted":false,"prevItem":{"title":"Cadence Community Spotlight Update - August 2023","permalink":"/blog/2023/08/31/community-spotlight-august-2023"},"nextItem":{"title":"Cadence Community Spotlight Update - July 2023","permalink":"/blog/2023/07/31/community-spotlight-july-2023"}}')}}]); \ No newline at end of file +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[8202],{5372:(e,t,o)=>{o.r(t),o.d(t,{assets:()=>c,contentTitle:()=>a,default:()=>h,frontMatter:()=>s,metadata:()=>n,toc:()=>l});var n=o(3315),i=o(4848),r=o(8453);const s={title:"Non-deterministic errors, replayers and shadowers",date:new Date("2023-08-27T00:00:00.000Z"),authors:"chopincode",tags:["deep-dive","testing"]},a=void 0,c={authorsImageUrls:[void 0]},l=[];function d(e){const t={a:"a",code:"code",p:"p",pre:"pre",...(0,r.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(t.p,{children:"It is conceivable that developers constantly update their Cadence workflow code based upon new business use cases and needs. However,\nthe definition of a Cadence workflow must be deterministic because behind the scenes cadence uses event sourcing to construct\nthe workflow state by replaying the historical events stored for this specific workflow. Introducing components that are not compatible\nwith an existing running workflow will yield to non-deterministic errors and sometimes developers find it tricky to debug. Consider the\nfollowing workflow that executes two activities."}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{className:"language-go",children:'func SampleWorkflow(ctx workflow.Context, data string) (string, error) {\n ao := workflow.ActivityOptions{\n ScheduleToStartTimeout: time.Minute,\n StartToCloseTimeout: time.Minute,\n }\n ctx = workflow.WithActivityOptions(ctx, ao)\n var result1 string\n err := workflow.ExecuteActivity(ctx, ActivityA, data).Get(ctx, &result1)\n if err != nil {\n return "", err\n }\n var result2 string\n err = workflow.ExecuteActivity(ctx, ActivityB, result1).Get(ctx, &result2)\n return result2, err\n}\n\n'})}),"\n",(0,i.jsx)(t.p,{children:"In this example, the workflow will execute ActivityA and Activity B in sequence. These activities may have other logics in background, such as polling long running operations or manipulate database reads or writes. Now if the developer replaces ActivityA with another activity ActivityC, a non-deterministic error could happen for an existing workflow. It is because the workflow expects results from ActivityA but since the definition of the workflow has been changed to use results from ActivityC, the workflow will fail due to failure of identifying history data of ActivityA. Such issues can be detected by introducing replayers and shadowers to the workflow unit tests."}),"\n",(0,i.jsx)(t.p,{children:"Cadence workflow replayer is a testing component for replaying existing workflow histories against a workflow definition. You may think of replayer as a mock which will rerun your workflow with exactly the same history as your real workflow. The replaying logic is the same as the one used for processing workflow tasks. If it detects any incompatible changes, the replay test will fail.\nWorkflow Replayer works well when verifying the compatibility against a small number of workflow histories. If there are lots of workflows in production that need to be verified, dumping all histories manually clearly won't work. Directly fetching histories from the cadence server might be a solution, but the time to replay all workflow histories might be too long for a test."}),"\n",(0,i.jsx)(t.p,{children:"Workflow Shadower is built on top of Workflow Replayer to address this problem. The basic idea of shadowing is: scan workflows based on the filters you defined, fetch history for each workflow in the scan result from Cadence server and run the replay test. It can be run either as a test to serve local development purposes or as a workflow in your worker to continuously replay production workflows."}),"\n",(0,i.jsxs)(t.p,{children:["You may find detailed instructions on how to use replayers and shadowers on ",(0,i.jsx)(t.a,{href:"https://cadenceworkflow.io/docs/go-client/workflow-replay-shadowing/",children:"our website"}),". We will introduce versioning in the next coming blogs."]})]})}function h(e={}){const{wrapper:t}={...(0,r.R)(),...e.components};return t?(0,i.jsx)(t,{...e,children:(0,i.jsx)(d,{...e})}):d(e)}},8453:(e,t,o)=>{o.d(t,{R:()=>s,x:()=>a});var n=o(6540);const i={},r=n.createContext(i);function s(e){const t=n.useContext(r);return n.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function a(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:s(e.components),n.createElement(r.Provider,{value:t},e.children)}},3315:e=>{e.exports=JSON.parse('{"permalink":"/Cadence-Docs/blog/2023/08/28/nondeterministic-errors-replayers-shadowers","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2023-08-28-nondeterministic-errors-replayers-shadowers.md","source":"@site/blog/2023-08-28-nondeterministic-errors-replayers-shadowers.md","title":"Non-deterministic errors, replayers and shadowers","description":"It is conceivable that developers constantly update their Cadence workflow code based upon new business use cases and needs. However,","date":"2023-08-27T00:00:00.000Z","tags":[{"inline":false,"label":"Deep Dives","permalink":"/Cadence-Docs/blog/tags/deep-dives","description":"Deep Dives tag description"},{"inline":false,"label":"Testing","permalink":"/Cadence-Docs/blog/tags/testing","description":"Testing tag description"}],"readingTime":2.305,"hasTruncateMarker":true,"authors":[{"name":"Chris Qin","title":"Applications Developer @ Uber","url":"https://www.linkedin.com/in/chrisqin0610/","page":{"permalink":"/Cadence-Docs/blog/authors/chopincode"},"socials":{"linkedin":"https://www.linkedin.com/in/chrisqin0610/","github":"https://github.com/chopincode"},"imageURL":"https://github.com/chopincode.png","key":"chopincode"}],"frontMatter":{"title":"Non-deterministic errors, replayers and shadowers","date":"2023-08-27T00:00:00.000Z","authors":"chopincode","tags":["deep-dive","testing"]},"unlisted":false,"prevItem":{"title":"Cadence Community Spotlight Update - August 2023","permalink":"/Cadence-Docs/blog/2023/08/31/community-spotlight-august-2023"},"nextItem":{"title":"Cadence Community Spotlight Update - July 2023","permalink":"/Cadence-Docs/blog/2023/07/31/community-spotlight-july-2023"}}')}}]); \ No newline at end of file diff --git a/assets/js/2a3fd662.b43041cb.js b/assets/js/2a3fd662.b43041cb.js deleted file mode 100644 index facbc87f1..000000000 --- a/assets/js/2a3fd662.b43041cb.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[2813],{9556:(e,s,t)=>{t.r(s),t.d(s,{assets:()=>c,contentTitle:()=>r,default:()=>h,frontMatter:()=>a,metadata:()=>n,toc:()=>l});const n=JSON.parse('{"id":"concepts/task-lists","title":"Task lists","description":"When a invokes an, it sends the `ScheduleActivityTask` to the","source":"@site/docs/03-concepts/06-task-lists.md","sourceDirName":"03-concepts","slug":"/concepts/task-lists","permalink":"/docs/concepts/task-lists","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/03-concepts/06-task-lists.md","tags":[],"version":"current","sidebarPosition":6,"frontMatter":{"layout":"default","title":"Task lists","permalink":"/docs/concepts/task-lists"},"sidebar":"docsSidebar","previous":{"title":"Deployment topology","permalink":"/docs/concepts/topology"},"next":{"title":"Archival","permalink":"/docs/concepts/archival"}}');var i=t(4848),o=t(8453);const a={layout:"default",title:"Task lists",permalink:"/docs/concepts/task-lists"},r="Task lists",c={},l=[];function d(e){const s={code:"code",em:"em",h1:"h1",header:"header",li:"li",p:"p",ul:"ul",...(0,o.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(s.header,{children:(0,i.jsx)(s.h1,{id:"task-lists",children:"Task lists"})}),"\n",(0,i.jsxs)(s.p,{children:["When a workflow invokes an activity, it sends the ",(0,i.jsx)(s.code,{children:"ScheduleActivityTask"})," decision to the\nCadence service. As a result, the service updates the workflow state and dispatches\nan activity_task to a worker that implements the activity.\nInstead of calling the worker directly, an intermediate queue is used. So the service adds an ",(0,i.jsx)(s.em,{children:"activity_task"})," to this\nqueue and a worker receives the task using a long poll request.\nCadence calls this queue used to dispatch activity_tasks an ",(0,i.jsx)(s.em,{children:"activity_task_list"}),"."]}),"\n",(0,i.jsxs)(s.p,{children:["Similarly, when a workflow needs to handle an external event, a decision_task is created.\nA decision_task_list is used to deliver it to the workflow_worker (also called ",(0,i.jsx)(s.em,{children:"decider"}),")."]}),"\n",(0,i.jsx)(s.p,{children:"While Cadence task_lists are queues, they have some differences from commonly used queuing technologies.\nThe main one is that they do not require explicit registration and are created on demand. The number of task_lists\nis not limited. A common use case is to have a task_list per worker process and use it to deliver activity_tasks\nto the process. Another use case is to have a task_list per pool of workers."}),"\n",(0,i.jsx)(s.p,{children:"There are multiple advantages of using a task_list to deliver tasks instead of invoking an activity_worker through a synchronous RPC:"}),"\n",(0,i.jsxs)(s.ul,{children:["\n",(0,i.jsx)(s.li,{children:"Worker doesn't need to have any open ports, which is more secure."}),"\n",(0,i.jsx)(s.li,{children:"Worker doesn't need to advertise itself through DNS or any other network discovery mechanism."}),"\n",(0,i.jsx)(s.li,{children:"When all workers are down, messages are persisted in a task_list waiting for the workers to recover."}),"\n",(0,i.jsx)(s.li,{children:"A worker polls for a message only when it has spare capacity, so it never gets overloaded."}),"\n",(0,i.jsx)(s.li,{children:"Automatic load balancing across a large number of workers."}),"\n",(0,i.jsx)(s.li,{children:"Task_lists support server side throttling. This allows you to limit the task dispatch rate to the pool of workers and still supports adding a task with a higher rate when spikes happen."}),"\n",(0,i.jsx)(s.li,{children:"Task_lists can be used to route a request to specific pools of workers or even a specific process."}),"\n"]})]})}function h(e={}){const{wrapper:s}={...(0,o.R)(),...e.components};return s?(0,i.jsx)(s,{...e,children:(0,i.jsx)(d,{...e})}):d(e)}},8453:(e,s,t)=>{t.d(s,{R:()=>a,x:()=>r});var n=t(6540);const i={},o=n.createContext(i);function a(e){const s=n.useContext(o);return n.useMemo((function(){return"function"==typeof e?e(s):{...s,...e}}),[s,e])}function r(e){let s;return s=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:a(e.components),n.createElement(o.Provider,{value:s},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/2a3fd662.e107e194.js b/assets/js/2a3fd662.e107e194.js new file mode 100644 index 000000000..972176b47 --- /dev/null +++ b/assets/js/2a3fd662.e107e194.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[2813],{9556:(e,s,t)=>{t.r(s),t.d(s,{assets:()=>c,contentTitle:()=>r,default:()=>h,frontMatter:()=>a,metadata:()=>n,toc:()=>l});const n=JSON.parse('{"id":"concepts/task-lists","title":"Task lists","description":"When a invokes an, it sends the `ScheduleActivityTask` to the","source":"@site/docs/03-concepts/06-task-lists.md","sourceDirName":"03-concepts","slug":"/concepts/task-lists","permalink":"/Cadence-Docs/docs/concepts/task-lists","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/03-concepts/06-task-lists.md","tags":[],"version":"current","sidebarPosition":6,"frontMatter":{"layout":"default","title":"Task lists","permalink":"/docs/concepts/task-lists"},"sidebar":"docsSidebar","previous":{"title":"Deployment topology","permalink":"/Cadence-Docs/docs/concepts/topology"},"next":{"title":"Archival","permalink":"/Cadence-Docs/docs/concepts/archival"}}');var i=t(4848),o=t(8453);const a={layout:"default",title:"Task lists",permalink:"/docs/concepts/task-lists"},r="Task lists",c={},l=[];function d(e){const s={code:"code",em:"em",h1:"h1",header:"header",li:"li",p:"p",ul:"ul",...(0,o.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(s.header,{children:(0,i.jsx)(s.h1,{id:"task-lists",children:"Task lists"})}),"\n",(0,i.jsxs)(s.p,{children:["When a workflow invokes an activity, it sends the ",(0,i.jsx)(s.code,{children:"ScheduleActivityTask"})," decision to the\nCadence service. As a result, the service updates the workflow state and dispatches\nan activity_task to a worker that implements the activity.\nInstead of calling the worker directly, an intermediate queue is used. So the service adds an ",(0,i.jsx)(s.em,{children:"activity_task"})," to this\nqueue and a worker receives the task using a long poll request.\nCadence calls this queue used to dispatch activity_tasks an ",(0,i.jsx)(s.em,{children:"activity_task_list"}),"."]}),"\n",(0,i.jsxs)(s.p,{children:["Similarly, when a workflow needs to handle an external event, a decision_task is created.\nA decision_task_list is used to deliver it to the workflow_worker (also called ",(0,i.jsx)(s.em,{children:"decider"}),")."]}),"\n",(0,i.jsx)(s.p,{children:"While Cadence task_lists are queues, they have some differences from commonly used queuing technologies.\nThe main one is that they do not require explicit registration and are created on demand. The number of task_lists\nis not limited. A common use case is to have a task_list per worker process and use it to deliver activity_tasks\nto the process. Another use case is to have a task_list per pool of workers."}),"\n",(0,i.jsx)(s.p,{children:"There are multiple advantages of using a task_list to deliver tasks instead of invoking an activity_worker through a synchronous RPC:"}),"\n",(0,i.jsxs)(s.ul,{children:["\n",(0,i.jsx)(s.li,{children:"Worker doesn't need to have any open ports, which is more secure."}),"\n",(0,i.jsx)(s.li,{children:"Worker doesn't need to advertise itself through DNS or any other network discovery mechanism."}),"\n",(0,i.jsx)(s.li,{children:"When all workers are down, messages are persisted in a task_list waiting for the workers to recover."}),"\n",(0,i.jsx)(s.li,{children:"A worker polls for a message only when it has spare capacity, so it never gets overloaded."}),"\n",(0,i.jsx)(s.li,{children:"Automatic load balancing across a large number of workers."}),"\n",(0,i.jsx)(s.li,{children:"Task_lists support server side throttling. This allows you to limit the task dispatch rate to the pool of workers and still supports adding a task with a higher rate when spikes happen."}),"\n",(0,i.jsx)(s.li,{children:"Task_lists can be used to route a request to specific pools of workers or even a specific process."}),"\n"]})]})}function h(e={}){const{wrapper:s}={...(0,o.R)(),...e.components};return s?(0,i.jsx)(s,{...e,children:(0,i.jsx)(d,{...e})}):d(e)}},8453:(e,s,t)=>{t.d(s,{R:()=>a,x:()=>r});var n=t(6540);const i={},o=n.createContext(i);function a(e){const s=n.useContext(o);return n.useMemo((function(){return"function"==typeof e?e(s):{...s,...e}}),[s,e])}function r(e){let s;return s=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:a(e.components),n.createElement(o.Provider,{value:s},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/2b58a6fe.9ff3e12f.js b/assets/js/2b58a6fe.9ff3e12f.js new file mode 100644 index 000000000..797fb0311 --- /dev/null +++ b/assets/js/2b58a6fe.9ff3e12f.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[3190],{5490:(e,n,r)=>{r.r(n),r.d(n,{assets:()=>s,contentTitle:()=>c,default:()=>p,frontMatter:()=>a,metadata:()=>o,toc:()=>l});const o=JSON.parse('{"id":"go-client/workers","title":"Worker service","description":"A or service is a service that hosts the and implementations. The polls the Cadence service fortaskstask, and communicates execution results back to the Cadence service.Worker: services are developed, deployed, and operated by Cadence customers.","source":"@site/docs/05-go-client/01-workers.md","sourceDirName":"05-go-client","slug":"/go-client/workers","permalink":"/Cadence-Docs/docs/go-client/workers","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/05-go-client/01-workers.md","tags":[],"version":"current","sidebarPosition":1,"frontMatter":{"layout":"default","title":"Worker service","permalink":"/docs/go-client/workers"},"sidebar":"docsSidebar","previous":{"title":"Introduction","permalink":"/Cadence-Docs/docs/go-client/"},"next":{"title":"Creating workflows","permalink":"/Cadence-Docs/docs/go-client/create-workflows"}}');var t=r(4848),i=r(8453);const a={layout:"default",title:"Worker service",permalink:"/docs/go-client/workers"},c="Worker service",s={},l=[];function d(e){const n={code:"code",em:"em",h1:"h1",header:"header",p:"p",pre:"pre",...(0,i.R)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.header,{children:(0,t.jsx)(n.h1,{id:"worker-service",children:"Worker service"})}),"\n",(0,t.jsxs)(n.p,{children:["A worker or ",(0,t.jsx)(n.em,{children:"worker service"})," is a service that hosts the workflow and activity implementations. The worker polls the ",(0,t.jsx)(n.em,{children:"Cadence service"})," for tasks, performs those tasks, and communicates task execution results back to the ",(0,t.jsx)(n.em,{children:"Cadence service"}),". Worker services are developed, deployed, and operated by Cadence customers."]}),"\n",(0,t.jsx)(n.p,{children:"You can run a Cadence worker in a new or an existing service. Use the framework APIs to start the Cadence worker and link in all activity and workflow implementations that you require the service to execute."}),"\n",(0,t.jsx)(n.p,{children:"The following is an example worker service utilising tchannel, one of the two transport protocols supported by Cadence."}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-go",children:'package main\n\nimport (\n\n "go.uber.org/cadence/.gen/go/cadence"\n "go.uber.org/cadence/.gen/go/cadence/workflowserviceclient"\n "go.uber.org/cadence/worker"\n\n "github.com/uber-go/tally"\n "go.uber.org/zap"\n "go.uber.org/zap/zapcore"\n "go.uber.org/yarpc"\n "go.uber.org/yarpc/api/transport"\n "go.uber.org/yarpc/transport/tchannel"\n)\n\nvar HostPort = "127.0.0.1:7933"\nvar Domain = "SimpleDomain"\nvar TaskListName = "SimpleWorker"\nvar ClientName = "SimpleWorker"\nvar CadenceService = "cadence-frontend"\n\nfunc main() {\n startWorker(buildLogger(), buildCadenceClient())\n}\n\nfunc buildLogger() *zap.Logger {\n config := zap.NewDevelopmentConfig()\n config.Level.SetLevel(zapcore.InfoLevel)\n\n var err error\n logger, err := config.Build()\n if err != nil {\n panic("Failed to setup logger")\n }\n\n return logger\n}\n\nfunc buildCadenceClient() workflowserviceclient.Interface {\n ch, err := tchannel.NewChannelTransport(tchannel.ServiceName(ClientName))\n if err != nil {\n panic("Failed to setup tchannel")\n }\n dispatcher := yarpc.NewDispatcher(yarpc.Config{\n Name: ClientName,\n Outbounds: yarpc.Outbounds{\n CadenceService: {Unary: ch.NewSingleOutbound(HostPort)},\n },\n })\n if err := dispatcher.Start(); err != nil {\n panic("Failed to start dispatcher")\n }\n\n return workflowserviceclient.New(dispatcher.ClientConfig(CadenceService))\n}\n\nfunc startWorker(logger *zap.Logger, service workflowserviceclient.Interface) {\n // TaskListName identifies set of client workflows, activities, and workers.\n // It could be your group or client or application name.\n workerOptions := worker.Options{\n Logger: logger,\n MetricsScope: tally.NewTestScope(TaskListName, map[string]string{}),\n }\n\n worker := worker.New(\n service,\n Domain,\n TaskListName,\n workerOptions)\n err := worker.Start()\n if err != nil {\n panic("Failed to start worker")\n }\n\n logger.Info("Started Worker.", zap.String("worker", TaskListName))\n}\n'})}),"\n",(0,t.jsxs)(n.p,{children:["The other supported transport protocol is gRPC. A worker service using gRPC can be set up in similar fashion, but the ",(0,t.jsx)(n.code,{children:"buildCadenceClient"})," function will need the following alterations, and some of the imported packages need to change."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-go",children:'\nimport (\n\n "go.uber.org/cadence/.gen/go/cadence"\n "go.uber.org/cadence/.gen/go/cadence/workflowserviceclient"\n "go.uber.org/cadence/compatibility"\n "go.uber.org/cadence/worker"\n\n apiv1 "github.com/cadence-workflow/cadence-idl/go/proto/api/v1"\n "github.com/uber-go/tally"\n "go.uber.org/zap"\n "go.uber.org/zap/zapcore"\n "go.uber.org/yarpc"\n "go.uber.org/yarpc/transport/grpc"\n)\n\n.\n.\n.\n\nfunc buildCadenceClient() workflowserviceclient.Interface {\n\n dispatcher := yarpc.NewDispatcher(yarpc.Config{\n Name: ClientName,\n Outbounds: yarpc.Outbounds{\n CadenceService: {Unary: grpc.NewTransport().NewSingleOutbound(HostPort)},\n },\n })\n if err := dispatcher.Start(); err != nil {\n panic("Failed to start dispatcher")\n }\n\n clientConfig := dispatcher.ClientConfig(CadenceService)\n\n return compatibility.NewThrift2ProtoAdapter(\n apiv1.NewDomainAPIYARPCClient(clientConfig),\n apiv1.NewWorkflowAPIYARPCClient(clientConfig),\n apiv1.NewWorkerAPIYARPCClient(clientConfig),\n apiv1.NewVisibilityAPIYARPCClient(clientConfig),\n )\n}\n'})}),"\n",(0,t.jsxs)(n.p,{children:["Note also that the ",(0,t.jsx)(n.code,{children:"HostPort"})," variable must be changed to target the gRPC listener port of the Cadence cluster (typically, 7833)."]}),"\n",(0,t.jsxs)(n.p,{children:["Finally, gRPC can also support TLS connections between Go clients and the Cadence server. This requires the following alterations to the imported packages, and the ",(0,t.jsx)(n.code,{children:"buildCadenceClient"})," function. Note that this also requires you replace ",(0,t.jsx)(n.code,{children:'"path/to/cert/file"'})," in the function with a path to a valid certificate file matching the TLS configuration of the Cadence server."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-go",children:'\nimport (\n\n "fmt"\n\n "go.uber.org/cadence/.gen/go/cadence"\n "go.uber.org/cadence/.gen/go/cadence/workflowserviceclient"\n "go.uber.org/cadence/compatibility"\n "go.uber.org/cadence/worker"\n\n apiv1 "github.com/cadence-workflow/cadence-idl/go/proto/api/v1"\n "github.com/uber-go/tally"\n "go.uber.org/zap"\n "go.uber.org/zap/zapcore"\n "go.uber.org/yarpc"\n "go.uber.org/yarpc/transport/grpc"\n "go.uber.org/yarpc/peer"\n "go.uber.org/yarpc/peer/hostport"\n\n "crypto/tls"\n "crypto/x509"\n "io/ioutil"\n\n "google.golang.org/grpc/credentials"\n)\n\n.\n.\n.\n\nfunc buildCadenceClient() workflowserviceclient.Interface {\n grpcTransport := grpc.NewTransport()\n var dialOptions []grpc.DialOption\n\n caCert, err := ioutil.ReadFile("/path/to/cert/file")\n if err != nil {\n fmt.Printf("Failed to load server CA certificate: %v", zap.Error(err))\n }\n\n caCertPool := x509.NewCertPool()\n if !caCertPool.AppendCertsFromPEM(caCert) {\n fmt.Errorf("Failed to add server CA\'s certificate")\n }\n\n tlsConfig := tls.Config{\n RootCAs: caCertPool,\n }\n\n creds := credentials.NewTLS(&tlsConfig)\n dialOptions = append(dialOptions, grpc.DialerCredentials(creds))\n\n dialer := grpcTransport.NewDialer(dialOptions...)\n outbound := grpcTransport.NewOutbound(\n peer.NewSingle(hostport.PeerIdentifier(HostPort), dialer)\n )\n\n dispatcher := yarpc.NewDispatcher(yarpc.Config{\n Name: ClientName,\n Outbounds: yarpc.Outbounds{\n CadenceService: {Unary: outbound},\n },\n })\n if err := dispatcher.Start(); err != nil {\n panic("Failed to start dispatcher")\n }\n\n clientConfig := dispatcher.ClientConfig(CadenceService)\n\n return compatibility.NewThrift2ProtoAdapter(\n apiv1.NewDomainAPIYARPCClient(clientConfig),\n apiv1.NewWorkflowAPIYARPCClient(clientConfig),\n apiv1.NewWorkerAPIYARPCClient(clientConfig),\n apiv1.NewVisibilityAPIYARPCClient(clientConfig),\n )\n}\n'})})]})}function p(e={}){const{wrapper:n}={...(0,i.R)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(d,{...e})}):d(e)}},8453:(e,n,r)=>{r.d(n,{R:()=>a,x:()=>c});var o=r(6540);const t={},i=o.createContext(t);function a(e){const n=o.useContext(i);return o.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function c(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(t):e.components||t:a(e.components),o.createElement(i.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/2b58a6fe.b463a0c8.js b/assets/js/2b58a6fe.b463a0c8.js deleted file mode 100644 index 8a486c4ae..000000000 --- a/assets/js/2b58a6fe.b463a0c8.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[3190],{5490:(e,n,r)=>{r.r(n),r.d(n,{assets:()=>s,contentTitle:()=>c,default:()=>p,frontMatter:()=>a,metadata:()=>o,toc:()=>l});const o=JSON.parse('{"id":"go-client/workers","title":"Worker service","description":"A or service is a service that hosts the and implementations. The polls the Cadence service fortaskstask, and communicates execution results back to the Cadence service.Worker: services are developed, deployed, and operated by Cadence customers.","source":"@site/docs/05-go-client/01-workers.md","sourceDirName":"05-go-client","slug":"/go-client/workers","permalink":"/docs/go-client/workers","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/05-go-client/01-workers.md","tags":[],"version":"current","sidebarPosition":1,"frontMatter":{"layout":"default","title":"Worker service","permalink":"/docs/go-client/workers"},"sidebar":"docsSidebar","previous":{"title":"Introduction","permalink":"/docs/go-client/"},"next":{"title":"Creating workflows","permalink":"/docs/go-client/create-workflows"}}');var t=r(4848),i=r(8453);const a={layout:"default",title:"Worker service",permalink:"/docs/go-client/workers"},c="Worker service",s={},l=[];function d(e){const n={code:"code",em:"em",h1:"h1",header:"header",p:"p",pre:"pre",...(0,i.R)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.header,{children:(0,t.jsx)(n.h1,{id:"worker-service",children:"Worker service"})}),"\n",(0,t.jsxs)(n.p,{children:["A worker or ",(0,t.jsx)(n.em,{children:"worker service"})," is a service that hosts the workflow and activity implementations. The worker polls the ",(0,t.jsx)(n.em,{children:"Cadence service"})," for tasks, performs those tasks, and communicates task execution results back to the ",(0,t.jsx)(n.em,{children:"Cadence service"}),". Worker services are developed, deployed, and operated by Cadence customers."]}),"\n",(0,t.jsx)(n.p,{children:"You can run a Cadence worker in a new or an existing service. Use the framework APIs to start the Cadence worker and link in all activity and workflow implementations that you require the service to execute."}),"\n",(0,t.jsx)(n.p,{children:"The following is an example worker service utilising tchannel, one of the two transport protocols supported by Cadence."}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-go",children:'package main\n\nimport (\n\n "go.uber.org/cadence/.gen/go/cadence"\n "go.uber.org/cadence/.gen/go/cadence/workflowserviceclient"\n "go.uber.org/cadence/worker"\n\n "github.com/uber-go/tally"\n "go.uber.org/zap"\n "go.uber.org/zap/zapcore"\n "go.uber.org/yarpc"\n "go.uber.org/yarpc/api/transport"\n "go.uber.org/yarpc/transport/tchannel"\n)\n\nvar HostPort = "127.0.0.1:7933"\nvar Domain = "SimpleDomain"\nvar TaskListName = "SimpleWorker"\nvar ClientName = "SimpleWorker"\nvar CadenceService = "cadence-frontend"\n\nfunc main() {\n startWorker(buildLogger(), buildCadenceClient())\n}\n\nfunc buildLogger() *zap.Logger {\n config := zap.NewDevelopmentConfig()\n config.Level.SetLevel(zapcore.InfoLevel)\n\n var err error\n logger, err := config.Build()\n if err != nil {\n panic("Failed to setup logger")\n }\n\n return logger\n}\n\nfunc buildCadenceClient() workflowserviceclient.Interface {\n ch, err := tchannel.NewChannelTransport(tchannel.ServiceName(ClientName))\n if err != nil {\n panic("Failed to setup tchannel")\n }\n dispatcher := yarpc.NewDispatcher(yarpc.Config{\n Name: ClientName,\n Outbounds: yarpc.Outbounds{\n CadenceService: {Unary: ch.NewSingleOutbound(HostPort)},\n },\n })\n if err := dispatcher.Start(); err != nil {\n panic("Failed to start dispatcher")\n }\n\n return workflowserviceclient.New(dispatcher.ClientConfig(CadenceService))\n}\n\nfunc startWorker(logger *zap.Logger, service workflowserviceclient.Interface) {\n // TaskListName identifies set of client workflows, activities, and workers.\n // It could be your group or client or application name.\n workerOptions := worker.Options{\n Logger: logger,\n MetricsScope: tally.NewTestScope(TaskListName, map[string]string{}),\n }\n\n worker := worker.New(\n service,\n Domain,\n TaskListName,\n workerOptions)\n err := worker.Start()\n if err != nil {\n panic("Failed to start worker")\n }\n\n logger.Info("Started Worker.", zap.String("worker", TaskListName))\n}\n'})}),"\n",(0,t.jsxs)(n.p,{children:["The other supported transport protocol is gRPC. A worker service using gRPC can be set up in similar fashion, but the ",(0,t.jsx)(n.code,{children:"buildCadenceClient"})," function will need the following alterations, and some of the imported packages need to change."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-go",children:'\nimport (\n\n "go.uber.org/cadence/.gen/go/cadence"\n "go.uber.org/cadence/.gen/go/cadence/workflowserviceclient"\n "go.uber.org/cadence/compatibility"\n "go.uber.org/cadence/worker"\n\n apiv1 "github.com/cadence-workflow/cadence-idl/go/proto/api/v1"\n "github.com/uber-go/tally"\n "go.uber.org/zap"\n "go.uber.org/zap/zapcore"\n "go.uber.org/yarpc"\n "go.uber.org/yarpc/transport/grpc"\n)\n\n.\n.\n.\n\nfunc buildCadenceClient() workflowserviceclient.Interface {\n\n dispatcher := yarpc.NewDispatcher(yarpc.Config{\n Name: ClientName,\n Outbounds: yarpc.Outbounds{\n CadenceService: {Unary: grpc.NewTransport().NewSingleOutbound(HostPort)},\n },\n })\n if err := dispatcher.Start(); err != nil {\n panic("Failed to start dispatcher")\n }\n\n clientConfig := dispatcher.ClientConfig(CadenceService)\n\n return compatibility.NewThrift2ProtoAdapter(\n apiv1.NewDomainAPIYARPCClient(clientConfig),\n apiv1.NewWorkflowAPIYARPCClient(clientConfig),\n apiv1.NewWorkerAPIYARPCClient(clientConfig),\n apiv1.NewVisibilityAPIYARPCClient(clientConfig),\n )\n}\n'})}),"\n",(0,t.jsxs)(n.p,{children:["Note also that the ",(0,t.jsx)(n.code,{children:"HostPort"})," variable must be changed to target the gRPC listener port of the Cadence cluster (typically, 7833)."]}),"\n",(0,t.jsxs)(n.p,{children:["Finally, gRPC can also support TLS connections between Go clients and the Cadence server. This requires the following alterations to the imported packages, and the ",(0,t.jsx)(n.code,{children:"buildCadenceClient"})," function. Note that this also requires you replace ",(0,t.jsx)(n.code,{children:'"path/to/cert/file"'})," in the function with a path to a valid certificate file matching the TLS configuration of the Cadence server."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-go",children:'\nimport (\n\n "fmt"\n\n "go.uber.org/cadence/.gen/go/cadence"\n "go.uber.org/cadence/.gen/go/cadence/workflowserviceclient"\n "go.uber.org/cadence/compatibility"\n "go.uber.org/cadence/worker"\n\n apiv1 "github.com/cadence-workflow/cadence-idl/go/proto/api/v1"\n "github.com/uber-go/tally"\n "go.uber.org/zap"\n "go.uber.org/zap/zapcore"\n "go.uber.org/yarpc"\n "go.uber.org/yarpc/transport/grpc"\n "go.uber.org/yarpc/peer"\n "go.uber.org/yarpc/peer/hostport"\n\n "crypto/tls"\n "crypto/x509"\n "io/ioutil"\n\n "google.golang.org/grpc/credentials"\n)\n\n.\n.\n.\n\nfunc buildCadenceClient() workflowserviceclient.Interface {\n grpcTransport := grpc.NewTransport()\n var dialOptions []grpc.DialOption\n\n caCert, err := ioutil.ReadFile("/path/to/cert/file")\n if err != nil {\n fmt.Printf("Failed to load server CA certificate: %v", zap.Error(err))\n }\n\n caCertPool := x509.NewCertPool()\n if !caCertPool.AppendCertsFromPEM(caCert) {\n fmt.Errorf("Failed to add server CA\'s certificate")\n }\n\n tlsConfig := tls.Config{\n RootCAs: caCertPool,\n }\n\n creds := credentials.NewTLS(&tlsConfig)\n dialOptions = append(dialOptions, grpc.DialerCredentials(creds))\n\n dialer := grpcTransport.NewDialer(dialOptions...)\n outbound := grpcTransport.NewOutbound(\n peer.NewSingle(hostport.PeerIdentifier(HostPort), dialer)\n )\n\n dispatcher := yarpc.NewDispatcher(yarpc.Config{\n Name: ClientName,\n Outbounds: yarpc.Outbounds{\n CadenceService: {Unary: outbound},\n },\n })\n if err := dispatcher.Start(); err != nil {\n panic("Failed to start dispatcher")\n }\n\n clientConfig := dispatcher.ClientConfig(CadenceService)\n\n return compatibility.NewThrift2ProtoAdapter(\n apiv1.NewDomainAPIYARPCClient(clientConfig),\n apiv1.NewWorkflowAPIYARPCClient(clientConfig),\n apiv1.NewWorkerAPIYARPCClient(clientConfig),\n apiv1.NewVisibilityAPIYARPCClient(clientConfig),\n )\n}\n'})})]})}function p(e={}){const{wrapper:n}={...(0,i.R)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(d,{...e})}):d(e)}},8453:(e,n,r)=>{r.d(n,{R:()=>a,x:()=>c});var o=r(6540);const t={},i=o.createContext(t);function a(e){const n=o.useContext(i);return o.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function c(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(t):e.components||t:a(e.components),o.createElement(i.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/2b6d3152.b9f02f3e.js b/assets/js/2b6d3152.b9f02f3e.js new file mode 100644 index 000000000..05060848a --- /dev/null +++ b/assets/js/2b6d3152.b9f02f3e.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[4468],{4450:e=>{e.exports=JSON.parse('{"tag":{"label":"Deep Dives","permalink":"/Cadence-Docs/blog/tags/deep-dives","description":"Deep Dives tag description","allTagsPath":"/Cadence-Docs/blog/tags","count":10,"unlisted":false},"listMetadata":{"permalink":"/Cadence-Docs/blog/tags/deep-dives","page":1,"postsPerPage":10,"totalPages":1,"totalCount":10,"blogDescription":"The latest news and updates from the Cadence team","blogTitle":"Cadence Blog"}}')}}]); \ No newline at end of file diff --git a/assets/js/2bc7f48b.58c6c915.js b/assets/js/2bc7f48b.58c6c915.js new file mode 100644 index 000000000..139fc727b --- /dev/null +++ b/assets/js/2bc7f48b.58c6c915.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[5861],{6082:(e,t,i)=>{i.r(t),i.d(t,{assets:()=>c,contentTitle:()=>a,default:()=>h,frontMatter:()=>s,metadata:()=>n,toc:()=>l});const n=JSON.parse('{"id":"go-client/retries","title":"Activity and workflow retries","description":"Activitiesworkflow can fail due to various intermediate conditions. In those cases, we want","source":"@site/docs/05-go-client/06-retries.md","sourceDirName":"05-go-client","slug":"/go-client/retries","permalink":"/Cadence-Docs/docs/go-client/retries","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/05-go-client/06-retries.md","tags":[],"version":"current","sidebarPosition":6,"frontMatter":{"layout":"default","title":"Activity and workflow retries","permalink":"/docs/go-client/retries"},"sidebar":"docsSidebar","previous":{"title":"Child workflows","permalink":"/Cadence-Docs/docs/go-client/child-workflows"},"next":{"title":"Error handling","permalink":"/Cadence-Docs/docs/go-client/error-handling"}}');var r=i(4848),o=i(8453);const s={layout:"default",title:"Activity and workflow retries",permalink:"/docs/go-client/retries"},a="Activity and workflow retries",c={},l=[];function d(e){const t={code:"code",h1:"h1",header:"header",li:"li",p:"p",pre:"pre",ul:"ul",...(0,o.R)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(t.header,{children:(0,r.jsx)(t.h1,{id:"activity-and-workflow-retries",children:"Activity and workflow retries"})}),"\n",(0,r.jsx)(t.p,{children:"Activities and workflows can fail due to various intermediate conditions. In those cases, we want\nto retry the failed activity or child workflow or even the parent workflow. This can be achieved\nby supplying an optional retry policy. A retry policy looks like the following:"}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{className:"language-go",children:'// RetryPolicy defines the retry policy.\nRetryPolicy struct {\n // Backoff interval for the first retry. If coefficient is 1.0 then it is used for all retries.\n // Required, no default value.\n InitialInterval time.Duration\n\n // Coefficient used to calculate the next retry backoff interval.\n // The next retry interval is previous interval multiplied by this coefficient.\n // Must be 1 or larger. Default is 2.0.\n BackoffCoefficient float64\n\n // Maximum backoff interval between retries. Exponential backoff leads to interval increase.\n // This value is the cap of the interval. Default is 100x of initial interval.\n MaximumInterval time.Duration\n\n // Maximum time to retry. Either ExpirationInterval or MaximumAttempts is required.\n // When exceeded the retries stop even if maximum retries is not reached yet.\n // First (non-retry) attempt is unaffected by this field and is guaranteed to run \n // for the entirety of the workflow timeout duration (ExecutionStartToCloseTimeoutSeconds).\n ExpirationInterval time.Duration\n\n // Maximum number of attempts. When exceeded the retries stop even if not expired yet.\n // If not set or set to 0, it means unlimited, and relies on ExpirationInterval to stop.\n // Either MaximumAttempts or ExpirationInterval is required.\n MaximumAttempts int32\n\n // Non-Retriable errors. This is optional. Cadence server will stop retry if error reason matches this list.\n // Error reason for custom error is specified when your activity/workflow returns cadence.NewCustomError(reason).\n // Error reason for panic error is "cadenceInternal:Panic".\n // Error reason for any other error is "cadenceInternal:Generic".\n // Error reason for timeouts is: "cadenceInternal:Timeout TIMEOUT_TYPE". TIMEOUT_TYPE could be START_TO_CLOSE or HEARTBEAT.\n // Note that cancellation is not a failure, so it won\'t be retried.\n NonRetriableErrorReasons []string\n}\n'})}),"\n",(0,r.jsxs)(t.p,{children:["To enable retry, supply a custom retry policy to ",(0,r.jsx)(t.code,{children:"ActivityOptions"})," or ",(0,r.jsx)(t.code,{children:"ChildWorkflowOptions"}),"\nwhen you execute them."]}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{className:"language-go",children:"expiration := time.Minute * 10\nretryPolicy := &cadence.RetryPolicy{\n InitialInterval: time.Second,\n BackoffCoefficient: 2,\n MaximumInterval: expiration,\n ExpirationInterval: time.Minute * 10,\n MaximumAttempts: 5,\n}\nao := workflow.ActivityOptions{\n ScheduleToStartTimeout: expiration,\n StartToCloseTimeout: expiration,\n HeartbeatTimeout: time.Second * 30,\n RetryPolicy: retryPolicy, // Enable retry.\n}\nctx = workflow.WithActivityOptions(ctx, ao)\nactivityFuture := workflow.ExecuteActivity(ctx, SampleActivity, params)\n"})}),"\n",(0,r.jsx)(t.p,{children:"If activity heartbeat its progress before it failed, the retry attempt will contain the progress\nso activity implementation could resume from failed progress like:"}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{className:"language-go",children:"func SampleActivity(ctx context.Context, inputArg InputParams) error {\n startIdx := inputArg.StartIndex\n if activity.HasHeartbeatDetails(ctx) {\n // Recover from finished progress.\n var finishedIndex int\n if err := activity.GetHeartbeatDetails(ctx, &finishedIndex); err == nil {\n startIdx = finishedIndex + 1 // Start from next one.\n }\n }\n\n // Normal activity logic...\n for i:=startIdx; i{i.d(t,{R:()=>s,x:()=>a});var n=i(6540);const r={},o=n.createContext(r);function s(e){const t=n.useContext(o);return n.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function a(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:s(e.components),n.createElement(o.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/2bc7f48b.d670efc8.js b/assets/js/2bc7f48b.d670efc8.js deleted file mode 100644 index 584f0b7d9..000000000 --- a/assets/js/2bc7f48b.d670efc8.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[5861],{6082:(e,t,i)=>{i.r(t),i.d(t,{assets:()=>c,contentTitle:()=>a,default:()=>h,frontMatter:()=>s,metadata:()=>r,toc:()=>l});const r=JSON.parse('{"id":"go-client/retries","title":"Activity and workflow retries","description":"Activitiesworkflow can fail due to various intermediate conditions. In those cases, we want","source":"@site/docs/05-go-client/06-retries.md","sourceDirName":"05-go-client","slug":"/go-client/retries","permalink":"/docs/go-client/retries","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/05-go-client/06-retries.md","tags":[],"version":"current","sidebarPosition":6,"frontMatter":{"layout":"default","title":"Activity and workflow retries","permalink":"/docs/go-client/retries"},"sidebar":"docsSidebar","previous":{"title":"Child workflows","permalink":"/docs/go-client/child-workflows"},"next":{"title":"Error handling","permalink":"/docs/go-client/error-handling"}}');var n=i(4848),o=i(8453);const s={layout:"default",title:"Activity and workflow retries",permalink:"/docs/go-client/retries"},a="Activity and workflow retries",c={},l=[];function d(e){const t={code:"code",h1:"h1",header:"header",li:"li",p:"p",pre:"pre",ul:"ul",...(0,o.R)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(t.header,{children:(0,n.jsx)(t.h1,{id:"activity-and-workflow-retries",children:"Activity and workflow retries"})}),"\n",(0,n.jsx)(t.p,{children:"Activities and workflows can fail due to various intermediate conditions. In those cases, we want\nto retry the failed activity or child workflow or even the parent workflow. This can be achieved\nby supplying an optional retry policy. A retry policy looks like the following:"}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{className:"language-go",children:'// RetryPolicy defines the retry policy.\nRetryPolicy struct {\n // Backoff interval for the first retry. If coefficient is 1.0 then it is used for all retries.\n // Required, no default value.\n InitialInterval time.Duration\n\n // Coefficient used to calculate the next retry backoff interval.\n // The next retry interval is previous interval multiplied by this coefficient.\n // Must be 1 or larger. Default is 2.0.\n BackoffCoefficient float64\n\n // Maximum backoff interval between retries. Exponential backoff leads to interval increase.\n // This value is the cap of the interval. Default is 100x of initial interval.\n MaximumInterval time.Duration\n\n // Maximum time to retry. Either ExpirationInterval or MaximumAttempts is required.\n // When exceeded the retries stop even if maximum retries is not reached yet.\n // First (non-retry) attempt is unaffected by this field and is guaranteed to run \n // for the entirety of the workflow timeout duration (ExecutionStartToCloseTimeoutSeconds).\n ExpirationInterval time.Duration\n\n // Maximum number of attempts. When exceeded the retries stop even if not expired yet.\n // If not set or set to 0, it means unlimited, and relies on ExpirationInterval to stop.\n // Either MaximumAttempts or ExpirationInterval is required.\n MaximumAttempts int32\n\n // Non-Retriable errors. This is optional. Cadence server will stop retry if error reason matches this list.\n // Error reason for custom error is specified when your activity/workflow returns cadence.NewCustomError(reason).\n // Error reason for panic error is "cadenceInternal:Panic".\n // Error reason for any other error is "cadenceInternal:Generic".\n // Error reason for timeouts is: "cadenceInternal:Timeout TIMEOUT_TYPE". TIMEOUT_TYPE could be START_TO_CLOSE or HEARTBEAT.\n // Note that cancellation is not a failure, so it won\'t be retried.\n NonRetriableErrorReasons []string\n}\n'})}),"\n",(0,n.jsxs)(t.p,{children:["To enable retry, supply a custom retry policy to ",(0,n.jsx)(t.code,{children:"ActivityOptions"})," or ",(0,n.jsx)(t.code,{children:"ChildWorkflowOptions"}),"\nwhen you execute them."]}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{className:"language-go",children:"expiration := time.Minute * 10\nretryPolicy := &cadence.RetryPolicy{\n InitialInterval: time.Second,\n BackoffCoefficient: 2,\n MaximumInterval: expiration,\n ExpirationInterval: time.Minute * 10,\n MaximumAttempts: 5,\n}\nao := workflow.ActivityOptions{\n ScheduleToStartTimeout: expiration,\n StartToCloseTimeout: expiration,\n HeartbeatTimeout: time.Second * 30,\n RetryPolicy: retryPolicy, // Enable retry.\n}\nctx = workflow.WithActivityOptions(ctx, ao)\nactivityFuture := workflow.ExecuteActivity(ctx, SampleActivity, params)\n"})}),"\n",(0,n.jsx)(t.p,{children:"If activity heartbeat its progress before it failed, the retry attempt will contain the progress\nso activity implementation could resume from failed progress like:"}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{className:"language-go",children:"func SampleActivity(ctx context.Context, inputArg InputParams) error {\n startIdx := inputArg.StartIndex\n if activity.HasHeartbeatDetails(ctx) {\n // Recover from finished progress.\n var finishedIndex int\n if err := activity.GetHeartbeatDetails(ctx, &finishedIndex); err == nil {\n startIdx = finishedIndex + 1 // Start from next one.\n }\n }\n\n // Normal activity logic...\n for i:=startIdx; i{i.d(t,{R:()=>s,x:()=>a});var r=i(6540);const n={},o=r.createContext(n);function s(e){const t=r.useContext(o);return r.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function a(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(n):e.components||n:s(e.components),r.createElement(o.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/31f8b8ae.06ee186c.js b/assets/js/31f8b8ae.f5c35a14.js similarity index 53% rename from assets/js/31f8b8ae.06ee186c.js rename to assets/js/31f8b8ae.f5c35a14.js index 9007092cb..8f6abccc9 100644 --- a/assets/js/31f8b8ae.06ee186c.js +++ b/assets/js/31f8b8ae.f5c35a14.js @@ -1 +1 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[4569],{9500:(e,o,t)=>{t.r(o),t.d(o,{assets:()=>s,contentTitle:()=>c,default:()=>h,frontMatter:()=>i,metadata:()=>n,toc:()=>d});var n=t(6850),r=t(4848),a=t(8453);const i={title:"Cadence Repositories Have Moved!",description:"Discover the latest update for Cadence Workflow! Our GitHub repositories have moved to the new cadence-workflow organization. Learn more about the migration, including updated links and how this change supports the growing Cadence community",authors:"ibarrajo",tags:["announcement"],date:"2024-11-18T14:00"},c=void 0,s={authorsImageUrls:[void 0]},d=[];function l(e){const o={a:"a",code:"code",p:"p",...(0,a.R)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsxs)(o.p,{children:["We\u2019re excited to announce that all Cadence GitHub repositories have been consolidated under the ",(0,r.jsx)(o.a,{href:"https://github.com/cadence-workflow",children:"cadence-workflow"})," organization! \ud83c\udf89"]}),"\n",(0,r.jsxs)(o.p,{children:["Previously, Cadence repositories were distributed across multiple organizations at Uber: ",(0,r.jsx)(o.a,{href:"https://github.com/uber",children:(0,r.jsx)(o.code,{children:"uber"})}),", ",(0,r.jsx)(o.a,{href:"https://github.com/uber-go",children:(0,r.jsx)(o.code,{children:"uber-go"})}),", ",(0,r.jsx)(o.a,{href:"https://github.com/uber-common",children:(0,r.jsx)(o.code,{children:"uber-common"})}),". To improve developer cohesiveness and simplify access, the Cadence Core team has migrated all open-source repositories to the ",(0,r.jsx)(o.a,{href:"https://github.com/cadence-workflow",children:(0,r.jsx)(o.code,{children:"cadence-workflow"})})," organization."]}),"\n",(0,r.jsx)(o.p,{children:"For example, our main repository has moved from:"}),"\n",(0,r.jsxs)(o.p,{children:["\ud83d\udc49 ",(0,r.jsx)(o.a,{href:"https://github.com/cadence-workflow/cadence",children:"uber/cadence"})]}),"\n",(0,r.jsx)(o.p,{children:"To its new home:"}),"\n",(0,r.jsxs)(o.p,{children:["\ud83d\udc49 ",(0,r.jsx)(o.a,{href:"https://github.com/cadence-workflow/cadence",children:"cadence-workflow/cadence"})]}),"\n",(0,r.jsxs)(o.p,{children:["You can find the full list of Cadence repositories here \ud83d\udc49 ",(0,r.jsx)(o.a,{href:"https://github.com/orgs/cadence-workflow/repositories",children:"orgs/cadence-workflow/repositories"})]})]})}function h(e={}){const{wrapper:o}={...(0,a.R)(),...e.components};return o?(0,r.jsx)(o,{...e,children:(0,r.jsx)(l,{...e})}):l(e)}},8453:(e,o,t)=>{t.d(o,{R:()=>i,x:()=>c});var n=t(6540);const r={},a=n.createContext(r);function i(e){const o=n.useContext(a);return n.useMemo((function(){return"function"==typeof e?e(o):{...o,...e}}),[o,e])}function c(e){let o;return o=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:i(e.components),n.createElement(a.Provider,{value:o},e.children)}},6850:e=>{e.exports=JSON.parse('{"permalink":"/blog/2024/11/18/cadence-workflows-github-organization","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2024-11-18-cadence-workflows-github-organization.md","source":"@site/blog/2024-11-18-cadence-workflows-github-organization.md","title":"Cadence Repositories Have Moved!","description":"Discover the latest update for Cadence Workflow! Our GitHub repositories have moved to the new cadence-workflow organization. Learn more about the migration, including updated links and how this change supports the growing Cadence community","date":"2024-11-18T14:00:00.000Z","tags":[{"inline":false,"label":"Announcement","permalink":"/blog/tags/announcements","description":"Announcement tag description"}],"readingTime":0.6,"hasTruncateMarker":true,"authors":[{"name":"Josu\xe9 Alexander Ibarra","title":"Developer Advocate @ Uber","url":"https://github.com/ibarrajo/","page":{"permalink":"/blog/authors/ibarrajo"},"socials":{"github":"https://github.com/ibarrajo","linkedin":"https://www.linkedin.com/in/elninja/"},"imageURL":"https://github.com/ibarrajo.png","key":"ibarrajo"}],"frontMatter":{"title":"Cadence Repositories Have Moved!","description":"Discover the latest update for Cadence Workflow! Our GitHub repositories have moved to the new cadence-workflow organization. Learn more about the migration, including updated links and how this change supports the growing Cadence community","authors":"ibarrajo","tags":["announcement"],"date":"2024-11-18T14:00"},"unlisted":false,"nextItem":{"title":"Zonal Isolation for Cadence Workflows","permalink":"/blog/zonal-isolation-v1/zonal-isolation-v1"}}')}}]); \ No newline at end of file +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[4569],{9500:(e,o,n)=>{n.r(o),n.d(o,{assets:()=>s,contentTitle:()=>c,default:()=>h,frontMatter:()=>i,metadata:()=>t,toc:()=>d});var t=n(6850),r=n(4848),a=n(8453);const i={title:"Cadence Repositories Have Moved!",description:"Discover the latest update for Cadence Workflow! Our GitHub repositories have moved to the new cadence-workflow organization. Learn more about the migration, including updated links and how this change supports the growing Cadence community",authors:"ibarrajo",tags:["announcement"],date:"2024-11-18T14:00"},c=void 0,s={authorsImageUrls:[void 0]},d=[];function l(e){const o={a:"a",code:"code",p:"p",...(0,a.R)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsxs)(o.p,{children:["We\u2019re excited to announce that all Cadence GitHub repositories have been consolidated under the ",(0,r.jsx)(o.a,{href:"https://github.com/cadence-workflow",children:"cadence-workflow"})," organization! \ud83c\udf89"]}),"\n",(0,r.jsxs)(o.p,{children:["Previously, Cadence repositories were distributed across multiple organizations at Uber: ",(0,r.jsx)(o.a,{href:"https://github.com/uber",children:(0,r.jsx)(o.code,{children:"uber"})}),", ",(0,r.jsx)(o.a,{href:"https://github.com/uber-go",children:(0,r.jsx)(o.code,{children:"uber-go"})}),", ",(0,r.jsx)(o.a,{href:"https://github.com/uber-common",children:(0,r.jsx)(o.code,{children:"uber-common"})}),". To improve developer cohesiveness and simplify access, the Cadence Core team has migrated all open-source repositories to the ",(0,r.jsx)(o.a,{href:"https://github.com/cadence-workflow",children:(0,r.jsx)(o.code,{children:"cadence-workflow"})})," organization."]}),"\n",(0,r.jsx)(o.p,{children:"For example, our main repository has moved from:"}),"\n",(0,r.jsxs)(o.p,{children:["\ud83d\udc49 ",(0,r.jsx)(o.a,{href:"https://github.com/cadence-workflow/cadence",children:"uber/cadence"})]}),"\n",(0,r.jsx)(o.p,{children:"To its new home:"}),"\n",(0,r.jsxs)(o.p,{children:["\ud83d\udc49 ",(0,r.jsx)(o.a,{href:"https://github.com/cadence-workflow/cadence",children:"cadence-workflow/cadence"})]}),"\n",(0,r.jsxs)(o.p,{children:["You can find the full list of Cadence repositories here \ud83d\udc49 ",(0,r.jsx)(o.a,{href:"https://github.com/orgs/cadence-workflow/repositories",children:"orgs/cadence-workflow/repositories"})]})]})}function h(e={}){const{wrapper:o}={...(0,a.R)(),...e.components};return o?(0,r.jsx)(o,{...e,children:(0,r.jsx)(l,{...e})}):l(e)}},8453:(e,o,n)=>{n.d(o,{R:()=>i,x:()=>c});var t=n(6540);const r={},a=t.createContext(r);function i(e){const o=t.useContext(a);return t.useMemo((function(){return"function"==typeof e?e(o):{...o,...e}}),[o,e])}function c(e){let o;return o=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:i(e.components),t.createElement(a.Provider,{value:o},e.children)}},6850:e=>{e.exports=JSON.parse('{"permalink":"/Cadence-Docs/blog/2024/11/18/cadence-workflows-github-organization","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2024-11-18-cadence-workflows-github-organization.md","source":"@site/blog/2024-11-18-cadence-workflows-github-organization.md","title":"Cadence Repositories Have Moved!","description":"Discover the latest update for Cadence Workflow! Our GitHub repositories have moved to the new cadence-workflow organization. Learn more about the migration, including updated links and how this change supports the growing Cadence community","date":"2024-11-18T14:00:00.000Z","tags":[{"inline":false,"label":"Announcement","permalink":"/Cadence-Docs/blog/tags/announcements","description":"Announcement tag description"}],"readingTime":0.6,"hasTruncateMarker":true,"authors":[{"name":"Josu\xe9 Alexander Ibarra","title":"Developer Advocate @ Uber","url":"https://github.com/ibarrajo/","page":{"permalink":"/Cadence-Docs/blog/authors/ibarrajo"},"socials":{"github":"https://github.com/ibarrajo","linkedin":"https://www.linkedin.com/in/elninja/"},"imageURL":"https://github.com/ibarrajo.png","key":"ibarrajo"}],"frontMatter":{"title":"Cadence Repositories Have Moved!","description":"Discover the latest update for Cadence Workflow! Our GitHub repositories have moved to the new cadence-workflow organization. Learn more about the migration, including updated links and how this change supports the growing Cadence community","authors":"ibarrajo","tags":["announcement"],"date":"2024-11-18T14:00"},"unlisted":false,"nextItem":{"title":"Zonal Isolation for Cadence Workflows","permalink":"/Cadence-Docs/blog/zonal-isolation-v1/zonal-isolation-v1"}}')}}]); \ No newline at end of file diff --git a/assets/js/33348b0e.47f64d26.js b/assets/js/33348b0e.47f64d26.js new file mode 100644 index 000000000..e4eced475 --- /dev/null +++ b/assets/js/33348b0e.47f64d26.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[4739],{2399:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>c,contentTitle:()=>s,default:()=>p,frontMatter:()=>r,metadata:()=>o,toc:()=>l});var o=n(2087),a=n(4848),i=n(8453);const r={title:"Cadence Community Spotlight Update - March 2024",date:new Date("2023-03-11T00:00:00.000Z"),authors:"kcorbett-netapp",tags:["community-spotlight"]},s=void 0,c={authorsImageUrls:[void 0]},l=[{value:"Proposal for Cadence Plugin System",id:"proposal-for-cadence-plugin-system",level:2}];function u(e){const t={a:"a",h2:"h2",li:"li",p:"p",ul:"ul",...(0,i.R)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsxs)(t.p,{children:["Welcome back to the latest in our regular Cadence community spotlight updates where we aim to deliver you news from in and around the Cadence community!\nIt\u2019s been a few months since our ",(0,a.jsx)(t.a,{href:"https://cadenceworkflow.io/blog/2023/11/30/community-spotlight-update-november-2023/",children:"last update"}),", so I have a bunch of exciting updates to share."]}),"\n",(0,a.jsx)(t.p,{children:"Let\u2019s get started!"}),"\n",(0,a.jsx)(t.h2,{id:"proposal-for-cadence-plugin-system",children:"Proposal for Cadence Plugin System"}),"\n",(0,a.jsxs)(t.p,{children:["Community member ",(0,a.jsx)(t.a,{href:"https://lt.linkedin.com/in/mantassidlauskas",children:"Mantas Sidlauskas"})," drafted a thorough proposal around putting together a plugin system in Cadence. Aimed at enhancing the flexibility of integrating various components like storage, document search, and archival, this system encourages the use of external plugins, promoting innovation and reducing dependency complications. Your insights and feedback are crucial; learn more and contribute your thoughts at the link below:"]}),"\n",(0,a.jsxs)(t.ul,{children:["\n",(0,a.jsx)(t.li,{children:(0,a.jsx)(t.a,{href:"https://github.com/cadence-workflow/cadence/issues/5593",children:"Cadence Plugin System Proposal"})}),"\n"]}),"\n",(0,a.jsx)(t.p,{children:"A huge thank you to Mantas for initiating this work. This is an excellent example of how we can collaborate together to bring about new features that benefit us all."})]})}function p(e={}){const{wrapper:t}={...(0,i.R)(),...e.components};return t?(0,a.jsx)(t,{...e,children:(0,a.jsx)(u,{...e})}):u(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>r,x:()=>s});var o=n(6540);const a={},i=o.createContext(a);function r(e){const t=o.useContext(i);return o.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function s(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:r(e.components),o.createElement(i.Provider,{value:t},e.children)}},2087:e=>{e.exports=JSON.parse('{"permalink":"/Cadence-Docs/blog/2024/3/11/community-spotlight-update-march-2024","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2024-3-11-community-spotlight-update-march-2024.md","source":"@site/blog/2024-3-11-community-spotlight-update-march-2024.md","title":"Cadence Community Spotlight Update - March 2024","description":"Welcome back to the latest in our regular Cadence community spotlight updates where we aim to deliver you news from in and around the Cadence community!","date":"2023-03-11T00:00:00.000Z","tags":[{"inline":false,"label":"Community Spotlight","permalink":"/Cadence-Docs/blog/tags/community-spotlights","description":"Community Spotlight tag description"}],"readingTime":2.91,"hasTruncateMarker":true,"authors":[{"name":"Kevin Corbett","title":"Open Source Community Manager | @instaclustr @NetApp","url":"https://github.com/kcorbett-netapp","page":{"permalink":"/Cadence-Docs/blog/authors/kcorbett-netapp"},"socials":{"linkedin":"https://www.linkedin.com/in/kcorb95/","github":"https://github.com/kcorbett-netapp"},"imageURL":"https://github.com/kcorbett-netapp.png","key":"kcorbett-netapp"}],"frontMatter":{"title":"Cadence Community Spotlight Update - March 2024","date":"2023-03-11T00:00:00.000Z","authors":"kcorbett-netapp","tags":["community-spotlight"]},"unlisted":false,"prevItem":{"title":"Cadence Community Spotlight Update - March 2023","permalink":"/Cadence-Docs/blog/2023/03/31/community-spotlight-march-2023"},"nextItem":{"title":"Cadence Community Spotlight Update - February 2023","permalink":"/Cadence-Docs/blog/2023/02/28/community-spotlight-february"}}')}}]); \ No newline at end of file diff --git a/assets/js/33348b0e.cd91b4b1.js b/assets/js/33348b0e.cd91b4b1.js deleted file mode 100644 index 266e14229..000000000 --- a/assets/js/33348b0e.cd91b4b1.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[4739],{2399:(t,e,n)=>{n.r(e),n.d(e,{assets:()=>c,contentTitle:()=>s,default:()=>p,frontMatter:()=>r,metadata:()=>o,toc:()=>l});var o=n(2087),a=n(4848),i=n(8453);const r={title:"Cadence Community Spotlight Update - March 2024",date:new Date("2023-03-11T00:00:00.000Z"),authors:"kcorbett-netapp",tags:["community-spotlight"]},s=void 0,c={authorsImageUrls:[void 0]},l=[{value:"Proposal for Cadence Plugin System",id:"proposal-for-cadence-plugin-system",level:2}];function u(t){const e={a:"a",h2:"h2",li:"li",p:"p",ul:"ul",...(0,i.R)(),...t.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsxs)(e.p,{children:["Welcome back to the latest in our regular Cadence community spotlight updates where we aim to deliver you news from in and around the Cadence community!\nIt\u2019s been a few months since our ",(0,a.jsx)(e.a,{href:"https://cadenceworkflow.io/blog/2023/11/30/community-spotlight-update-november-2023/",children:"last update"}),", so I have a bunch of exciting updates to share."]}),"\n",(0,a.jsx)(e.p,{children:"Let\u2019s get started!"}),"\n",(0,a.jsx)(e.h2,{id:"proposal-for-cadence-plugin-system",children:"Proposal for Cadence Plugin System"}),"\n",(0,a.jsxs)(e.p,{children:["Community member ",(0,a.jsx)(e.a,{href:"https://lt.linkedin.com/in/mantassidlauskas",children:"Mantas Sidlauskas"})," drafted a thorough proposal around putting together a plugin system in Cadence. Aimed at enhancing the flexibility of integrating various components like storage, document search, and archival, this system encourages the use of external plugins, promoting innovation and reducing dependency complications. Your insights and feedback are crucial; learn more and contribute your thoughts at the link below:"]}),"\n",(0,a.jsxs)(e.ul,{children:["\n",(0,a.jsx)(e.li,{children:(0,a.jsx)(e.a,{href:"https://github.com/cadence-workflow/cadence/issues/5593",children:"Cadence Plugin System Proposal"})}),"\n"]}),"\n",(0,a.jsx)(e.p,{children:"A huge thank you to Mantas for initiating this work. This is an excellent example of how we can collaborate together to bring about new features that benefit us all."})]})}function p(t={}){const{wrapper:e}={...(0,i.R)(),...t.components};return e?(0,a.jsx)(e,{...t,children:(0,a.jsx)(u,{...t})}):u(t)}},8453:(t,e,n)=>{n.d(e,{R:()=>r,x:()=>s});var o=n(6540);const a={},i=o.createContext(a);function r(t){const e=o.useContext(i);return o.useMemo((function(){return"function"==typeof t?t(e):{...e,...t}}),[e,t])}function s(t){let e;return e=t.disableParentContext?"function"==typeof t.components?t.components(a):t.components||a:r(t.components),o.createElement(i.Provider,{value:e},t.children)}},2087:t=>{t.exports=JSON.parse('{"permalink":"/blog/2024/3/11/community-spotlight-update-march-2024","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2024-3-11-community-spotlight-update-march-2024.md","source":"@site/blog/2024-3-11-community-spotlight-update-march-2024.md","title":"Cadence Community Spotlight Update - March 2024","description":"Welcome back to the latest in our regular Cadence community spotlight updates where we aim to deliver you news from in and around the Cadence community!","date":"2023-03-11T00:00:00.000Z","tags":[{"inline":false,"label":"Community Spotlight","permalink":"/blog/tags/community-spotlights","description":"Community Spotlight tag description"}],"readingTime":2.91,"hasTruncateMarker":true,"authors":[{"name":"Kevin Corbett","title":"Open Source Community Manager | @instaclustr @NetApp","url":"https://github.com/kcorbett-netapp","page":{"permalink":"/blog/authors/kcorbett-netapp"},"socials":{"linkedin":"https://www.linkedin.com/in/kcorb95/","github":"https://github.com/kcorbett-netapp"},"imageURL":"https://github.com/kcorbett-netapp.png","key":"kcorbett-netapp"}],"frontMatter":{"title":"Cadence Community Spotlight Update - March 2024","date":"2023-03-11T00:00:00.000Z","authors":"kcorbett-netapp","tags":["community-spotlight"]},"unlisted":false,"prevItem":{"title":"Cadence Community Spotlight Update - March 2023","permalink":"/blog/2023/03/31/community-spotlight-march-2023"},"nextItem":{"title":"Cadence Community Spotlight Update - February 2023","permalink":"/blog/2023/02/28/community-spotlight-february"}}')}}]); \ No newline at end of file diff --git a/assets/js/33cf8314.2949d817.js b/assets/js/33cf8314.5a52ce83.js similarity index 61% rename from assets/js/33cf8314.2949d817.js rename to assets/js/33cf8314.5a52ce83.js index 98bbcda21..86decb1f5 100644 --- a/assets/js/33cf8314.2949d817.js +++ b/assets/js/33cf8314.5a52ce83.js @@ -1 +1 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[6806],{8644:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>c,contentTitle:()=>r,default:()=>u,frontMatter:()=>i,metadata:()=>o,toc:()=>h});var o=n(3258),a=n(4848),s=n(8453);const i={title:"Cadence Community Spotlight Update - January 2023",date:new Date("2023-01-31T00:00:00.000Z"),authors:"sharanf",tags:["community-spotlight"]},r=void 0,c={authorsImageUrls:[void 0]},h=[{value:"Closing Down Cadence Office Hours",id:"closing-down-cadence-office-hours",level:2}];function l(e){const t={a:"a",h2:"h2",p:"p",...(0,s.R)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(t.p,{children:"Happy New Year everyone! Here\u2019s the latest in our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!"}),"\n",(0,a.jsx)(t.p,{children:"Please see below for a roundup of the highlights:"}),"\n",(0,a.jsx)(t.h2,{id:"closing-down-cadence-office-hours",children:"Closing Down Cadence Office Hours"}),"\n",(0,a.jsx)(t.p,{children:"We have been running Office Hours sessions every month since May last year. The aim was to give the community an opportunity to speak directly with some of the Cadence core developers and experts to answer questions on particular issues you may be having. We have found that the most preferred method for community questions has been the support Slack channel so have decided to stop this monthly call."}),"\n",(0,a.jsxs)(t.p,{children:["Thanks very much to ",(0,a.jsx)(t.a,{href:"https://www.linkedin.com/in/enderdemirkaya/",children:"Ender Demirkaya"}),"and the Uber team for making themselves available for these sessions."]}),"\n",(0,a.jsxs)(t.p,{children:["Please remember that if you have question about Cadence or are facing a specific issue then you can post your question in our #support ",(0,a.jsx)(t.a,{href:"http://t.uber.com/cadence-slack",children:"Slack"})," channel. If you also post the details on StackOverflow with the cadence workflow tag then there will be a searchable history for others who encounter the same issue to find a solution."]})]})}function u(e={}){const{wrapper:t}={...(0,s.R)(),...e.components};return t?(0,a.jsx)(t,{...e,children:(0,a.jsx)(l,{...e})}):l(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>i,x:()=>r});var o=n(6540);const a={},s=o.createContext(a);function i(e){const t=o.useContext(s);return o.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function r(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:i(e.components),o.createElement(s.Provider,{value:t},e.children)}},3258:e=>{e.exports=JSON.parse('{"permalink":"/blog/2023/01/31/community-spotlight-january-2023","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2023-01-31-community-spotlight-january-2023.md","source":"@site/blog/2023-01-31-community-spotlight-january-2023.md","title":"Cadence Community Spotlight Update - January 2023","description":"Happy New Year everyone! Here\u2019s the latest in our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!","date":"2023-01-31T00:00:00.000Z","tags":[{"inline":false,"label":"Community Spotlight","permalink":"/blog/tags/community-spotlights","description":"Community Spotlight tag description"}],"readingTime":2.06,"hasTruncateMarker":true,"authors":[{"name":"Sharan Foga","title":"Director of Operations & Customer Success @ Encube Technologies","url":"https://www.linkedin.com/in/sfoga/","page":{"permalink":"/blog/authors/sharanf"},"socials":{"linkedin":"https://www.linkedin.com/in/sfoga/","github":"https://github.com/sharanf"},"imageURL":"https://github.com/sharanf.png","key":"sharanf"}],"frontMatter":{"title":"Cadence Community Spotlight Update - January 2023","date":"2023-01-31T00:00:00.000Z","authors":"sharanf","tags":["community-spotlight"]},"unlisted":false,"prevItem":{"title":"Cadence Community Spotlight Update - February 2023","permalink":"/blog/2023/02/28/community-spotlight-february"},"nextItem":{"title":"Cadence Community Spotlight Update - December 2022","permalink":"/blog/2022/12/23/community-spotlight-december-2022"}}')}}]); \ No newline at end of file +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[6806],{8644:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>c,contentTitle:()=>r,default:()=>u,frontMatter:()=>i,metadata:()=>o,toc:()=>h});var o=n(3258),a=n(4848),s=n(8453);const i={title:"Cadence Community Spotlight Update - January 2023",date:new Date("2023-01-31T00:00:00.000Z"),authors:"sharanf",tags:["community-spotlight"]},r=void 0,c={authorsImageUrls:[void 0]},h=[{value:"Closing Down Cadence Office Hours",id:"closing-down-cadence-office-hours",level:2}];function l(e){const t={a:"a",h2:"h2",p:"p",...(0,s.R)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(t.p,{children:"Happy New Year everyone! Here\u2019s the latest in our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!"}),"\n",(0,a.jsx)(t.p,{children:"Please see below for a roundup of the highlights:"}),"\n",(0,a.jsx)(t.h2,{id:"closing-down-cadence-office-hours",children:"Closing Down Cadence Office Hours"}),"\n",(0,a.jsx)(t.p,{children:"We have been running Office Hours sessions every month since May last year. The aim was to give the community an opportunity to speak directly with some of the Cadence core developers and experts to answer questions on particular issues you may be having. We have found that the most preferred method for community questions has been the support Slack channel so have decided to stop this monthly call."}),"\n",(0,a.jsxs)(t.p,{children:["Thanks very much to ",(0,a.jsx)(t.a,{href:"https://www.linkedin.com/in/enderdemirkaya/",children:"Ender Demirkaya"}),"and the Uber team for making themselves available for these sessions."]}),"\n",(0,a.jsxs)(t.p,{children:["Please remember that if you have question about Cadence or are facing a specific issue then you can post your question in our #support ",(0,a.jsx)(t.a,{href:"http://t.uber.com/cadence-slack",children:"Slack"})," channel. If you also post the details on StackOverflow with the cadence workflow tag then there will be a searchable history for others who encounter the same issue to find a solution."]})]})}function u(e={}){const{wrapper:t}={...(0,s.R)(),...e.components};return t?(0,a.jsx)(t,{...e,children:(0,a.jsx)(l,{...e})}):l(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>i,x:()=>r});var o=n(6540);const a={},s=o.createContext(a);function i(e){const t=o.useContext(s);return o.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function r(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:i(e.components),o.createElement(s.Provider,{value:t},e.children)}},3258:e=>{e.exports=JSON.parse('{"permalink":"/Cadence-Docs/blog/2023/01/31/community-spotlight-january-2023","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2023-01-31-community-spotlight-january-2023.md","source":"@site/blog/2023-01-31-community-spotlight-january-2023.md","title":"Cadence Community Spotlight Update - January 2023","description":"Happy New Year everyone! Here\u2019s the latest in our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!","date":"2023-01-31T00:00:00.000Z","tags":[{"inline":false,"label":"Community Spotlight","permalink":"/Cadence-Docs/blog/tags/community-spotlights","description":"Community Spotlight tag description"}],"readingTime":2.06,"hasTruncateMarker":true,"authors":[{"name":"Sharan Foga","title":"Director of Operations & Customer Success @ Encube Technologies","url":"https://www.linkedin.com/in/sfoga/","page":{"permalink":"/Cadence-Docs/blog/authors/sharanf"},"socials":{"linkedin":"https://www.linkedin.com/in/sfoga/","github":"https://github.com/sharanf"},"imageURL":"https://github.com/sharanf.png","key":"sharanf"}],"frontMatter":{"title":"Cadence Community Spotlight Update - January 2023","date":"2023-01-31T00:00:00.000Z","authors":"sharanf","tags":["community-spotlight"]},"unlisted":false,"prevItem":{"title":"Cadence Community Spotlight Update - February 2023","permalink":"/Cadence-Docs/blog/2023/02/28/community-spotlight-february"},"nextItem":{"title":"Cadence Community Spotlight Update - December 2022","permalink":"/Cadence-Docs/blog/2022/12/23/community-spotlight-december-2022"}}')}}]); \ No newline at end of file diff --git a/assets/js/3408eb41.96cbd93f.js b/assets/js/3408eb41.96cbd93f.js new file mode 100644 index 000000000..58d7d3c70 --- /dev/null +++ b/assets/js/3408eb41.96cbd93f.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[9866],{7521:(e,o,l)=>{l.r(o),l.d(o,{assets:()=>s,contentTitle:()=>i,default:()=>f,frontMatter:()=>r,metadata:()=>n,toc:()=>c});const n=JSON.parse('{"id":"get-started/java-hello-world","title":"Java hello world","description":"This section provides step by step instructions on how to write and run a HelloWorld with Java.","source":"@site/docs/01-get-started/02-java-hello-world.md","sourceDirName":"01-get-started","slug":"/get-started/java-hello-world","permalink":"/Cadence-Docs/docs/get-started/java-hello-world","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/01-get-started/02-java-hello-world.md","tags":[],"version":"current","sidebarPosition":2,"frontMatter":{"layout":"default","title":"Java hello world","permalink":"/docs/get-started/java-hello-world"},"sidebar":"docsSidebar","previous":{"title":"Server Installation","permalink":"/Cadence-Docs/docs/get-started/server-installation"},"next":{"title":"Golang hello world","permalink":"/Cadence-Docs/docs/get-started/golang-hello-world"}}');var t=l(4848),a=l(8453);const r={layout:"default",title:"Java hello world",permalink:"/docs/get-started/java-hello-world"},i="Java Hello World",s={},c=[{value:"Include Cadence Java Client Dependency",id:"include-cadence-java-client-dependency",level:2},{value:"Implement Hello World Workflow",id:"implement-hello-world-workflow",level:2},{value:"Execute Hello World Workflow using the CLI",id:"execute-hello-world-workflow-using-the-cli",level:2},{value:"List Workflows and Workflow History",id:"list-workflows-and-workflow-history",level:2},{value:"What is Next",id:"what-is-next",level:2}];function d(e){const o={a:"a",code:"code",h1:"h1",h2:"h2",header:"header",p:"p",pre:"pre",...(0,a.R)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(o.header,{children:(0,t.jsx)(o.h1,{id:"java-hello-world",children:"Java Hello World"})}),"\n",(0,t.jsx)(o.p,{children:"This section provides step by step instructions on how to write and run a HelloWorld with Java."}),"\n",(0,t.jsxs)(o.p,{children:["For complete, ready to build samples covering all the key Cadence concepts go to ",(0,t.jsx)(o.a,{href:"https://github.com/cadence-workflow/cadence-java-samples",children:"Cadence-Java-Samples"}),"."]}),"\n",(0,t.jsxs)(o.p,{children:["You can also review ",(0,t.jsx)(o.a,{href:"/docs/java-client",children:"Java-Client"})," and ",(0,t.jsx)(o.a,{href:"https://www.javadoc.io/doc/com.uber.cadence/cadence-client/latest/index.html",children:"java-docs"})," for more documentation."]}),"\n",(0,t.jsx)(o.h2,{id:"include-cadence-java-client-dependency",children:"Include Cadence Java Client Dependency"}),"\n",(0,t.jsxs)(o.p,{children:["Go to the ",(0,t.jsx)(o.a,{href:"https://mvnrepository.com/artifact/com.uber.cadence/cadence-client",children:"Maven Repository Uber Cadence Java Client Page"}),"\nand find the latest version of the library. Include it as a dependency into your Java project. For example if you\nare using Gradle the dependency looks like:"]}),"\n",(0,t.jsx)(o.pre,{children:(0,t.jsx)(o.code,{className:"language-bash",children:"compile group: 'com.uber.cadence', name: 'cadence-client', version: ''\n"})}),"\n",(0,t.jsx)(o.p,{children:"Also add the following dependencies that cadence-client relies on:"}),"\n",(0,t.jsx)(o.pre,{children:(0,t.jsx)(o.code,{className:"language-bash",children:"compile group: 'commons-configuration', name: 'commons-configuration', version: '1.9'\ncompile group: 'ch.qos.logback', name: 'logback-classic', version: '1.2.3'\n"})}),"\n",(0,t.jsx)(o.p,{children:"Make sure that the following code compiles:"}),"\n",(0,t.jsx)(o.pre,{children:(0,t.jsx)(o.code,{className:"language-java",children:"import com.uber.cadence.workflow.Workflow;\nimport com.uber.cadence.workflow.WorkflowMethod;\nimport org.slf4j.Logger;\n\npublic class GettingStarted {\n\n private static Logger logger = Workflow.getLogger(GettingStarted.class);\n\n public interface HelloWorld {\n @WorkflowMethod\n void sayHello(String name);\n }\n\n}\n"})}),"\n",(0,t.jsxs)(o.p,{children:["If you are having problems setting up the build files use the\n",(0,t.jsx)(o.a,{href:"https://github.com/cadence-workflow/cadence-java-samples",children:"Cadence Java Samples"})," GitHub repository as a reference."]}),"\n",(0,t.jsx)(o.p,{children:"Also add the following logback config file somewhere in your classpath:"}),"\n",(0,t.jsx)(o.pre,{children:(0,t.jsx)(o.code,{className:"language-xml",children:'\n \n \x3c!-- encoders are assigned the type\n ch.qos.logback.classic.encoder.PatternLayoutEncoder by default --\x3e\n \n %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n\n \n \n \n \n \n \n\n'})}),"\n",(0,t.jsx)(o.h2,{id:"implement-hello-world-workflow",children:"Implement Hello World Workflow"}),"\n",(0,t.jsxs)(o.p,{children:["Let's add ",(0,t.jsx)(o.code,{children:"HelloWorldImpl"})," with the ",(0,t.jsx)(o.code,{children:"sayHello"}),' method that just logs the "Hello ..." and returns.']}),"\n",(0,t.jsx)(o.pre,{children:(0,t.jsx)(o.code,{className:"language-java",children:'import com.uber.cadence.worker.Worker;\nimport com.uber.cadence.workflow.Workflow;\nimport com.uber.cadence.workflow.WorkflowMethod;\nimport org.slf4j.Logger;\n\npublic class GettingStarted {\n\n private static Logger logger = Workflow.getLogger(GettingStarted.class);\n\n public interface HelloWorld {\n @WorkflowMethod\n void sayHello(String name);\n }\n\n public static class HelloWorldImpl implements HelloWorld {\n\n @Override\n public void sayHello(String name) {\n logger.info("Hello " + name + "!");\n }\n }\n}\n'})}),"\n",(0,t.jsx)(o.p,{children:"To link the workflow implementation to the Cadence framework, it should be registered with a worker that connects to\na Cadence Service. By default the worker connects to the locally running Cadence service."}),"\n",(0,t.jsx)(o.pre,{children:(0,t.jsx)(o.code,{className:"language-java",children:"public static void main(String[] args) {\n WorkflowClient workflowClient =\n WorkflowClient.newInstance(\n new WorkflowServiceTChannel(ClientOptions.defaultInstance()),\n WorkflowClientOptions.newBuilder().setDomain(DOMAIN).build());\n // Get worker to poll the task list.\n WorkerFactory factory = WorkerFactory.newInstance(workflowClient);\n Worker worker = factory.newWorker(TASK_LIST);\n worker.registerWorkflowImplementationTypes(HelloWorldImpl.class);\n factory.start();\n}\n"})}),"\n",(0,t.jsx)(o.p,{children:"The code is slightly different if you are using client version prior to 3.0.0:"}),"\n",(0,t.jsx)(o.pre,{children:(0,t.jsx)(o.code,{className:"language-java",children:'public static void main(String[] args) {\n Worker.Factory factory = new Worker.Factory("test-domain");\n Worker worker = factory.newWorker("HelloWorldTaskList");\n worker.registerWorkflowImplementationTypes(HelloWorldImpl.class);\n factory.start();\n}\n'})}),"\n",(0,t.jsx)(o.h2,{id:"execute-hello-world-workflow-using-the-cli",children:"Execute Hello World Workflow using the CLI"}),"\n",(0,t.jsx)(o.p,{children:"Now run the worker program. Following is an example log:"}),"\n",(0,t.jsx)(o.pre,{children:(0,t.jsx)(o.code,{className:"language-log",children:'13:35:02.575 [main] INFO c.u.c.s.WorkflowServiceTChannel - Initialized TChannel for service cadence-frontend, LibraryVersion: 2.2.0, FeatureVersion: 1.0.0\n13:35:02.671 [main] INFO c.u.cadence.internal.worker.Poller - start(): Poller{options=PollerOptions{maximumPollRateIntervalMilliseconds=1000, maximumPollRatePerSecond=0.0, pollBackoffCoefficient=2.0, pollBackoffInitialInterval=PT0.2S, pollBackoffMaximumInterval=PT20S, pollThreadCount=1, pollThreadNamePrefix=\'Workflow Poller taskList="HelloWorldTaskList", domain="test-domain", type="workflow"\'}, identity=45937@maxim-C02XD0AAJGH6}\n13:35:02.673 [main] INFO c.u.cadence.internal.worker.Poller - start(): Poller{options=PollerOptions{maximumPollRateIntervalMilliseconds=1000, maximumPollRatePerSecond=0.0, pollBackoffCoefficient=2.0, pollBackoffInitialInterval=PT0.2S, pollBackoffMaximumInterval=PT20S, pollThreadCount=1, pollThreadNamePrefix=\'null\'}, identity=81b8d0ac-ff89-47e8-b842-3dd26337feea}\n'})}),"\n",(0,t.jsx)(o.p,{children:"No Hello printed. This is expected because a worker is just a workflow code host. The workflow has to be started to execute. Let's use Cadence CLI to start the workflow:"}),"\n",(0,t.jsx)(o.pre,{children:(0,t.jsx)(o.code,{className:"language-sh-session",children:'$ docker run --network=host --rm ubercadence/cli:master --do test-domain workflow start --tasklist HelloWorldTaskList --workflow_type HelloWorld::sayHello --execution_timeout 3600 --input \\"World\\"\nStarted Workflow Id: bcacfabd-9f9a-46ac-9b25-83bcea5d7fd7, run Id: e7c40431-8e23-485b-9649-e8f161219efe\n'})}),"\n",(0,t.jsx)(o.p,{children:"The output of the program should change to:"}),"\n",(0,t.jsx)(o.pre,{children:(0,t.jsx)(o.code,{className:"language-log",children:'13:35:02.575 [main] INFO c.u.c.s.WorkflowServiceTChannel - Initialized TChannel for service cadence-frontend, LibraryVersion: 2.2.0, FeatureVersion: 1.0.0\n13:35:02.671 [main] INFO c.u.cadence.internal.worker.Poller - start(): Poller{options=PollerOptions{maximumPollRateIntervalMilliseconds=1000, maximumPollRatePerSecond=0.0, pollBackoffCoefficient=2.0, pollBackoffInitialInterval=PT0.2S, pollBackoffMaximumInterval=PT20S, pollThreadCount=1, pollThreadNamePrefix=\'Workflow Poller taskList="HelloWorldTaskList", domain="test-domain", type="workflow"\'}, identity=45937@maxim-C02XD0AAJGH6}\n13:35:02.673 [main] INFO c.u.cadence.internal.worker.Poller - start(): Poller{options=PollerOptions{maximumPollRateIntervalMilliseconds=1000, maximumPollRatePerSecond=0.0, pollBackoffCoefficient=2.0, pollBackoffInitialInterval=PT0.2S, pollBackoffMaximumInterval=PT20S, pollThreadCount=1, pollThreadNamePrefix=\'null\'}, identity=81b8d0ac-ff89-47e8-b842-3dd26337feea}\n13:40:28.308 [workflow-root] INFO c.u.c.samples.hello.GettingStarted - Hello World!\n'})}),"\n",(0,t.jsx)(o.p,{children:"Let's start another "}),"\n",(0,t.jsx)(o.pre,{children:(0,t.jsx)(o.code,{className:"language-sh-session",children:'$ docker run --network=host --rm ubercadence/cli:master --do test-domain workflow start --tasklist HelloWorldTaskList --workflow_type HelloWorld::sayHello --execution_timeout 3600 --input \\"Cadence\\"\nStarted Workflow Id: d2083532-9c68-49ab-90e1-d960175377a7, run Id: 331bfa04-834b-45a7-861e-bcb9f6ddae3e\n'})}),"\n",(0,t.jsx)(o.p,{children:"And the output changed to:"}),"\n",(0,t.jsx)(o.pre,{children:(0,t.jsx)(o.code,{className:"language-log",children:'13:35:02.575 [main] INFO c.u.c.s.WorkflowServiceTChannel - Initialized TChannel for service cadence-frontend, LibraryVersion: 2.2.0, FeatureVersion: 1.0.0\n13:35:02.671 [main] INFO c.u.cadence.internal.worker.Poller - start(): Poller{options=PollerOptions{maximumPollRateIntervalMilliseconds=1000, maximumPollRatePerSecond=0.0, pollBackoffCoefficient=2.0, pollBackoffInitialInterval=PT0.2S, pollBackoffMaximumInterval=PT20S, pollThreadCount=1, pollThreadNamePrefix=\'Workflow Poller taskList="HelloWorldTaskList", domain="test-domain", type="workflow"\'}, identity=45937@maxim-C02XD0AAJGH6}\n13:35:02.673 [main] INFO c.u.cadence.internal.worker.Poller - start(): Poller{options=PollerOptions{maximumPollRateIntervalMilliseconds=1000, maximumPollRatePerSecond=0.0, pollBackoffCoefficient=2.0, pollBackoffInitialInterval=PT0.2S, pollBackoffMaximumInterval=PT20S, pollThreadCount=1, pollThreadNamePrefix=\'null\'}, identity=81b8d0ac-ff89-47e8-b842-3dd26337feea}\n13:40:28.308 [workflow-root] INFO c.u.c.samples.hello.GettingStarted - Hello World!\n13:42:34.994 [workflow-root] INFO c.u.c.samples.hello.GettingStarted - Hello Cadence!\n'})}),"\n",(0,t.jsx)(o.h2,{id:"list-workflows-and-workflow-history",children:"List Workflows and Workflow History"}),"\n",(0,t.jsx)(o.p,{children:"Let's list our workflow in the "}),"\n",(0,t.jsx)(o.pre,{children:(0,t.jsx)(o.code,{className:"language-sh-session",children:"$ docker run --network=host --rm ubercadence/cli:master --do test-domain workflow list\n WORKFLOW TYPE | WORKFLOW ID | RUN ID | START TIME | EXECUTION TIME | END TIME\n HelloWorld::sayHello | d2083532-9c68-49ab-90e1-d960175377a7 | 331bfa04-834b-45a7-861e-bcb9f6ddae3e | 20:42:34 | 20:42:34 | 20:42:35\n HelloWorld::sayHello | bcacfabd-9f9a-46ac-9b25-83bcea5d7fd7 | e7c40431-8e23-485b-9649-e8f161219efe | 20:40:28 | 20:40:28 | 20:40:29\n"})}),"\n",(0,t.jsx)(o.p,{children:"Now let's look at the workflow_execution history:"}),"\n",(0,t.jsx)(o.pre,{children:(0,t.jsx)(o.code,{className:"language-sh-session",children:'$ docker run --network=host --rm ubercadence/cli:master --do test-domain workflow showid 1965109f-607f-4b14-a5f2-24399a7b8fa7\n 1 WorkflowExecutionStarted {WorkflowType:{Name:HelloWorld::sayHello},\n TaskList:{Name:HelloWorldTaskList},\n Input:["World"],\n ExecutionStartToCloseTimeoutSeconds:3600,\n TaskStartToCloseTimeoutSeconds:10,\n ContinuedFailureDetails:[],\n LastCompletionResult:[],\n Identity:cadence-cli@linuxkit-025000000001,\n Attempt:0,\n FirstDecisionTaskBackoffSeconds:0}\n 2 DecisionTaskScheduled {TaskList:{Name:HelloWorldTaskList},\n StartToCloseTimeoutSeconds:10,\n Attempt:0}\n 3 DecisionTaskStarted {ScheduledEventId:2,\n Identity:45937@maxim-C02XD0AAJGH6,\n RequestId:481a14e5-67a4-436e-9a23-7f7fb7f87ef3}\n 4 DecisionTaskCompleted {ExecutionContext:[],\n ScheduledEventId:2,\n StartedEventId:3,\n Identity:45937@maxim-C02XD0AAJGH6}\n 5 WorkflowExecutionCompleted {Result:[],\n DecisionTaskCompletedEventId:4}\n'})}),"\n",(0,t.jsx)(o.p,{children:"Even for such a trivial workflow, the history gives a lot of useful information. For complex workflows this is a really useful tool for production and development troubleshooting. History can be automatically archived to a long-term blob store (for example Amazon S3) upon workflow completion for compliance, analytical, and troubleshooting purposes."}),"\n",(0,t.jsx)(o.h2,{id:"what-is-next",children:"What is Next"}),"\n",(0,t.jsxs)(o.p,{children:["Now you have completed the tutorials. You can continue to explore the key ",(0,t.jsx)(o.a,{href:"/docs/concepts",children:"concepts"})," in Cadence, and also how to use them with ",(0,t.jsx)(o.a,{href:"/docs/java-client",children:"Java Client"})]})]})}function f(e={}){const{wrapper:o}={...(0,a.R)(),...e.components};return o?(0,t.jsx)(o,{...e,children:(0,t.jsx)(d,{...e})}):d(e)}},8453:(e,o,l)=>{l.d(o,{R:()=>r,x:()=>i});var n=l(6540);const t={},a=n.createContext(t);function r(e){const o=n.useContext(a);return n.useMemo((function(){return"function"==typeof e?e(o):{...o,...e}}),[o,e])}function i(e){let o;return o=e.disableParentContext?"function"==typeof e.components?e.components(t):e.components||t:r(e.components),n.createElement(a.Provider,{value:o},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/3408eb41.efbfc908.js b/assets/js/3408eb41.efbfc908.js deleted file mode 100644 index b27763d23..000000000 --- a/assets/js/3408eb41.efbfc908.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[9866],{7521:(e,o,l)=>{l.r(o),l.d(o,{assets:()=>s,contentTitle:()=>i,default:()=>f,frontMatter:()=>r,metadata:()=>n,toc:()=>c});const n=JSON.parse('{"id":"get-started/java-hello-world","title":"Java hello world","description":"This section provides step by step instructions on how to write and run a HelloWorld with Java.","source":"@site/docs/01-get-started/02-java-hello-world.md","sourceDirName":"01-get-started","slug":"/get-started/java-hello-world","permalink":"/docs/get-started/java-hello-world","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/01-get-started/02-java-hello-world.md","tags":[],"version":"current","sidebarPosition":2,"frontMatter":{"layout":"default","title":"Java hello world","permalink":"/docs/get-started/java-hello-world"},"sidebar":"docsSidebar","previous":{"title":"Server Installation","permalink":"/docs/get-started/server-installation"},"next":{"title":"Golang hello world","permalink":"/docs/get-started/golang-hello-world"}}');var t=l(4848),a=l(8453);const r={layout:"default",title:"Java hello world",permalink:"/docs/get-started/java-hello-world"},i="Java Hello World",s={},c=[{value:"Include Cadence Java Client Dependency",id:"include-cadence-java-client-dependency",level:2},{value:"Implement Hello World Workflow",id:"implement-hello-world-workflow",level:2},{value:"Execute Hello World Workflow using the CLI",id:"execute-hello-world-workflow-using-the-cli",level:2},{value:"List Workflows and Workflow History",id:"list-workflows-and-workflow-history",level:2},{value:"What is Next",id:"what-is-next",level:2}];function d(e){const o={a:"a",code:"code",h1:"h1",h2:"h2",header:"header",p:"p",pre:"pre",...(0,a.R)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(o.header,{children:(0,t.jsx)(o.h1,{id:"java-hello-world",children:"Java Hello World"})}),"\n",(0,t.jsx)(o.p,{children:"This section provides step by step instructions on how to write and run a HelloWorld with Java."}),"\n",(0,t.jsxs)(o.p,{children:["For complete, ready to build samples covering all the key Cadence concepts go to ",(0,t.jsx)(o.a,{href:"https://github.com/cadence-workflow/cadence-java-samples",children:"Cadence-Java-Samples"}),"."]}),"\n",(0,t.jsxs)(o.p,{children:["You can also review ",(0,t.jsx)(o.a,{href:"/docs/java-client",children:"Java-Client"})," and ",(0,t.jsx)(o.a,{href:"https://www.javadoc.io/doc/com.uber.cadence/cadence-client/latest/index.html",children:"java-docs"})," for more documentation."]}),"\n",(0,t.jsx)(o.h2,{id:"include-cadence-java-client-dependency",children:"Include Cadence Java Client Dependency"}),"\n",(0,t.jsxs)(o.p,{children:["Go to the ",(0,t.jsx)(o.a,{href:"https://mvnrepository.com/artifact/com.uber.cadence/cadence-client",children:"Maven Repository Uber Cadence Java Client Page"}),"\nand find the latest version of the library. Include it as a dependency into your Java project. For example if you\nare using Gradle the dependency looks like:"]}),"\n",(0,t.jsx)(o.pre,{children:(0,t.jsx)(o.code,{className:"language-bash",children:"compile group: 'com.uber.cadence', name: 'cadence-client', version: ''\n"})}),"\n",(0,t.jsx)(o.p,{children:"Also add the following dependencies that cadence-client relies on:"}),"\n",(0,t.jsx)(o.pre,{children:(0,t.jsx)(o.code,{className:"language-bash",children:"compile group: 'commons-configuration', name: 'commons-configuration', version: '1.9'\ncompile group: 'ch.qos.logback', name: 'logback-classic', version: '1.2.3'\n"})}),"\n",(0,t.jsx)(o.p,{children:"Make sure that the following code compiles:"}),"\n",(0,t.jsx)(o.pre,{children:(0,t.jsx)(o.code,{className:"language-java",children:"import com.uber.cadence.workflow.Workflow;\nimport com.uber.cadence.workflow.WorkflowMethod;\nimport org.slf4j.Logger;\n\npublic class GettingStarted {\n\n private static Logger logger = Workflow.getLogger(GettingStarted.class);\n\n public interface HelloWorld {\n @WorkflowMethod\n void sayHello(String name);\n }\n\n}\n"})}),"\n",(0,t.jsxs)(o.p,{children:["If you are having problems setting up the build files use the\n",(0,t.jsx)(o.a,{href:"https://github.com/cadence-workflow/cadence-java-samples",children:"Cadence Java Samples"})," GitHub repository as a reference."]}),"\n",(0,t.jsx)(o.p,{children:"Also add the following logback config file somewhere in your classpath:"}),"\n",(0,t.jsx)(o.pre,{children:(0,t.jsx)(o.code,{className:"language-xml",children:'\n \n \x3c!-- encoders are assigned the type\n ch.qos.logback.classic.encoder.PatternLayoutEncoder by default --\x3e\n \n %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n\n \n \n \n \n \n \n\n'})}),"\n",(0,t.jsx)(o.h2,{id:"implement-hello-world-workflow",children:"Implement Hello World Workflow"}),"\n",(0,t.jsxs)(o.p,{children:["Let's add ",(0,t.jsx)(o.code,{children:"HelloWorldImpl"})," with the ",(0,t.jsx)(o.code,{children:"sayHello"}),' method that just logs the "Hello ..." and returns.']}),"\n",(0,t.jsx)(o.pre,{children:(0,t.jsx)(o.code,{className:"language-java",children:'import com.uber.cadence.worker.Worker;\nimport com.uber.cadence.workflow.Workflow;\nimport com.uber.cadence.workflow.WorkflowMethod;\nimport org.slf4j.Logger;\n\npublic class GettingStarted {\n\n private static Logger logger = Workflow.getLogger(GettingStarted.class);\n\n public interface HelloWorld {\n @WorkflowMethod\n void sayHello(String name);\n }\n\n public static class HelloWorldImpl implements HelloWorld {\n\n @Override\n public void sayHello(String name) {\n logger.info("Hello " + name + "!");\n }\n }\n}\n'})}),"\n",(0,t.jsx)(o.p,{children:"To link the workflow implementation to the Cadence framework, it should be registered with a worker that connects to\na Cadence Service. By default the worker connects to the locally running Cadence service."}),"\n",(0,t.jsx)(o.pre,{children:(0,t.jsx)(o.code,{className:"language-java",children:"public static void main(String[] args) {\n WorkflowClient workflowClient =\n WorkflowClient.newInstance(\n new WorkflowServiceTChannel(ClientOptions.defaultInstance()),\n WorkflowClientOptions.newBuilder().setDomain(DOMAIN).build());\n // Get worker to poll the task list.\n WorkerFactory factory = WorkerFactory.newInstance(workflowClient);\n Worker worker = factory.newWorker(TASK_LIST);\n worker.registerWorkflowImplementationTypes(HelloWorldImpl.class);\n factory.start();\n}\n"})}),"\n",(0,t.jsx)(o.p,{children:"The code is slightly different if you are using client version prior to 3.0.0:"}),"\n",(0,t.jsx)(o.pre,{children:(0,t.jsx)(o.code,{className:"language-java",children:'public static void main(String[] args) {\n Worker.Factory factory = new Worker.Factory("test-domain");\n Worker worker = factory.newWorker("HelloWorldTaskList");\n worker.registerWorkflowImplementationTypes(HelloWorldImpl.class);\n factory.start();\n}\n'})}),"\n",(0,t.jsx)(o.h2,{id:"execute-hello-world-workflow-using-the-cli",children:"Execute Hello World Workflow using the CLI"}),"\n",(0,t.jsx)(o.p,{children:"Now run the worker program. Following is an example log:"}),"\n",(0,t.jsx)(o.pre,{children:(0,t.jsx)(o.code,{className:"language-log",children:'13:35:02.575 [main] INFO c.u.c.s.WorkflowServiceTChannel - Initialized TChannel for service cadence-frontend, LibraryVersion: 2.2.0, FeatureVersion: 1.0.0\n13:35:02.671 [main] INFO c.u.cadence.internal.worker.Poller - start(): Poller{options=PollerOptions{maximumPollRateIntervalMilliseconds=1000, maximumPollRatePerSecond=0.0, pollBackoffCoefficient=2.0, pollBackoffInitialInterval=PT0.2S, pollBackoffMaximumInterval=PT20S, pollThreadCount=1, pollThreadNamePrefix=\'Workflow Poller taskList="HelloWorldTaskList", domain="test-domain", type="workflow"\'}, identity=45937@maxim-C02XD0AAJGH6}\n13:35:02.673 [main] INFO c.u.cadence.internal.worker.Poller - start(): Poller{options=PollerOptions{maximumPollRateIntervalMilliseconds=1000, maximumPollRatePerSecond=0.0, pollBackoffCoefficient=2.0, pollBackoffInitialInterval=PT0.2S, pollBackoffMaximumInterval=PT20S, pollThreadCount=1, pollThreadNamePrefix=\'null\'}, identity=81b8d0ac-ff89-47e8-b842-3dd26337feea}\n'})}),"\n",(0,t.jsx)(o.p,{children:"No Hello printed. This is expected because a worker is just a workflow code host. The workflow has to be started to execute. Let's use Cadence CLI to start the workflow:"}),"\n",(0,t.jsx)(o.pre,{children:(0,t.jsx)(o.code,{className:"language-sh-session",children:'$ docker run --network=host --rm ubercadence/cli:master --do test-domain workflow start --tasklist HelloWorldTaskList --workflow_type HelloWorld::sayHello --execution_timeout 3600 --input \\"World\\"\nStarted Workflow Id: bcacfabd-9f9a-46ac-9b25-83bcea5d7fd7, run Id: e7c40431-8e23-485b-9649-e8f161219efe\n'})}),"\n",(0,t.jsx)(o.p,{children:"The output of the program should change to:"}),"\n",(0,t.jsx)(o.pre,{children:(0,t.jsx)(o.code,{className:"language-log",children:'13:35:02.575 [main] INFO c.u.c.s.WorkflowServiceTChannel - Initialized TChannel for service cadence-frontend, LibraryVersion: 2.2.0, FeatureVersion: 1.0.0\n13:35:02.671 [main] INFO c.u.cadence.internal.worker.Poller - start(): Poller{options=PollerOptions{maximumPollRateIntervalMilliseconds=1000, maximumPollRatePerSecond=0.0, pollBackoffCoefficient=2.0, pollBackoffInitialInterval=PT0.2S, pollBackoffMaximumInterval=PT20S, pollThreadCount=1, pollThreadNamePrefix=\'Workflow Poller taskList="HelloWorldTaskList", domain="test-domain", type="workflow"\'}, identity=45937@maxim-C02XD0AAJGH6}\n13:35:02.673 [main] INFO c.u.cadence.internal.worker.Poller - start(): Poller{options=PollerOptions{maximumPollRateIntervalMilliseconds=1000, maximumPollRatePerSecond=0.0, pollBackoffCoefficient=2.0, pollBackoffInitialInterval=PT0.2S, pollBackoffMaximumInterval=PT20S, pollThreadCount=1, pollThreadNamePrefix=\'null\'}, identity=81b8d0ac-ff89-47e8-b842-3dd26337feea}\n13:40:28.308 [workflow-root] INFO c.u.c.samples.hello.GettingStarted - Hello World!\n'})}),"\n",(0,t.jsx)(o.p,{children:"Let's start another "}),"\n",(0,t.jsx)(o.pre,{children:(0,t.jsx)(o.code,{className:"language-sh-session",children:'$ docker run --network=host --rm ubercadence/cli:master --do test-domain workflow start --tasklist HelloWorldTaskList --workflow_type HelloWorld::sayHello --execution_timeout 3600 --input \\"Cadence\\"\nStarted Workflow Id: d2083532-9c68-49ab-90e1-d960175377a7, run Id: 331bfa04-834b-45a7-861e-bcb9f6ddae3e\n'})}),"\n",(0,t.jsx)(o.p,{children:"And the output changed to:"}),"\n",(0,t.jsx)(o.pre,{children:(0,t.jsx)(o.code,{className:"language-log",children:'13:35:02.575 [main] INFO c.u.c.s.WorkflowServiceTChannel - Initialized TChannel for service cadence-frontend, LibraryVersion: 2.2.0, FeatureVersion: 1.0.0\n13:35:02.671 [main] INFO c.u.cadence.internal.worker.Poller - start(): Poller{options=PollerOptions{maximumPollRateIntervalMilliseconds=1000, maximumPollRatePerSecond=0.0, pollBackoffCoefficient=2.0, pollBackoffInitialInterval=PT0.2S, pollBackoffMaximumInterval=PT20S, pollThreadCount=1, pollThreadNamePrefix=\'Workflow Poller taskList="HelloWorldTaskList", domain="test-domain", type="workflow"\'}, identity=45937@maxim-C02XD0AAJGH6}\n13:35:02.673 [main] INFO c.u.cadence.internal.worker.Poller - start(): Poller{options=PollerOptions{maximumPollRateIntervalMilliseconds=1000, maximumPollRatePerSecond=0.0, pollBackoffCoefficient=2.0, pollBackoffInitialInterval=PT0.2S, pollBackoffMaximumInterval=PT20S, pollThreadCount=1, pollThreadNamePrefix=\'null\'}, identity=81b8d0ac-ff89-47e8-b842-3dd26337feea}\n13:40:28.308 [workflow-root] INFO c.u.c.samples.hello.GettingStarted - Hello World!\n13:42:34.994 [workflow-root] INFO c.u.c.samples.hello.GettingStarted - Hello Cadence!\n'})}),"\n",(0,t.jsx)(o.h2,{id:"list-workflows-and-workflow-history",children:"List Workflows and Workflow History"}),"\n",(0,t.jsx)(o.p,{children:"Let's list our workflow in the "}),"\n",(0,t.jsx)(o.pre,{children:(0,t.jsx)(o.code,{className:"language-sh-session",children:"$ docker run --network=host --rm ubercadence/cli:master --do test-domain workflow list\n WORKFLOW TYPE | WORKFLOW ID | RUN ID | START TIME | EXECUTION TIME | END TIME\n HelloWorld::sayHello | d2083532-9c68-49ab-90e1-d960175377a7 | 331bfa04-834b-45a7-861e-bcb9f6ddae3e | 20:42:34 | 20:42:34 | 20:42:35\n HelloWorld::sayHello | bcacfabd-9f9a-46ac-9b25-83bcea5d7fd7 | e7c40431-8e23-485b-9649-e8f161219efe | 20:40:28 | 20:40:28 | 20:40:29\n"})}),"\n",(0,t.jsx)(o.p,{children:"Now let's look at the workflow_execution history:"}),"\n",(0,t.jsx)(o.pre,{children:(0,t.jsx)(o.code,{className:"language-sh-session",children:'$ docker run --network=host --rm ubercadence/cli:master --do test-domain workflow showid 1965109f-607f-4b14-a5f2-24399a7b8fa7\n 1 WorkflowExecutionStarted {WorkflowType:{Name:HelloWorld::sayHello},\n TaskList:{Name:HelloWorldTaskList},\n Input:["World"],\n ExecutionStartToCloseTimeoutSeconds:3600,\n TaskStartToCloseTimeoutSeconds:10,\n ContinuedFailureDetails:[],\n LastCompletionResult:[],\n Identity:cadence-cli@linuxkit-025000000001,\n Attempt:0,\n FirstDecisionTaskBackoffSeconds:0}\n 2 DecisionTaskScheduled {TaskList:{Name:HelloWorldTaskList},\n StartToCloseTimeoutSeconds:10,\n Attempt:0}\n 3 DecisionTaskStarted {ScheduledEventId:2,\n Identity:45937@maxim-C02XD0AAJGH6,\n RequestId:481a14e5-67a4-436e-9a23-7f7fb7f87ef3}\n 4 DecisionTaskCompleted {ExecutionContext:[],\n ScheduledEventId:2,\n StartedEventId:3,\n Identity:45937@maxim-C02XD0AAJGH6}\n 5 WorkflowExecutionCompleted {Result:[],\n DecisionTaskCompletedEventId:4}\n'})}),"\n",(0,t.jsx)(o.p,{children:"Even for such a trivial workflow, the history gives a lot of useful information. For complex workflows this is a really useful tool for production and development troubleshooting. History can be automatically archived to a long-term blob store (for example Amazon S3) upon workflow completion for compliance, analytical, and troubleshooting purposes."}),"\n",(0,t.jsx)(o.h2,{id:"what-is-next",children:"What is Next"}),"\n",(0,t.jsxs)(o.p,{children:["Now you have completed the tutorials. You can continue to explore the key ",(0,t.jsx)(o.a,{href:"/docs/concepts",children:"concepts"})," in Cadence, and also how to use them with ",(0,t.jsx)(o.a,{href:"/docs/java-client",children:"Java Client"})]})]})}function f(e={}){const{wrapper:o}={...(0,a.R)(),...e.components};return o?(0,t.jsx)(o,{...e,children:(0,t.jsx)(d,{...e})}):d(e)}},8453:(e,o,l)=>{l.d(o,{R:()=>r,x:()=>i});var n=l(6540);const t={},a=n.createContext(t);function r(e){const o=n.useContext(a);return n.useMemo((function(){return"function"==typeof e?e(o):{...o,...e}}),[o,e])}function i(e){let o;return o=e.disableParentContext?"function"==typeof e.components?e.components(t):e.components||t:r(e.components),n.createElement(a.Provider,{value:o},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/3485e756.a92df76b.js b/assets/js/3485e756.a92df76b.js deleted file mode 100644 index 88d7ee3e6..000000000 --- a/assets/js/3485e756.a92df76b.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[4378],{5263:a=>{a.exports=JSON.parse('{"author":{"name":"Vytautas Karpavicius","title":"Software Engineer @ Uber","url":"https://www.linkedin.com/in/vytautas-karpavicius","page":{"permalink":"/blog/authors/vytautas-karpavicius"},"socials":{"linkedin":"https://www.linkedin.com/in/vytautas-karpavicius","github":"https://github.com/vytautas-karpavicius"},"imageURL":"https://github.com/vytautas-karpavicius.png","key":"vytautas-karpavicius","count":1},"listMetadata":{"permalink":"/blog/authors/vytautas-karpavicius","page":1,"postsPerPage":10,"totalPages":1,"totalCount":1,"blogDescription":"The latest news and updates from the Cadence team","blogTitle":"Cadence Blog"}}')}}]); \ No newline at end of file diff --git a/assets/js/3525dd13.1d38f764.js b/assets/js/3525dd13.1d38f764.js deleted file mode 100644 index cdb0d719b..000000000 --- a/assets/js/3525dd13.1d38f764.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[7240],{5477:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>c,contentTitle:()=>r,default:()=>h,frontMatter:()=>i,metadata:()=>a,toc:()=>l});const a=JSON.parse('{"id":"concepts/events","title":"Event handling","description":"Fault-oblivious statefulworkflowssignal about an external. A is always point to point destined to a specific instance.Signals: are always processed in the order in which they are received.","source":"@site/docs/03-concepts/03-events.md","sourceDirName":"03-concepts","slug":"/concepts/events","permalink":"/docs/concepts/events","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/03-concepts/03-events.md","tags":[],"version":"current","sidebarPosition":3,"frontMatter":{"layout":"default","title":"Event handling","permalink":"/docs/concepts/events"},"sidebar":"docsSidebar","previous":{"title":"Activities","permalink":"/docs/concepts/activities"},"next":{"title":"Synchronous query","permalink":"/docs/concepts/queries"}}');var s=n(4848),o=n(8453);const i={layout:"default",title:"Event handling",permalink:"/docs/concepts/events"},r="Event handling",c={},l=[{value:"Event Aggregation and Correlation",id:"event-aggregation-and-correlation",level:2},{value:"Human Tasks",id:"human-tasks",level:2},{value:"Process Execution Alteration",id:"process-execution-alteration",level:2},{value:"Synchronization",id:"synchronization",level:2}];function d(e){const t={a:"a",code:"code",h1:"h1",h2:"h2",header:"header",p:"p",...(0,o.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(t.header,{children:(0,s.jsx)(t.h1,{id:"event-handling",children:"Event handling"})}),"\n",(0,s.jsx)(t.p,{children:"Fault-oblivious stateful workflows can be signalled about an external event. A signal is always point to point destined to a specific workflow instance. Signals are always processed in the order in which they are received."}),"\n",(0,s.jsx)(t.p,{children:"There are multiple scenarios for which signals are useful."}),"\n",(0,s.jsx)(t.h2,{id:"event-aggregation-and-correlation",children:"Event Aggregation and Correlation"}),"\n",(0,s.jsx)(t.p,{children:"Cadence is not a replacement for generic stream processing engines like Apache Flink or Apache Spark. But in certain scenarios it is a better fit. For example, when all events that should be aggregated and correlated are always applied to some business entity with a clear ID. And then when a certain condition is met, actions should be executed."}),"\n",(0,s.jsx)(t.p,{children:"The main limitation is that a single Cadence workflow has a pretty limited throughput, while the number of workflows is practically unlimited. So if you need to aggregate events per customer, and your application has 100 million customers and each customer doesn't generate more than 20 events per second, then Cadence would work fine. But if you want to aggregate all events for US customers then the rate of these events would be beyond the single workflow capacity."}),"\n",(0,s.jsx)(t.p,{children:"For example, an IoT device generates events and a certain sequence of events indicates that the device should be reprovisioned. A workflow instance per device would be created and each instance would manage the state machine of the device and execute reprovision activity when necessary."}),"\n",(0,s.jsxs)(t.p,{children:["Another use case is a customer loyalty program. Every time a customer makes a purchase, an event is generated into Apache Kafka for downstream systems to process. A loyalty service Kafka consumer receives the event and signals a customer workflow about the purchase using the Cadence ",(0,s.jsx)(t.code,{children:"signalWorkflowExecution"})," API. The workflow accumulates the count of the purchases. If a specified threshold is achieved, the workflow executes an activity that notifies some external service that the customer has reached the next level of loyalty program. The workflow also executes activities to periodically message the customer about their current status."]}),"\n",(0,s.jsx)(t.h2,{id:"human-tasks",children:"Human Tasks"}),"\n",(0,s.jsx)(t.p,{children:"A lot of business processes involve human participants. The standard Cadence pattern for implementing an external interaction is to execute an activity that creates a human task in an external system. It can be an email with a form, or a record in some external database, or a mobile app notification. When a user changes the status of the task, a signal is sent to the corresponding workflow. For example, when the form is submitted, or a mobile app notification is acknowledged. Some tasks have multiple possible actions like claim, return, complete, reject. So multiple signals can be sent in relation to it."}),"\n",(0,s.jsx)(t.h2,{id:"process-execution-alteration",children:"Process Execution Alteration"}),"\n",(0,s.jsx)(t.p,{children:"Some business processes should change their behavior if some external event has happened. For example, while executing an order shipment workflow, any change in item quantity could be delivered in a form of a signal."}),"\n",(0,s.jsx)(t.p,{children:"Another example is a service deployment workflow. While rolling out new software version to a Kubernetes cluster some problem was identified. A signal can be used to ask the workflow to pause while the problem is investigated. Then either a continue or a rollback signal can be used to execute the appropriate action."}),"\n",(0,s.jsx)(t.h2,{id:"synchronization",children:"Synchronization"}),"\n",(0,s.jsxs)(t.p,{children:["Cadence workflows are strongly consistent so they can be used as a synchronization point for executing actions. For example, there is a requirement that all messages for a single user are processed sequentially but the underlying messaging infrastructure can deliver them in parallel. The Cadence solution would be to have a workflow per user and signal it when an event is received. Then the workflow would buffer all signals in an internal data structure and then call an activity for every signal received. See the following ",(0,s.jsx)(t.a,{href:"https://stackoverflow.com/a/56615120/1664318",children:"Stack Overflow answer"})," for an example."]})]})}function h(e={}){const{wrapper:t}={...(0,o.R)(),...e.components};return t?(0,s.jsx)(t,{...e,children:(0,s.jsx)(d,{...e})}):d(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>i,x:()=>r});var a=n(6540);const s={},o=a.createContext(s);function i(e){const t=a.useContext(o);return a.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function r(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:i(e.components),a.createElement(o.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/3525dd13.649d5746.js b/assets/js/3525dd13.649d5746.js new file mode 100644 index 000000000..482866948 --- /dev/null +++ b/assets/js/3525dd13.649d5746.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[7240],{5477:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>c,contentTitle:()=>r,default:()=>h,frontMatter:()=>i,metadata:()=>a,toc:()=>l});const a=JSON.parse('{"id":"concepts/events","title":"Event handling","description":"Fault-oblivious statefulworkflowssignal about an external. A is always point to point destined to a specific instance.Signals: are always processed in the order in which they are received.","source":"@site/docs/03-concepts/03-events.md","sourceDirName":"03-concepts","slug":"/concepts/events","permalink":"/Cadence-Docs/docs/concepts/events","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/03-concepts/03-events.md","tags":[],"version":"current","sidebarPosition":3,"frontMatter":{"layout":"default","title":"Event handling","permalink":"/docs/concepts/events"},"sidebar":"docsSidebar","previous":{"title":"Activities","permalink":"/Cadence-Docs/docs/concepts/activities"},"next":{"title":"Synchronous query","permalink":"/Cadence-Docs/docs/concepts/queries"}}');var s=n(4848),o=n(8453);const i={layout:"default",title:"Event handling",permalink:"/docs/concepts/events"},r="Event handling",c={},l=[{value:"Event Aggregation and Correlation",id:"event-aggregation-and-correlation",level:2},{value:"Human Tasks",id:"human-tasks",level:2},{value:"Process Execution Alteration",id:"process-execution-alteration",level:2},{value:"Synchronization",id:"synchronization",level:2}];function d(e){const t={a:"a",code:"code",h1:"h1",h2:"h2",header:"header",p:"p",...(0,o.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(t.header,{children:(0,s.jsx)(t.h1,{id:"event-handling",children:"Event handling"})}),"\n",(0,s.jsx)(t.p,{children:"Fault-oblivious stateful workflows can be signalled about an external event. A signal is always point to point destined to a specific workflow instance. Signals are always processed in the order in which they are received."}),"\n",(0,s.jsx)(t.p,{children:"There are multiple scenarios for which signals are useful."}),"\n",(0,s.jsx)(t.h2,{id:"event-aggregation-and-correlation",children:"Event Aggregation and Correlation"}),"\n",(0,s.jsx)(t.p,{children:"Cadence is not a replacement for generic stream processing engines like Apache Flink or Apache Spark. But in certain scenarios it is a better fit. For example, when all events that should be aggregated and correlated are always applied to some business entity with a clear ID. And then when a certain condition is met, actions should be executed."}),"\n",(0,s.jsx)(t.p,{children:"The main limitation is that a single Cadence workflow has a pretty limited throughput, while the number of workflows is practically unlimited. So if you need to aggregate events per customer, and your application has 100 million customers and each customer doesn't generate more than 20 events per second, then Cadence would work fine. But if you want to aggregate all events for US customers then the rate of these events would be beyond the single workflow capacity."}),"\n",(0,s.jsx)(t.p,{children:"For example, an IoT device generates events and a certain sequence of events indicates that the device should be reprovisioned. A workflow instance per device would be created and each instance would manage the state machine of the device and execute reprovision activity when necessary."}),"\n",(0,s.jsxs)(t.p,{children:["Another use case is a customer loyalty program. Every time a customer makes a purchase, an event is generated into Apache Kafka for downstream systems to process. A loyalty service Kafka consumer receives the event and signals a customer workflow about the purchase using the Cadence ",(0,s.jsx)(t.code,{children:"signalWorkflowExecution"})," API. The workflow accumulates the count of the purchases. If a specified threshold is achieved, the workflow executes an activity that notifies some external service that the customer has reached the next level of loyalty program. The workflow also executes activities to periodically message the customer about their current status."]}),"\n",(0,s.jsx)(t.h2,{id:"human-tasks",children:"Human Tasks"}),"\n",(0,s.jsx)(t.p,{children:"A lot of business processes involve human participants. The standard Cadence pattern for implementing an external interaction is to execute an activity that creates a human task in an external system. It can be an email with a form, or a record in some external database, or a mobile app notification. When a user changes the status of the task, a signal is sent to the corresponding workflow. For example, when the form is submitted, or a mobile app notification is acknowledged. Some tasks have multiple possible actions like claim, return, complete, reject. So multiple signals can be sent in relation to it."}),"\n",(0,s.jsx)(t.h2,{id:"process-execution-alteration",children:"Process Execution Alteration"}),"\n",(0,s.jsx)(t.p,{children:"Some business processes should change their behavior if some external event has happened. For example, while executing an order shipment workflow, any change in item quantity could be delivered in a form of a signal."}),"\n",(0,s.jsx)(t.p,{children:"Another example is a service deployment workflow. While rolling out new software version to a Kubernetes cluster some problem was identified. A signal can be used to ask the workflow to pause while the problem is investigated. Then either a continue or a rollback signal can be used to execute the appropriate action."}),"\n",(0,s.jsx)(t.h2,{id:"synchronization",children:"Synchronization"}),"\n",(0,s.jsxs)(t.p,{children:["Cadence workflows are strongly consistent so they can be used as a synchronization point for executing actions. For example, there is a requirement that all messages for a single user are processed sequentially but the underlying messaging infrastructure can deliver them in parallel. The Cadence solution would be to have a workflow per user and signal it when an event is received. Then the workflow would buffer all signals in an internal data structure and then call an activity for every signal received. See the following ",(0,s.jsx)(t.a,{href:"https://stackoverflow.com/a/56615120/1664318",children:"Stack Overflow answer"})," for an example."]})]})}function h(e={}){const{wrapper:t}={...(0,o.R)(),...e.components};return t?(0,s.jsx)(t,{...e,children:(0,s.jsx)(d,{...e})}):d(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>i,x:()=>r});var a=n(6540);const s={},o=a.createContext(s);function i(e){const t=a.useContext(o);return a.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function r(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:i(e.components),a.createElement(o.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/36aefe7c.6501ae5a.js b/assets/js/36aefe7c.6501ae5a.js deleted file mode 100644 index ad3a3b215..000000000 --- a/assets/js/36aefe7c.6501ae5a.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[9379],{8047:(t,e,n)=>{n.r(e),n.d(e,{assets:()=>u,contentTitle:()=>s,default:()=>m,frontMatter:()=>r,metadata:()=>o,toc:()=>l});var o=n(964),i=n(4848),a=n(8453);const r={title:"Cadence Community Spotlight Update - February 2023",date:new Date("2023-02-28T00:00:00.000Z"),authors:"sharanf",tags:["community-spotlight"]},s=void 0,u={authorsImageUrls:[void 0]},l=[{value:"Community Survey",id:"community-survey",level:2}];function c(t){const e={a:"a",h2:"h2",p:"p",...(0,a.R)(),...t.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(e.p,{children:"Here\u2019s the latest in our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!"}),"\n",(0,i.jsx)(e.p,{children:"Please see below for a roundup of the highlights:"}),"\n",(0,i.jsx)(e.h2,{id:"community-survey",children:"Community Survey"}),"\n",(0,i.jsx)(e.p,{children:"We've been talking about doing a community survey for a while and during February we sent it out. We are still collating the results so it's not too late to send in your response."}),"\n",(0,i.jsx)(e.p,{children:"The survey takes 5 minutes and is your opportunity to provide feedback to the project and highlight areas you think we need to focus on."}),"\n",(0,i.jsxs)(e.p,{children:["Use this ",(0,i.jsx)(e.a,{href:"https://uber.surveymonkey.com/r/ZS83WJW",children:"Survey Link"})]}),"\n",(0,i.jsx)(e.p,{children:"Please take a few minutes to give us your opinion."})]})}function m(t={}){const{wrapper:e}={...(0,a.R)(),...t.components};return e?(0,i.jsx)(e,{...t,children:(0,i.jsx)(c,{...t})}):c(t)}},8453:(t,e,n)=>{n.d(e,{R:()=>r,x:()=>s});var o=n(6540);const i={},a=o.createContext(i);function r(t){const e=o.useContext(a);return o.useMemo((function(){return"function"==typeof t?t(e):{...e,...t}}),[e,t])}function s(t){let e;return e=t.disableParentContext?"function"==typeof t.components?t.components(i):t.components||i:r(t.components),o.createElement(a.Provider,{value:e},t.children)}},964:t=>{t.exports=JSON.parse('{"permalink":"/blog/2023/02/28/community-spotlight-february","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2023-02-28-community-spotlight-february.md","source":"@site/blog/2023-02-28-community-spotlight-february.md","title":"Cadence Community Spotlight Update - February 2023","description":"Here\u2019s the latest in our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!","date":"2023-02-28T00:00:00.000Z","tags":[{"inline":false,"label":"Community Spotlight","permalink":"/blog/tags/community-spotlights","description":"Community Spotlight tag description"}],"readingTime":1.875,"hasTruncateMarker":true,"authors":[{"name":"Sharan Foga","title":"Director of Operations & Customer Success @ Encube Technologies","url":"https://www.linkedin.com/in/sfoga/","page":{"permalink":"/blog/authors/sharanf"},"socials":{"linkedin":"https://www.linkedin.com/in/sfoga/","github":"https://github.com/sharanf"},"imageURL":"https://github.com/sharanf.png","key":"sharanf"}],"frontMatter":{"title":"Cadence Community Spotlight Update - February 2023","date":"2023-02-28T00:00:00.000Z","authors":"sharanf","tags":["community-spotlight"]},"unlisted":false,"prevItem":{"title":"Cadence Community Spotlight Update - March 2024","permalink":"/blog/2024/3/11/community-spotlight-update-march-2024"},"nextItem":{"title":"Cadence Community Spotlight Update - January 2023","permalink":"/blog/2023/01/31/community-spotlight-january-2023"}}')}}]); \ No newline at end of file diff --git a/assets/js/36aefe7c.78389325.js b/assets/js/36aefe7c.78389325.js new file mode 100644 index 000000000..af84dcc6a --- /dev/null +++ b/assets/js/36aefe7c.78389325.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[9379],{8047:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>u,contentTitle:()=>s,default:()=>m,frontMatter:()=>r,metadata:()=>o,toc:()=>c});var o=n(964),a=n(4848),i=n(8453);const r={title:"Cadence Community Spotlight Update - February 2023",date:new Date("2023-02-28T00:00:00.000Z"),authors:"sharanf",tags:["community-spotlight"]},s=void 0,u={authorsImageUrls:[void 0]},c=[{value:"Community Survey",id:"community-survey",level:2}];function l(e){const t={a:"a",h2:"h2",p:"p",...(0,i.R)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(t.p,{children:"Here\u2019s the latest in our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!"}),"\n",(0,a.jsx)(t.p,{children:"Please see below for a roundup of the highlights:"}),"\n",(0,a.jsx)(t.h2,{id:"community-survey",children:"Community Survey"}),"\n",(0,a.jsx)(t.p,{children:"We've been talking about doing a community survey for a while and during February we sent it out. We are still collating the results so it's not too late to send in your response."}),"\n",(0,a.jsx)(t.p,{children:"The survey takes 5 minutes and is your opportunity to provide feedback to the project and highlight areas you think we need to focus on."}),"\n",(0,a.jsxs)(t.p,{children:["Use this ",(0,a.jsx)(t.a,{href:"https://uber.surveymonkey.com/r/ZS83WJW",children:"Survey Link"})]}),"\n",(0,a.jsx)(t.p,{children:"Please take a few minutes to give us your opinion."})]})}function m(e={}){const{wrapper:t}={...(0,i.R)(),...e.components};return t?(0,a.jsx)(t,{...e,children:(0,a.jsx)(l,{...e})}):l(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>r,x:()=>s});var o=n(6540);const a={},i=o.createContext(a);function r(e){const t=o.useContext(i);return o.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function s(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:r(e.components),o.createElement(i.Provider,{value:t},e.children)}},964:e=>{e.exports=JSON.parse('{"permalink":"/Cadence-Docs/blog/2023/02/28/community-spotlight-february","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2023-02-28-community-spotlight-february.md","source":"@site/blog/2023-02-28-community-spotlight-february.md","title":"Cadence Community Spotlight Update - February 2023","description":"Here\u2019s the latest in our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!","date":"2023-02-28T00:00:00.000Z","tags":[{"inline":false,"label":"Community Spotlight","permalink":"/Cadence-Docs/blog/tags/community-spotlights","description":"Community Spotlight tag description"}],"readingTime":1.875,"hasTruncateMarker":true,"authors":[{"name":"Sharan Foga","title":"Director of Operations & Customer Success @ Encube Technologies","url":"https://www.linkedin.com/in/sfoga/","page":{"permalink":"/Cadence-Docs/blog/authors/sharanf"},"socials":{"linkedin":"https://www.linkedin.com/in/sfoga/","github":"https://github.com/sharanf"},"imageURL":"https://github.com/sharanf.png","key":"sharanf"}],"frontMatter":{"title":"Cadence Community Spotlight Update - February 2023","date":"2023-02-28T00:00:00.000Z","authors":"sharanf","tags":["community-spotlight"]},"unlisted":false,"prevItem":{"title":"Cadence Community Spotlight Update - March 2024","permalink":"/Cadence-Docs/blog/2024/3/11/community-spotlight-update-march-2024"},"nextItem":{"title":"Cadence Community Spotlight Update - January 2023","permalink":"/Cadence-Docs/blog/2023/01/31/community-spotlight-january-2023"}}')}}]); \ No newline at end of file diff --git a/assets/js/393be207.5f69cc18.js b/assets/js/393be207.5f69cc18.js new file mode 100644 index 000000000..2eb91ab83 --- /dev/null +++ b/assets/js/393be207.5f69cc18.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[4134],{591:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>p,contentTitle:()=>c,default:()=>l,frontMatter:()=>s,metadata:()=>a,toc:()=>d});const a=JSON.parse('{"type":"mdx","permalink":"/Cadence-Docs/markdown-page","source":"@site/src/pages/markdown-page.md","title":"Markdown page example","description":"You don\'t need React to write simple standalone pages.","frontMatter":{"title":"Markdown page example"},"unlisted":false}');var o=t(4848),r=t(8453);const s={title:"Markdown page example"},c="Markdown page example",p={},d=[];function i(e){const n={h1:"h1",header:"header",p:"p",...(0,r.R)(),...e.components};return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsx)(n.header,{children:(0,o.jsx)(n.h1,{id:"markdown-page-example",children:"Markdown page example"})}),"\n",(0,o.jsx)(n.p,{children:"You don't need React to write simple standalone pages."})]})}function l(e={}){const{wrapper:n}={...(0,r.R)(),...e.components};return n?(0,o.jsx)(n,{...e,children:(0,o.jsx)(i,{...e})}):i(e)}},8453:(e,n,t)=>{t.d(n,{R:()=>s,x:()=>c});var a=t(6540);const o={},r=a.createContext(o);function s(e){const n=a.useContext(r);return a.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function c(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:s(e.components),a.createElement(r.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/393be207.825f5c39.js b/assets/js/393be207.825f5c39.js deleted file mode 100644 index b30a5572e..000000000 --- a/assets/js/393be207.825f5c39.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[4134],{591:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>p,contentTitle:()=>c,default:()=>l,frontMatter:()=>s,metadata:()=>a,toc:()=>d});const a=JSON.parse('{"type":"mdx","permalink":"/markdown-page","source":"@site/src/pages/markdown-page.md","title":"Markdown page example","description":"You don\'t need React to write simple standalone pages.","frontMatter":{"title":"Markdown page example"},"unlisted":false}');var o=t(4848),r=t(8453);const s={title:"Markdown page example"},c="Markdown page example",p={},d=[];function i(e){const n={h1:"h1",header:"header",p:"p",...(0,r.R)(),...e.components};return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsx)(n.header,{children:(0,o.jsx)(n.h1,{id:"markdown-page-example",children:"Markdown page example"})}),"\n",(0,o.jsx)(n.p,{children:"You don't need React to write simple standalone pages."})]})}function l(e={}){const{wrapper:n}={...(0,r.R)(),...e.components};return n?(0,o.jsx)(n,{...e,children:(0,o.jsx)(i,{...e})}):i(e)}},8453:(e,n,t)=>{t.d(n,{R:()=>s,x:()=>c});var a=t(6540);const o={},r=a.createContext(o);function s(e){const n=a.useContext(r);return a.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function c(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:s(e.components),a.createElement(r.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/3a2db09e.3787f744.js b/assets/js/3a2db09e.3787f744.js deleted file mode 100644 index b7d80e6b0..000000000 --- a/assets/js/3a2db09e.3787f744.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[8121],{8070:e=>{e.exports=JSON.parse('{"tags":[{"label":"Announcement","permalink":"/blog/tags/announcements","description":"Announcement tag description","count":7},{"label":"Deep Dives","permalink":"/blog/tags/deep-dives","description":"Deep Dives tag description","count":10},{"label":"Cadence Operations","permalink":"/blog/tags/cadence-operations","description":"Cadence Operations tag description","count":2},{"label":"Roadmap","permalink":"/blog/tags/roadmap","description":"Roadmap tag description","count":3},{"label":"Community Spotlight","permalink":"/blog/tags/community-spotlights","description":"Community Spotlight tag description","count":20},{"label":"Introduction to Cadence","permalink":"/blog/tags/introduction-to-cadence","description":"Introduction to Cadence tag description","count":5},{"label":"Testing","permalink":"/blog/tags/testing","description":"Testing tag description","count":1},{"label":"Releases","permalink":"/blog/tags/releases","description":"Releases tag description","count":2}]}')}}]); \ No newline at end of file diff --git a/assets/js/3ca3c927.02badfed.js b/assets/js/3ca3c927.f3b6a47f.js similarity index 78% rename from assets/js/3ca3c927.02badfed.js rename to assets/js/3ca3c927.f3b6a47f.js index dda6090c7..2fa544dc7 100644 --- a/assets/js/3ca3c927.02badfed.js +++ b/assets/js/3ca3c927.f3b6a47f.js @@ -1 +1 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[4552],{3438:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>c,contentTitle:()=>r,default:()=>h,frontMatter:()=>s,metadata:()=>o,toc:()=>l});var o=t(4734),a=t(4848),i=t(8453);const s={title:"Cadence Community Spotlight Update - January 2022",date:new Date("2022-01-31T00:00:00.000Z"),authors:"sharanf",tags:["community-spotlight","roadmap"]},r=void 0,c={authorsImageUrls:[void 0]},l=[{value:"Community Related Office Hours",id:"community-related-office-hours",level:2},{value:"Adopting a Cadence Community Code of Conduct",id:"adopting-a-cadence-community-code-of-conduct",level:2},{value:"Recording from Cadence Meetup Available",id:"recording-from-cadence-meetup-available",level:2},{value:"Cadence in the News!",id:"cadence-in-the-news",level:2},{value:"Upcoming Events",id:"upcoming-events",level:2}];function d(e){const n={a:"a",h2:"h2",li:"li",p:"p",ul:"ul",...(0,i.R)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(n.p,{children:"Welcome to our very first Cadence Community Spotlight update!"}),"\n",(0,a.jsx)(n.p,{children:"This monthly update focuses on news from the wider Cadence community and is all about what you have been doing with Cadence. Do you have an interesting project that uses Cadence? If so then we want to hear from you. Also if you have any news items, blogs, articles, videos or events where Cadence has been mentioned then that is good too. We want to showcase that our community is active and is doing exciting and interesting things."}),"\n",(0,a.jsx)(n.p,{children:"Please see below for a short round up of things that have happened recently in the community."}),"\n",(0,a.jsx)(n.h2,{id:"community-related-office-hours",children:"Community Related Office Hours"}),"\n",(0,a.jsx)(n.p,{children:"On the 12th January 2022 we held our first Cadence Community Related Office Hours. This session was focused on discussing how we plan and organise things for the community. This includes things such as Code of Conduct, managing social media and making sure we regularly communicate project news and events."}),"\n",(0,a.jsx)(n.p,{children:"And you can see that this monthly update is the result of the feedback from that session! We are happy to get any feedback for comments you may have. Please remember that this update is for you so getting your feedback will help us improve it."}),"\n",(0,a.jsx)(n.p,{children:"We will be planning other Community Related Office Hour sessions so please watch out for updates."}),"\n",(0,a.jsx)(n.h2,{id:"adopting-a-cadence-community-code-of-conduct",children:"Adopting a Cadence Community Code of Conduct"}),"\n",(0,a.jsxs)(n.p,{children:["Some of you may already know that our community has adopted this version of the ",(0,a.jsx)(n.a,{href:"https://github.com/uber/.github/blob/dcd96c52f2d1d839208315a2572cf37f48e52e96/CODE_OF_CONDUCT.md",children:"Contributor Covenant"})," as our Code of Conduct. We want our community to be an open, welcoming and supportive place where everyone can collaborate."]}),"\n",(0,a.jsx)(n.h2,{id:"recording-from-cadence-meetup-available",children:"Recording from Cadence Meetup Available"}),"\n",(0,a.jsxs)(n.p,{children:["Please don't worry if you missed our online ",(0,a.jsx)(n.a,{href:"https://www.meetup.com/UberEvents/events/281975343/",children:"November Cadence meetup"})," because the recording is now available. You can find out more details about the meetup and get access to recordings ",(0,a.jsx)(n.a,{href:"https://www.youtube.com/watch?v=pXgCd1BilLQ",children:"here"})]}),"\n",(0,a.jsx)(n.h2,{id:"cadence-in-the-news",children:"Cadence in the News!"}),"\n",(0,a.jsx)(n.p,{children:"Below are a selection of Cadence related articles, blogs and whitepapers. Please take a look and feel free to share via your own social media channels."}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsx)(n.li,{children:(0,a.jsx)(n.a,{href:"https://thenewstack.io/meet-cadence-workflow-engine-for-taming-complex-processes/",children:"Meet Cadence: Workflow Engine for Taming Complex Processes"})}),"\n",(0,a.jsx)(n.li,{children:(0,a.jsx)(n.a,{href:"https://www.instaclustr.com/blog/spinning-your-workflows-with-cadence/",children:"Spinning Your Workflows with Cadence"})}),"\n",(0,a.jsx)(n.li,{children:(0,a.jsx)(n.a,{href:"https://www.globenewswire.com/news-release/2021/12/07/2347314/0/en/Instaclustr-Joins-the-Engineering-Team-at-Uber-in-Supporting-Cadence-the-Powerful-Open-Source-Orchestration-Engine.html",children:"Instaclustr Joins the Engineering Team at Uber in Supporting Cadence, the Powerful Open Source Orchestration Engine"})}),"\n"]}),"\n",(0,a.jsx)(n.h2,{id:"upcoming-events",children:"Upcoming Events"}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsx)(n.li,{children:(0,a.jsx)(n.a,{href:"https://info.instaclustr.com/webinar-emea-what-is-cadence.html?_ga=2.191041518.510582234.1643223308-2138855655.1638190316",children:"Webinar : What is Cadence? And is it right for you?"})}),"\n"]}),"\n",(0,a.jsxs)(n.p,{children:["If you have any news or topics you'd like us to include in our next update then please join our ",(0,a.jsx)(n.a,{href:"http://t.uber.com/cadence-slack",children:"slack"}),"#community channel."]})]})}function h(e={}){const{wrapper:n}={...(0,i.R)(),...e.components};return n?(0,a.jsx)(n,{...e,children:(0,a.jsx)(d,{...e})}):d(e)}},8453:(e,n,t)=>{t.d(n,{R:()=>s,x:()=>r});var o=t(6540);const a={},i=o.createContext(a);function s(e){const n=o.useContext(i);return o.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function r(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:s(e.components),o.createElement(i.Provider,{value:n},e.children)}},4734:e=>{e.exports=JSON.parse('{"permalink":"/blog/2022/01/31/community-spotlight-january-2022","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2022-01-31-community-spotlight-january-2022.md","source":"@site/blog/2022-01-31-community-spotlight-january-2022.md","title":"Cadence Community Spotlight Update - January 2022","description":"Welcome to our very first Cadence Community Spotlight update!","date":"2022-01-31T00:00:00.000Z","tags":[{"inline":false,"label":"Community Spotlight","permalink":"/blog/tags/community-spotlights","description":"Community Spotlight tag description"},{"inline":false,"label":"Roadmap","permalink":"/blog/tags/roadmap","description":"Roadmap tag description"}],"readingTime":2.04,"hasTruncateMarker":true,"authors":[{"name":"Sharan Foga","title":"Director of Operations & Customer Success @ Encube Technologies","url":"https://www.linkedin.com/in/sfoga/","page":{"permalink":"/blog/authors/sharanf"},"socials":{"linkedin":"https://www.linkedin.com/in/sfoga/","github":"https://github.com/sharanf"},"imageURL":"https://github.com/sharanf.png","key":"sharanf"}],"frontMatter":{"title":"Cadence Community Spotlight Update - January 2022","date":"2022-01-31T00:00:00.000Z","authors":"sharanf","tags":["community-spotlight","roadmap"]},"unlisted":false,"prevItem":{"title":"Cadence Community Spotlight Update - February 2022","permalink":"/blog/2022/02/28/community-spotlight-february-2022"},"nextItem":{"title":"Moving to gRPC","permalink":"/blog/2021/10/19/2021-10-19-moving-to-grpc/moving-to-grpc"}}')}}]); \ No newline at end of file +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[4552],{3438:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>c,contentTitle:()=>r,default:()=>h,frontMatter:()=>s,metadata:()=>o,toc:()=>l});var o=t(4734),a=t(4848),i=t(8453);const s={title:"Cadence Community Spotlight Update - January 2022",date:new Date("2022-01-31T00:00:00.000Z"),authors:"sharanf",tags:["community-spotlight","roadmap"]},r=void 0,c={authorsImageUrls:[void 0]},l=[{value:"Community Related Office Hours",id:"community-related-office-hours",level:2},{value:"Adopting a Cadence Community Code of Conduct",id:"adopting-a-cadence-community-code-of-conduct",level:2},{value:"Recording from Cadence Meetup Available",id:"recording-from-cadence-meetup-available",level:2},{value:"Cadence in the News!",id:"cadence-in-the-news",level:2},{value:"Upcoming Events",id:"upcoming-events",level:2}];function d(e){const n={a:"a",h2:"h2",li:"li",p:"p",ul:"ul",...(0,i.R)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(n.p,{children:"Welcome to our very first Cadence Community Spotlight update!"}),"\n",(0,a.jsx)(n.p,{children:"This monthly update focuses on news from the wider Cadence community and is all about what you have been doing with Cadence. Do you have an interesting project that uses Cadence? If so then we want to hear from you. Also if you have any news items, blogs, articles, videos or events where Cadence has been mentioned then that is good too. We want to showcase that our community is active and is doing exciting and interesting things."}),"\n",(0,a.jsx)(n.p,{children:"Please see below for a short round up of things that have happened recently in the community."}),"\n",(0,a.jsx)(n.h2,{id:"community-related-office-hours",children:"Community Related Office Hours"}),"\n",(0,a.jsx)(n.p,{children:"On the 12th January 2022 we held our first Cadence Community Related Office Hours. This session was focused on discussing how we plan and organise things for the community. This includes things such as Code of Conduct, managing social media and making sure we regularly communicate project news and events."}),"\n",(0,a.jsx)(n.p,{children:"And you can see that this monthly update is the result of the feedback from that session! We are happy to get any feedback for comments you may have. Please remember that this update is for you so getting your feedback will help us improve it."}),"\n",(0,a.jsx)(n.p,{children:"We will be planning other Community Related Office Hour sessions so please watch out for updates."}),"\n",(0,a.jsx)(n.h2,{id:"adopting-a-cadence-community-code-of-conduct",children:"Adopting a Cadence Community Code of Conduct"}),"\n",(0,a.jsxs)(n.p,{children:["Some of you may already know that our community has adopted this version of the ",(0,a.jsx)(n.a,{href:"https://github.com/uber/.github/blob/dcd96c52f2d1d839208315a2572cf37f48e52e96/CODE_OF_CONDUCT.md",children:"Contributor Covenant"})," as our Code of Conduct. We want our community to be an open, welcoming and supportive place where everyone can collaborate."]}),"\n",(0,a.jsx)(n.h2,{id:"recording-from-cadence-meetup-available",children:"Recording from Cadence Meetup Available"}),"\n",(0,a.jsxs)(n.p,{children:["Please don't worry if you missed our online ",(0,a.jsx)(n.a,{href:"https://www.meetup.com/UberEvents/events/281975343/",children:"November Cadence meetup"})," because the recording is now available. You can find out more details about the meetup and get access to recordings ",(0,a.jsx)(n.a,{href:"https://www.youtube.com/watch?v=pXgCd1BilLQ",children:"here"})]}),"\n",(0,a.jsx)(n.h2,{id:"cadence-in-the-news",children:"Cadence in the News!"}),"\n",(0,a.jsx)(n.p,{children:"Below are a selection of Cadence related articles, blogs and whitepapers. Please take a look and feel free to share via your own social media channels."}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsx)(n.li,{children:(0,a.jsx)(n.a,{href:"https://thenewstack.io/meet-cadence-workflow-engine-for-taming-complex-processes/",children:"Meet Cadence: Workflow Engine for Taming Complex Processes"})}),"\n",(0,a.jsx)(n.li,{children:(0,a.jsx)(n.a,{href:"https://www.instaclustr.com/blog/spinning-your-workflows-with-cadence/",children:"Spinning Your Workflows with Cadence"})}),"\n",(0,a.jsx)(n.li,{children:(0,a.jsx)(n.a,{href:"https://www.globenewswire.com/news-release/2021/12/07/2347314/0/en/Instaclustr-Joins-the-Engineering-Team-at-Uber-in-Supporting-Cadence-the-Powerful-Open-Source-Orchestration-Engine.html",children:"Instaclustr Joins the Engineering Team at Uber in Supporting Cadence, the Powerful Open Source Orchestration Engine"})}),"\n"]}),"\n",(0,a.jsx)(n.h2,{id:"upcoming-events",children:"Upcoming Events"}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsx)(n.li,{children:(0,a.jsx)(n.a,{href:"https://info.instaclustr.com/webinar-emea-what-is-cadence.html?_ga=2.191041518.510582234.1643223308-2138855655.1638190316",children:"Webinar : What is Cadence? And is it right for you?"})}),"\n"]}),"\n",(0,a.jsxs)(n.p,{children:["If you have any news or topics you'd like us to include in our next update then please join our ",(0,a.jsx)(n.a,{href:"http://t.uber.com/cadence-slack",children:"slack"}),"#community channel."]})]})}function h(e={}){const{wrapper:n}={...(0,i.R)(),...e.components};return n?(0,a.jsx)(n,{...e,children:(0,a.jsx)(d,{...e})}):d(e)}},8453:(e,n,t)=>{t.d(n,{R:()=>s,x:()=>r});var o=t(6540);const a={},i=o.createContext(a);function s(e){const n=o.useContext(i);return o.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function r(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:s(e.components),o.createElement(i.Provider,{value:n},e.children)}},4734:e=>{e.exports=JSON.parse('{"permalink":"/Cadence-Docs/blog/2022/01/31/community-spotlight-january-2022","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2022-01-31-community-spotlight-january-2022.md","source":"@site/blog/2022-01-31-community-spotlight-january-2022.md","title":"Cadence Community Spotlight Update - January 2022","description":"Welcome to our very first Cadence Community Spotlight update!","date":"2022-01-31T00:00:00.000Z","tags":[{"inline":false,"label":"Community Spotlight","permalink":"/Cadence-Docs/blog/tags/community-spotlights","description":"Community Spotlight tag description"},{"inline":false,"label":"Roadmap","permalink":"/Cadence-Docs/blog/tags/roadmap","description":"Roadmap tag description"}],"readingTime":2.04,"hasTruncateMarker":true,"authors":[{"name":"Sharan Foga","title":"Director of Operations & Customer Success @ Encube Technologies","url":"https://www.linkedin.com/in/sfoga/","page":{"permalink":"/Cadence-Docs/blog/authors/sharanf"},"socials":{"linkedin":"https://www.linkedin.com/in/sfoga/","github":"https://github.com/sharanf"},"imageURL":"https://github.com/sharanf.png","key":"sharanf"}],"frontMatter":{"title":"Cadence Community Spotlight Update - January 2022","date":"2022-01-31T00:00:00.000Z","authors":"sharanf","tags":["community-spotlight","roadmap"]},"unlisted":false,"prevItem":{"title":"Cadence Community Spotlight Update - February 2022","permalink":"/Cadence-Docs/blog/2022/02/28/community-spotlight-february-2022"},"nextItem":{"title":"Moving to gRPC","permalink":"/Cadence-Docs/blog/2021/10/19/2021-10-19-moving-to-grpc/moving-to-grpc"}}')}}]); \ No newline at end of file diff --git a/assets/js/3ce9624a.01c0ada4.js b/assets/js/3ce9624a.01c0ada4.js new file mode 100644 index 000000000..4f5ee81e1 --- /dev/null +++ b/assets/js/3ce9624a.01c0ada4.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[2450],{3284:(e,n,s)=>{s.r(n),s.d(n,{assets:()=>a,contentTitle:()=>c,default:()=>u,frontMatter:()=>o,metadata:()=>t,toc:()=>d});const t=JSON.parse('{"id":"resources","title":"Resources","description":"Cadence documentation","source":"@site/community/2-resources.mdx","sourceDirName":".","slug":"/resources","permalink":"/Cadence-Docs/community/resources","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/edit/master/community/2-resources.mdx","tags":[],"version":"current","lastUpdatedBy":"Josue Ibarra","lastUpdatedAt":1733775743000,"sidebarPosition":2,"frontMatter":{}}');var i=s(4848),r=s(8453);const o={},c="Resources",a={},d=[{value:"Cadence documentation",id:"documentation",level:2},{value:"Videos",id:"videos",level:2},{value:"Articles",id:"articles",level:2},{value:"Enterprise usage",id:"enterprise-usage",level:2}];function l(e){const n={a:"a",admonition:"admonition",h1:"h1",h2:"h2",header:"header",li:"li",ul:"ul",...(0,r.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.header,{children:(0,i.jsx)(n.h1,{id:"resources",children:"Resources"})}),"\n",(0,i.jsx)(n.h2,{id:"documentation",children:"Cadence documentation"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["Official Documentation is available on this ",(0,i.jsx)(n.a,{href:"/docs/get-started",children:"site"})]}),"\n"]}),"\n",(0,i.jsx)(n.admonition,{type:"info"}),"\n",(0,i.jsx)(n.h2,{id:"videos",children:"Videos"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{}),"\n"]}),"\n",(0,i.jsx)(n.h2,{id:"articles",children:"Articles"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{}),"\n"]}),"\n",(0,i.jsx)(n.h2,{id:"enterprise-usage",children:"Enterprise usage"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"Uber"}),"\n",(0,i.jsx)(n.li,{children:"Hashicorp"}),"\n",(0,i.jsx)(n.li,{children:"Coinbase"}),"\n",(0,i.jsx)(n.li,{children:"DoorDash"}),"\n"]})]})}function u(e={}){const{wrapper:n}={...(0,r.R)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(l,{...e})}):l(e)}},8453:(e,n,s)=>{s.d(n,{R:()=>o,x:()=>c});var t=s(6540);const i={},r=t.createContext(i);function o(e){const n=t.useContext(r);return t.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function c(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:o(e.components),t.createElement(r.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/3ce9624a.0e422100.js b/assets/js/3ce9624a.0e422100.js deleted file mode 100644 index 1ad8cd260..000000000 --- a/assets/js/3ce9624a.0e422100.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[2450],{3284:(e,n,s)=>{s.r(n),s.d(n,{assets:()=>a,contentTitle:()=>c,default:()=>u,frontMatter:()=>o,metadata:()=>t,toc:()=>d});const t=JSON.parse('{"id":"resources","title":"Resources","description":"Cadence documentation","source":"@site/community/2-resources.mdx","sourceDirName":".","slug":"/resources","permalink":"/community/resources","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/edit/master/community/2-resources.mdx","tags":[],"version":"current","lastUpdatedBy":"Josue Ibarra","lastUpdatedAt":1733775743000,"sidebarPosition":2,"frontMatter":{}}');var i=s(4848),r=s(8453);const o={},c="Resources",a={},d=[{value:"Cadence documentation",id:"documentation",level:2},{value:"Videos",id:"videos",level:2},{value:"Articles",id:"articles",level:2},{value:"Enterprise usage",id:"enterprise-usage",level:2}];function l(e){const n={a:"a",admonition:"admonition",h1:"h1",h2:"h2",header:"header",li:"li",ul:"ul",...(0,r.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.header,{children:(0,i.jsx)(n.h1,{id:"resources",children:"Resources"})}),"\n",(0,i.jsx)(n.h2,{id:"documentation",children:"Cadence documentation"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["Official Documentation is available on this ",(0,i.jsx)(n.a,{href:"/docs/get-started",children:"site"})]}),"\n"]}),"\n",(0,i.jsx)(n.admonition,{type:"info"}),"\n",(0,i.jsx)(n.h2,{id:"videos",children:"Videos"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{}),"\n"]}),"\n",(0,i.jsx)(n.h2,{id:"articles",children:"Articles"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{}),"\n"]}),"\n",(0,i.jsx)(n.h2,{id:"enterprise-usage",children:"Enterprise usage"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"Uber"}),"\n",(0,i.jsx)(n.li,{children:"Hashicorp"}),"\n",(0,i.jsx)(n.li,{children:"Coinbase"}),"\n",(0,i.jsx)(n.li,{children:"DoorDash"}),"\n"]})]})}function u(e={}){const{wrapper:n}={...(0,r.R)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(l,{...e})}):l(e)}},8453:(e,n,s)=>{s.d(n,{R:()=>o,x:()=>c});var t=s(6540);const i={},r=t.createContext(i);function o(e){const n=t.useContext(r);return t.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function c(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:o(e.components),t.createElement(r.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/3d5497b2.d5b73ab5.js b/assets/js/3d5497b2.d5b73ab5.js deleted file mode 100644 index 19d47ae52..000000000 --- a/assets/js/3d5497b2.d5b73ab5.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[2529],{6742:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>r,contentTitle:()=>c,default:()=>d,frontMatter:()=>i,metadata:()=>o,toc:()=>l});var o=n(64),a=n(4848),s=n(8453);const i={title:"Cadence Community Spotlight Update - April 2022",date:new Date("2022-04-30T00:00:00.000Z"),authors:"sharanf",tags:["community-spotlight"]},c=void 0,r={authorsImageUrls:[void 0]},l=[{value:"SD Times Names Cadence Open Source Project of the Week",id:"sd-times-names-cadence-open-source-project-of-the-week",level:2},{value:"Follow Us on LinkedIn and Twitter!",id:"follow-us-on-linkedin-and-twitter",level:2},{value:"Proposal to Change the Way We Write Workflows",id:"proposal-to-change-the-way-we-write-workflows",level:2},{value:"Help Us Improve Cadence",id:"help-us-improve-cadence",level:2},{value:"Next Cadence Technical Office Hours: 30th May 2022",id:"next-cadence-technical-office-hours-30th-may-2022",level:2},{value:"Cadence in the News!",id:"cadence-in-the-news",level:2},{value:"Upcoming Events",id:"upcoming-events",level:2}];function h(e){const t={a:"a",em:"em",h2:"h2",li:"li",p:"p",ul:"ul",...(0,s.R)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(t.p,{children:"Welcome to our Cadence Community Spotlight update!"}),"\n",(0,a.jsx)(t.p,{children:"This is our monthly blog post series focused on news from in and around the Cadence community."}),"\n",(0,a.jsx)(t.p,{children:"Please see below for a short activity roundup of what has happened recently in the community."}),"\n",(0,a.jsx)(t.h2,{id:"sd-times-names-cadence-open-source-project-of-the-week",children:"SD Times Names Cadence Open Source Project of the Week"}),"\n",(0,a.jsxs)(t.p,{children:["In April Cadence was named as open source project of the week by the SD Times. Being named gives the project some great publicity and means the project is getting noticed. You can find a link to the article in the ",(0,a.jsx)(t.em,{children:"Cadence in the News"})," section below."]}),"\n",(0,a.jsx)(t.h2,{id:"follow-us-on-linkedin-and-twitter",children:"Follow Us on LinkedIn and Twitter!"}),"\n",(0,a.jsxs)(t.p,{children:["We have now set up Cadence accounts on ",(0,a.jsx)(t.a,{href:"https://www.linkedin.com/company/cadenceworkflow/",children:"LinkedIn"})," and ",(0,a.jsx)(t.a,{href:"https://twitter.com/cadenceworkflow",children:"Twitter"})," where you can keep up to date with what is happening in the community. We will be using these social media accounts to share news, articles, stories and links related to Cadence - so please follow us!"]}),"\n",(0,a.jsx)(t.p,{children:"And don\u2019t forget to share your news with us. We are looking forward to receiving your feedback and comments. The more we interact - the more we build our community!"}),"\n",(0,a.jsx)(t.h2,{id:"proposal-to-change-the-way-we-write-workflows",children:"Proposal to Change the Way We Write Workflows"}),"\n",(0,a.jsxs)(t.p,{children:["If you haven\u2019t seen the proposal from community member ",(0,a.jsx)(t.a,{href:"https://www.linkedin.com/in/prclqz/",children:"Quanzheng Long"})," about creating a new way to write Cadence workflows then please take a look:",(0,a.jsx)(t.a,{href:"https://github.com/cadence-workflow/cadence/issues/4785",children:"https://github.com/cadence-workflow/cadence/issues/4785"}),". He has already received some initial feedback and is currently working on putting together a proof of concept demo to show the community. As soon as we have more news about it - we will let you know!"]}),"\n",(0,a.jsx)(t.h2,{id:"help-us-improve-cadence",children:"Help Us Improve Cadence"}),"\n",(0,a.jsxs)(t.p,{children:["Do you want to help us improve Cadence? We are always looking for contributors so any contribution you can make - however small is welcome. If you would like to start contributing then please take a look at the list of ",(0,a.jsx)(t.a,{href:"https://github.com/cadence-workflow/cadence/issues",children:"Cadence Issues on Github"}),". We have some issues flagged with a tag of ",(0,a.jsx)(t.em,{children:"\u2018good first issue'"})," that would be a great place to start."]}),"\n",(0,a.jsx)(t.p,{children:"Remember that we are not only looking for code contributions but also non coding ones such as documentation improvements so please take a look and select something to work on."}),"\n",(0,a.jsx)(t.h2,{id:"next-cadence-technical-office-hours-30th-may-2022",children:"Next Cadence Technical Office Hours: 30th May 2022"}),"\n",(0,a.jsx)(t.p,{children:"Every month we hold a Technical Office Hours session via Zoom where you can speak directly with some of our Cadence experts. If you have a question about Cadence or are facing a particular issue getting it setup then please come along and chat to one of our experts!"}),"\n",(0,a.jsx)(t.p,{children:"Meetings are held on the last Monday of every month so please make sure you mark the dates in your calendars. Our next session will be on the 30th May at 9am PT so hope to see you there!"}),"\n",(0,a.jsx)(t.h2,{id:"cadence-in-the-news",children:"Cadence in the News!"}),"\n",(0,a.jsx)(t.p,{children:"Below are a selection of Cadence related articles, blogs and whitepapers. Please take a look and feel free to share via your own social media channels."}),"\n",(0,a.jsxs)(t.ul,{children:["\n",(0,a.jsxs)(t.li,{children:["\n",(0,a.jsx)(t.p,{children:(0,a.jsx)(t.a,{href:"https://sdtimes.com/softwaredev/sd-times-open-source-project-of-the-week-cadence/",children:"SD Times Open Source Project of the Week : Cadence"})}),"\n"]}),"\n",(0,a.jsxs)(t.li,{children:["\n",(0,a.jsx)(t.p,{children:(0,a.jsx)(t.a,{href:"https://www.youtube.com/watch?v=-f1m5EI4cRo",children:"The New Stack Interview: Meet Cadence: The Open-Source Orchestration Workflow Engine"})}),"\n"]}),"\n",(0,a.jsxs)(t.li,{children:["\n",(0,a.jsx)(t.p,{children:(0,a.jsx)(t.a,{href:"https://thenewstack.io/instaclustr-adds-managed-cadence-to-its-platform/",children:"The New Stack: Instaclustr Adds Managed Cadence to Its Platform"})}),"\n"]}),"\n"]}),"\n",(0,a.jsx)(t.h2,{id:"upcoming-events",children:"Upcoming Events"}),"\n",(0,a.jsxs)(t.ul,{children:["\n",(0,a.jsx)(t.li,{children:(0,a.jsx)(t.a,{href:"https://calendar.google.com/calendar/u/0/embed?src=e6r40gp3c2r01054id7e99dlac@group.calendar.google.com&ctz=America/Los_Angeles",children:"Cadence Technical Office Hours - 30th May 2022 @ 9am PT"})}),"\n"]}),"\n",(0,a.jsxs)(t.p,{children:["If you have any news or topics you'd like us to include in our next update then please join our ",(0,a.jsx)(t.a,{href:"http://t.uber.com/cadence-slack",children:"Slack"}),"#community channel."]}),"\n",(0,a.jsxs)(t.p,{children:["Please remember that this update is for you - so if you have any comments or feedback that could help us improve it then please share it with us in the #community ",(0,a.jsx)(t.a,{href:"http://t.uber.com/cadence-slack",children:"Slack"})," channel."]})]})}function d(e={}){const{wrapper:t}={...(0,s.R)(),...e.components};return t?(0,a.jsx)(t,{...e,children:(0,a.jsx)(h,{...e})}):h(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>i,x:()=>c});var o=n(6540);const a={},s=o.createContext(a);function i(e){const t=o.useContext(s);return o.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function c(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:i(e.components),o.createElement(s.Provider,{value:t},e.children)}},64:e=>{e.exports=JSON.parse('{"permalink":"/blog/2022/04/30/community-spotlight-update-april-2022","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2022-04-30-community-spotlight-update-april-2022.md","source":"@site/blog/2022-04-30-community-spotlight-update-april-2022.md","title":"Cadence Community Spotlight Update - April 2022","description":"Welcome to our Cadence Community Spotlight update!","date":"2022-04-30T00:00:00.000Z","tags":[{"inline":false,"label":"Community Spotlight","permalink":"/blog/tags/community-spotlights","description":"Community Spotlight tag description"}],"readingTime":2.955,"hasTruncateMarker":true,"authors":[{"name":"Sharan Foga","title":"Director of Operations & Customer Success @ Encube Technologies","url":"https://www.linkedin.com/in/sfoga/","page":{"permalink":"/blog/authors/sharanf"},"socials":{"linkedin":"https://www.linkedin.com/in/sfoga/","github":"https://github.com/sharanf"},"imageURL":"https://github.com/sharanf.png","key":"sharanf"}],"frontMatter":{"title":"Cadence Community Spotlight Update - April 2022","date":"2022-04-30T00:00:00.000Z","authors":"sharanf","tags":["community-spotlight"]},"unlisted":false,"prevItem":{"title":"Cadence Community Spotlight Update - May 2022","permalink":"/blog/2022/05/31/community-spotlight-update-may-2022"},"nextItem":{"title":"Cadence Community Spotlight Update - March 2022","permalink":"/blog/2022/03/31/community-spotlight-update-march-2022"}}')}}]); \ No newline at end of file diff --git a/assets/js/3d5497b2.d7badbc4.js b/assets/js/3d5497b2.d7badbc4.js new file mode 100644 index 000000000..a7a83c8ee --- /dev/null +++ b/assets/js/3d5497b2.d7badbc4.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[2529],{6742:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>r,contentTitle:()=>c,default:()=>d,frontMatter:()=>i,metadata:()=>o,toc:()=>l});var o=n(7683),a=n(4848),s=n(8453);const i={title:"Cadence Community Spotlight Update - April 2022",date:new Date("2022-04-30T00:00:00.000Z"),authors:"sharanf",tags:["community-spotlight"]},c=void 0,r={authorsImageUrls:[void 0]},l=[{value:"SD Times Names Cadence Open Source Project of the Week",id:"sd-times-names-cadence-open-source-project-of-the-week",level:2},{value:"Follow Us on LinkedIn and Twitter!",id:"follow-us-on-linkedin-and-twitter",level:2},{value:"Proposal to Change the Way We Write Workflows",id:"proposal-to-change-the-way-we-write-workflows",level:2},{value:"Help Us Improve Cadence",id:"help-us-improve-cadence",level:2},{value:"Next Cadence Technical Office Hours: 30th May 2022",id:"next-cadence-technical-office-hours-30th-may-2022",level:2},{value:"Cadence in the News!",id:"cadence-in-the-news",level:2},{value:"Upcoming Events",id:"upcoming-events",level:2}];function h(e){const t={a:"a",em:"em",h2:"h2",li:"li",p:"p",ul:"ul",...(0,s.R)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(t.p,{children:"Welcome to our Cadence Community Spotlight update!"}),"\n",(0,a.jsx)(t.p,{children:"This is our monthly blog post series focused on news from in and around the Cadence community."}),"\n",(0,a.jsx)(t.p,{children:"Please see below for a short activity roundup of what has happened recently in the community."}),"\n",(0,a.jsx)(t.h2,{id:"sd-times-names-cadence-open-source-project-of-the-week",children:"SD Times Names Cadence Open Source Project of the Week"}),"\n",(0,a.jsxs)(t.p,{children:["In April Cadence was named as open source project of the week by the SD Times. Being named gives the project some great publicity and means the project is getting noticed. You can find a link to the article in the ",(0,a.jsx)(t.em,{children:"Cadence in the News"})," section below."]}),"\n",(0,a.jsx)(t.h2,{id:"follow-us-on-linkedin-and-twitter",children:"Follow Us on LinkedIn and Twitter!"}),"\n",(0,a.jsxs)(t.p,{children:["We have now set up Cadence accounts on ",(0,a.jsx)(t.a,{href:"https://www.linkedin.com/company/cadenceworkflow/",children:"LinkedIn"})," and ",(0,a.jsx)(t.a,{href:"https://twitter.com/cadenceworkflow",children:"Twitter"})," where you can keep up to date with what is happening in the community. We will be using these social media accounts to share news, articles, stories and links related to Cadence - so please follow us!"]}),"\n",(0,a.jsx)(t.p,{children:"And don\u2019t forget to share your news with us. We are looking forward to receiving your feedback and comments. The more we interact - the more we build our community!"}),"\n",(0,a.jsx)(t.h2,{id:"proposal-to-change-the-way-we-write-workflows",children:"Proposal to Change the Way We Write Workflows"}),"\n",(0,a.jsxs)(t.p,{children:["If you haven\u2019t seen the proposal from community member ",(0,a.jsx)(t.a,{href:"https://www.linkedin.com/in/prclqz/",children:"Quanzheng Long"})," about creating a new way to write Cadence workflows then please take a look:",(0,a.jsx)(t.a,{href:"https://github.com/cadence-workflow/cadence/issues/4785",children:"https://github.com/cadence-workflow/cadence/issues/4785"}),". He has already received some initial feedback and is currently working on putting together a proof of concept demo to show the community. As soon as we have more news about it - we will let you know!"]}),"\n",(0,a.jsx)(t.h2,{id:"help-us-improve-cadence",children:"Help Us Improve Cadence"}),"\n",(0,a.jsxs)(t.p,{children:["Do you want to help us improve Cadence? We are always looking for contributors so any contribution you can make - however small is welcome. If you would like to start contributing then please take a look at the list of ",(0,a.jsx)(t.a,{href:"https://github.com/cadence-workflow/cadence/issues",children:"Cadence Issues on Github"}),". We have some issues flagged with a tag of ",(0,a.jsx)(t.em,{children:"\u2018good first issue'"})," that would be a great place to start."]}),"\n",(0,a.jsx)(t.p,{children:"Remember that we are not only looking for code contributions but also non coding ones such as documentation improvements so please take a look and select something to work on."}),"\n",(0,a.jsx)(t.h2,{id:"next-cadence-technical-office-hours-30th-may-2022",children:"Next Cadence Technical Office Hours: 30th May 2022"}),"\n",(0,a.jsx)(t.p,{children:"Every month we hold a Technical Office Hours session via Zoom where you can speak directly with some of our Cadence experts. If you have a question about Cadence or are facing a particular issue getting it setup then please come along and chat to one of our experts!"}),"\n",(0,a.jsx)(t.p,{children:"Meetings are held on the last Monday of every month so please make sure you mark the dates in your calendars. Our next session will be on the 30th May at 9am PT so hope to see you there!"}),"\n",(0,a.jsx)(t.h2,{id:"cadence-in-the-news",children:"Cadence in the News!"}),"\n",(0,a.jsx)(t.p,{children:"Below are a selection of Cadence related articles, blogs and whitepapers. Please take a look and feel free to share via your own social media channels."}),"\n",(0,a.jsxs)(t.ul,{children:["\n",(0,a.jsxs)(t.li,{children:["\n",(0,a.jsx)(t.p,{children:(0,a.jsx)(t.a,{href:"https://sdtimes.com/softwaredev/sd-times-open-source-project-of-the-week-cadence/",children:"SD Times Open Source Project of the Week : Cadence"})}),"\n"]}),"\n",(0,a.jsxs)(t.li,{children:["\n",(0,a.jsx)(t.p,{children:(0,a.jsx)(t.a,{href:"https://www.youtube.com/watch?v=-f1m5EI4cRo",children:"The New Stack Interview: Meet Cadence: The Open-Source Orchestration Workflow Engine"})}),"\n"]}),"\n",(0,a.jsxs)(t.li,{children:["\n",(0,a.jsx)(t.p,{children:(0,a.jsx)(t.a,{href:"https://thenewstack.io/instaclustr-adds-managed-cadence-to-its-platform/",children:"The New Stack: Instaclustr Adds Managed Cadence to Its Platform"})}),"\n"]}),"\n"]}),"\n",(0,a.jsx)(t.h2,{id:"upcoming-events",children:"Upcoming Events"}),"\n",(0,a.jsxs)(t.ul,{children:["\n",(0,a.jsx)(t.li,{children:(0,a.jsx)(t.a,{href:"https://calendar.google.com/calendar/u/0/embed?src=e6r40gp3c2r01054id7e99dlac@group.calendar.google.com&ctz=America/Los_Angeles",children:"Cadence Technical Office Hours - 30th May 2022 @ 9am PT"})}),"\n"]}),"\n",(0,a.jsxs)(t.p,{children:["If you have any news or topics you'd like us to include in our next update then please join our ",(0,a.jsx)(t.a,{href:"http://t.uber.com/cadence-slack",children:"Slack"}),"#community channel."]}),"\n",(0,a.jsxs)(t.p,{children:["Please remember that this update is for you - so if you have any comments or feedback that could help us improve it then please share it with us in the #community ",(0,a.jsx)(t.a,{href:"http://t.uber.com/cadence-slack",children:"Slack"})," channel."]})]})}function d(e={}){const{wrapper:t}={...(0,s.R)(),...e.components};return t?(0,a.jsx)(t,{...e,children:(0,a.jsx)(h,{...e})}):h(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>i,x:()=>c});var o=n(6540);const a={},s=o.createContext(a);function i(e){const t=o.useContext(s);return o.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function c(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:i(e.components),o.createElement(s.Provider,{value:t},e.children)}},7683:e=>{e.exports=JSON.parse('{"permalink":"/Cadence-Docs/blog/2022/04/30/community-spotlight-update-april-2022","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2022-04-30-community-spotlight-update-april-2022.md","source":"@site/blog/2022-04-30-community-spotlight-update-april-2022.md","title":"Cadence Community Spotlight Update - April 2022","description":"Welcome to our Cadence Community Spotlight update!","date":"2022-04-30T00:00:00.000Z","tags":[{"inline":false,"label":"Community Spotlight","permalink":"/Cadence-Docs/blog/tags/community-spotlights","description":"Community Spotlight tag description"}],"readingTime":2.955,"hasTruncateMarker":true,"authors":[{"name":"Sharan Foga","title":"Director of Operations & Customer Success @ Encube Technologies","url":"https://www.linkedin.com/in/sfoga/","page":{"permalink":"/Cadence-Docs/blog/authors/sharanf"},"socials":{"linkedin":"https://www.linkedin.com/in/sfoga/","github":"https://github.com/sharanf"},"imageURL":"https://github.com/sharanf.png","key":"sharanf"}],"frontMatter":{"title":"Cadence Community Spotlight Update - April 2022","date":"2022-04-30T00:00:00.000Z","authors":"sharanf","tags":["community-spotlight"]},"unlisted":false,"prevItem":{"title":"Cadence Community Spotlight Update - May 2022","permalink":"/Cadence-Docs/blog/2022/05/31/community-spotlight-update-may-2022"},"nextItem":{"title":"Cadence Community Spotlight Update - March 2022","permalink":"/Cadence-Docs/blog/2022/03/31/community-spotlight-update-march-2022"}}')}}]); \ No newline at end of file diff --git a/assets/js/3e206144.3079e23a.js b/assets/js/3e206144.3079e23a.js new file mode 100644 index 000000000..b7843b81b --- /dev/null +++ b/assets/js/3e206144.3079e23a.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[1898],{5335:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>i,contentTitle:()=>a,default:()=>u,frontMatter:()=>c,metadata:()=>s,toc:()=>l});const s=JSON.parse('{"id":"support","title":"Support","description":"On this page we\'ve listed some Cadence-related communities that you can be a part of.","source":"@site/community/0-support.mdx","sourceDirName":".","slug":"/support","permalink":"/Cadence-Docs/community/support","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/edit/master/community/0-support.mdx","tags":[],"version":"current","lastUpdatedBy":"Josue Ibarra","lastUpdatedAt":1733775712000,"sidebarPosition":0,"frontMatter":{},"sidebar":"community","next":{"title":"Team","permalink":"/Cadence-Docs/community/team"}}');var o=n(4848),r=n(8453);const c={},a="Support",i={},l=[{value:"Stack Overflow",id:"stack-overflow",level:2},{value:"Discussion forums",id:"discussion-forums",level:2},{value:"Feature requests",id:"feature-requests",level:2},{value:"Bug Reports",id:"bug-reports",level:2},{value:"News",id:"news",level:2}];function d(e){const t={a:"a",h1:"h1",h2:"h2",header:"header",li:"li",p:"p",strong:"strong",ul:"ul",...(0,r.R)(),...e.components};return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsx)(t.header,{children:(0,o.jsx)(t.h1,{id:"support",children:"Support"})}),"\n",(0,o.jsx)(t.p,{children:"On this page we've listed some Cadence-related communities that you can be a part of.\nYou can look up other resources in this section for additional learning materials."}),"\n",(0,o.jsxs)(t.p,{children:["Before participating in Cadence' communities, ",(0,o.jsx)(t.a,{href:"https://github.com/cadence-workflow/cadence/tree/master?tab=coc-ov-file#readme",children:"please read our Code of Conduct"}),". We have adopted the ",(0,o.jsx)(t.a,{href:"https://www.contributor-covenant.org/",children:"Contributor Covenant"})," and we expect that all community members adhere to the guidelines within."]}),"\n",(0,o.jsx)(t.h2,{id:"stack-overflow",children:"Stack Overflow"}),"\n",(0,o.jsxs)(t.p,{children:["Stack Overflow is a popular forum to ask code-level questions or if you're stuck with a specific error. Read through the ",(0,o.jsx)(t.a,{href:"https://stackoverflow.com/questions/tagged/cadence-workflow+uber-cadence",children:"existing questions"})," tagged with ",(0,o.jsx)(t.strong,{children:"cadence"})," or ",(0,o.jsx)(t.a,{href:"https://stackoverflow.com/questions/ask?tags=cadence-workflow",children:"ask your own"}),"!"]}),"\n",(0,o.jsx)(t.h2,{id:"discussion-forums",children:"Discussion forums"}),"\n",(0,o.jsx)(t.p,{children:"There are many online forums for discussion about best practices and application architecture as well as the future of Cadence. If you have an answerable code-level question, Stack Overflow is usually a better fit."}),"\n",(0,o.jsxs)(t.ul,{children:["\n",(0,o.jsx)(t.li,{children:(0,o.jsx)(t.a,{href:"http://t.uber.com/cadence-slack",children:"Cadence Community Slack"})}),"\n"]}),"\n",(0,o.jsx)(t.h2,{id:"feature-requests",children:"Feature requests"}),"\n",(0,o.jsxs)(t.ul,{children:["\n",(0,o.jsx)(t.li,{children:(0,o.jsx)(t.a,{href:"https://github.com/cadence-workflow/cadence/discussions",children:"Github Discussions"})}),"\n"]}),"\n",(0,o.jsx)(t.h2,{id:"bug-reports",children:"Bug Reports"}),"\n",(0,o.jsxs)(t.p,{children:["You can report Cadence bugs by opening an issue on the most relevant repository, the primary being ",(0,o.jsx)(t.a,{href:"https://github.com/cadence-workflow/cadence/issues",children:"cadence-workflow/cadence"})]}),"\n",(0,o.jsx)(t.h2,{id:"news",children:"News"}),"\n",(0,o.jsxs)(t.p,{children:["For the latest news about Cadence, follow the ",(0,o.jsx)(t.a,{href:"/blog",children:"official Cadence blog"})," on this website, ",(0,o.jsxs)(t.a,{href:"https://www.linkedin.com/company/cadenceworkflow",children:[(0,o.jsx)(t.strong,{children:"Cadence Workflow"})," on LinkedIn"]})," and ",(0,o.jsxs)(t.a,{href:"https://x.com/cadenceworkflow",children:[(0,o.jsx)(t.strong,{children:"@cadenceworkflow"})," on X"]})]})]})}function u(e={}){const{wrapper:t}={...(0,r.R)(),...e.components};return t?(0,o.jsx)(t,{...e,children:(0,o.jsx)(d,{...e})}):d(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>c,x:()=>a});var s=n(6540);const o={},r=s.createContext(o);function c(e){const t=s.useContext(r);return s.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function a(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:c(e.components),s.createElement(r.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/3e206144.9c7dec07.js b/assets/js/3e206144.9c7dec07.js deleted file mode 100644 index 270fed164..000000000 --- a/assets/js/3e206144.9c7dec07.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[1898],{5335:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>i,contentTitle:()=>a,default:()=>u,frontMatter:()=>c,metadata:()=>s,toc:()=>l});const s=JSON.parse('{"id":"support","title":"Support","description":"On this page we\'ve listed some Cadence-related communities that you can be a part of.","source":"@site/community/0-support.mdx","sourceDirName":".","slug":"/support","permalink":"/community/support","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/edit/master/community/0-support.mdx","tags":[],"version":"current","lastUpdatedBy":"Josue Ibarra","lastUpdatedAt":1733775712000,"sidebarPosition":0,"frontMatter":{},"sidebar":"community","next":{"title":"Team","permalink":"/community/team"}}');var o=n(4848),r=n(8453);const c={},a="Support",i={},l=[{value:"Stack Overflow",id:"stack-overflow",level:2},{value:"Discussion forums",id:"discussion-forums",level:2},{value:"Feature requests",id:"feature-requests",level:2},{value:"Bug Reports",id:"bug-reports",level:2},{value:"News",id:"news",level:2}];function d(e){const t={a:"a",h1:"h1",h2:"h2",header:"header",li:"li",p:"p",strong:"strong",ul:"ul",...(0,r.R)(),...e.components};return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsx)(t.header,{children:(0,o.jsx)(t.h1,{id:"support",children:"Support"})}),"\n",(0,o.jsx)(t.p,{children:"On this page we've listed some Cadence-related communities that you can be a part of.\nYou can look up other resources in this section for additional learning materials."}),"\n",(0,o.jsxs)(t.p,{children:["Before participating in Cadence' communities, ",(0,o.jsx)(t.a,{href:"https://github.com/cadence-workflow/cadence/tree/master?tab=coc-ov-file#readme",children:"please read our Code of Conduct"}),". We have adopted the ",(0,o.jsx)(t.a,{href:"https://www.contributor-covenant.org/",children:"Contributor Covenant"})," and we expect that all community members adhere to the guidelines within."]}),"\n",(0,o.jsx)(t.h2,{id:"stack-overflow",children:"Stack Overflow"}),"\n",(0,o.jsxs)(t.p,{children:["Stack Overflow is a popular forum to ask code-level questions or if you're stuck with a specific error. Read through the ",(0,o.jsx)(t.a,{href:"https://stackoverflow.com/questions/tagged/cadence-workflow+uber-cadence",children:"existing questions"})," tagged with ",(0,o.jsx)(t.strong,{children:"cadence"})," or ",(0,o.jsx)(t.a,{href:"https://stackoverflow.com/questions/ask?tags=cadence-workflow",children:"ask your own"}),"!"]}),"\n",(0,o.jsx)(t.h2,{id:"discussion-forums",children:"Discussion forums"}),"\n",(0,o.jsx)(t.p,{children:"There are many online forums for discussion about best practices and application architecture as well as the future of Cadence. If you have an answerable code-level question, Stack Overflow is usually a better fit."}),"\n",(0,o.jsxs)(t.ul,{children:["\n",(0,o.jsx)(t.li,{children:(0,o.jsx)(t.a,{href:"http://t.uber.com/cadence-slack",children:"Cadence Community Slack"})}),"\n"]}),"\n",(0,o.jsx)(t.h2,{id:"feature-requests",children:"Feature requests"}),"\n",(0,o.jsxs)(t.ul,{children:["\n",(0,o.jsx)(t.li,{children:(0,o.jsx)(t.a,{href:"https://github.com/cadence-workflow/cadence/discussions",children:"Github Discussions"})}),"\n"]}),"\n",(0,o.jsx)(t.h2,{id:"bug-reports",children:"Bug Reports"}),"\n",(0,o.jsxs)(t.p,{children:["You can report Cadence bugs by opening an issue on the most relevant repository, the primary being ",(0,o.jsx)(t.a,{href:"https://github.com/cadence-workflow/cadence/issues",children:"cadence-workflow/cadence"})]}),"\n",(0,o.jsx)(t.h2,{id:"news",children:"News"}),"\n",(0,o.jsxs)(t.p,{children:["For the latest news about Cadence, follow the ",(0,o.jsx)(t.a,{href:"/blog",children:"official Cadence blog"})," on this website, ",(0,o.jsxs)(t.a,{href:"https://www.linkedin.com/company/cadenceworkflow",children:[(0,o.jsx)(t.strong,{children:"Cadence Workflow"})," on LinkedIn"]})," and ",(0,o.jsxs)(t.a,{href:"https://x.com/cadenceworkflow",children:[(0,o.jsx)(t.strong,{children:"@cadenceworkflow"})," on X"]})]})]})}function u(e={}){const{wrapper:t}={...(0,r.R)(),...e.components};return t?(0,o.jsx)(t,{...e,children:(0,o.jsx)(d,{...e})}):d(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>c,x:()=>a});var s=n(6540);const o={},r=s.createContext(o);function c(e){const t=s.useContext(r);return s.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function a(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:c(e.components),s.createElement(r.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/3e30df86.238a33ad.js b/assets/js/3e30df86.238a33ad.js new file mode 100644 index 000000000..44bd2656e --- /dev/null +++ b/assets/js/3e30df86.238a33ad.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[2222],{725:(e,t,o)=>{o.r(t),o.d(t,{assets:()=>a,contentTitle:()=>l,default:()=>w,frontMatter:()=>s,metadata:()=>n,toc:()=>c});const n=JSON.parse('{"id":"go-client/02.5-starting-workflows","title":"Starting workflows","description":"Starting workflows can be done from any service that can send requests to","source":"@site/docs/05-go-client/02.5-starting-workflows.md","sourceDirName":"05-go-client","slug":"/go-client/02.5-starting-workflows","permalink":"/Cadence-Docs/docs/go-client/02.5-starting-workflows","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/05-go-client/02.5-starting-workflows.md","tags":[],"version":"current","frontMatter":{"layout":"default","title":"Starting workflows","permalink":"/docs/go-client/start-workflows"},"sidebar":"docsSidebar","previous":{"title":"Creating workflows","permalink":"/Cadence-Docs/docs/go-client/create-workflows"},"next":{"title":"Activity overview","permalink":"/Cadence-Docs/docs/go-client/activities"}}');var r=o(4848),i=o(8453);const s={layout:"default",title:"Starting workflows",permalink:"/docs/go-client/start-workflows"},l="Starting workflows",a={},c=[{value:"Starting a workflow",id:"starting-a-workflow",level:2},{value:"Jitter Start and Batches of Workflows",id:"jitter-start-and-batches-of-workflows",level:2},{value:"StartWorkflowOptions",id:"startworkflowoptions",level:2}];function d(e){const t={a:"a",code:"code",em:"em",h1:"h1",h2:"h2",header:"header",p:"p",pre:"pre",...(0,i.R)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(t.header,{children:(0,r.jsx)(t.h1,{id:"starting-workflows",children:"Starting workflows"})}),"\n",(0,r.jsx)(t.p,{children:"Starting workflows can be done from any service that can send requests to\nthe Cadence server. There is no requirement for workflows to be started from the\nworker services."}),"\n",(0,r.jsxs)(t.p,{children:["Generally workflows can either be started using a direct reference to the\nworkflow code, or by referring to the registered name of the function. In\n",(0,r.jsx)(t.a,{href:"/docs/go-client/create-workflows/#registration",children:"Workflow Registration"})," we show\nhow to register the workflows."]}),"\n",(0,r.jsx)(t.h2,{id:"starting-a-workflow",children:"Starting a workflow"}),"\n",(0,r.jsxs)(t.p,{children:["After ",(0,r.jsx)(t.a,{href:"/docs/go-client/create-workflows",children:"creating a workflow"})," we can start it.\nThis can be done ",(0,r.jsx)(t.a,{href:"/docs/cli/#start-workflow",children:"from the cli"}),", but typically\nwe want to start workflow programmatically e.g. from an http handler. We can do\nthis using the\n",(0,r.jsx)(t.a,{href:"https://pkg.go.dev/go.uber.org/cadence/client#Client",children:(0,r.jsx)(t.code,{children:"client.StartWorkflow"})}),"\nfunction:"]}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{className:"language-go",children:'import "go.uber.org/cadence/client"\n\nvar cadenceClient client.Client \n# Initialize cadenceClient\n\ncadenceClient.StartWorkflow(\n ctx,\n client.StartWorkflowOptions{\n TaskList: "workflow-task-list",\n ExecutionStartToCloseTimeout: 10 * time.Second,\n },\n WorkflowFunc,\n workflowArg1,\n workflowArg2,\n workflowArg3,\n ...\n)\n'})}),"\n",(0,r.jsxs)(t.p,{children:["The will start the workflow defined in the function ",(0,r.jsx)(t.code,{children:"WorkflowFunc"}),", note that\nfor named workflows ",(0,r.jsx)(t.code,{children:"WorkflowFunc"})," could be replaced by the name e.g.\n",(0,r.jsx)(t.code,{children:'"WorkflowFuncName"'}),"."]}),"\n",(0,r.jsxs)(t.p,{children:[(0,r.jsx)(t.code,{children:"workflowArg1"}),", ",(0,r.jsx)(t.code,{children:"workflowArg2"}),", ",(0,r.jsx)(t.code,{children:"workflowArg3"})," are arguments to the workflow, as\nspecified in ",(0,r.jsx)(t.code,{children:"WorkflowFunc"}),", note that the arguments needs to be ",(0,r.jsx)(t.em,{children:"serializable"}),"."]}),"\n",(0,r.jsx)(t.h2,{id:"jitter-start-and-batches-of-workflows",children:"Jitter Start and Batches of Workflows"}),"\n",(0,r.jsxs)(t.p,{children:["Below we list all the ",(0,r.jsx)(t.code,{children:"startWorkflowOptions"}),", however a particularly useful option is\n",(0,r.jsx)(t.code,{children:"JitterStart"}),"."]}),"\n",(0,r.jsx)(t.p,{children:"Starting many workflows at the same time will have Cadence trying to schedule\nall the workflows immediately. This can result in overloading Cadence and the\ndatabase backing Cadence, as well as the workers processing the workflows."}),"\n",(0,r.jsx)(t.p,{children:"This is especially bad when the workflow starts comes in batches, such as an end\nof month load. These sudden loads can lead to both Cadence and the workers\nneeding to immediately scale up. Scaling up often takes some time, causing\nqueues in Cadence, delaying the execution of all workflows, potentially causing\nworkflows to timeout."}),"\n",(0,r.jsxs)(t.p,{children:["To solve this we can start our workflows with ",(0,r.jsx)(t.code,{children:"JitterStart"}),". ",(0,r.jsx)(t.code,{children:"JitterStart"})," will start\nthe workflow at a random point between ",(0,r.jsx)(t.code,{children:"now"})," and ",(0,r.jsx)(t.code,{children:"now + JitterStart"}),", so if we\ne.g. start 1000 workflows at 12:00 AM with a ",(0,r.jsx)(t.code,{children:"JitterStart"})," of 6 hours, the\nworkflows will be randomly started between 12:00 AM and 6:00 PM."]}),"\n",(0,r.jsx)(t.p,{children:"This makes the sudden load of 1000 workflows much more manageable."}),"\n",(0,r.jsx)(t.p,{children:"For many batch-like workloads a random delay is completely acceptable as the\nbatch just needs to be processed e.g. before the end of the day."}),"\n",(0,r.jsx)(t.p,{children:"Adding a JitterStart of 6 hours in the example above is as simple as adding"}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{className:"language-go",children:"JitterStart: 6 * time.Hour,\n"})}),"\n",(0,r.jsx)(t.p,{children:"to the options like so,"}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{className:"language-go",children:'import "go.uber.org/cadence/client"\n\nvar cadenceClient client.Client\n# Initialize cadenceClient\n\ncadenceClient.StartWorkflow(\n ctx,\n client.StartWorkflowOptions{\n TaskList: "workflow-task-list",\n ExecutionStartToCloseTimeout: 10 * time.Second,\n JitterStart: 6 * time.Hour, // Added JitterStart\n },\n WorkflowFunc,\n workflowArg1,\n workflowArg2,\n workflowArg3,\n ...\n)\n'})}),"\n",(0,r.jsx)(t.p,{children:"now the workflow will start at a random point between now and six hours from now."}),"\n",(0,r.jsx)(t.h2,{id:"startworkflowoptions",children:"StartWorkflowOptions"}),"\n",(0,r.jsxs)(t.p,{children:["The\n",(0,r.jsx)(t.a,{href:"https://pkg.go.dev/go.uber.org/cadence/internal#StartWorkflowOptions",children:"client.StartWorkflowOptions"}),"\nspecifies the behavior of this particular workflow. The invocation above only\nspecifies the two mandatory options; ",(0,r.jsx)(t.code,{children:"TaskList"})," and\n",(0,r.jsx)(t.code,{children:"ExecutionStartToCloseTimeout"}),", all the options are described in the ",(0,r.jsx)(t.a,{href:"https://pkg.go.dev/go.uber.org/cadence/internal#StartWorkflowOptions",children:"inline\ndocumentation"}),":"]}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{className:"language-go",children:"type StartWorkflowOptions struct {\n\t// ID - The business identifier of the workflow execution.\n\t// Optional: defaulted to a uuid.\n\tID string\n\n\t// TaskList - The decisions of the workflow are scheduled on this queue.\n\t// This is also the default task list on which activities are scheduled. The workflow author can choose\n\t// to override this using activity options.\n\t// Mandatory: No default.\n\tTaskList string\n\n\t// ExecutionStartToCloseTimeout - The timeout for duration of workflow execution.\n\t// The resolution is seconds.\n\t// Mandatory: No default.\n\tExecutionStartToCloseTimeout time.Duration\n\n\t// DecisionTaskStartToCloseTimeout - The timeout for processing decision task from the time the worker\n\t// pulled this task. If a decision task is lost, it is retried after this timeout.\n\t// The resolution is seconds.\n\t// Optional: defaulted to 10 secs.\n\tDecisionTaskStartToCloseTimeout time.Duration\n\n\t// WorkflowIDReusePolicy - Whether server allow reuse of workflow ID, can be useful\n\t// for dedup logic if set to WorkflowIdReusePolicyRejectDuplicate.\n\t// Optional: defaulted to WorkflowIDReusePolicyAllowDuplicateFailedOnly.\n\tWorkflowIDReusePolicy WorkflowIDReusePolicy\n\n\t// RetryPolicy - Optional retry policy for workflow. If a retry policy is specified, in case of workflow failure\n\t// server will start new workflow execution if needed based on the retry policy.\n\tRetryPolicy *RetryPolicy\n\n\t// CronSchedule - Optional cron schedule for workflow. If a cron schedule is specified, the workflow will run\n\t// as a cron based on the schedule. The scheduling will be based on UTC time. Schedule for next run only happen\n\t// after the current run is completed/failed/timeout. If a RetryPolicy is also supplied, and the workflow failed\n\t// or timeout, the workflow will be retried based on the retry policy. While the workflow is retrying, it won't\n\t// schedule its next run. If next schedule is due while workflow is running (or retrying), then it will skip that\n\t// schedule. Cron workflow will not stop until it is terminated or cancelled (by returning cadence.CanceledError).\n\t// The cron spec is as following:\n\t// \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 minute (0 - 59)\n\t// \u2502 \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 hour (0 - 23)\n\t// \u2502 \u2502 \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 day of the month (1 - 31)\n\t// \u2502 \u2502 \u2502 \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 month (1 - 12)\n\t// \u2502 \u2502 \u2502 \u2502 \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 day of the week (0 - 6) (Sunday to Saturday)\n\t// \u2502 \u2502 \u2502 \u2502 \u2502\n\t// \u2502 \u2502 \u2502 \u2502 \u2502\n\t// * * * * *\n\tCronSchedule string\n\n\t// Memo - Optional non-indexed info that will be shown in list workflow.\n\tMemo map[string]interface{}\n\n\t// SearchAttributes - Optional indexed info that can be used in query of List/Scan/Count workflow APIs (only\n\t// supported when Cadence server is using ElasticSearch). The key and value type must be registered on Cadence server side.\n\t// Use GetSearchAttributes API to get valid key and corresponding value type.\n\tSearchAttributes map[string]interface{}\n\n\t// DelayStartSeconds - Seconds to delay the workflow start\n\t// The resolution is seconds.\n\t// Optional: defaulted to 0 seconds\n\tDelayStart time.Duration\n\n\t// JitterStart - Seconds to jitter the workflow start. For example, if set to 10, the workflow will start some time between 0-10 seconds.\n\t// This works with CronSchedule and with DelayStart.\n\t// Optional: defaulted to 0 seconds\n\tJitterStart time.Duration\n}\n"})})]})}function w(e={}){const{wrapper:t}={...(0,i.R)(),...e.components};return t?(0,r.jsx)(t,{...e,children:(0,r.jsx)(d,{...e})}):d(e)}},8453:(e,t,o)=>{o.d(t,{R:()=>s,x:()=>l});var n=o(6540);const r={},i=n.createContext(r);function s(e){const t=n.useContext(i);return n.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function l(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:s(e.components),n.createElement(i.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/3e30df86.88ff1f58.js b/assets/js/3e30df86.88ff1f58.js deleted file mode 100644 index 7db080c8b..000000000 --- a/assets/js/3e30df86.88ff1f58.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[2222],{725:(e,t,o)=>{o.r(t),o.d(t,{assets:()=>a,contentTitle:()=>l,default:()=>w,frontMatter:()=>s,metadata:()=>n,toc:()=>c});const n=JSON.parse('{"id":"go-client/02.5-starting-workflows","title":"Starting workflows","description":"Starting workflows can be done from any service that can send requests to","source":"@site/docs/05-go-client/02.5-starting-workflows.md","sourceDirName":"05-go-client","slug":"/go-client/02.5-starting-workflows","permalink":"/docs/go-client/02.5-starting-workflows","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/05-go-client/02.5-starting-workflows.md","tags":[],"version":"current","frontMatter":{"layout":"default","title":"Starting workflows","permalink":"/docs/go-client/start-workflows"},"sidebar":"docsSidebar","previous":{"title":"Creating workflows","permalink":"/docs/go-client/create-workflows"},"next":{"title":"Activity overview","permalink":"/docs/go-client/activities"}}');var r=o(4848),i=o(8453);const s={layout:"default",title:"Starting workflows",permalink:"/docs/go-client/start-workflows"},l="Starting workflows",a={},c=[{value:"Starting a workflow",id:"starting-a-workflow",level:2},{value:"Jitter Start and Batches of Workflows",id:"jitter-start-and-batches-of-workflows",level:2},{value:"StartWorkflowOptions",id:"startworkflowoptions",level:2}];function d(e){const t={a:"a",code:"code",em:"em",h1:"h1",h2:"h2",header:"header",p:"p",pre:"pre",...(0,i.R)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(t.header,{children:(0,r.jsx)(t.h1,{id:"starting-workflows",children:"Starting workflows"})}),"\n",(0,r.jsx)(t.p,{children:"Starting workflows can be done from any service that can send requests to\nthe Cadence server. There is no requirement for workflows to be started from the\nworker services."}),"\n",(0,r.jsxs)(t.p,{children:["Generally workflows can either be started using a direct reference to the\nworkflow code, or by referring to the registered name of the function. In\n",(0,r.jsx)(t.a,{href:"/docs/go-client/create-workflows/#registration",children:"Workflow Registration"})," we show\nhow to register the workflows."]}),"\n",(0,r.jsx)(t.h2,{id:"starting-a-workflow",children:"Starting a workflow"}),"\n",(0,r.jsxs)(t.p,{children:["After ",(0,r.jsx)(t.a,{href:"/docs/go-client/create-workflows",children:"creating a workflow"})," we can start it.\nThis can be done ",(0,r.jsx)(t.a,{href:"/docs/cli/#start-workflow",children:"from the cli"}),", but typically\nwe want to start workflow programmatically e.g. from an http handler. We can do\nthis using the\n",(0,r.jsx)(t.a,{href:"https://pkg.go.dev/go.uber.org/cadence/client#Client",children:(0,r.jsx)(t.code,{children:"client.StartWorkflow"})}),"\nfunction:"]}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{className:"language-go",children:'import "go.uber.org/cadence/client"\n\nvar cadenceClient client.Client \n# Initialize cadenceClient\n\ncadenceClient.StartWorkflow(\n ctx,\n client.StartWorkflowOptions{\n TaskList: "workflow-task-list",\n ExecutionStartToCloseTimeout: 10 * time.Second,\n },\n WorkflowFunc,\n workflowArg1,\n workflowArg2,\n workflowArg3,\n ...\n)\n'})}),"\n",(0,r.jsxs)(t.p,{children:["The will start the workflow defined in the function ",(0,r.jsx)(t.code,{children:"WorkflowFunc"}),", note that\nfor named workflows ",(0,r.jsx)(t.code,{children:"WorkflowFunc"})," could be replaced by the name e.g.\n",(0,r.jsx)(t.code,{children:'"WorkflowFuncName"'}),"."]}),"\n",(0,r.jsxs)(t.p,{children:[(0,r.jsx)(t.code,{children:"workflowArg1"}),", ",(0,r.jsx)(t.code,{children:"workflowArg2"}),", ",(0,r.jsx)(t.code,{children:"workflowArg3"})," are arguments to the workflow, as\nspecified in ",(0,r.jsx)(t.code,{children:"WorkflowFunc"}),", note that the arguments needs to be ",(0,r.jsx)(t.em,{children:"serializable"}),"."]}),"\n",(0,r.jsx)(t.h2,{id:"jitter-start-and-batches-of-workflows",children:"Jitter Start and Batches of Workflows"}),"\n",(0,r.jsxs)(t.p,{children:["Below we list all the ",(0,r.jsx)(t.code,{children:"startWorkflowOptions"}),", however a particularly useful option is\n",(0,r.jsx)(t.code,{children:"JitterStart"}),"."]}),"\n",(0,r.jsx)(t.p,{children:"Starting many workflows at the same time will have Cadence trying to schedule\nall the workflows immediately. This can result in overloading Cadence and the\ndatabase backing Cadence, as well as the workers processing the workflows."}),"\n",(0,r.jsx)(t.p,{children:"This is especially bad when the workflow starts comes in batches, such as an end\nof month load. These sudden loads can lead to both Cadence and the workers\nneeding to immediately scale up. Scaling up often takes some time, causing\nqueues in Cadence, delaying the execution of all workflows, potentially causing\nworkflows to timeout."}),"\n",(0,r.jsxs)(t.p,{children:["To solve this we can start our workflows with ",(0,r.jsx)(t.code,{children:"JitterStart"}),". ",(0,r.jsx)(t.code,{children:"JitterStart"})," will start\nthe workflow at a random point between ",(0,r.jsx)(t.code,{children:"now"})," and ",(0,r.jsx)(t.code,{children:"now + JitterStart"}),", so if we\ne.g. start 1000 workflows at 12:00 AM with a ",(0,r.jsx)(t.code,{children:"JitterStart"})," of 6 hours, the\nworkflows will be randomly started between 12:00 AM and 6:00 PM."]}),"\n",(0,r.jsx)(t.p,{children:"This makes the sudden load of 1000 workflows much more manageable."}),"\n",(0,r.jsx)(t.p,{children:"For many batch-like workloads a random delay is completely acceptable as the\nbatch just needs to be processed e.g. before the end of the day."}),"\n",(0,r.jsx)(t.p,{children:"Adding a JitterStart of 6 hours in the example above is as simple as adding"}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{className:"language-go",children:"JitterStart: 6 * time.Hour,\n"})}),"\n",(0,r.jsx)(t.p,{children:"to the options like so,"}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{className:"language-go",children:'import "go.uber.org/cadence/client"\n\nvar cadenceClient client.Client\n# Initialize cadenceClient\n\ncadenceClient.StartWorkflow(\n ctx,\n client.StartWorkflowOptions{\n TaskList: "workflow-task-list",\n ExecutionStartToCloseTimeout: 10 * time.Second,\n JitterStart: 6 * time.Hour, // Added JitterStart\n },\n WorkflowFunc,\n workflowArg1,\n workflowArg2,\n workflowArg3,\n ...\n)\n'})}),"\n",(0,r.jsx)(t.p,{children:"now the workflow will start at a random point between now and six hours from now."}),"\n",(0,r.jsx)(t.h2,{id:"startworkflowoptions",children:"StartWorkflowOptions"}),"\n",(0,r.jsxs)(t.p,{children:["The\n",(0,r.jsx)(t.a,{href:"https://pkg.go.dev/go.uber.org/cadence/internal#StartWorkflowOptions",children:"client.StartWorkflowOptions"}),"\nspecifies the behavior of this particular workflow. The invocation above only\nspecifies the two mandatory options; ",(0,r.jsx)(t.code,{children:"TaskList"})," and\n",(0,r.jsx)(t.code,{children:"ExecutionStartToCloseTimeout"}),", all the options are described in the ",(0,r.jsx)(t.a,{href:"https://pkg.go.dev/go.uber.org/cadence/internal#StartWorkflowOptions",children:"inline\ndocumentation"}),":"]}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{className:"language-go",children:"type StartWorkflowOptions struct {\n\t// ID - The business identifier of the workflow execution.\n\t// Optional: defaulted to a uuid.\n\tID string\n\n\t// TaskList - The decisions of the workflow are scheduled on this queue.\n\t// This is also the default task list on which activities are scheduled. The workflow author can choose\n\t// to override this using activity options.\n\t// Mandatory: No default.\n\tTaskList string\n\n\t// ExecutionStartToCloseTimeout - The timeout for duration of workflow execution.\n\t// The resolution is seconds.\n\t// Mandatory: No default.\n\tExecutionStartToCloseTimeout time.Duration\n\n\t// DecisionTaskStartToCloseTimeout - The timeout for processing decision task from the time the worker\n\t// pulled this task. If a decision task is lost, it is retried after this timeout.\n\t// The resolution is seconds.\n\t// Optional: defaulted to 10 secs.\n\tDecisionTaskStartToCloseTimeout time.Duration\n\n\t// WorkflowIDReusePolicy - Whether server allow reuse of workflow ID, can be useful\n\t// for dedup logic if set to WorkflowIdReusePolicyRejectDuplicate.\n\t// Optional: defaulted to WorkflowIDReusePolicyAllowDuplicateFailedOnly.\n\tWorkflowIDReusePolicy WorkflowIDReusePolicy\n\n\t// RetryPolicy - Optional retry policy for workflow. If a retry policy is specified, in case of workflow failure\n\t// server will start new workflow execution if needed based on the retry policy.\n\tRetryPolicy *RetryPolicy\n\n\t// CronSchedule - Optional cron schedule for workflow. If a cron schedule is specified, the workflow will run\n\t// as a cron based on the schedule. The scheduling will be based on UTC time. Schedule for next run only happen\n\t// after the current run is completed/failed/timeout. If a RetryPolicy is also supplied, and the workflow failed\n\t// or timeout, the workflow will be retried based on the retry policy. While the workflow is retrying, it won't\n\t// schedule its next run. If next schedule is due while workflow is running (or retrying), then it will skip that\n\t// schedule. Cron workflow will not stop until it is terminated or cancelled (by returning cadence.CanceledError).\n\t// The cron spec is as following:\n\t// \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 minute (0 - 59)\n\t// \u2502 \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 hour (0 - 23)\n\t// \u2502 \u2502 \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 day of the month (1 - 31)\n\t// \u2502 \u2502 \u2502 \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 month (1 - 12)\n\t// \u2502 \u2502 \u2502 \u2502 \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 day of the week (0 - 6) (Sunday to Saturday)\n\t// \u2502 \u2502 \u2502 \u2502 \u2502\n\t// \u2502 \u2502 \u2502 \u2502 \u2502\n\t// * * * * *\n\tCronSchedule string\n\n\t// Memo - Optional non-indexed info that will be shown in list workflow.\n\tMemo map[string]interface{}\n\n\t// SearchAttributes - Optional indexed info that can be used in query of List/Scan/Count workflow APIs (only\n\t// supported when Cadence server is using ElasticSearch). The key and value type must be registered on Cadence server side.\n\t// Use GetSearchAttributes API to get valid key and corresponding value type.\n\tSearchAttributes map[string]interface{}\n\n\t// DelayStartSeconds - Seconds to delay the workflow start\n\t// The resolution is seconds.\n\t// Optional: defaulted to 0 seconds\n\tDelayStart time.Duration\n\n\t// JitterStart - Seconds to jitter the workflow start. For example, if set to 10, the workflow will start some time between 0-10 seconds.\n\t// This works with CronSchedule and with DelayStart.\n\t// Optional: defaulted to 0 seconds\n\tJitterStart time.Duration\n}\n"})})]})}function w(e={}){const{wrapper:t}={...(0,i.R)(),...e.components};return t?(0,r.jsx)(t,{...e,children:(0,r.jsx)(d,{...e})}):d(e)}},8453:(e,t,o)=>{o.d(t,{R:()=>s,x:()=>l});var n=o(6540);const r={},i=n.createContext(r);function s(e){const t=n.useContext(i);return n.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function l(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:s(e.components),n.createElement(i.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/3faec549.6ba3d7c4.js b/assets/js/3faec549.6ba3d7c4.js new file mode 100644 index 000000000..2c161d9ac --- /dev/null +++ b/assets/js/3faec549.6ba3d7c4.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[2559],{6885:(e,n,r)=>{r.r(n),r.d(n,{assets:()=>l,contentTitle:()=>o,default:()=>h,frontMatter:()=>i,metadata:()=>t,toc:()=>d});const t=JSON.parse('{"id":"operation-guide/migration","title":"Cluster Migration","description":"There could be some reasons that you need to migrate Cadence clusters:","source":"@site/docs/07-operation-guide/05-migration.md","sourceDirName":"07-operation-guide","slug":"/operation-guide/migration","permalink":"/Cadence-Docs/docs/operation-guide/migration","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/07-operation-guide/05-migration.md","tags":[],"version":"current","sidebarPosition":5,"frontMatter":{"layout":"default","title":"Cluster Migration","permalink":"/docs/operation-guide/migration"},"sidebar":"docsSidebar","previous":{"title":"Cluster Troubleshooting","permalink":"/Cadence-Docs/docs/operation-guide/troubleshooting"},"next":{"title":"Overview","permalink":"/Cadence-Docs/docs/workflow-troubleshooting/"}}');var a=r(4848),s=r(8453);const i={layout:"default",title:"Cluster Migration",permalink:"/docs/operation-guide/migration"},o="Migrate Cadence cluster.",l={},d=[{value:"Migrate with naive approach",id:"migrate-with-naive-approach",level:2},{value:"Migrate with Global Domain Replication feature",id:"migrate-with-global-domain-replication-feature",level:2},{value:"Step 0 - Verify clusters' setup is correct",id:"step-0---verify-clusters-setup-is-correct",level:3},{value:"Step 1 - Connect the two clusters using global domain(replication) feature",id:"step-1---connect-the-two-clusters-using-global-domainreplication-feature",level:3},{value:"Step 2 - Test Replicating one domain",id:"step-2---test-replicating-one-domain",level:3},{value:"Step 3 - Start to replicate all domains",id:"step-3---start-to-replicate-all-domains",level:3},{value:"Step 4 - Complete the migration",id:"step-4---complete-the-migration",level:3}];function c(e){const n={a:"a",code:"code",h1:"h1",h2:"h2",h3:"h3",header:"header",li:"li",ol:"ol",p:"p",pre:"pre",ul:"ul",...(0,s.R)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(n.header,{children:(0,a.jsx)(n.h1,{id:"migrate-cadence-cluster",children:"Migrate Cadence cluster."})}),"\n",(0,a.jsx)(n.p,{children:"There could be some reasons that you need to migrate Cadence clusters:"}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsx)(n.li,{children:"Migrate to different storage, for example from Postgres/MySQL to Cassandra, or using multiple SQL database as a sharded SQL cluster for Cadence"}),"\n",(0,a.jsx)(n.li,{children:"Split traffic"}),"\n",(0,a.jsx)(n.li,{children:"Datacenter migration"}),"\n",(0,a.jsx)(n.li,{children:"Scale up -- to change numOfHistoryShards."}),"\n"]}),"\n",(0,a.jsx)(n.p,{children:"Below is two different approaches for migrating a cluster."}),"\n",(0,a.jsx)(n.h2,{id:"migrate-with-naive-approach",children:"Migrate with naive approach"}),"\n",(0,a.jsxs)(n.ol,{children:["\n",(0,a.jsx)(n.li,{children:"Set up a new Cadence cluster"}),"\n",(0,a.jsx)(n.li,{children:"Connect client workers to both old and new clusters"}),"\n",(0,a.jsx)(n.li,{children:"Change workflow code to start new workflows only in the new cluster"}),"\n",(0,a.jsx)(n.li,{children:"Wait for all old workflows to finish in the old cluster"}),"\n",(0,a.jsx)(n.li,{children:"Shutdown the old Cadence cluster and stop the client workers from connecting to it."}),"\n"]}),"\n",(0,a.jsx)(n.p,{children:"NOTE 1: With this approach, workflow history/visibility will not be migrated to new cluster."}),"\n",(0,a.jsx)(n.p,{children:"NOTE 2: This is the only way to migrate a local domain, because a local domain cannot be converted to a global domain, even after a cluster enables XDC feature."}),"\n",(0,a.jsxs)(n.p,{children:["NOTE 3: Starting from ",(0,a.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence/releases/tag/v0.22.0",children:"version 0.22.0"}),", global domain is preferred/recommended. Please ensure you create and use global domains only.\nIf you are using local domains, an easy way is to create a global domain and migrate to the new global domain using the above steps."]}),"\n",(0,a.jsxs)(n.h2,{id:"migrate-with-global-domain-replication-feature",children:["Migrate with ",(0,a.jsx)(n.a,{href:"/docs/concepts/cross-dc-replication/#running-in-production",children:"Global Domain Replication"})," feature"]}),"\n",(0,a.jsxs)(n.p,{children:["NOTE 1: If a domain are NOT a global domain, you cannot use the XDC feature to migrate. The only way is to migrate in a ",(0,a.jsx)(n.a,{href:"migration#migrate-with-naive-approach",children:"naive approach"})]}),"\n",(0,a.jsx)(n.p,{children:"NOTE 2: Only migrating to the same numHistoryShards is allowed."}),"\n",(0,a.jsx)(n.h3,{id:"step-0---verify-clusters-setup-is-correct",children:"Step 0 - Verify clusters' setup is correct"}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsx)(n.li,{children:"Make sure the new cluster doesn\u2019t already have the domain names that needs to be migrated (otherwise domain replication would fail)."}),"\n"]}),"\n",(0,a.jsx)(n.p,{children:"To get all the domains from current cluster:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-bash",children:"cadence --address admin domain list\n"})}),"\n",(0,a.jsx)(n.p,{children:"Then\nFor each global domain"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-bash",children:"cadence --address --do domain describe\n"})}),"\n",(0,a.jsx)(n.p,{children:"to make sure it doesn't exist in the new cluster."}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsxs)(n.li,{children:["\n",(0,a.jsx)(n.p,{children:"Target replication cluster should have numHistoryShards >= source cluster"}),"\n"]}),"\n",(0,a.jsxs)(n.li,{children:["\n",(0,a.jsx)(n.p,{children:"Target cluster should have the same search attributes enabled in dynamic configuration and in ElasticSearch."}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsxs)(n.li,{children:["\n",(0,a.jsxs)(n.p,{children:["Check the dynamic configuration to see if they have the same list of ",(0,a.jsx)(n.code,{children:"frontend.validSearchAttributes"}),". If any is missing in the new cluster, update the dynamic config for the new cluster."]}),"\n"]}),"\n",(0,a.jsxs)(n.li,{children:["\n",(0,a.jsx)(n.p,{children:"Check results of the below command to make sure that the ES fields matched with the dynamic configuration"}),"\n"]}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-bash",children:"curl -u : -X GET https:///cadence-visibility-index -H 'Content-Type: application/json'| jq .\n"})}),"\n",(0,a.jsx)(n.p,{children:"If any search attribute is missing, add the missing search attributes to target cluster."}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-bash",children:"cadence --address adm cluster add-search-attr --search_attr_key <> --search_attr_type <>\n"})}),"\n",(0,a.jsx)(n.h3,{id:"step-1---connect-the-two-clusters-using-global-domainreplication-feature",children:"Step 1 - Connect the two clusters using global domain(replication) feature"}),"\n",(0,a.jsx)(n.p,{children:"Include the Cluster Information for both the old and new clusters in the ClusterMetadata config of both clusters.\nExample config for currentCluster"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-yaml",children:'dcRedirectionPolicy:\n policy: "all-domain-apis-forwarding" # use selected-apis-forwarding if using older versions don\'t support this policy\n\nclusterMetadata:\n enableGlobalDomain: true\n failoverVersionIncrement: 10\n masterClusterName: ""\n currentClusterName: ""\n clusterInformation:\n :\n enabled: true\n initialFailoverVersion: 1\n rpcName: "cadence-frontend"\n rpcAddress: ""\n :\n enabled: true\n initialFailoverVersion: 0\n rpcName: "cadence-frontend"\n rpcAddress: ""\n'})}),"\n",(0,a.jsx)(n.p,{children:"for newClusterName:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-yaml",children:'dcRedirectionPolicy:\n policy: "all-domain-apis-forwarding"\n\nclusterMetadata:\n enableGlobalDomain: true\n failoverVersionIncrement: 10\n masterClusterName: ""\n currentClusterName: ""\n clusterInformation:\n :\n enabled: true\n initialFailoverVersion: 1\n rpcName: "cadence-frontend"\n rpcAddress: ""\n :\n enabled: true\n initialFailoverVersion: 0\n rpcName: "cadence-frontend"\n rpcAddress: ""\n'})}),"\n",(0,a.jsxs)(n.p,{children:["Deploy the config.\nIn older versions(",(0,a.jsx)(n.code,{children:"<= v0.22"}),"), only ",(0,a.jsx)(n.code,{children:"selected-apis-forwarding"})," is supported. This would require you to deploy a different set of workflow/activity connected to the new Cadence cluster during migration, if high availability/seamless migration is required. Because ",(0,a.jsx)(n.code,{children:"selected-apis-forwarding"})," only forwarding the non-worker APIs."]}),"\n",(0,a.jsxs)(n.p,{children:["With ",(0,a.jsx)(n.code,{children:"all-domain-apis-forwarding"})," policy, all worker + non-worker APIs are forwarded by Cadence cluster. You don't need to make any deployment change to your workflow/activity workers during migration. Once migration, let all workers connect to the new Cadence cluster before removing/shutdown the old cluster."]}),"\n",(0,a.jsxs)(n.p,{children:["Therefore, it's recommended to upgrade your Cadence cluster to a higher version with ",(0,a.jsx)(n.code,{children:"all-domain-apis-forwarding"})," policy supported. The below steps assuming you are using this policy."]}),"\n",(0,a.jsx)(n.h3,{id:"step-2---test-replicating-one-domain",children:"Step 2 - Test Replicating one domain"}),"\n",(0,a.jsxs)(n.p,{children:["First of all, try replicating a single domain to make sure everything work. Here uses ",(0,a.jsx)(n.code,{children:"domain update"})," to failover, you can also use ",(0,a.jsx)(n.code,{children:"managed failover"})," feature to failover. You may use some testing domains for this like ",(0,a.jsx)(n.code,{children:"cadence-canary"}),"."]}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsxs)(n.li,{children:["2.1 Assuming the domain only contain ",(0,a.jsx)(n.code,{children:"currentCluster"})," in the cluster list, let's add the new cluster to the domain."]}),"\n"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-bash",children:"cadence --address --do domain update --clusters \n"})}),"\n",(0,a.jsx)(n.p,{children:"Run the command below to refresh the domain after adding a new cluster to the cluster list; we need to update the active_cluster to the same value that it appears to be."}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-bash",children:"cadence --address --do domain update --active_cluster \n"})}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsx)(n.li,{children:"2.2 failover the domain to be active in new cluster"}),"\n"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-bash",children:"cadence --address --do workflow-prototype domain update --active_cluster \n"})}),"\n",(0,a.jsx)(n.p,{children:"Use the domain describe command to verify the entire domain is replicated to the new cluster."}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-bash",children:"cadence --address --do domain describe\n"})}),"\n",(0,a.jsx)(n.p,{children:"Find an open workflowID that we want to replicate (you can get it from the UI). Use this command to describe it to make sure it\u2019s open and running:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-bash",children:"cadence --address --do workflow describe --workflow_id \n"})}),"\n",(0,a.jsx)(n.p,{children:"Run a signal command against any workflow and check that it was replicated to the new cluster. Example:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-bash",children:"cadence --address --do workflow signal --workflow_id --name \n"})}),"\n",(0,a.jsx)(n.p,{children:"This command will send a noop signal to workflows to trigger a decision, which will trigger history replication if needed."}),"\n",(0,a.jsx)(n.p,{children:"Verify the workflow is replicated in the new cluster"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-bash",children:"cadence --address --st --do workflow describe --workflow_id \n"})}),"\n",(0,a.jsx)(n.p,{children:"Also compare the history between the two clusters:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-bash",children:"cadence --address --do workflow show --workflow_id \n"})}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-bash",children:"cadence --address --do workflow show --workflow_id \n"})}),"\n",(0,a.jsx)(n.h3,{id:"step-3---start-to-replicate-all-domains",children:"Step 3 - Start to replicate all domains"}),"\n",(0,a.jsxs)(n.p,{children:["You can repeat Step 2 for all the domains. Or you can use the managed failover feature to failover all the domains in the cluster with a single command. See more details in the ",(0,a.jsx)(n.a,{href:"/docs/concepts/cross-dc-replication",children:"global domain documentation"}),"."]}),"\n",(0,a.jsx)(n.p,{children:"Because replication cannot be triggered without a decision. Again best way is to send a garbage signal to all the workflows."}),"\n",(0,a.jsx)(n.p,{children:"If advanced visibility is enabled, then use batch signal command to start a batch job to trigger replication for all open workflows:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-bash",children:"cadence --address --do workflow batch start --batch_type signal --query \u201cCloseTime = missing\u201d --signal_name --reason --input --yes\n"})}),"\n",(0,a.jsx)(n.p,{children:"Watch metrics & dashboard while this is happening. Also observe the signal batch job to make sure it's completed."}),"\n",(0,a.jsx)(n.h3,{id:"step-4---complete-the-migration",children:"Step 4 - Complete the migration"}),"\n",(0,a.jsx)(n.p,{children:"After a few days, make sure everything is stable on the new cluster. The old cluster should only be forwarding requests to new cluster."}),"\n",(0,a.jsx)(n.p,{children:"A few things need to do in order to shutdown the old cluster."}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsx)(n.li,{children:"Migrate all applications to connect to the frontend of new cluster instead of relying on the forwarding"}),"\n",(0,a.jsx)(n.li,{children:"Watch metric dashboard to make sure no any traffic is happening on the old cluster"}),"\n",(0,a.jsx)(n.li,{children:"Delete the old cluster from domain cluster list. This needs to be done for every domain."}),"\n"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-bash",children:"cadence --address --do domain update --clusters \n"})}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsx)(n.li,{children:"Delete the old cluster from the configuration of the new cluster."}),"\n"]}),"\n",(0,a.jsx)(n.p,{children:"Once above is done, you can shutdown the old cluster safely."})]})}function h(e={}){const{wrapper:n}={...(0,s.R)(),...e.components};return n?(0,a.jsx)(n,{...e,children:(0,a.jsx)(c,{...e})}):c(e)}},8453:(e,n,r)=>{r.d(n,{R:()=>i,x:()=>o});var t=r(6540);const a={},s=t.createContext(a);function i(e){const n=t.useContext(s);return t.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function o(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:i(e.components),t.createElement(s.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/3faec549.b14e7ae2.js b/assets/js/3faec549.b14e7ae2.js deleted file mode 100644 index 8bf1dbe7e..000000000 --- a/assets/js/3faec549.b14e7ae2.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[2559],{6885:(e,n,r)=>{r.r(n),r.d(n,{assets:()=>l,contentTitle:()=>o,default:()=>h,frontMatter:()=>s,metadata:()=>t,toc:()=>d});const t=JSON.parse('{"id":"operation-guide/migration","title":"Cluster Migration","description":"There could be some reasons that you need to migrate Cadence clusters:","source":"@site/docs/07-operation-guide/05-migration.md","sourceDirName":"07-operation-guide","slug":"/operation-guide/migration","permalink":"/docs/operation-guide/migration","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/07-operation-guide/05-migration.md","tags":[],"version":"current","sidebarPosition":5,"frontMatter":{"layout":"default","title":"Cluster Migration","permalink":"/docs/operation-guide/migration"},"sidebar":"docsSidebar","previous":{"title":"Cluster Troubleshooting","permalink":"/docs/operation-guide/troubleshooting"},"next":{"title":"Overview","permalink":"/docs/workflow-troubleshooting/"}}');var a=r(4848),i=r(8453);const s={layout:"default",title:"Cluster Migration",permalink:"/docs/operation-guide/migration"},o="Migrate Cadence cluster.",l={},d=[{value:"Migrate with naive approach",id:"migrate-with-naive-approach",level:2},{value:"Migrate with Global Domain Replication feature",id:"migrate-with-global-domain-replication-feature",level:2},{value:"Step 0 - Verify clusters' setup is correct",id:"step-0---verify-clusters-setup-is-correct",level:3},{value:"Step 1 - Connect the two clusters using global domain(replication) feature",id:"step-1---connect-the-two-clusters-using-global-domainreplication-feature",level:3},{value:"Step 2 - Test Replicating one domain",id:"step-2---test-replicating-one-domain",level:3},{value:"Step 3 - Start to replicate all domains",id:"step-3---start-to-replicate-all-domains",level:3},{value:"Step 4 - Complete the migration",id:"step-4---complete-the-migration",level:3}];function c(e){const n={a:"a",code:"code",h1:"h1",h2:"h2",h3:"h3",header:"header",li:"li",ol:"ol",p:"p",pre:"pre",ul:"ul",...(0,i.R)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(n.header,{children:(0,a.jsx)(n.h1,{id:"migrate-cadence-cluster",children:"Migrate Cadence cluster."})}),"\n",(0,a.jsx)(n.p,{children:"There could be some reasons that you need to migrate Cadence clusters:"}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsx)(n.li,{children:"Migrate to different storage, for example from Postgres/MySQL to Cassandra, or using multiple SQL database as a sharded SQL cluster for Cadence"}),"\n",(0,a.jsx)(n.li,{children:"Split traffic"}),"\n",(0,a.jsx)(n.li,{children:"Datacenter migration"}),"\n",(0,a.jsx)(n.li,{children:"Scale up -- to change numOfHistoryShards."}),"\n"]}),"\n",(0,a.jsx)(n.p,{children:"Below is two different approaches for migrating a cluster."}),"\n",(0,a.jsx)(n.h2,{id:"migrate-with-naive-approach",children:"Migrate with naive approach"}),"\n",(0,a.jsxs)(n.ol,{children:["\n",(0,a.jsx)(n.li,{children:"Set up a new Cadence cluster"}),"\n",(0,a.jsx)(n.li,{children:"Connect client workers to both old and new clusters"}),"\n",(0,a.jsx)(n.li,{children:"Change workflow code to start new workflows only in the new cluster"}),"\n",(0,a.jsx)(n.li,{children:"Wait for all old workflows to finish in the old cluster"}),"\n",(0,a.jsx)(n.li,{children:"Shutdown the old Cadence cluster and stop the client workers from connecting to it."}),"\n"]}),"\n",(0,a.jsx)(n.p,{children:"NOTE 1: With this approach, workflow history/visibility will not be migrated to new cluster."}),"\n",(0,a.jsx)(n.p,{children:"NOTE 2: This is the only way to migrate a local domain, because a local domain cannot be converted to a global domain, even after a cluster enables XDC feature."}),"\n",(0,a.jsxs)(n.p,{children:["NOTE 3: Starting from ",(0,a.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence/releases/tag/v0.22.0",children:"version 0.22.0"}),", global domain is preferred/recommended. Please ensure you create and use global domains only.\nIf you are using local domains, an easy way is to create a global domain and migrate to the new global domain using the above steps."]}),"\n",(0,a.jsxs)(n.h2,{id:"migrate-with-global-domain-replication-feature",children:["Migrate with ",(0,a.jsx)(n.a,{href:"/docs/concepts/cross-dc-replication/#running-in-production",children:"Global Domain Replication"})," feature"]}),"\n",(0,a.jsxs)(n.p,{children:["NOTE 1: If a domain are NOT a global domain, you cannot use the XDC feature to migrate. The only way is to migrate in a ",(0,a.jsx)(n.a,{href:"migration#migrate-with-naive-approach",children:"naive approach"})]}),"\n",(0,a.jsx)(n.p,{children:"NOTE 2: Only migrating to the same numHistoryShards is allowed."}),"\n",(0,a.jsx)(n.h3,{id:"step-0---verify-clusters-setup-is-correct",children:"Step 0 - Verify clusters' setup is correct"}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsx)(n.li,{children:"Make sure the new cluster doesn\u2019t already have the domain names that needs to be migrated (otherwise domain replication would fail)."}),"\n"]}),"\n",(0,a.jsx)(n.p,{children:"To get all the domains from current cluster:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-bash",children:"cadence --address admin domain list\n"})}),"\n",(0,a.jsx)(n.p,{children:"Then\nFor each global domain"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-bash",children:"cadence --address --do domain describe\n"})}),"\n",(0,a.jsx)(n.p,{children:"to make sure it doesn't exist in the new cluster."}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsxs)(n.li,{children:["\n",(0,a.jsx)(n.p,{children:"Target replication cluster should have numHistoryShards >= source cluster"}),"\n"]}),"\n",(0,a.jsxs)(n.li,{children:["\n",(0,a.jsx)(n.p,{children:"Target cluster should have the same search attributes enabled in dynamic configuration and in ElasticSearch."}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsxs)(n.li,{children:["\n",(0,a.jsxs)(n.p,{children:["Check the dynamic configuration to see if they have the same list of ",(0,a.jsx)(n.code,{children:"frontend.validSearchAttributes"}),". If any is missing in the new cluster, update the dynamic config for the new cluster."]}),"\n"]}),"\n",(0,a.jsxs)(n.li,{children:["\n",(0,a.jsx)(n.p,{children:"Check results of the below command to make sure that the ES fields matched with the dynamic configuration"}),"\n"]}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-bash",children:"curl -u : -X GET https:///cadence-visibility-index -H 'Content-Type: application/json'| jq .\n"})}),"\n",(0,a.jsx)(n.p,{children:"If any search attribute is missing, add the missing search attributes to target cluster."}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-bash",children:"cadence --address adm cluster add-search-attr --search_attr_key <> --search_attr_type <>\n"})}),"\n",(0,a.jsx)(n.h3,{id:"step-1---connect-the-two-clusters-using-global-domainreplication-feature",children:"Step 1 - Connect the two clusters using global domain(replication) feature"}),"\n",(0,a.jsx)(n.p,{children:"Include the Cluster Information for both the old and new clusters in the ClusterMetadata config of both clusters.\nExample config for currentCluster"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-yaml",children:'dcRedirectionPolicy:\n policy: "all-domain-apis-forwarding" # use selected-apis-forwarding if using older versions don\'t support this policy\n\nclusterMetadata:\n enableGlobalDomain: true\n failoverVersionIncrement: 10\n masterClusterName: ""\n currentClusterName: ""\n clusterInformation:\n :\n enabled: true\n initialFailoverVersion: 1\n rpcName: "cadence-frontend"\n rpcAddress: ""\n :\n enabled: true\n initialFailoverVersion: 0\n rpcName: "cadence-frontend"\n rpcAddress: ""\n'})}),"\n",(0,a.jsx)(n.p,{children:"for newClusterName:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-yaml",children:'dcRedirectionPolicy:\n policy: "all-domain-apis-forwarding"\n\nclusterMetadata:\n enableGlobalDomain: true\n failoverVersionIncrement: 10\n masterClusterName: ""\n currentClusterName: ""\n clusterInformation:\n :\n enabled: true\n initialFailoverVersion: 1\n rpcName: "cadence-frontend"\n rpcAddress: ""\n :\n enabled: true\n initialFailoverVersion: 0\n rpcName: "cadence-frontend"\n rpcAddress: ""\n'})}),"\n",(0,a.jsxs)(n.p,{children:["Deploy the config.\nIn older versions(",(0,a.jsx)(n.code,{children:"<= v0.22"}),"), only ",(0,a.jsx)(n.code,{children:"selected-apis-forwarding"})," is supported. This would require you to deploy a different set of workflow/activity connected to the new Cadence cluster during migration, if high availability/seamless migration is required. Because ",(0,a.jsx)(n.code,{children:"selected-apis-forwarding"})," only forwarding the non-worker APIs."]}),"\n",(0,a.jsxs)(n.p,{children:["With ",(0,a.jsx)(n.code,{children:"all-domain-apis-forwarding"})," policy, all worker + non-worker APIs are forwarded by Cadence cluster. You don't need to make any deployment change to your workflow/activity workers during migration. Once migration, let all workers connect to the new Cadence cluster before removing/shutdown the old cluster."]}),"\n",(0,a.jsxs)(n.p,{children:["Therefore, it's recommended to upgrade your Cadence cluster to a higher version with ",(0,a.jsx)(n.code,{children:"all-domain-apis-forwarding"})," policy supported. The below steps assuming you are using this policy."]}),"\n",(0,a.jsx)(n.h3,{id:"step-2---test-replicating-one-domain",children:"Step 2 - Test Replicating one domain"}),"\n",(0,a.jsxs)(n.p,{children:["First of all, try replicating a single domain to make sure everything work. Here uses ",(0,a.jsx)(n.code,{children:"domain update"})," to failover, you can also use ",(0,a.jsx)(n.code,{children:"managed failover"})," feature to failover. You may use some testing domains for this like ",(0,a.jsx)(n.code,{children:"cadence-canary"}),"."]}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsxs)(n.li,{children:["2.1 Assuming the domain only contain ",(0,a.jsx)(n.code,{children:"currentCluster"})," in the cluster list, let's add the new cluster to the domain."]}),"\n"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-bash",children:"cadence --address --do domain update --clusters \n"})}),"\n",(0,a.jsx)(n.p,{children:"Run the command below to refresh the domain after adding a new cluster to the cluster list; we need to update the active_cluster to the same value that it appears to be."}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-bash",children:"cadence --address --do domain update --active_cluster \n"})}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsx)(n.li,{children:"2.2 failover the domain to be active in new cluster"}),"\n"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-bash",children:"cadence --address --do workflow-prototype domain update --active_cluster \n"})}),"\n",(0,a.jsx)(n.p,{children:"Use the domain describe command to verify the entire domain is replicated to the new cluster."}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-bash",children:"cadence --address --do domain describe\n"})}),"\n",(0,a.jsx)(n.p,{children:"Find an open workflowID that we want to replicate (you can get it from the UI). Use this command to describe it to make sure it\u2019s open and running:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-bash",children:"cadence --address --do workflow describe --workflow_id \n"})}),"\n",(0,a.jsx)(n.p,{children:"Run a signal command against any workflow and check that it was replicated to the new cluster. Example:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-bash",children:"cadence --address --do workflow signal --workflow_id --name \n"})}),"\n",(0,a.jsx)(n.p,{children:"This command will send a noop signal to workflows to trigger a decision, which will trigger history replication if needed."}),"\n",(0,a.jsx)(n.p,{children:"Verify the workflow is replicated in the new cluster"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-bash",children:"cadence --address --st --do workflow describe --workflow_id \n"})}),"\n",(0,a.jsx)(n.p,{children:"Also compare the history between the two clusters:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-bash",children:"cadence --address --do workflow show --workflow_id \n"})}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-bash",children:"cadence --address --do workflow show --workflow_id \n"})}),"\n",(0,a.jsx)(n.h3,{id:"step-3---start-to-replicate-all-domains",children:"Step 3 - Start to replicate all domains"}),"\n",(0,a.jsxs)(n.p,{children:["You can repeat Step 2 for all the domains. Or you can use the managed failover feature to failover all the domains in the cluster with a single command. See more details in the ",(0,a.jsx)(n.a,{href:"/docs/concepts/cross-dc-replication",children:"global domain documentation"}),"."]}),"\n",(0,a.jsx)(n.p,{children:"Because replication cannot be triggered without a decision. Again best way is to send a garbage signal to all the workflows."}),"\n",(0,a.jsx)(n.p,{children:"If advanced visibility is enabled, then use batch signal command to start a batch job to trigger replication for all open workflows:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-bash",children:"cadence --address --do workflow batch start --batch_type signal --query \u201cCloseTime = missing\u201d --signal_name --reason --input --yes\n"})}),"\n",(0,a.jsx)(n.p,{children:"Watch metrics & dashboard while this is happening. Also observe the signal batch job to make sure it's completed."}),"\n",(0,a.jsx)(n.h3,{id:"step-4---complete-the-migration",children:"Step 4 - Complete the migration"}),"\n",(0,a.jsx)(n.p,{children:"After a few days, make sure everything is stable on the new cluster. The old cluster should only be forwarding requests to new cluster."}),"\n",(0,a.jsx)(n.p,{children:"A few things need to do in order to shutdown the old cluster."}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsx)(n.li,{children:"Migrate all applications to connect to the frontend of new cluster instead of relying on the forwarding"}),"\n",(0,a.jsx)(n.li,{children:"Watch metric dashboard to make sure no any traffic is happening on the old cluster"}),"\n",(0,a.jsx)(n.li,{children:"Delete the old cluster from domain cluster list. This needs to be done for every domain."}),"\n"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-bash",children:"cadence --address --do domain update --clusters \n"})}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsx)(n.li,{children:"Delete the old cluster from the configuration of the new cluster."}),"\n"]}),"\n",(0,a.jsx)(n.p,{children:"Once above is done, you can shutdown the old cluster safely."})]})}function h(e={}){const{wrapper:n}={...(0,i.R)(),...e.components};return n?(0,a.jsx)(n,{...e,children:(0,a.jsx)(c,{...e})}):c(e)}},8453:(e,n,r)=>{r.d(n,{R:()=>s,x:()=>o});var t=r(6540);const a={},i=t.createContext(a);function s(e){const n=t.useContext(i);return t.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function o(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:s(e.components),t.createElement(i.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/40011a75.43cf0444.js b/assets/js/40011a75.43cf0444.js deleted file mode 100644 index d75ccf4c4..000000000 --- a/assets/js/40011a75.43cf0444.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[492],{5443:e=>{e.exports=JSON.parse('{"metadata":{"permalink":"/blog/page/4","page":4,"postsPerPage":10,"totalPages":4,"totalCount":35,"previousPage":"/blog/page/3","blogDescription":"The latest news and updates from the Cadence team","blogTitle":"Cadence Blog"}}')}}]); \ No newline at end of file diff --git a/assets/js/41417ef6.6e42ecef.js b/assets/js/41417ef6.6e42ecef.js deleted file mode 100644 index 4f1d259ea..000000000 --- a/assets/js/41417ef6.6e42ecef.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[6323],{3795:(e,n,s)=>{s.r(n),s.d(n,{assets:()=>l,contentTitle:()=>r,default:()=>p,frontMatter:()=>i,metadata:()=>t,toc:()=>c});const t=JSON.parse('{"id":"use-cases/deployment","title":"Deployment","description":"Implementing CI/CD pipelines and deployment of applications to containers or virtual or physical machines is a non-trivial process.","source":"@site/docs/02-use-cases/08-deployment.md","sourceDirName":"02-use-cases","slug":"/use-cases/deployment","permalink":"/docs/use-cases/deployment","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/02-use-cases/08-deployment.md","tags":[],"version":"current","sidebarPosition":8,"frontMatter":{"layout":"default","title":"Deployment","permalink":"/docs/use-cases/deployment"},"sidebar":"docsSidebar","previous":{"title":"Infrastructure provisioning","permalink":"/docs/use-cases/provisioning"},"next":{"title":"Operational management","permalink":"/docs/use-cases/operational-management"}}');var o=s(4848),a=s(8453);const i={layout:"default",title:"Deployment",permalink:"/docs/use-cases/deployment"},r="CI/CD and Deployment",l={},c=[];function d(e){const n={h1:"h1",header:"header",li:"li",p:"p",ul:"ul",...(0,a.R)(),...e.components};return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsx)(n.header,{children:(0,o.jsx)(n.h1,{id:"cicd-and-deployment",children:"CI/CD and Deployment"})}),"\n",(0,o.jsx)(n.p,{children:"Implementing CI/CD pipelines and deployment of applications to containers or virtual or physical machines is a non-trivial process.\nIts business logic has to deal with complex requirements around rolling upgrades, canary deployments, and rollbacks.\nCadence is a perfect platform for building a deployment solution because it provides all the necessary guarantees and abstractions\nallowing developers to focus on the business logic."}),"\n",(0,o.jsx)(n.p,{children:"Example production systems:"}),"\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsx)(n.li,{children:"Uber internal deployment infrastructure"}),"\n",(0,o.jsx)(n.li,{children:"Update push to IoT devices"}),"\n"]})]})}function p(e={}){const{wrapper:n}={...(0,a.R)(),...e.components};return n?(0,o.jsx)(n,{...e,children:(0,o.jsx)(d,{...e})}):d(e)}},8453:(e,n,s)=>{s.d(n,{R:()=>i,x:()=>r});var t=s(6540);const o={},a=t.createContext(o);function i(e){const n=t.useContext(a);return t.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function r(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:i(e.components),t.createElement(a.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/41417ef6.c7c3692e.js b/assets/js/41417ef6.c7c3692e.js new file mode 100644 index 000000000..39a02788a --- /dev/null +++ b/assets/js/41417ef6.c7c3692e.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[6323],{3795:(e,n,s)=>{s.r(n),s.d(n,{assets:()=>c,contentTitle:()=>r,default:()=>p,frontMatter:()=>i,metadata:()=>t,toc:()=>l});const t=JSON.parse('{"id":"use-cases/deployment","title":"Deployment","description":"Implementing CI/CD pipelines and deployment of applications to containers or virtual or physical machines is a non-trivial process.","source":"@site/docs/02-use-cases/08-deployment.md","sourceDirName":"02-use-cases","slug":"/use-cases/deployment","permalink":"/Cadence-Docs/docs/use-cases/deployment","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/02-use-cases/08-deployment.md","tags":[],"version":"current","sidebarPosition":8,"frontMatter":{"layout":"default","title":"Deployment","permalink":"/docs/use-cases/deployment"},"sidebar":"docsSidebar","previous":{"title":"Infrastructure provisioning","permalink":"/Cadence-Docs/docs/use-cases/provisioning"},"next":{"title":"Operational management","permalink":"/Cadence-Docs/docs/use-cases/operational-management"}}');var o=s(4848),a=s(8453);const i={layout:"default",title:"Deployment",permalink:"/docs/use-cases/deployment"},r="CI/CD and Deployment",c={},l=[];function d(e){const n={h1:"h1",header:"header",li:"li",p:"p",ul:"ul",...(0,a.R)(),...e.components};return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsx)(n.header,{children:(0,o.jsx)(n.h1,{id:"cicd-and-deployment",children:"CI/CD and Deployment"})}),"\n",(0,o.jsx)(n.p,{children:"Implementing CI/CD pipelines and deployment of applications to containers or virtual or physical machines is a non-trivial process.\nIts business logic has to deal with complex requirements around rolling upgrades, canary deployments, and rollbacks.\nCadence is a perfect platform for building a deployment solution because it provides all the necessary guarantees and abstractions\nallowing developers to focus on the business logic."}),"\n",(0,o.jsx)(n.p,{children:"Example production systems:"}),"\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsx)(n.li,{children:"Uber internal deployment infrastructure"}),"\n",(0,o.jsx)(n.li,{children:"Update push to IoT devices"}),"\n"]})]})}function p(e={}){const{wrapper:n}={...(0,a.R)(),...e.components};return n?(0,o.jsx)(n,{...e,children:(0,o.jsx)(d,{...e})}):d(e)}},8453:(e,n,s)=>{s.d(n,{R:()=>i,x:()=>r});var t=s(6540);const o={},a=t.createContext(o);function i(e){const n=t.useContext(a);return t.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function r(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:i(e.components),t.createElement(a.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/43e9f1b6.9d9f2509.js b/assets/js/43e9f1b6.9d9f2509.js deleted file mode 100644 index acde5e92d..000000000 --- a/assets/js/43e9f1b6.9d9f2509.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[8817],{4512:(e,t,s)=>{s.r(t),s.d(t,{assets:()=>l,contentTitle:()=>a,default:()=>u,frontMatter:()=>r,metadata:()=>o,toc:()=>d});const o=JSON.parse('{"id":"operation-guide/troubleshooting","title":"Cluster Troubleshooting","description":"This section is to cover some common operation issues as a RunBook. Feel free to add more, or raise issues in the to ask for more in cadence-docs project.Or talk to us in Slack support channel!","source":"@site/docs/07-operation-guide/04-troubleshooting.md","sourceDirName":"07-operation-guide","slug":"/operation-guide/troubleshooting","permalink":"/docs/operation-guide/troubleshooting","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/07-operation-guide/04-troubleshooting.md","tags":[],"version":"current","sidebarPosition":4,"frontMatter":{"layout":"default","title":"Cluster Troubleshooting","permalink":"/docs/operation-guide/troubleshooting"},"sidebar":"docsSidebar","previous":{"title":"Cluster Monitoring","permalink":"/docs/operation-guide/monitoring"},"next":{"title":"Cluster Migration","permalink":"/docs/operation-guide/migration"}}');var i=s(4848),n=s(8453);const r={layout:"default",title:"Cluster Troubleshooting",permalink:"/docs/operation-guide/troubleshooting"},a="Cluster Troubleshooting",l={},d=[{value:"Errors",id:"errors",level:2},{value:"API high latency, timeout, Task disptaching slowness Or Too many operations onto DB and timeouts",id:"api-high-latency-timeout-task-disptaching-slowness-or-too-many-operations-onto-db-and-timeouts",level:2}];function c(e){const t={a:"a",code:"code",h1:"h1",h2:"h2",header:"header",li:"li",p:"p",ul:"ul",...(0,n.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(t.header,{children:(0,i.jsx)(t.h1,{id:"cluster-troubleshooting",children:"Cluster Troubleshooting"})}),"\n",(0,i.jsxs)(t.p,{children:["This section is to cover some common operation issues as a RunBook. Feel free to add more, or raise issues in the to ask for more in ",(0,i.jsx)(t.a,{href:"https://github.com/cadence-workflow/Cadence-Docs/issues",children:"cadence-docs"})," project.Or talk to us in Slack support channel!"]}),"\n",(0,i.jsx)(t.p,{children:"We will keep adding more stuff. Any contribution is very welcome."}),"\n",(0,i.jsx)(t.h2,{id:"errors",children:"Errors"}),"\n",(0,i.jsxs)(t.ul,{children:["\n",(0,i.jsxs)(t.li,{children:[(0,i.jsx)(t.code,{children:"Persistence Max QPS Reached for List Operations"}),"\n",(0,i.jsxs)(t.ul,{children:["\n",(0,i.jsxs)(t.li,{children:["Check metrics to see how many List operations are performed per second on the domain. Alternatively you can enable ",(0,i.jsx)(t.code,{children:"debug"})," log level to see more details of how a List request is ratelimited, if it's a staging/QA cluster."]}),"\n",(0,i.jsx)(t.li,{children:"Raise the ratelimiting for the domain if you believe the default ratelimit is too low"}),"\n"]}),"\n"]}),"\n",(0,i.jsxs)(t.li,{children:[(0,i.jsx)(t.code,{children:"Failed to lock shard. Previous range ID: 132; new range ID: 133"})," and ",(0,i.jsx)(t.code,{children:"Failed to update shard. Previous range ID: 210; new range ID: 212"}),"\n",(0,i.jsxs)(t.ul,{children:["\n",(0,i.jsx)(t.li,{children:"When this keep happening, it's very likely a critical configuration error. Either there are two clusters using the same database, or two clusters are using the same ringpop(bootstrap hosts)."}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(t.h2,{id:"api-high-latency-timeout-task-disptaching-slowness-or-too-many-operations-onto-db-and-timeouts",children:"API high latency, timeout, Task disptaching slowness Or Too many operations onto DB and timeouts"}),"\n",(0,i.jsxs)(t.ul,{children:["\n",(0,i.jsxs)(t.li,{children:["\n",(0,i.jsx)(t.p,{children:"If it happens after you attemped to truncate tables inorder to reuse the same database/keyspace for a new cluster, it's possible that the data is not deleted completely. You should make sure to shutdown the Cadence when trucating, and make sure the database is cleaned. Alternatively, use a different keyspace/database is a safer way."}),"\n"]}),"\n",(0,i.jsxs)(t.li,{children:["\n",(0,i.jsxs)(t.p,{children:["Timeout pushing task to matching engine, e.g. ",(0,i.jsx)(t.code,{children:'"Fail to process task","service":"cadence-history","shard-id":431,"address":"172.31.48.64:7934","component":"transfer-queue-processor","cluster-name":"active","shard-id":431,"queue-task-id":590357768,"queue-task-visibility-timestamp":1637356594382077880,"xdc-failover-version":-24,"queue-task-type":0,"wf-domain-id":"f4d6824f-9d24-4a82-81e0-e0e080be4c21","wf-id":"55d64d58-e398-4bf5-88bc-a4696a2ba87f:63ed7cda-afcf-41cd-9d5a-ee5e1b0f2844","wf-run-id":"53b52ee0-3218-418e-a9bf-7768e671f9c1","error":"code:deadline-exceeded message:timeout","lifecycle":"ProcessingFailed","logging-call-at":"task.go:331"'})]}),"\n",(0,i.jsxs)(t.ul,{children:["\n",(0,i.jsxs)(t.li,{children:["If this happens after traffic increased for a certain domain, it's likely that a tasklist is overloaded. Consider ",(0,i.jsx)(t.a,{href:"/docs/operation-guide/maintain/#scale-up-a-tasklist-using-scalable-tasklist-feature",children:"scale up the tasklist"})]}),"\n"]}),"\n"]}),"\n",(0,i.jsxs)(t.li,{children:["\n",(0,i.jsxs)(t.p,{children:["If the request volume aligned with the traffic increased on all domain, consider ",(0,i.jsx)(t.a,{href:"/docs/operation-guide/maintain/#scale-up--down-cluster",children:"scale up the cluster"})]}),"\n"]}),"\n"]})]})}function u(e={}){const{wrapper:t}={...(0,n.R)(),...e.components};return t?(0,i.jsx)(t,{...e,children:(0,i.jsx)(c,{...e})}):c(e)}},8453:(e,t,s)=>{s.d(t,{R:()=>r,x:()=>a});var o=s(6540);const i={},n=o.createContext(i);function r(e){const t=o.useContext(n);return o.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function a(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:r(e.components),o.createElement(n.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/43e9f1b6.d87d7fac.js b/assets/js/43e9f1b6.d87d7fac.js new file mode 100644 index 000000000..289b36f31 --- /dev/null +++ b/assets/js/43e9f1b6.d87d7fac.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[8817],{4512:(e,t,s)=>{s.r(t),s.d(t,{assets:()=>l,contentTitle:()=>a,default:()=>u,frontMatter:()=>r,metadata:()=>o,toc:()=>c});const o=JSON.parse('{"id":"operation-guide/troubleshooting","title":"Cluster Troubleshooting","description":"This section is to cover some common operation issues as a RunBook. Feel free to add more, or raise issues in the to ask for more in cadence-docs project.Or talk to us in Slack support channel!","source":"@site/docs/07-operation-guide/04-troubleshooting.md","sourceDirName":"07-operation-guide","slug":"/operation-guide/troubleshooting","permalink":"/Cadence-Docs/docs/operation-guide/troubleshooting","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/07-operation-guide/04-troubleshooting.md","tags":[],"version":"current","sidebarPosition":4,"frontMatter":{"layout":"default","title":"Cluster Troubleshooting","permalink":"/docs/operation-guide/troubleshooting"},"sidebar":"docsSidebar","previous":{"title":"Cluster Monitoring","permalink":"/Cadence-Docs/docs/operation-guide/monitoring"},"next":{"title":"Cluster Migration","permalink":"/Cadence-Docs/docs/operation-guide/migration"}}');var n=s(4848),i=s(8453);const r={layout:"default",title:"Cluster Troubleshooting",permalink:"/docs/operation-guide/troubleshooting"},a="Cluster Troubleshooting",l={},c=[{value:"Errors",id:"errors",level:2},{value:"API high latency, timeout, Task disptaching slowness Or Too many operations onto DB and timeouts",id:"api-high-latency-timeout-task-disptaching-slowness-or-too-many-operations-onto-db-and-timeouts",level:2}];function d(e){const t={a:"a",code:"code",h1:"h1",h2:"h2",header:"header",li:"li",p:"p",ul:"ul",...(0,i.R)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(t.header,{children:(0,n.jsx)(t.h1,{id:"cluster-troubleshooting",children:"Cluster Troubleshooting"})}),"\n",(0,n.jsxs)(t.p,{children:["This section is to cover some common operation issues as a RunBook. Feel free to add more, or raise issues in the to ask for more in ",(0,n.jsx)(t.a,{href:"https://github.com/cadence-workflow/Cadence-Docs/issues",children:"cadence-docs"})," project.Or talk to us in Slack support channel!"]}),"\n",(0,n.jsx)(t.p,{children:"We will keep adding more stuff. Any contribution is very welcome."}),"\n",(0,n.jsx)(t.h2,{id:"errors",children:"Errors"}),"\n",(0,n.jsxs)(t.ul,{children:["\n",(0,n.jsxs)(t.li,{children:[(0,n.jsx)(t.code,{children:"Persistence Max QPS Reached for List Operations"}),"\n",(0,n.jsxs)(t.ul,{children:["\n",(0,n.jsxs)(t.li,{children:["Check metrics to see how many List operations are performed per second on the domain. Alternatively you can enable ",(0,n.jsx)(t.code,{children:"debug"})," log level to see more details of how a List request is ratelimited, if it's a staging/QA cluster."]}),"\n",(0,n.jsx)(t.li,{children:"Raise the ratelimiting for the domain if you believe the default ratelimit is too low"}),"\n"]}),"\n"]}),"\n",(0,n.jsxs)(t.li,{children:[(0,n.jsx)(t.code,{children:"Failed to lock shard. Previous range ID: 132; new range ID: 133"})," and ",(0,n.jsx)(t.code,{children:"Failed to update shard. Previous range ID: 210; new range ID: 212"}),"\n",(0,n.jsxs)(t.ul,{children:["\n",(0,n.jsx)(t.li,{children:"When this keep happening, it's very likely a critical configuration error. Either there are two clusters using the same database, or two clusters are using the same ringpop(bootstrap hosts)."}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,n.jsx)(t.h2,{id:"api-high-latency-timeout-task-disptaching-slowness-or-too-many-operations-onto-db-and-timeouts",children:"API high latency, timeout, Task disptaching slowness Or Too many operations onto DB and timeouts"}),"\n",(0,n.jsxs)(t.ul,{children:["\n",(0,n.jsxs)(t.li,{children:["\n",(0,n.jsx)(t.p,{children:"If it happens after you attemped to truncate tables inorder to reuse the same database/keyspace for a new cluster, it's possible that the data is not deleted completely. You should make sure to shutdown the Cadence when trucating, and make sure the database is cleaned. Alternatively, use a different keyspace/database is a safer way."}),"\n"]}),"\n",(0,n.jsxs)(t.li,{children:["\n",(0,n.jsxs)(t.p,{children:["Timeout pushing task to matching engine, e.g. ",(0,n.jsx)(t.code,{children:'"Fail to process task","service":"cadence-history","shard-id":431,"address":"172.31.48.64:7934","component":"transfer-queue-processor","cluster-name":"active","shard-id":431,"queue-task-id":590357768,"queue-task-visibility-timestamp":1637356594382077880,"xdc-failover-version":-24,"queue-task-type":0,"wf-domain-id":"f4d6824f-9d24-4a82-81e0-e0e080be4c21","wf-id":"55d64d58-e398-4bf5-88bc-a4696a2ba87f:63ed7cda-afcf-41cd-9d5a-ee5e1b0f2844","wf-run-id":"53b52ee0-3218-418e-a9bf-7768e671f9c1","error":"code:deadline-exceeded message:timeout","lifecycle":"ProcessingFailed","logging-call-at":"task.go:331"'})]}),"\n",(0,n.jsxs)(t.ul,{children:["\n",(0,n.jsxs)(t.li,{children:["If this happens after traffic increased for a certain domain, it's likely that a tasklist is overloaded. Consider ",(0,n.jsx)(t.a,{href:"/docs/operation-guide/maintain/#scale-up-a-tasklist-using-scalable-tasklist-feature",children:"scale up the tasklist"})]}),"\n"]}),"\n"]}),"\n",(0,n.jsxs)(t.li,{children:["\n",(0,n.jsxs)(t.p,{children:["If the request volume aligned with the traffic increased on all domain, consider ",(0,n.jsx)(t.a,{href:"/docs/operation-guide/maintain/#scale-up--down-cluster",children:"scale up the cluster"})]}),"\n"]}),"\n"]})]})}function u(e={}){const{wrapper:t}={...(0,i.R)(),...e.components};return t?(0,n.jsx)(t,{...e,children:(0,n.jsx)(d,{...e})}):d(e)}},8453:(e,t,s)=>{s.d(t,{R:()=>r,x:()=>a});var o=s(6540);const n={},i=o.createContext(n);function r(e){const t=o.useContext(i);return o.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function a(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(n):e.components||n:r(e.components),o.createElement(i.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/44abbaf5.d310d2f5.js b/assets/js/44abbaf5.d310d2f5.js new file mode 100644 index 000000000..388369041 --- /dev/null +++ b/assets/js/44abbaf5.d310d2f5.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[7682],{6513:(e,o,n)=>{n.r(o),n.d(o,{assets:()=>a,contentTitle:()=>s,default:()=>d,frontMatter:()=>l,metadata:()=>t,toc:()=>c});const t=JSON.parse('{"id":"java-client/starting-workflow-executions","title":"Starting workflows","description":"Creating a WorkflowClient","source":"@site/docs/04-java-client/04-starting-workflow-executions.md","sourceDirName":"04-java-client","slug":"/java-client/starting-workflow-executions","permalink":"/Cadence-Docs/docs/java-client/starting-workflow-executions","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/04-java-client/04-starting-workflow-executions.md","tags":[],"version":"current","sidebarPosition":4,"frontMatter":{"layout":"default","title":"Starting workflows","permalink":"/docs/java-client/starting-workflow-executions"},"sidebar":"docsSidebar","previous":{"title":"Implementing workflows","permalink":"/Cadence-Docs/docs/java-client/implementing-workflows"},"next":{"title":"Activity interface","permalink":"/Cadence-Docs/docs/java-client/activity-interface"}}');var r=n(4848),i=n(8453);const l={layout:"default",title:"Starting workflows",permalink:"/docs/java-client/starting-workflow-executions"},s="Starting workflow executions",a={},c=[{value:"Creating a WorkflowClient",id:"creating-a-workflowclient",level:2},{value:"Executing Workflows",id:"executing-workflows",level:2}];function w(e){const o={code:"code",em:"em",h1:"h1",h2:"h2",header:"header",p:"p",pre:"pre",...(0,i.R)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(o.header,{children:(0,r.jsx)(o.h1,{id:"starting-workflow-executions",children:"Starting workflow executions"})}),"\n",(0,r.jsx)(o.h2,{id:"creating-a-workflowclient",children:"Creating a WorkflowClient"}),"\n",(0,r.jsxs)(o.p,{children:["A workflow interface that executes a workflow requires initializing a ",(0,r.jsx)(o.code,{children:"WorkflowClient"})," instance, creating\na client side stub to the workflow, and then calling a method annotated with @WorkflowMethod."]}),"\n",(0,r.jsxs)(o.p,{children:["A simple ",(0,r.jsx)(o.code,{children:"WorkflowClient"})," instance that utilises the tchannel communication protocol can be initialised as follows:"]}),"\n",(0,r.jsx)(o.pre,{children:(0,r.jsx)(o.code,{className:"language-java",children:"WorkflowClient workflowClient =\n WorkflowClient.newInstance(\n new WorkflowServiceTChannel(\n ClientOptions.newBuilder().setHost(cadenceServiceHost).setPort(cadenceServicePort).build()),\n WorkflowClientOptions.newBuilder().setDomain(domain).build());\n// Create a workflow stub.\nFileProcessingWorkflow workflow = workflowClient.newWorkflowStub(FileProcessingWorkflow.class);\n"})}),"\n",(0,r.jsxs)(o.p,{children:["Alternatively, if wishing to create a ",(0,r.jsx)(o.code,{children:"WorkflowClient"})," that uses TLS, we can initialise a client that uses the gRPC communication protocol instead. First, additions will need to be made to the project's ",(0,r.jsx)(o.em,{children:"pom.xml"}),":"]}),"\n",(0,r.jsxs)("dependency",{children:[(0,r.jsx)("groupId",{children:"io.grpc"}),(0,r.jsx)("artifactId",{children:"grpc-netty"}),(0,r.jsx)("version",{children:"LATEST.RELEASE.VERSION"})]}),"\n",(0,r.jsxs)("dependency",{children:[(0,r.jsx)("groupId",{children:"io.netty"}),(0,r.jsx)("artifactId",{children:"netty-all"}),(0,r.jsx)("version",{children:"LATEST.RELEASE.VERSION"})]}),"\n",(0,r.jsxs)(o.p,{children:["Then, use the following client implementation; provide a TLS certificate with which the cluster has also been configured (replace ",(0,r.jsx)(o.code,{children:'"/path/to/cert/file"'})," in the sample):"]}),"\n",(0,r.jsx)(o.pre,{children:(0,r.jsx)(o.code,{className:"language-java",children:'WorkflowClient workflowClient =\n WorkflowClient.newInstance(\n new Thrift2ProtoAdapter(\n IGrpcServiceStubs.newInstance(\n ClientOptions.newBuilder().setGRPCChannel(\n NettyChannelBuilder.forAddress(cadenceServiceHost, cadenceServicePort)\n .useTransportSecurity()\n .defaultLoadBalancingPolicy("round_robin")\n .sslContext(GrpcSslContexts.forClient()\n .trustManager(new File("/path/to/cert/file"))\n .build()).build()).build())),\n WorkflowClientOptions.newBuilder().setDomain(domain).build());\n// Create a workflow stub.\nFileProcessingWorkflow workflow = workflowClient.newWorkflowStub(FileProcessingWorkflow.class);\n'})}),"\n",(0,r.jsxs)(o.p,{children:["Or, if you are using version prior to 3.0.0, a ",(0,r.jsx)(o.code,{children:"WorkflowClient"})," can be created as follows:"]}),"\n",(0,r.jsx)(o.pre,{children:(0,r.jsx)(o.code,{className:"language-java",children:"WorkflowClient workflowClient = WorkflowClient.newClient(cadenceServiceHost, cadenceServicePort, domain);\n// Create a workflow stub.\nFileProcessingWorkflow workflow = workflowClient.newWorkflowStub(FileProcessingWorkflow.class);\n"})}),"\n",(0,r.jsx)(o.h2,{id:"executing-workflows",children:"Executing Workflows"}),"\n",(0,r.jsx)(o.p,{children:"There are two ways to start asynchronously and synchronously. Asynchronous start initiates a workflow_execution and immediately returns to the caller. This is the most common way to start workflows in production code. Synchronous invocation starts a workflow\nand then waits for its completion. If the process that started the workflow crashes or stops waiting, the workflow continues executing.\nBecause workflows are potentially long running, and crashes of clients happen, this is not very commonly found in production use."}),"\n",(0,r.jsx)(o.p,{children:"Asynchronous start:"}),"\n",(0,r.jsx)(o.pre,{children:(0,r.jsx)(o.code,{className:"language-java",children:'// Returns as soon as the workflow starts.\nWorkflowExecution workflowExecution = WorkflowClient.start(workflow::processFile, workflowArgs);\n\nSystem.out.println("Started process file workflow with workflowId=\\"" + workflowExecution.getWorkflowId()\n + "\\" and runId=\\"" + workflowExecution.getRunId() + "\\"");\n'})}),"\n",(0,r.jsx)(o.p,{children:"Synchronous start:"}),"\n",(0,r.jsx)(o.pre,{children:(0,r.jsx)(o.code,{className:"language-java",children:"// Start a workflow and then wait for a result.\n// Note that if the waiting process is killed, the workflow will continue execution.\nString result = workflow.processFile(workflowArgs);\n"})}),"\n",(0,r.jsxs)(o.p,{children:["If you need to wait for a workflow completion after an asynchronous start, the most straightforward way\nis to call the blocking version again. If ",(0,r.jsx)(o.code,{children:"WorkflowOptions.WorkflowIdReusePolicy"})," is not ",(0,r.jsx)(o.code,{children:"AllowDuplicate"}),", then instead\nof throwing ",(0,r.jsx)(o.code,{children:"DuplicateWorkflowException"}),", it reconnects to an existing workflow and waits for its completion.\nThe following example shows how to do this from a different process than the one that started the workflow. All this process\nneeds is a ",(0,r.jsx)(o.code,{children:"WorkflowID"}),"."]}),"\n",(0,r.jsx)(o.pre,{children:(0,r.jsx)(o.code,{className:"language-java",children:"WorkflowExecution execution = new WorkflowExecution().setWorkflowId(workflowId);\nFileProcessingWorkflow workflow = workflowClient.newWorkflowStub(execution);\n// Returns result potentially waiting for workflow to complete.\nString result = workflow.processFile(workflowArgs);\n"})})]})}function d(e={}){const{wrapper:o}={...(0,i.R)(),...e.components};return o?(0,r.jsx)(o,{...e,children:(0,r.jsx)(w,{...e})}):w(e)}},8453:(e,o,n)=>{n.d(o,{R:()=>l,x:()=>s});var t=n(6540);const r={},i=t.createContext(r);function l(e){const o=t.useContext(i);return t.useMemo((function(){return"function"==typeof e?e(o):{...o,...e}}),[o,e])}function s(e){let o;return o=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:l(e.components),t.createElement(i.Provider,{value:o},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/44abbaf5.e200fa03.js b/assets/js/44abbaf5.e200fa03.js deleted file mode 100644 index 61bc51aa1..000000000 --- a/assets/js/44abbaf5.e200fa03.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[7682],{6513:(e,o,n)=>{n.r(o),n.d(o,{assets:()=>a,contentTitle:()=>s,default:()=>d,frontMatter:()=>l,metadata:()=>t,toc:()=>c});const t=JSON.parse('{"id":"java-client/starting-workflow-executions","title":"Starting workflows","description":"Creating a WorkflowClient","source":"@site/docs/04-java-client/04-starting-workflow-executions.md","sourceDirName":"04-java-client","slug":"/java-client/starting-workflow-executions","permalink":"/docs/java-client/starting-workflow-executions","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/04-java-client/04-starting-workflow-executions.md","tags":[],"version":"current","sidebarPosition":4,"frontMatter":{"layout":"default","title":"Starting workflows","permalink":"/docs/java-client/starting-workflow-executions"},"sidebar":"docsSidebar","previous":{"title":"Implementing workflows","permalink":"/docs/java-client/implementing-workflows"},"next":{"title":"Activity interface","permalink":"/docs/java-client/activity-interface"}}');var r=n(4848),i=n(8453);const l={layout:"default",title:"Starting workflows",permalink:"/docs/java-client/starting-workflow-executions"},s="Starting workflow executions",a={},c=[{value:"Creating a WorkflowClient",id:"creating-a-workflowclient",level:2},{value:"Executing Workflows",id:"executing-workflows",level:2}];function w(e){const o={code:"code",em:"em",h1:"h1",h2:"h2",header:"header",p:"p",pre:"pre",...(0,i.R)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(o.header,{children:(0,r.jsx)(o.h1,{id:"starting-workflow-executions",children:"Starting workflow executions"})}),"\n",(0,r.jsx)(o.h2,{id:"creating-a-workflowclient",children:"Creating a WorkflowClient"}),"\n",(0,r.jsxs)(o.p,{children:["A workflow interface that executes a workflow requires initializing a ",(0,r.jsx)(o.code,{children:"WorkflowClient"})," instance, creating\na client side stub to the workflow, and then calling a method annotated with @WorkflowMethod."]}),"\n",(0,r.jsxs)(o.p,{children:["A simple ",(0,r.jsx)(o.code,{children:"WorkflowClient"})," instance that utilises the tchannel communication protocol can be initialised as follows:"]}),"\n",(0,r.jsx)(o.pre,{children:(0,r.jsx)(o.code,{className:"language-java",children:"WorkflowClient workflowClient =\n WorkflowClient.newInstance(\n new WorkflowServiceTChannel(\n ClientOptions.newBuilder().setHost(cadenceServiceHost).setPort(cadenceServicePort).build()),\n WorkflowClientOptions.newBuilder().setDomain(domain).build());\n// Create a workflow stub.\nFileProcessingWorkflow workflow = workflowClient.newWorkflowStub(FileProcessingWorkflow.class);\n"})}),"\n",(0,r.jsxs)(o.p,{children:["Alternatively, if wishing to create a ",(0,r.jsx)(o.code,{children:"WorkflowClient"})," that uses TLS, we can initialise a client that uses the gRPC communication protocol instead. First, additions will need to be made to the project's ",(0,r.jsx)(o.em,{children:"pom.xml"}),":"]}),"\n",(0,r.jsxs)("dependency",{children:[(0,r.jsx)("groupId",{children:"io.grpc"}),(0,r.jsx)("artifactId",{children:"grpc-netty"}),(0,r.jsx)("version",{children:"LATEST.RELEASE.VERSION"})]}),"\n",(0,r.jsxs)("dependency",{children:[(0,r.jsx)("groupId",{children:"io.netty"}),(0,r.jsx)("artifactId",{children:"netty-all"}),(0,r.jsx)("version",{children:"LATEST.RELEASE.VERSION"})]}),"\n",(0,r.jsxs)(o.p,{children:["Then, use the following client implementation; provide a TLS certificate with which the cluster has also been configured (replace ",(0,r.jsx)(o.code,{children:'"/path/to/cert/file"'})," in the sample):"]}),"\n",(0,r.jsx)(o.pre,{children:(0,r.jsx)(o.code,{className:"language-java",children:'WorkflowClient workflowClient =\n WorkflowClient.newInstance(\n new Thrift2ProtoAdapter(\n IGrpcServiceStubs.newInstance(\n ClientOptions.newBuilder().setGRPCChannel(\n NettyChannelBuilder.forAddress(cadenceServiceHost, cadenceServicePort)\n .useTransportSecurity()\n .defaultLoadBalancingPolicy("round_robin")\n .sslContext(GrpcSslContexts.forClient()\n .trustManager(new File("/path/to/cert/file"))\n .build()).build()).build())),\n WorkflowClientOptions.newBuilder().setDomain(domain).build());\n// Create a workflow stub.\nFileProcessingWorkflow workflow = workflowClient.newWorkflowStub(FileProcessingWorkflow.class);\n'})}),"\n",(0,r.jsxs)(o.p,{children:["Or, if you are using version prior to 3.0.0, a ",(0,r.jsx)(o.code,{children:"WorkflowClient"})," can be created as follows:"]}),"\n",(0,r.jsx)(o.pre,{children:(0,r.jsx)(o.code,{className:"language-java",children:"WorkflowClient workflowClient = WorkflowClient.newClient(cadenceServiceHost, cadenceServicePort, domain);\n// Create a workflow stub.\nFileProcessingWorkflow workflow = workflowClient.newWorkflowStub(FileProcessingWorkflow.class);\n"})}),"\n",(0,r.jsx)(o.h2,{id:"executing-workflows",children:"Executing Workflows"}),"\n",(0,r.jsx)(o.p,{children:"There are two ways to start asynchronously and synchronously. Asynchronous start initiates a workflow_execution and immediately returns to the caller. This is the most common way to start workflows in production code. Synchronous invocation starts a workflow\nand then waits for its completion. If the process that started the workflow crashes or stops waiting, the workflow continues executing.\nBecause workflows are potentially long running, and crashes of clients happen, this is not very commonly found in production use."}),"\n",(0,r.jsx)(o.p,{children:"Asynchronous start:"}),"\n",(0,r.jsx)(o.pre,{children:(0,r.jsx)(o.code,{className:"language-java",children:'// Returns as soon as the workflow starts.\nWorkflowExecution workflowExecution = WorkflowClient.start(workflow::processFile, workflowArgs);\n\nSystem.out.println("Started process file workflow with workflowId=\\"" + workflowExecution.getWorkflowId()\n + "\\" and runId=\\"" + workflowExecution.getRunId() + "\\"");\n'})}),"\n",(0,r.jsx)(o.p,{children:"Synchronous start:"}),"\n",(0,r.jsx)(o.pre,{children:(0,r.jsx)(o.code,{className:"language-java",children:"// Start a workflow and then wait for a result.\n// Note that if the waiting process is killed, the workflow will continue execution.\nString result = workflow.processFile(workflowArgs);\n"})}),"\n",(0,r.jsxs)(o.p,{children:["If you need to wait for a workflow completion after an asynchronous start, the most straightforward way\nis to call the blocking version again. If ",(0,r.jsx)(o.code,{children:"WorkflowOptions.WorkflowIdReusePolicy"})," is not ",(0,r.jsx)(o.code,{children:"AllowDuplicate"}),", then instead\nof throwing ",(0,r.jsx)(o.code,{children:"DuplicateWorkflowException"}),", it reconnects to an existing workflow and waits for its completion.\nThe following example shows how to do this from a different process than the one that started the workflow. All this process\nneeds is a ",(0,r.jsx)(o.code,{children:"WorkflowID"}),"."]}),"\n",(0,r.jsx)(o.pre,{children:(0,r.jsx)(o.code,{className:"language-java",children:"WorkflowExecution execution = new WorkflowExecution().setWorkflowId(workflowId);\nFileProcessingWorkflow workflow = workflowClient.newWorkflowStub(execution);\n// Returns result potentially waiting for workflow to complete.\nString result = workflow.processFile(workflowArgs);\n"})})]})}function d(e={}){const{wrapper:o}={...(0,i.R)(),...e.components};return o?(0,r.jsx)(o,{...e,children:(0,r.jsx)(w,{...e})}):w(e)}},8453:(e,o,n)=>{n.d(o,{R:()=>l,x:()=>s});var t=n(6540);const r={},i=t.createContext(r);function l(e){const o=t.useContext(i);return t.useMemo((function(){return"function"==typeof e?e(o):{...o,...e}}),[o,e])}function s(e){let o;return o=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:l(e.components),t.createElement(i.Provider,{value:o},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/44d6dde1.691185e4.js b/assets/js/44d6dde1.25e7264c.js similarity index 63% rename from assets/js/44d6dde1.691185e4.js rename to assets/js/44d6dde1.25e7264c.js index 65a53ee6e..d42d6d73b 100644 --- a/assets/js/44d6dde1.691185e4.js +++ b/assets/js/44d6dde1.25e7264c.js @@ -1 +1 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[4471],{7739:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>d,contentTitle:()=>s,default:()=>p,frontMatter:()=>o,metadata:()=>a,toc:()=>l});var a=n(4568),i=n(4848),r=n(8453);const o={title:"2024 Cadence Yearly Roadmap Update",date:new Date("2024-07-11T00:00:00.000Z"),authors:"enderdemirkaya",tags:["roadmap","deep-dive"]},s=void 0,d={authorsImageUrls:[void 0]},l=[{value:"Introduction",id:"introduction",level:2},{value:"What is a Workflow?",id:"what-is-a-workflow",level:3}];function c(e){const t={h2:"h2",h3:"h3",img:"img",li:"li",p:"p",ul:"ul",...(0,r.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(t.h2,{id:"introduction",children:"Introduction"}),"\n",(0,i.jsx)(t.p,{children:"If you haven\u2019t heard about Cadence, this section is for you. In a short description, Cadence is a code-driven workflow orchestration engine. The definition itself may not tell enough, so it would help splitting it into three parts:"}),"\n",(0,i.jsxs)(t.ul,{children:["\n",(0,i.jsx)(t.li,{children:"What\u2019s a workflow? (everyone has a different definition)"}),"\n",(0,i.jsx)(t.li,{children:"Why does it matter to be code-driven?"}),"\n",(0,i.jsx)(t.li,{children:"Benefits of Cadence"}),"\n"]}),"\n",(0,i.jsx)(t.h3,{id:"what-is-a-workflow",children:"What is a Workflow?"}),"\n",(0,i.jsx)(t.p,{children:(0,i.jsx)(t.img,{alt:"workflow.png",src:n(5177).A+"",width:"650",height:"394"})}),"\n",(0,i.jsx)(t.p,{children:"In the simplest definition, it is \u201ca multi-step execution\u201d. Step here represents individual operations that are a little heavier than small in-process function calls. Although they are not limited to those: it could be a separate service call, processing a large dataset, map-reduce, thread sleep, scheduling next run, waiting for an external input, starting a sub workflow etc. It\u2019s anything a user thinks as a single unit of logic in their code. Those steps often have dependencies among themselves. Some steps, including the very first step, might require external triggers (e.g. button click) or schedules. In the more broader meaning, any multi-step function or service is a workflow in principle."})]})}function p(e={}){const{wrapper:t}={...(0,r.R)(),...e.components};return t?(0,i.jsx)(t,{...e,children:(0,i.jsx)(c,{...e})}):c(e)}},5177:(e,t,n)=>{n.d(t,{A:()=>a});const a=n.p+"assets/images/workflow-84ef76d93c7ff138714a0aa7c9b92841.png"},8453:(e,t,n)=>{n.d(t,{R:()=>o,x:()=>s});var a=n(6540);const i={},r=a.createContext(i);function o(e){const t=a.useContext(r);return a.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function s(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:o(e.components),a.createElement(r.Provider,{value:t},e.children)}},4568:e=>{e.exports=JSON.parse('{"permalink":"/blog/2024/07/11/2024-07-11-yearly-roadmap-update/yearly-roadmap-update","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2024-07-11-yearly-roadmap-update/2024-07-11-yearly-roadmap-update.md","source":"@site/blog/2024-07-11-yearly-roadmap-update/2024-07-11-yearly-roadmap-update.md","title":"2024 Cadence Yearly Roadmap Update","description":"Introduction","date":"2024-07-11T00:00:00.000Z","tags":[{"inline":false,"label":"Roadmap","permalink":"/blog/tags/roadmap","description":"Roadmap tag description"},{"inline":false,"label":"Deep Dives","permalink":"/blog/tags/deep-dives","description":"Deep Dives tag description"}],"readingTime":16.31,"hasTruncateMarker":true,"authors":[{"name":"Ender Demirkaya","title":"Senior Manager at Uber, Cadence. Author of the Software Engineering Handbook","url":"https://www.linkedin.com/in/enderdemirkaya/","page":{"permalink":"/blog/authors/enderdemirkaya"},"socials":{"linkedin":"https://www.linkedin.com/in/enderdemirkaya/","github":"https://github.com/demirkayaender"},"imageURL":"https://github.com/demirkayaender.png","key":"enderdemirkaya"}],"frontMatter":{"title":"2024 Cadence Yearly Roadmap Update","date":"2024-07-11T00:00:00.000Z","authors":"enderdemirkaya","tags":["roadmap","deep-dive"]},"unlisted":false,"prevItem":{"title":"Minimizing blast radius in Cadence: Introducing Workflow ID-based Rate Limits","permalink":"/blog/2024/09/05/workflow-specific-rate-limits"},"nextItem":{"title":"Cadence non-derministic errors common question Q&A (part 1)","permalink":"/blog/2024/02/15/cadence-non-deterministic-common-qa"}}')}}]); \ No newline at end of file +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[4471],{7739:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>d,contentTitle:()=>s,default:()=>p,frontMatter:()=>o,metadata:()=>a,toc:()=>l});var a=n(4568),i=n(4848),r=n(8453);const o={title:"2024 Cadence Yearly Roadmap Update",date:new Date("2024-07-11T00:00:00.000Z"),authors:"enderdemirkaya",tags:["roadmap","deep-dive"]},s=void 0,d={authorsImageUrls:[void 0]},l=[{value:"Introduction",id:"introduction",level:2},{value:"What is a Workflow?",id:"what-is-a-workflow",level:3}];function c(e){const t={h2:"h2",h3:"h3",img:"img",li:"li",p:"p",ul:"ul",...(0,r.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(t.h2,{id:"introduction",children:"Introduction"}),"\n",(0,i.jsx)(t.p,{children:"If you haven\u2019t heard about Cadence, this section is for you. In a short description, Cadence is a code-driven workflow orchestration engine. The definition itself may not tell enough, so it would help splitting it into three parts:"}),"\n",(0,i.jsxs)(t.ul,{children:["\n",(0,i.jsx)(t.li,{children:"What\u2019s a workflow? (everyone has a different definition)"}),"\n",(0,i.jsx)(t.li,{children:"Why does it matter to be code-driven?"}),"\n",(0,i.jsx)(t.li,{children:"Benefits of Cadence"}),"\n"]}),"\n",(0,i.jsx)(t.h3,{id:"what-is-a-workflow",children:"What is a Workflow?"}),"\n",(0,i.jsx)(t.p,{children:(0,i.jsx)(t.img,{alt:"workflow.png",src:n(5177).A+"",width:"650",height:"394"})}),"\n",(0,i.jsx)(t.p,{children:"In the simplest definition, it is \u201ca multi-step execution\u201d. Step here represents individual operations that are a little heavier than small in-process function calls. Although they are not limited to those: it could be a separate service call, processing a large dataset, map-reduce, thread sleep, scheduling next run, waiting for an external input, starting a sub workflow etc. It\u2019s anything a user thinks as a single unit of logic in their code. Those steps often have dependencies among themselves. Some steps, including the very first step, might require external triggers (e.g. button click) or schedules. In the more broader meaning, any multi-step function or service is a workflow in principle."})]})}function p(e={}){const{wrapper:t}={...(0,r.R)(),...e.components};return t?(0,i.jsx)(t,{...e,children:(0,i.jsx)(c,{...e})}):c(e)}},5177:(e,t,n)=>{n.d(t,{A:()=>a});const a=n.p+"assets/images/workflow-84ef76d93c7ff138714a0aa7c9b92841.png"},8453:(e,t,n)=>{n.d(t,{R:()=>o,x:()=>s});var a=n(6540);const i={},r=a.createContext(i);function o(e){const t=a.useContext(r);return a.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function s(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:o(e.components),a.createElement(r.Provider,{value:t},e.children)}},4568:e=>{e.exports=JSON.parse('{"permalink":"/Cadence-Docs/blog/2024/07/11/2024-07-11-yearly-roadmap-update/yearly-roadmap-update","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2024-07-11-yearly-roadmap-update/2024-07-11-yearly-roadmap-update.md","source":"@site/blog/2024-07-11-yearly-roadmap-update/2024-07-11-yearly-roadmap-update.md","title":"2024 Cadence Yearly Roadmap Update","description":"Introduction","date":"2024-07-11T00:00:00.000Z","tags":[{"inline":false,"label":"Roadmap","permalink":"/Cadence-Docs/blog/tags/roadmap","description":"Roadmap tag description"},{"inline":false,"label":"Deep Dives","permalink":"/Cadence-Docs/blog/tags/deep-dives","description":"Deep Dives tag description"}],"readingTime":16.31,"hasTruncateMarker":true,"authors":[{"name":"Ender Demirkaya","title":"Senior Manager at Uber, Cadence. Author of the Software Engineering Handbook","url":"https://www.linkedin.com/in/enderdemirkaya/","page":{"permalink":"/Cadence-Docs/blog/authors/enderdemirkaya"},"socials":{"linkedin":"https://www.linkedin.com/in/enderdemirkaya/","github":"https://github.com/demirkayaender"},"imageURL":"https://github.com/demirkayaender.png","key":"enderdemirkaya"}],"frontMatter":{"title":"2024 Cadence Yearly Roadmap Update","date":"2024-07-11T00:00:00.000Z","authors":"enderdemirkaya","tags":["roadmap","deep-dive"]},"unlisted":false,"prevItem":{"title":"Minimizing blast radius in Cadence: Introducing Workflow ID-based Rate Limits","permalink":"/Cadence-Docs/blog/2024/09/05/workflow-specific-rate-limits"},"nextItem":{"title":"Cadence non-derministic errors common question Q&A (part 1)","permalink":"/Cadence-Docs/blog/2024/02/15/cadence-non-deterministic-common-qa"}}')}}]); \ No newline at end of file diff --git a/assets/js/45f9d173.9cbe9fac.js b/assets/js/45f9d173.9cbe9fac.js new file mode 100644 index 000000000..bfeff714e --- /dev/null +++ b/assets/js/45f9d173.9cbe9fac.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[4790],{3607:e=>{e.exports=JSON.parse('{"author":{"name":"Zijian Chen","title":"Software Engineer @ Uber","url":"https://www.linkedin.com/in/zijian-chen-5868938b/","page":{"permalink":"/Cadence-Docs/blog/authors/shaddoll"},"socials":{"linkedin":"https://www.linkedin.com/in/zijian-chen-5868938b/","github":"https://github.com/Shaddoll"},"imageURL":"https://github.com/Shaddoll.png","key":"shaddoll","count":1},"listMetadata":{"permalink":"/Cadence-Docs/blog/authors/shaddoll","page":1,"postsPerPage":10,"totalPages":1,"totalCount":1,"blogDescription":"The latest news and updates from the Cadence team","blogTitle":"Cadence Blog"}}')}}]); \ No newline at end of file diff --git a/assets/js/47f0ea92.7860b482.js b/assets/js/47f0ea92.7860b482.js new file mode 100644 index 000000000..32280f745 --- /dev/null +++ b/assets/js/47f0ea92.7860b482.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[4669],{6981:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>s,contentTitle:()=>r,default:()=>h,frontMatter:()=>c,metadata:()=>o,toc:()=>l});const o=JSON.parse('{"id":"java-client/continue-as-new","title":"Continue As New","description":"Workflows: that need to rerun periodically could naively be implemented as a big for loop with","source":"@site/docs/04-java-client/15-continue-as-new.md","sourceDirName":"04-java-client","slug":"/java-client/continue-as-new","permalink":"/Cadence-Docs/docs/java-client/continue-as-new","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/04-java-client/15-continue-as-new.md","tags":[],"version":"current","sidebarPosition":15,"frontMatter":{"layout":"default","title":"Continue As New","permalink":"/docs/java-client/continue-as-new"},"sidebar":"docsSidebar","previous":{"title":"Exception Handling","permalink":"/Cadence-Docs/docs/java-client/exception-handling"},"next":{"title":"Side Effect","permalink":"/Cadence-Docs/docs/java-client/side-effect"}}');var i=t(4848),a=t(8453);const c={layout:"default",title:"Continue As New",permalink:"/docs/java-client/continue-as-new"},r="Continue as new",s={},l=[];function d(e){const n={a:"a",code:"code",h1:"h1",header:"header",p:"p",pre:"pre",strong:"strong",...(0,a.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.header,{children:(0,i.jsx)(n.h1,{id:"continue-as-new",children:"Continue as new"})}),"\n",(0,i.jsxs)(n.p,{children:["Workflows that need to rerun periodically could naively be implemented as a big ",(0,i.jsx)(n.strong,{children:"for"})," loop with\na sleep where the entire logic of the workflow is inside the body of the ",(0,i.jsx)(n.strong,{children:"for"})," loop. The problem\nwith this approach is that the history for that workflow will keep growing to a point where it\nreaches the maximum size enforced by the service."]}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.a,{href:"https://www.javadoc.io/static/com.uber.cadence/cadence-client/2.7.9-alpha/com/cadence-workflow/cadence/workflow/Workflow.html#continueAsNew-java.lang.Object...-",children:(0,i.jsx)(n.strong,{children:"ContinueAsNew"})}),"\nis the low level construct that enables implementing such workflows without the\nrisk of failures down the road. The operation atomically completes the current execution and starts\na new execution of the workflow with the same ",(0,i.jsx)(n.strong,{children:"workflow_ID"}),". The new execution will not carry\nover any history from the old execution."]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",children:'@Override\npublic void greet(String name) {\n activities.greet("Hello " + name + "!");\n Workflow.continueAsNew(name);\n}\n\n'})})]})}function h(e={}){const{wrapper:n}={...(0,a.R)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(d,{...e})}):d(e)}},8453:(e,n,t)=>{t.d(n,{R:()=>c,x:()=>r});var o=t(6540);const i={},a=o.createContext(i);function c(e){const n=o.useContext(a);return o.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function r(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:c(e.components),o.createElement(a.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/47f0ea92.d05b70b3.js b/assets/js/47f0ea92.d05b70b3.js deleted file mode 100644 index ae2777057..000000000 --- a/assets/js/47f0ea92.d05b70b3.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[4669],{6981:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>s,contentTitle:()=>r,default:()=>h,frontMatter:()=>c,metadata:()=>o,toc:()=>l});const o=JSON.parse('{"id":"java-client/continue-as-new","title":"Continue As New","description":"Workflows: that need to rerun periodically could naively be implemented as a big for loop with","source":"@site/docs/04-java-client/15-continue-as-new.md","sourceDirName":"04-java-client","slug":"/java-client/continue-as-new","permalink":"/docs/java-client/continue-as-new","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/04-java-client/15-continue-as-new.md","tags":[],"version":"current","sidebarPosition":15,"frontMatter":{"layout":"default","title":"Continue As New","permalink":"/docs/java-client/continue-as-new"},"sidebar":"docsSidebar","previous":{"title":"Exception Handling","permalink":"/docs/java-client/exception-handling"},"next":{"title":"Side Effect","permalink":"/docs/java-client/side-effect"}}');var i=t(4848),a=t(8453);const c={layout:"default",title:"Continue As New",permalink:"/docs/java-client/continue-as-new"},r="Continue as new",s={},l=[];function d(e){const n={a:"a",code:"code",h1:"h1",header:"header",p:"p",pre:"pre",strong:"strong",...(0,a.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.header,{children:(0,i.jsx)(n.h1,{id:"continue-as-new",children:"Continue as new"})}),"\n",(0,i.jsxs)(n.p,{children:["Workflows that need to rerun periodically could naively be implemented as a big ",(0,i.jsx)(n.strong,{children:"for"})," loop with\na sleep where the entire logic of the workflow is inside the body of the ",(0,i.jsx)(n.strong,{children:"for"})," loop. The problem\nwith this approach is that the history for that workflow will keep growing to a point where it\nreaches the maximum size enforced by the service."]}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.a,{href:"https://www.javadoc.io/static/com.uber.cadence/cadence-client/2.7.9-alpha/com/cadence-workflow/cadence/workflow/Workflow.html#continueAsNew-java.lang.Object...-",children:(0,i.jsx)(n.strong,{children:"ContinueAsNew"})}),"\nis the low level construct that enables implementing such workflows without the\nrisk of failures down the road. The operation atomically completes the current execution and starts\na new execution of the workflow with the same ",(0,i.jsx)(n.strong,{children:"workflow_ID"}),". The new execution will not carry\nover any history from the old execution."]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",children:'@Override\npublic void greet(String name) {\n activities.greet("Hello " + name + "!");\n Workflow.continueAsNew(name);\n}\n\n'})})]})}function h(e={}){const{wrapper:n}={...(0,a.R)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(d,{...e})}):d(e)}},8453:(e,n,t)=>{t.d(n,{R:()=>c,x:()=>r});var o=t(6540);const i={},a=o.createContext(i);function c(e){const n=o.useContext(a);return o.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function r(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:c(e.components),o.createElement(a.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/4807c528.34de51fe.js b/assets/js/4807c528.34de51fe.js new file mode 100644 index 000000000..c73afc504 --- /dev/null +++ b/assets/js/4807c528.34de51fe.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[278],{5958:a=>{a.exports=JSON.parse('{"author":{"name":"Jakob Haahr Taankvist","title":"Software Engineer II @ Uber","url":"https://www.linkedin.com/in/jakob-taankvist/","page":{"permalink":"/Cadence-Docs/blog/authors/jakobht"},"socials":{"linkedin":"https://www.linkedin.com/in/jakob-taankvist/","github":"https://github.com/jakobht"},"imageURL":"https://github.com/jakobht.png","key":"jakobht","count":1},"listMetadata":{"permalink":"/Cadence-Docs/blog/authors/jakobht","page":1,"postsPerPage":10,"totalPages":1,"totalCount":1,"blogDescription":"The latest news and updates from the Cadence team","blogTitle":"Cadence Blog"}}')}}]); \ No newline at end of file diff --git a/assets/js/4b94b3ad.7b3691f7.js b/assets/js/4b94b3ad.e7f89e40.js similarity index 75% rename from assets/js/4b94b3ad.7b3691f7.js rename to assets/js/4b94b3ad.e7f89e40.js index cbcaf2be0..042721bb0 100644 --- a/assets/js/4b94b3ad.7b3691f7.js +++ b/assets/js/4b94b3ad.e7f89e40.js @@ -1 +1 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[1816],{2088:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>c,contentTitle:()=>r,default:()=>d,frontMatter:()=>a,metadata:()=>o,toc:()=>l});var o=t(9476),i=t(4848),s=t(8453);const a={title:"Cadence Community Spotlight Update - June 2022",date:new Date("2022-06-30T00:00:00.000Z"),authors:"sharanf",tags:["community-spotlight"]},r=void 0,c={authorsImageUrls:[void 0]},l=[{value:"Knowledge Sharing and Support",id:"knowledge-sharing-and-support",level:2},{value:"Improving Technical Office Hours",id:"improving-technical-office-hours",level:2},{value:"Cadence Stability Improvements",id:"cadence-stability-improvements",level:2},{value:"Sprechen Sie Deutsch?",id:"sprechen-sie-deutsch",level:2},{value:"Cadence in the News!",id:"cadence-in-the-news",level:2},{value:"Upcoming Events",id:"upcoming-events",level:2}];function h(e){const n={a:"a",h2:"h2",li:"li",p:"p",strong:"strong",ul:"ul",...(0,s.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.p,{children:"It\u2019s time for our monthly Cadence Community Spotlight update with news from in and around the Cadence community!"}),"\n",(0,i.jsx)(n.p,{children:"Please see below for a roundup of the highlights:"}),"\n",(0,i.jsx)(n.h2,{id:"knowledge-sharing-and-support",children:"Knowledge Sharing and Support"}),"\n",(0,i.jsx)(n.p,{children:"Our Slack #support channel has been busy this month with 13 questions asked this month by 12 different community members. Six community members took time to respond to those questions which clearly shows our community is growing, collaborating and keen to share knowledge."}),"\n",(0,i.jsxs)(n.p,{children:["Please don\u2019t forget that we encourage everyone to post questions on StackOverflow using the ",(0,i.jsx)(n.strong,{children:"cadence-workflow"})," and ",(0,i.jsx)(n.strong,{children:"uber-cadence"})," tags so that others with similar questions or issues can easily search for and find an answer."]}),"\n",(0,i.jsx)(n.h2,{id:"improving-technical-office-hours",children:"Improving Technical Office Hours"}),"\n",(0,i.jsx)(n.p,{children:"Over the last few months we have been holding regular monthly Office Hours meetings but they have not attracted as many participants as we would like. We would like to understand if there is something preventing people from attending (e.g perhaps the timing or dates are not convenient) so we are planning to send out a short community survey."}),"\n",(0,i.jsx)(n.p,{children:"If you have any ideas or comments about how we can improve our community office hours sessions then please include this in your feedback or contact us in the #community Slack channel."}),"\n",(0,i.jsx)(n.h2,{id:"cadence-stability-improvements",children:"Cadence Stability Improvements"}),"\n",(0,i.jsx)(n.p,{children:"Is Cadence getting better? Yes it is! Many of you may have noticed that Cadence is improving.That is because of the amount of work being done behind the scenes. The Cadence core team has been doing a lot of work to stabilise Cadence functionality. Keep watching out for even more improvements!"}),"\n",(0,i.jsx)(n.h2,{id:"sprechen-sie-deutsch",children:"Sprechen Sie Deutsch?"}),"\n",(0,i.jsx)(n.p,{children:"Do you speak German? If you do speak then we have some good news for you. A couple of Cadence blog posts have been translated into German to help promote it to a wider audience. The links are as below and we hope you find them useful!"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"https://www.credativ.de/blog/howtos/workflows-mit-cadence-optimieren/",children:"Workflows mit Cadence optimieren!"})}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"https://www.credativ.de/blog/howtos/apache-kafka-microservices-mit-cadence-workflows-optimieren/",children:"Apache Kafka\xae Microservices mit Cadence-Workflows optimieren"})}),"\n"]}),"\n",(0,i.jsx)(n.h2,{id:"cadence-in-the-news",children:"Cadence in the News!"}),"\n",(0,i.jsx)(n.p,{children:"Below are a selection of Cadence related articles, blogs and whitepapers. Please take a look and feel free to share via your own social media channels."}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://www.instaclustr.com/blog/workflow-comparison-uber-cadence-vs-netflix-conductor/",children:"Workflow Comparison: Uber Cadence vs Netflix Conductor"})}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://www.instaclustr.com/blog/securing-cadence-web-using-nginx/",children:"Securing Cadence Web Using NGINX"})}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.h2,{id:"upcoming-events",children:"Upcoming Events"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://calendar.google.com/calendar/u/0/embed?src=e6r40gp3c2r01054id7e99dlac@group.calendar.google.com&ctz=America/Los_Angeles",children:"Cadence Technical Office Hours - 25th July 2022 @ 9am PT"})}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://info.instaclustr.com/webinar-building-cadence-workflow",children:"Webinar: Building Your First Cadence Workflow with Java and Go - 19th July 2022"})}),"\n"]}),"\n"]}),"\n",(0,i.jsxs)(n.p,{children:["If you have any news or topics you'd like us to include in our next update then please join our ",(0,i.jsx)(n.a,{href:"http://t.uber.com/cadence-slack",children:"Slack"}),"#community channel."]}),"\n",(0,i.jsxs)(n.p,{children:["Please remember that this update is for you - so if you have any comments or feedback that could help us improve it then please share it with us in the #community ",(0,i.jsx)(n.a,{href:"http://t.uber.com/cadence-slack",children:"Slack"})," channel."]})]})}function d(e={}){const{wrapper:n}={...(0,s.R)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(h,{...e})}):h(e)}},8453:(e,n,t)=>{t.d(n,{R:()=>a,x:()=>r});var o=t(6540);const i={},s=o.createContext(i);function a(e){const n=o.useContext(s);return o.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function r(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:a(e.components),o.createElement(s.Provider,{value:n},e.children)}},9476:e=>{e.exports=JSON.parse('{"permalink":"/blog/2022/06/30/community-spotlight-update-june-2022","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2022-06-30-community-spotlight-update-june-2022.md","source":"@site/blog/2022-06-30-community-spotlight-update-june-2022.md","title":"Cadence Community Spotlight Update - June 2022","description":"It\u2019s time for our monthly Cadence Community Spotlight update with news from in and around the Cadence community!","date":"2022-06-30T00:00:00.000Z","tags":[{"inline":false,"label":"Community Spotlight","permalink":"/blog/tags/community-spotlights","description":"Community Spotlight tag description"}],"readingTime":2.285,"hasTruncateMarker":true,"authors":[{"name":"Sharan Foga","title":"Director of Operations & Customer Success @ Encube Technologies","url":"https://www.linkedin.com/in/sfoga/","page":{"permalink":"/blog/authors/sharanf"},"socials":{"linkedin":"https://www.linkedin.com/in/sfoga/","github":"https://github.com/sharanf"},"imageURL":"https://github.com/sharanf.png","key":"sharanf"}],"frontMatter":{"title":"Cadence Community Spotlight Update - June 2022","date":"2022-06-30T00:00:00.000Z","authors":"sharanf","tags":["community-spotlight"]},"unlisted":false,"prevItem":{"title":"Cadence Community Spotlight Update - July 2022","permalink":"/blog/2022/07/31/community-spotlight-update-july-2022"},"nextItem":{"title":"Cadence Community Spotlight Update - May 2022","permalink":"/blog/2022/05/31/community-spotlight-update-may-2022"}}')}}]); \ No newline at end of file +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[1816],{2088:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>r,contentTitle:()=>c,default:()=>d,frontMatter:()=>a,metadata:()=>o,toc:()=>l});var o=t(9476),i=t(4848),s=t(8453);const a={title:"Cadence Community Spotlight Update - June 2022",date:new Date("2022-06-30T00:00:00.000Z"),authors:"sharanf",tags:["community-spotlight"]},c=void 0,r={authorsImageUrls:[void 0]},l=[{value:"Knowledge Sharing and Support",id:"knowledge-sharing-and-support",level:2},{value:"Improving Technical Office Hours",id:"improving-technical-office-hours",level:2},{value:"Cadence Stability Improvements",id:"cadence-stability-improvements",level:2},{value:"Sprechen Sie Deutsch?",id:"sprechen-sie-deutsch",level:2},{value:"Cadence in the News!",id:"cadence-in-the-news",level:2},{value:"Upcoming Events",id:"upcoming-events",level:2}];function h(e){const n={a:"a",h2:"h2",li:"li",p:"p",strong:"strong",ul:"ul",...(0,s.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.p,{children:"It\u2019s time for our monthly Cadence Community Spotlight update with news from in and around the Cadence community!"}),"\n",(0,i.jsx)(n.p,{children:"Please see below for a roundup of the highlights:"}),"\n",(0,i.jsx)(n.h2,{id:"knowledge-sharing-and-support",children:"Knowledge Sharing and Support"}),"\n",(0,i.jsx)(n.p,{children:"Our Slack #support channel has been busy this month with 13 questions asked this month by 12 different community members. Six community members took time to respond to those questions which clearly shows our community is growing, collaborating and keen to share knowledge."}),"\n",(0,i.jsxs)(n.p,{children:["Please don\u2019t forget that we encourage everyone to post questions on StackOverflow using the ",(0,i.jsx)(n.strong,{children:"cadence-workflow"})," and ",(0,i.jsx)(n.strong,{children:"uber-cadence"})," tags so that others with similar questions or issues can easily search for and find an answer."]}),"\n",(0,i.jsx)(n.h2,{id:"improving-technical-office-hours",children:"Improving Technical Office Hours"}),"\n",(0,i.jsx)(n.p,{children:"Over the last few months we have been holding regular monthly Office Hours meetings but they have not attracted as many participants as we would like. We would like to understand if there is something preventing people from attending (e.g perhaps the timing or dates are not convenient) so we are planning to send out a short community survey."}),"\n",(0,i.jsx)(n.p,{children:"If you have any ideas or comments about how we can improve our community office hours sessions then please include this in your feedback or contact us in the #community Slack channel."}),"\n",(0,i.jsx)(n.h2,{id:"cadence-stability-improvements",children:"Cadence Stability Improvements"}),"\n",(0,i.jsx)(n.p,{children:"Is Cadence getting better? Yes it is! Many of you may have noticed that Cadence is improving.That is because of the amount of work being done behind the scenes. The Cadence core team has been doing a lot of work to stabilise Cadence functionality. Keep watching out for even more improvements!"}),"\n",(0,i.jsx)(n.h2,{id:"sprechen-sie-deutsch",children:"Sprechen Sie Deutsch?"}),"\n",(0,i.jsx)(n.p,{children:"Do you speak German? If you do speak then we have some good news for you. A couple of Cadence blog posts have been translated into German to help promote it to a wider audience. The links are as below and we hope you find them useful!"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"https://www.credativ.de/blog/howtos/workflows-mit-cadence-optimieren/",children:"Workflows mit Cadence optimieren!"})}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"https://www.credativ.de/blog/howtos/apache-kafka-microservices-mit-cadence-workflows-optimieren/",children:"Apache Kafka\xae Microservices mit Cadence-Workflows optimieren"})}),"\n"]}),"\n",(0,i.jsx)(n.h2,{id:"cadence-in-the-news",children:"Cadence in the News!"}),"\n",(0,i.jsx)(n.p,{children:"Below are a selection of Cadence related articles, blogs and whitepapers. Please take a look and feel free to share via your own social media channels."}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://www.instaclustr.com/blog/workflow-comparison-uber-cadence-vs-netflix-conductor/",children:"Workflow Comparison: Uber Cadence vs Netflix Conductor"})}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://www.instaclustr.com/blog/securing-cadence-web-using-nginx/",children:"Securing Cadence Web Using NGINX"})}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.h2,{id:"upcoming-events",children:"Upcoming Events"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://calendar.google.com/calendar/u/0/embed?src=e6r40gp3c2r01054id7e99dlac@group.calendar.google.com&ctz=America/Los_Angeles",children:"Cadence Technical Office Hours - 25th July 2022 @ 9am PT"})}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://info.instaclustr.com/webinar-building-cadence-workflow",children:"Webinar: Building Your First Cadence Workflow with Java and Go - 19th July 2022"})}),"\n"]}),"\n"]}),"\n",(0,i.jsxs)(n.p,{children:["If you have any news or topics you'd like us to include in our next update then please join our ",(0,i.jsx)(n.a,{href:"http://t.uber.com/cadence-slack",children:"Slack"}),"#community channel."]}),"\n",(0,i.jsxs)(n.p,{children:["Please remember that this update is for you - so if you have any comments or feedback that could help us improve it then please share it with us in the #community ",(0,i.jsx)(n.a,{href:"http://t.uber.com/cadence-slack",children:"Slack"})," channel."]})]})}function d(e={}){const{wrapper:n}={...(0,s.R)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(h,{...e})}):h(e)}},8453:(e,n,t)=>{t.d(n,{R:()=>a,x:()=>c});var o=t(6540);const i={},s=o.createContext(i);function a(e){const n=o.useContext(s);return o.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function c(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:a(e.components),o.createElement(s.Provider,{value:n},e.children)}},9476:e=>{e.exports=JSON.parse('{"permalink":"/Cadence-Docs/blog/2022/06/30/community-spotlight-update-june-2022","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2022-06-30-community-spotlight-update-june-2022.md","source":"@site/blog/2022-06-30-community-spotlight-update-june-2022.md","title":"Cadence Community Spotlight Update - June 2022","description":"It\u2019s time for our monthly Cadence Community Spotlight update with news from in and around the Cadence community!","date":"2022-06-30T00:00:00.000Z","tags":[{"inline":false,"label":"Community Spotlight","permalink":"/Cadence-Docs/blog/tags/community-spotlights","description":"Community Spotlight tag description"}],"readingTime":2.285,"hasTruncateMarker":true,"authors":[{"name":"Sharan Foga","title":"Director of Operations & Customer Success @ Encube Technologies","url":"https://www.linkedin.com/in/sfoga/","page":{"permalink":"/Cadence-Docs/blog/authors/sharanf"},"socials":{"linkedin":"https://www.linkedin.com/in/sfoga/","github":"https://github.com/sharanf"},"imageURL":"https://github.com/sharanf.png","key":"sharanf"}],"frontMatter":{"title":"Cadence Community Spotlight Update - June 2022","date":"2022-06-30T00:00:00.000Z","authors":"sharanf","tags":["community-spotlight"]},"unlisted":false,"prevItem":{"title":"Cadence Community Spotlight Update - July 2022","permalink":"/Cadence-Docs/blog/2022/07/31/community-spotlight-update-july-2022"},"nextItem":{"title":"Cadence Community Spotlight Update - May 2022","permalink":"/Cadence-Docs/blog/2022/05/31/community-spotlight-update-may-2022"}}')}}]); \ No newline at end of file diff --git a/assets/js/4c35ffca.12f32ac3.js b/assets/js/4c35ffca.12f32ac3.js deleted file mode 100644 index c9392eba1..000000000 --- a/assets/js/4c35ffca.12f32ac3.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[2872],{8539:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>l,contentTitle:()=>c,default:()=>p,frontMatter:()=>a,metadata:()=>o,toc:()=>s});const o=JSON.parse('{"id":"java-client/exception-handling","title":"Exception Handling","description":"By default, Exceptions thrown by an activity are received by the workflow wrapped into an com.uber.cadence.workflow.ActivityFailureException,","source":"@site/docs/04-java-client/14-exception-handling.md","sourceDirName":"04-java-client","slug":"/java-client/exception-handling","permalink":"/docs/java-client/exception-handling","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/04-java-client/14-exception-handling.md","tags":[],"version":"current","sidebarPosition":14,"frontMatter":{"layout":"default","title":"Exception Handling","permalink":"/docs/java-client/exception-handling"},"sidebar":"docsSidebar","previous":{"title":"Child workflows","permalink":"/docs/java-client/child-workflows"},"next":{"title":"Continue As New","permalink":"/docs/java-client/continue-as-new"}}');var i=t(4848),r=t(8453);const a={layout:"default",title:"Exception Handling",permalink:"/docs/java-client/exception-handling"},c="Exception Handling",l={},s=[];function d(e){const n={a:"a",code:"code",h1:"h1",header:"header",p:"p",pre:"pre",...(0,r.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.header,{children:(0,i.jsx)(n.h1,{id:"exception-handling",children:"Exception Handling"})}),"\n",(0,i.jsxs)(n.p,{children:["By default, Exceptions thrown by an activity are received by the workflow wrapped into an ",(0,i.jsx)(n.code,{children:"com.uber.cadence.workflow.ActivityFailureException"}),","]}),"\n",(0,i.jsxs)(n.p,{children:["Exceptions thrown by a child workflow are received by a parent workflow wrapped into a ",(0,i.jsx)(n.code,{children:"com.uber.cadence.workflow.ChildWorkflowFailureException"})]}),"\n",(0,i.jsxs)(n.p,{children:["Exceptions thrown by a workflow are received by a workflow client wrapped into ",(0,i.jsx)(n.code,{children:"com.uber.cadence.client.WorkflowFailureException"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["In this ",(0,i.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence-java-samples/blob/master/src/main/java/com/uber/cadence/samples/hello/HelloException.java",children:"example"})," a Workflow Client executes a workflow which executes a child workflow which\nexecutes an activity which throws an IOException. The resulting exception stack trace is:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-log",children:' com.uber.cadence.client.WorkflowFailureException: WorkflowType="GreetingWorkflow::getGreeting", WorkflowID="38b9ce7a-e370-4cd8-a9f3-35e7295f7b3d", RunID="37ceb58c-9271-4fca-b5aa-ba06c5495214\n at com.uber.cadence.internal.dispatcher.UntypedWorkflowStubImpl.getResult(UntypedWorkflowStubImpl.java:139)\n at com.uber.cadence.internal.dispatcher.UntypedWorkflowStubImpl.getResult(UntypedWorkflowStubImpl.java:111)\n at com.uber.cadence.internal.dispatcher.WorkflowExternalInvocationHandler.startWorkflow(WorkflowExternalInvocationHandler.java:187)\n at com.uber.cadence.internal.dispatcher.WorkflowExternalInvocationHandler.invoke(WorkflowExternalInvocationHandler.java:113)\n at com.sun.proxy.$Proxy2.getGreeting(Unknown Source)\n at com.uber.cadence.samples.hello.HelloException.main(HelloException.java:117)\n Caused by: com.uber.cadence.workflow.ChildWorkflowFailureException: WorkflowType="GreetingChild::composeGreeting", ID="37ceb58c-9271-4fca-b5aa-ba06c5495214:1", RunID="47859b47-da4c-4225-876a-462421c98c72, EventID=10\n at java.lang.Thread.getStackTrace(Thread.java:1559)\n at com.uber.cadence.internal.dispatcher.ChildWorkflowInvocationHandler.executeChildWorkflow(ChildWorkflowInvocationHandler.java:114)\n at com.uber.cadence.internal.dispatcher.ChildWorkflowInvocationHandler.invoke(ChildWorkflowInvocationHandler.java:71)\n at com.sun.proxy.$Proxy5.composeGreeting(Unknown Source:0)\n at com.uber.cadence.samples.hello.HelloException$GreetingWorkflowImpl.getGreeting(HelloException.java:70)\n at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method:0)\n at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)\n at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)\n at java.lang.reflect.Method.invoke(Method.java:498)\n at com.uber.cadence.internal.worker.POJOWorkflowImplementationFactory$POJOWorkflowImplementation.execute(POJOWorkflowImplementationFactory.java:160)\n Caused by: com.uber.cadence.workflow.ActivityFailureException: ActivityType="GreetingActivities::composeGreeting" ActivityID="1", EventID=7\n at java.lang.Thread.getStackTrace(Thread.java:1559)\n at com.uber.cadence.internal.dispatcher.ActivityInvocationHandler.invoke(ActivityInvocationHandler.java:75)\n at com.sun.proxy.$Proxy6.composeGreeting(Unknown Source:0)\n at com.uber.cadence.samples.hello.HelloException$GreetingChildImpl.composeGreeting(HelloException.java:85)\n ... 5 more\n Caused by: java.io.IOException: Hello World!\n at com.uber.cadence.samples.hello.HelloException$GreetingActivitiesImpl.composeGreeting(HelloException.java:93)\n at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method:0)\n at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)\n at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)\n at java.lang.reflect.Method.invoke(Method.java:498)\n at com.uber.cadence.internal.worker.POJOActivityImplementationFactory$POJOActivityImplementation.execute(POJOActivityImplementationFactory.java:162)\n'})}),"\n",(0,i.jsxs)(n.p,{children:["Note that IOException is a checked exception. The standard Java way of adding\nthrows IOException to method signature of activity, child and workflow interfaces is not going to help. It is\nbecause at all levels it is never received directly, but in wrapped form. Propagating it without\nwrapping would not allow adding additional context information like activity, child workflow and\nparent workflow types and IDs. The Cadence library solution is to provide a special wrapper\nmethod ",(0,i.jsx)(n.code,{children:"Workflow.wrap(Exception)"})," which wraps a checked exception in a special runtime\nexception. It is special because the framework strips it when chaining exceptions across logical\nprocess boundaries. In this example IOException is directly attached to ActivityFailureException\nbesides being wrapped when rethrown."]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",children:'public class HelloException {\n\n static final String TASK_LIST = "HelloException";\n\n public interface GreetingWorkflow {\n @WorkflowMethod\n String getGreeting(String name);\n }\n\n public interface GreetingChild {\n @WorkflowMethod\n String composeGreeting(String greeting, String name);\n }\n\n public interface GreetingActivities {\n String composeGreeting(String greeting, String name);\n }\n\n /** Parent implementation that calls GreetingChild#composeGreeting.**/\n public static class GreetingWorkflowImpl implements GreetingWorkflow {\n\n @Override\n public String getGreeting(String name) {\n GreetingChild child = Workflow.newChildWorkflowStub(GreetingChild.class);\n return child.composeGreeting("Hello", name);\n }\n }\n\n /** Child workflow implementation.**/\n public static class GreetingChildImpl implements GreetingChild {\n private final GreetingActivities activities =\n Workflow.newActivityStub(\n GreetingActivities.class,\n new ActivityOptions.Builder()\n .setScheduleToCloseTimeout(Duration.ofSeconds(10))\n .build());\n\n @Override\n public String composeGreeting(String greeting, String name) {\n return activities.composeGreeting(greeting, name);\n }\n }\n\n static class GreetingActivitiesImpl implements GreetingActivities {\n @Override\n public String composeGreeting(String greeting, String name) {\n try {\n throw new IOException(greeting + " " + name + "!");\n } catch (IOException e) {\n // Wrapping the exception as checked exceptions in activity and workflow interface methods\n // are prohibited.\n // It will be unwrapped and attached as a cause to the ActivityFailureException.\n throw Workflow.wrap(e);\n }\n }\n }\n\n public static void main(String[] args) {\n // Get a new client\n // NOTE: to set a different options, you can do like this:\n // ClientOptions.newBuilder().setRpcTimeout(5 * 1000).build();\n WorkflowClient workflowClient =\n WorkflowClient.newInstance(\n new WorkflowServiceTChannel(ClientOptions.defaultInstance()),\n WorkflowClientOptions.newBuilder().setDomain(DOMAIN).build());\n // Get worker to poll the task list.\n WorkerFactory factory = WorkerFactory.newInstance(workflowClient);\n Worker worker = factory.newWorker(TASK_LIST);\n worker.registerWorkflowImplementationTypes(GreetingWorkflowImpl.class, GreetingChildImpl.class);\n worker.registerActivitiesImplementations(new GreetingActivitiesImpl());\n factory.start();\n\n WorkflowOptions workflowOptions =\n new WorkflowOptions.Builder()\n .setTaskList(TASK_LIST)\n .setExecutionStartToCloseTimeout(Duration.ofSeconds(30))\n .build();\n GreetingWorkflow workflow =\n workflowClient.newWorkflowStub(GreetingWorkflow.class, workflowOptions);\n try {\n workflow.getGreeting("World");\n throw new IllegalStateException("unreachable");\n } catch (WorkflowException e) {\n Throwable cause = Throwables.getRootCause(e);\n // prints "Hello World!"\n System.out.println(cause.getMessage());\n System.out.println("\\nStack Trace:\\n" + Throwables.getStackTraceAsString(e));\n }\n System.exit(0);\n }\n\n}\n'})}),"\n",(0,i.jsx)(n.p,{children:"The code is slightly different if you are using client version prior to 3.0.0:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",children:'public static void main(String[] args) {\n Worker.Factory factory = new Worker.Factory(DOMAIN);\n Worker worker = factory.newWorker(TASK_LIST);\n worker.registerWorkflowImplementationTypes(GreetingWorkflowImpl.class, GreetingChildImpl.class);\n worker.registerActivitiesImplementations(new GreetingActivitiesImpl());\n factory.start();\n\n WorkflowClient workflowClient = WorkflowClient.newInstance(DOMAIN);\n WorkflowOptions workflowOptions =\n new WorkflowOptions.Builder()\n .setTaskList(TASK_LIST)\n .setExecutionStartToCloseTimeout(Duration.ofSeconds(30))\n .build();\n GreetingWorkflow workflow =\n workflowClient.newWorkflowStub(GreetingWorkflow.class, workflowOptions);\n try {\n workflow.getGreeting("World");\n throw new IllegalStateException("unreachable");\n } catch (WorkflowException e) {\n Throwable cause = Throwables.getRootCause(e);\n // prints "Hello World!"\n System.out.println(cause.getMessage());\n System.out.println("\\nStack Trace:\\n" + Throwables.getStackTraceAsString(e));\n }\n System.exit(0);\n}\n'})})]})}function p(e={}){const{wrapper:n}={...(0,r.R)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(d,{...e})}):d(e)}},8453:(e,n,t)=>{t.d(n,{R:()=>a,x:()=>c});var o=t(6540);const i={},r=o.createContext(i);function a(e){const n=o.useContext(r);return o.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function c(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:a(e.components),o.createElement(r.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/4c35ffca.80b7cc98.js b/assets/js/4c35ffca.80b7cc98.js new file mode 100644 index 000000000..943d73515 --- /dev/null +++ b/assets/js/4c35ffca.80b7cc98.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[2872],{8539:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>l,contentTitle:()=>c,default:()=>p,frontMatter:()=>a,metadata:()=>o,toc:()=>s});const o=JSON.parse('{"id":"java-client/exception-handling","title":"Exception Handling","description":"By default, Exceptions thrown by an activity are received by the workflow wrapped into an com.uber.cadence.workflow.ActivityFailureException,","source":"@site/docs/04-java-client/14-exception-handling.md","sourceDirName":"04-java-client","slug":"/java-client/exception-handling","permalink":"/Cadence-Docs/docs/java-client/exception-handling","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/04-java-client/14-exception-handling.md","tags":[],"version":"current","sidebarPosition":14,"frontMatter":{"layout":"default","title":"Exception Handling","permalink":"/docs/java-client/exception-handling"},"sidebar":"docsSidebar","previous":{"title":"Child workflows","permalink":"/Cadence-Docs/docs/java-client/child-workflows"},"next":{"title":"Continue As New","permalink":"/Cadence-Docs/docs/java-client/continue-as-new"}}');var i=t(4848),r=t(8453);const a={layout:"default",title:"Exception Handling",permalink:"/docs/java-client/exception-handling"},c="Exception Handling",l={},s=[];function d(e){const n={a:"a",code:"code",h1:"h1",header:"header",p:"p",pre:"pre",...(0,r.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.header,{children:(0,i.jsx)(n.h1,{id:"exception-handling",children:"Exception Handling"})}),"\n",(0,i.jsxs)(n.p,{children:["By default, Exceptions thrown by an activity are received by the workflow wrapped into an ",(0,i.jsx)(n.code,{children:"com.uber.cadence.workflow.ActivityFailureException"}),","]}),"\n",(0,i.jsxs)(n.p,{children:["Exceptions thrown by a child workflow are received by a parent workflow wrapped into a ",(0,i.jsx)(n.code,{children:"com.uber.cadence.workflow.ChildWorkflowFailureException"})]}),"\n",(0,i.jsxs)(n.p,{children:["Exceptions thrown by a workflow are received by a workflow client wrapped into ",(0,i.jsx)(n.code,{children:"com.uber.cadence.client.WorkflowFailureException"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["In this ",(0,i.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence-java-samples/blob/master/src/main/java/com/uber/cadence/samples/hello/HelloException.java",children:"example"})," a Workflow Client executes a workflow which executes a child workflow which\nexecutes an activity which throws an IOException. The resulting exception stack trace is:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-log",children:' com.uber.cadence.client.WorkflowFailureException: WorkflowType="GreetingWorkflow::getGreeting", WorkflowID="38b9ce7a-e370-4cd8-a9f3-35e7295f7b3d", RunID="37ceb58c-9271-4fca-b5aa-ba06c5495214\n at com.uber.cadence.internal.dispatcher.UntypedWorkflowStubImpl.getResult(UntypedWorkflowStubImpl.java:139)\n at com.uber.cadence.internal.dispatcher.UntypedWorkflowStubImpl.getResult(UntypedWorkflowStubImpl.java:111)\n at com.uber.cadence.internal.dispatcher.WorkflowExternalInvocationHandler.startWorkflow(WorkflowExternalInvocationHandler.java:187)\n at com.uber.cadence.internal.dispatcher.WorkflowExternalInvocationHandler.invoke(WorkflowExternalInvocationHandler.java:113)\n at com.sun.proxy.$Proxy2.getGreeting(Unknown Source)\n at com.uber.cadence.samples.hello.HelloException.main(HelloException.java:117)\n Caused by: com.uber.cadence.workflow.ChildWorkflowFailureException: WorkflowType="GreetingChild::composeGreeting", ID="37ceb58c-9271-4fca-b5aa-ba06c5495214:1", RunID="47859b47-da4c-4225-876a-462421c98c72, EventID=10\n at java.lang.Thread.getStackTrace(Thread.java:1559)\n at com.uber.cadence.internal.dispatcher.ChildWorkflowInvocationHandler.executeChildWorkflow(ChildWorkflowInvocationHandler.java:114)\n at com.uber.cadence.internal.dispatcher.ChildWorkflowInvocationHandler.invoke(ChildWorkflowInvocationHandler.java:71)\n at com.sun.proxy.$Proxy5.composeGreeting(Unknown Source:0)\n at com.uber.cadence.samples.hello.HelloException$GreetingWorkflowImpl.getGreeting(HelloException.java:70)\n at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method:0)\n at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)\n at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)\n at java.lang.reflect.Method.invoke(Method.java:498)\n at com.uber.cadence.internal.worker.POJOWorkflowImplementationFactory$POJOWorkflowImplementation.execute(POJOWorkflowImplementationFactory.java:160)\n Caused by: com.uber.cadence.workflow.ActivityFailureException: ActivityType="GreetingActivities::composeGreeting" ActivityID="1", EventID=7\n at java.lang.Thread.getStackTrace(Thread.java:1559)\n at com.uber.cadence.internal.dispatcher.ActivityInvocationHandler.invoke(ActivityInvocationHandler.java:75)\n at com.sun.proxy.$Proxy6.composeGreeting(Unknown Source:0)\n at com.uber.cadence.samples.hello.HelloException$GreetingChildImpl.composeGreeting(HelloException.java:85)\n ... 5 more\n Caused by: java.io.IOException: Hello World!\n at com.uber.cadence.samples.hello.HelloException$GreetingActivitiesImpl.composeGreeting(HelloException.java:93)\n at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method:0)\n at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)\n at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)\n at java.lang.reflect.Method.invoke(Method.java:498)\n at com.uber.cadence.internal.worker.POJOActivityImplementationFactory$POJOActivityImplementation.execute(POJOActivityImplementationFactory.java:162)\n'})}),"\n",(0,i.jsxs)(n.p,{children:["Note that IOException is a checked exception. The standard Java way of adding\nthrows IOException to method signature of activity, child and workflow interfaces is not going to help. It is\nbecause at all levels it is never received directly, but in wrapped form. Propagating it without\nwrapping would not allow adding additional context information like activity, child workflow and\nparent workflow types and IDs. The Cadence library solution is to provide a special wrapper\nmethod ",(0,i.jsx)(n.code,{children:"Workflow.wrap(Exception)"})," which wraps a checked exception in a special runtime\nexception. It is special because the framework strips it when chaining exceptions across logical\nprocess boundaries. In this example IOException is directly attached to ActivityFailureException\nbesides being wrapped when rethrown."]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",children:'public class HelloException {\n\n static final String TASK_LIST = "HelloException";\n\n public interface GreetingWorkflow {\n @WorkflowMethod\n String getGreeting(String name);\n }\n\n public interface GreetingChild {\n @WorkflowMethod\n String composeGreeting(String greeting, String name);\n }\n\n public interface GreetingActivities {\n String composeGreeting(String greeting, String name);\n }\n\n /** Parent implementation that calls GreetingChild#composeGreeting.**/\n public static class GreetingWorkflowImpl implements GreetingWorkflow {\n\n @Override\n public String getGreeting(String name) {\n GreetingChild child = Workflow.newChildWorkflowStub(GreetingChild.class);\n return child.composeGreeting("Hello", name);\n }\n }\n\n /** Child workflow implementation.**/\n public static class GreetingChildImpl implements GreetingChild {\n private final GreetingActivities activities =\n Workflow.newActivityStub(\n GreetingActivities.class,\n new ActivityOptions.Builder()\n .setScheduleToCloseTimeout(Duration.ofSeconds(10))\n .build());\n\n @Override\n public String composeGreeting(String greeting, String name) {\n return activities.composeGreeting(greeting, name);\n }\n }\n\n static class GreetingActivitiesImpl implements GreetingActivities {\n @Override\n public String composeGreeting(String greeting, String name) {\n try {\n throw new IOException(greeting + " " + name + "!");\n } catch (IOException e) {\n // Wrapping the exception as checked exceptions in activity and workflow interface methods\n // are prohibited.\n // It will be unwrapped and attached as a cause to the ActivityFailureException.\n throw Workflow.wrap(e);\n }\n }\n }\n\n public static void main(String[] args) {\n // Get a new client\n // NOTE: to set a different options, you can do like this:\n // ClientOptions.newBuilder().setRpcTimeout(5 * 1000).build();\n WorkflowClient workflowClient =\n WorkflowClient.newInstance(\n new WorkflowServiceTChannel(ClientOptions.defaultInstance()),\n WorkflowClientOptions.newBuilder().setDomain(DOMAIN).build());\n // Get worker to poll the task list.\n WorkerFactory factory = WorkerFactory.newInstance(workflowClient);\n Worker worker = factory.newWorker(TASK_LIST);\n worker.registerWorkflowImplementationTypes(GreetingWorkflowImpl.class, GreetingChildImpl.class);\n worker.registerActivitiesImplementations(new GreetingActivitiesImpl());\n factory.start();\n\n WorkflowOptions workflowOptions =\n new WorkflowOptions.Builder()\n .setTaskList(TASK_LIST)\n .setExecutionStartToCloseTimeout(Duration.ofSeconds(30))\n .build();\n GreetingWorkflow workflow =\n workflowClient.newWorkflowStub(GreetingWorkflow.class, workflowOptions);\n try {\n workflow.getGreeting("World");\n throw new IllegalStateException("unreachable");\n } catch (WorkflowException e) {\n Throwable cause = Throwables.getRootCause(e);\n // prints "Hello World!"\n System.out.println(cause.getMessage());\n System.out.println("\\nStack Trace:\\n" + Throwables.getStackTraceAsString(e));\n }\n System.exit(0);\n }\n\n}\n'})}),"\n",(0,i.jsx)(n.p,{children:"The code is slightly different if you are using client version prior to 3.0.0:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",children:'public static void main(String[] args) {\n Worker.Factory factory = new Worker.Factory(DOMAIN);\n Worker worker = factory.newWorker(TASK_LIST);\n worker.registerWorkflowImplementationTypes(GreetingWorkflowImpl.class, GreetingChildImpl.class);\n worker.registerActivitiesImplementations(new GreetingActivitiesImpl());\n factory.start();\n\n WorkflowClient workflowClient = WorkflowClient.newInstance(DOMAIN);\n WorkflowOptions workflowOptions =\n new WorkflowOptions.Builder()\n .setTaskList(TASK_LIST)\n .setExecutionStartToCloseTimeout(Duration.ofSeconds(30))\n .build();\n GreetingWorkflow workflow =\n workflowClient.newWorkflowStub(GreetingWorkflow.class, workflowOptions);\n try {\n workflow.getGreeting("World");\n throw new IllegalStateException("unreachable");\n } catch (WorkflowException e) {\n Throwable cause = Throwables.getRootCause(e);\n // prints "Hello World!"\n System.out.println(cause.getMessage());\n System.out.println("\\nStack Trace:\\n" + Throwables.getStackTraceAsString(e));\n }\n System.exit(0);\n}\n'})})]})}function p(e={}){const{wrapper:n}={...(0,r.R)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(d,{...e})}):d(e)}},8453:(e,n,t)=>{t.d(n,{R:()=>a,x:()=>c});var o=t(6540);const i={},r=o.createContext(i);function a(e){const n=o.useContext(r);return o.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function c(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:a(e.components),o.createElement(r.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/4c8ff8e7.d567bd35.js b/assets/js/4c8ff8e7.d567bd35.js new file mode 100644 index 000000000..d45e70ad5 --- /dev/null +++ b/assets/js/4c8ff8e7.d567bd35.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[9092],{6191:e=>{e.exports=JSON.parse('{"author":{"name":"Taylan Isikdemir","title":"Sr. Staff Software Engineer @ Uber","url":"https://www.linkedin.com/in/taylan-isikdemir","page":{"permalink":"/Cadence-Docs/blog/authors/taylanisikdemir"},"socials":{"linkedin":"https://www.linkedin.com/in/taylan-isikdemir","github":"https://github.com/taylanisikdemir"},"imageURL":"https://github.com/taylanisikdemir.png","key":"taylanisikdemir","count":1},"listMetadata":{"permalink":"/Cadence-Docs/blog/authors/taylanisikdemir","page":1,"postsPerPage":10,"totalPages":1,"totalCount":1,"blogDescription":"The latest news and updates from the Cadence team","blogTitle":"Cadence Blog"}}')}}]); \ No newline at end of file diff --git a/assets/js/4c9d8eaa.4d42e69d.js b/assets/js/4c9d8eaa.4d42e69d.js new file mode 100644 index 000000000..0591d94dd --- /dev/null +++ b/assets/js/4c9d8eaa.4d42e69d.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[3116],{9614:(e,i,n)=>{n.r(i),n.d(i,{assets:()=>u,contentTitle:()=>m,default:()=>p,frontMatter:()=>d,metadata:()=>t,toc:()=>b});const t=JSON.parse('{"id":"team","title":"Team","description":"Core Team","source":"@site/community/1-team.mdx","sourceDirName":".","slug":"/team","permalink":"/Cadence-Docs/community/team","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/edit/master/community/1-team.mdx","tags":[],"version":"current","lastUpdatedBy":"Josue Ibarra","lastUpdatedAt":1733779660000,"sidebarPosition":1,"frontMatter":{},"sidebar":"community","previous":{"title":"Support","permalink":"/Cadence-Docs/community/support"}}');var a=n(4848),s=n(8453),r=(n(6540),n(1312),n(8774)),o=n(1107);function l(e){let{className:i,name:n,children:t,githubUrl:s,xUrl:l,linkedinUrl:h}=e;return(0,a.jsx)("div",{className:i,children:(0,a.jsxs)("div",{className:"card card--full-height item shadow--md",children:[(0,a.jsx)("div",{className:"card__header",children:(0,a.jsxs)("div",{className:"avatar avatar--horizontal",children:[(0,a.jsx)("img",{className:"avatar__photo avatar__photo--xl",src:`${s}.png`,alt:`${n}'s avatar`}),(0,a.jsx)("div",{className:"avatar__intro",children:(0,a.jsx)(o.A,{as:"h3",className:"avatar__name",children:n})})]})}),(0,a.jsx)("div",{className:"card__body",children:t}),(0,a.jsx)("div",{className:"card__footer",children:(0,a.jsxs)("div",{className:"button-group button-group--block",children:[s&&(0,a.jsx)(r.A,{className:"button button--secondary",href:s,children:"GitHub"}),l&&(0,a.jsx)(r.A,{className:"button button--secondary",href:l,children:"X"}),h&&(0,a.jsx)(r.A,{className:"button button--secondary",href:h,children:"LinkedIn"})]})})]})})}function h(e){return(0,a.jsx)(l,{...e,className:"col col--6 margin-bottom--lg"})}function c(){return(0,a.jsxs)("div",{className:"row",children:[(0,a.jsxs)(h,{name:"Abhishek Jha",githubUrl:"https://github.com/abhishekj720",linkedinUrl:"https://www.linkedin.com/in/mrjhaabhishek/",children:["\ud83d\udc4b\ud83c\udffb Abhishek Jha is a Software Developer for Cadence Workflows at Uber, specializing in developing robust distributed systems.",(0,a.jsx)("br",{}),"He is passionate about leveraging emerging technologies, particularly Applied AI, to enhance system reliability and scalability.",(0,a.jsx)("br",{}),"Outside of work, Abhishek enjoys hiking, singing/guitar, and playing various sports. He is always eager to discuss the future of technology, investments, and other intriguing topics. \ud83e\uddd1\ud83c\udffb\u200d\ud83d\udcbb\ud83e\udd7e\ud83c\udfbe\ud83c\udfb6"]}),(0,a.jsx)(h,{name:"Adhitya Mamallan",githubUrl:"https://github.com/adhityamamallan",children:" "}),(0,a.jsx)(h,{name:"Andre Oliveira",githubUrl:"https://github.com/uandreo",children:" "}),(0,a.jsx)(h,{name:"Assem Hafez",githubUrl:"https://github.com/Assem-Uber",children:" "}),(0,a.jsx)(h,{name:"Bowen Xiao",githubUrl:"https://github.com/bowenxia",children:" "}),(0,a.jsx)(h,{name:"chopincode",githubUrl:"https://github.com/chopincode",children:" "}),(0,a.jsx)(h,{name:"David Porter",githubUrl:"https://github.com/davidporter-id-au",children:" "}),(0,a.jsxs)(h,{name:"Ender Demirkaya",githubUrl:"https://github.com/demirkayaender",linkedinUrl:"https://www.linkedin.com/in/enderdemirkaya/",children:["Ender joined the Cadence team as a tech lead and later transitioned into a management role. ",(0,a.jsx)("br",{}),"His career started with his own startup, followed with Microsoft, working for another startup and Meta. ",(0,a.jsx)("br",{}),"His prior work involves building Bing's/Azure's key value store (ObjectStore), distributed NAS, and search engines. ",(0,a.jsx)("br",{}),"He's into outdoors and endurance sports while not working."]}),(0,a.jsx)(h,{name:"Felipe Imanishi",githubUrl:"https://github.com/fimanishi",linkedinUrl:"https://www.linkedin.com/in/fimanishi",children:"Felipe is a Software Engineer contributing to Cadence from San Francisco. He found CS later in his career, and he is glad he did. Felipe is always looking to learn more and Cadence is provides an endless source of topics. Outside of work, Felipe is probably doing something with his two sons."}),(0,a.jsx)(h,{name:"Gaziza Yestemirova",githubUrl:"https://github.com/gazi-yestemirova",children:" "}),(0,a.jsx)(h,{name:"Ilya Ozherelyev",githubUrl:"https://github.com/3vilhamster",children:" "}),(0,a.jsxs)(h,{name:"Jakob Haahr Taankvist",githubUrl:"https://github.com/jakobht",linkedinUrl:"https://www.linkedin.com/in/jakob-taankvist/",children:["Jakob Haahr Taankvist is a Software Engineer, contributing to the Cadence project from Denmark. With a background in formal games and traffic optimization, he now explores workflow orchestration.",(0,a.jsx)("br",{}),"Outside of work, Jakob is on a mission to evaluate how well Danish ice hockey arenas double as programming spots while cheering on his son's games. \ud83c\udfd2\ud83d\udcbb"]}),(0,a.jsx)(h,{name:"Jonathan Baker",githubUrl:"https://github.com/jonathanbaker7",children:" "}),(0,a.jsxs)(h,{name:"Josu\xe9 Alexander Ibarra",githubUrl:"https://github.com/ibarrajo",linkedinUrl:"https://www.linkedin.com/in/elninja/",children:["Josue Ibarra is a Developer Advocate for Cadence Workflows at Uber, based in Seattle.",(0,a.jsx)("br",{}),"Passionate about building better systems with Cadence, he balances his love for coding with hobbies like motorcycles, sailing, and cooking. \ud83d\ude80\ud83c\udf73\ud83c\udfcd\ufe0f"]}),(0,a.jsx)(h,{name:"Ketsia Mbaku",githubUrl:"https://github.com/ketsiambaku",children:" "}),(0,a.jsx)(h,{name:"Kisel Jan",githubUrl:"https://github.com/dkrotx",children:" "}),(0,a.jsx)(h,{name:"Nate Mortensen",githubUrl:"https://github.com/natemort",children:"Nate originally got into programming by modding Minecraft and has been contributing to open source software ever since. When he's not working on Cadence he's on a mission to try every pizza in Seattle."}),(0,a.jsx)(h,{name:"Neil Xie",githubUrl:"https://github.com/neil-xie",linkedinUrl:"https://www.linkedin.com/in/neil-huakun-xie-b9373a162/",children:"Neil is a Software Engineer contrinuting to Cadence based in Seattle. He is a camping enthusiast who enjoys exploring the outdoors with his two dogs."}),(0,a.jsx)(h,{name:"Sankari Gopalakrishnan",githubUrl:"https://github.com/sankari165",linkedinUrl:"https://www.linkedin.com/in/sankari-gopalakrishnan165",children:"Sankari is a Software Engineer at Uber, working on Cadence from Denmark. With a career spanning multiple domains, she has mastered the art of connecting the dots. Outside her technical pursuits, she finds joy in therapeutic art, channeling her love for sugar, spices, and colors into creative expression."}),(0,a.jsx)(h,{name:"Shaddoll",githubUrl:"https://github.com/Shaddoll",children:" "}),(0,a.jsx)(h,{name:"Shijie Sheng",githubUrl:"https://github.com/shijiesheng",children:" "}),(0,a.jsx)(h,{name:"Steven L",githubUrl:"https://github.com/Groxx",children:" "}),(0,a.jsxs)(h,{name:"Taylan Isikdemir",githubUrl:"https://github.com/taylanisikdemir",linkedinUrl:"https://www.linkedin.com/in/taylan-isikdemir",children:["Taylan majored in CS and his software engineering journey includes working at Microsoft Azure, Google Cloud, and helping build an observability startup from ground up. ",(0,a.jsx)("br",{}),"Taylan is tech lead of Cadence team at Uber, based in Seattle. ",(0,a.jsx)("br",{}),"When he is not working, you'll probably find him playing basketball or kickboxing."]}),(0,a.jsx)(h,{name:"Tim Li",githubUrl:"https://github.com/timl3136",children:" "}),(0,a.jsx)(h,{name:"tubignat",githubUrl:"https://github.com/tubignat",children:" "}),(0,a.jsx)(h,{name:"Vinay Kumar Yadav",githubUrl:"https://github.com/vinay116",children:" "}),(0,a.jsx)(h,{name:"Vsevolod Kaloshin",githubUrl:"https://github.com/arzonus",children:" "})]})}const d={},m="Team",u={},b=[{value:"Core Team",id:"core-team",level:2}];function g(e){const i={blockquote:"blockquote",h1:"h1",h2:"h2",header:"header",p:"p",...(0,s.R)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(i.header,{children:(0,a.jsx)(i.h1,{id:"team",children:"Team"})}),"\n","\n",(0,a.jsx)(i.h2,{id:"core-team",children:"Core Team"}),"\n",(0,a.jsxs)(i.blockquote,{children:["\n",(0,a.jsx)(i.p,{children:"The Cadence team develops and maintains the Cadence open source project as well as foundational services for Uber's Platform.\nCurrent members of the Cadence team are listed in alphabetical order below."}),"\n"]}),"\n",(0,a.jsx)(c,{})]})}function p(e={}){const{wrapper:i}={...(0,s.R)(),...e.components};return i?(0,a.jsx)(i,{...e,children:(0,a.jsx)(g,{...e})}):g(e)}},8453:(e,i,n)=>{n.d(i,{R:()=>r,x:()=>o});var t=n(6540);const a={},s=t.createContext(a);function r(e){const i=t.useContext(s);return t.useMemo((function(){return"function"==typeof e?e(i):{...i,...e}}),[i,e])}function o(e){let i;return i=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:r(e.components),t.createElement(s.Provider,{value:i},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/4c9d8eaa.771c094c.js b/assets/js/4c9d8eaa.771c094c.js deleted file mode 100644 index a89e73638..000000000 --- a/assets/js/4c9d8eaa.771c094c.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[3116],{9614:(e,i,n)=>{n.r(i),n.d(i,{assets:()=>u,contentTitle:()=>m,default:()=>p,frontMatter:()=>d,metadata:()=>t,toc:()=>b});const t=JSON.parse('{"id":"team","title":"Team","description":"Core Team","source":"@site/community/1-team.mdx","sourceDirName":".","slug":"/team","permalink":"/community/team","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/edit/master/community/1-team.mdx","tags":[],"version":"current","lastUpdatedBy":"Josue Ibarra","lastUpdatedAt":1733779660000,"sidebarPosition":1,"frontMatter":{},"sidebar":"community","previous":{"title":"Support","permalink":"/community/support"}}');var a=n(4848),s=n(8453),r=(n(6540),n(1312),n(8774)),o=n(1107);function l(e){let{className:i,name:n,children:t,githubUrl:s,xUrl:l,linkedinUrl:h}=e;return(0,a.jsx)("div",{className:i,children:(0,a.jsxs)("div",{className:"card card--full-height item shadow--md",children:[(0,a.jsx)("div",{className:"card__header",children:(0,a.jsxs)("div",{className:"avatar avatar--horizontal",children:[(0,a.jsx)("img",{className:"avatar__photo avatar__photo--xl",src:`${s}.png`,alt:`${n}'s avatar`}),(0,a.jsx)("div",{className:"avatar__intro",children:(0,a.jsx)(o.A,{as:"h3",className:"avatar__name",children:n})})]})}),(0,a.jsx)("div",{className:"card__body",children:t}),(0,a.jsx)("div",{className:"card__footer",children:(0,a.jsxs)("div",{className:"button-group button-group--block",children:[s&&(0,a.jsx)(r.A,{className:"button button--secondary",href:s,children:"GitHub"}),l&&(0,a.jsx)(r.A,{className:"button button--secondary",href:l,children:"X"}),h&&(0,a.jsx)(r.A,{className:"button button--secondary",href:h,children:"LinkedIn"})]})})]})})}function h(e){return(0,a.jsx)(l,{...e,className:"col col--6 margin-bottom--lg"})}function c(){return(0,a.jsxs)("div",{className:"row",children:[(0,a.jsxs)(h,{name:"Abhishek Jha",githubUrl:"https://github.com/abhishekj720",linkedinUrl:"https://www.linkedin.com/in/mrjhaabhishek/",children:["\ud83d\udc4b\ud83c\udffb Abhishek Jha is a Software Developer for Cadence Workflows at Uber, specializing in developing robust distributed systems.",(0,a.jsx)("br",{}),"He is passionate about leveraging emerging technologies, particularly Applied AI, to enhance system reliability and scalability.",(0,a.jsx)("br",{}),"Outside of work, Abhishek enjoys hiking, singing/guitar, and playing various sports. He is always eager to discuss the future of technology, investments, and other intriguing topics. \ud83e\uddd1\ud83c\udffb\u200d\ud83d\udcbb\ud83e\udd7e\ud83c\udfbe\ud83c\udfb6"]}),(0,a.jsx)(h,{name:"Adhitya Mamallan",githubUrl:"https://github.com/adhityamamallan",children:" "}),(0,a.jsx)(h,{name:"Andre Oliveira",githubUrl:"https://github.com/uandreo",children:" "}),(0,a.jsx)(h,{name:"Assem Hafez",githubUrl:"https://github.com/Assem-Uber",children:" "}),(0,a.jsx)(h,{name:"Bowen Xiao",githubUrl:"https://github.com/bowenxia",children:" "}),(0,a.jsx)(h,{name:"chopincode",githubUrl:"https://github.com/chopincode",children:" "}),(0,a.jsx)(h,{name:"David Porter",githubUrl:"https://github.com/davidporter-id-au",children:" "}),(0,a.jsxs)(h,{name:"Ender Demirkaya",githubUrl:"https://github.com/demirkayaender",linkedinUrl:"https://www.linkedin.com/in/enderdemirkaya/",children:["Ender joined the Cadence team as a tech lead and later transitioned into a management role. ",(0,a.jsx)("br",{}),"His career started with his own startup, followed with Microsoft, working for another startup and Meta. ",(0,a.jsx)("br",{}),"His prior work involves building Bing's/Azure's key value store (ObjectStore), distributed NAS, and search engines. ",(0,a.jsx)("br",{}),"He's into outdoors and endurance sports while not working."]}),(0,a.jsx)(h,{name:"Felipe Imanishi",githubUrl:"https://github.com/fimanishi",linkedinUrl:"https://www.linkedin.com/in/fimanishi",children:"Felipe is a Software Engineer contributing to Cadence from San Francisco. He found CS later in his career, and he is glad he did. Felipe is always looking to learn more and Cadence is provides an endless source of topics. Outside of work, Felipe is probably doing something with his two sons."}),(0,a.jsx)(h,{name:"Gaziza Yestemirova",githubUrl:"https://github.com/gazi-yestemirova",children:" "}),(0,a.jsx)(h,{name:"Ilya Ozherelyev",githubUrl:"https://github.com/3vilhamster",children:" "}),(0,a.jsxs)(h,{name:"Jakob Haahr Taankvist",githubUrl:"https://github.com/jakobht",linkedinUrl:"https://www.linkedin.com/in/jakob-taankvist/",children:["Jakob Haahr Taankvist is a Software Engineer, contributing to the Cadence project from Denmark. With a background in formal games and traffic optimization, he now explores workflow orchestration.",(0,a.jsx)("br",{}),"Outside of work, Jakob is on a mission to evaluate how well Danish ice hockey arenas double as programming spots while cheering on his son's games. \ud83c\udfd2\ud83d\udcbb"]}),(0,a.jsx)(h,{name:"Jonathan Baker",githubUrl:"https://github.com/jonathanbaker7",children:" "}),(0,a.jsxs)(h,{name:"Josu\xe9 Alexander Ibarra",githubUrl:"https://github.com/ibarrajo",linkedinUrl:"https://www.linkedin.com/in/elninja/",children:["Josue Ibarra is a Developer Advocate for Cadence Workflows at Uber, based in Seattle.",(0,a.jsx)("br",{}),"Passionate about building better systems with Cadence, he balances his love for coding with hobbies like motorcycles, sailing, and cooking. \ud83d\ude80\ud83c\udf73\ud83c\udfcd\ufe0f"]}),(0,a.jsx)(h,{name:"Ketsia Mbaku",githubUrl:"https://github.com/ketsiambaku",children:" "}),(0,a.jsx)(h,{name:"Kisel Jan",githubUrl:"https://github.com/dkrotx",children:" "}),(0,a.jsx)(h,{name:"Nate Mortensen",githubUrl:"https://github.com/natemort",children:"Nate originally got into programming by modding Minecraft and has been contributing to open source software ever since. When he's not working on Cadence he's on a mission to try every pizza in Seattle."}),(0,a.jsx)(h,{name:"Neil Xie",githubUrl:"https://github.com/neil-xie",linkedinUrl:"https://www.linkedin.com/in/neil-huakun-xie-b9373a162/",children:"Neil is a Software Engineer contrinuting to Cadence based in Seattle. He is a camping enthusiast who enjoys exploring the outdoors with his two dogs."}),(0,a.jsx)(h,{name:"Sankari Gopalakrishnan",githubUrl:"https://github.com/sankari165",linkedinUrl:"https://www.linkedin.com/in/sankari-gopalakrishnan165",children:"Sankari is a Software Engineer at Uber, working on Cadence from Denmark. With a career spanning multiple domains, she has mastered the art of connecting the dots. Outside her technical pursuits, she finds joy in therapeutic art, channeling her love for sugar, spices, and colors into creative expression."}),(0,a.jsx)(h,{name:"Shaddoll",githubUrl:"https://github.com/Shaddoll",children:" "}),(0,a.jsx)(h,{name:"Shijie Sheng",githubUrl:"https://github.com/shijiesheng",children:" "}),(0,a.jsx)(h,{name:"Steven L",githubUrl:"https://github.com/Groxx",children:" "}),(0,a.jsxs)(h,{name:"Taylan Isikdemir",githubUrl:"https://github.com/taylanisikdemir",linkedinUrl:"https://www.linkedin.com/in/taylan-isikdemir",children:["Taylan majored in CS and his software engineering journey includes working at Microsoft Azure, Google Cloud, and helping build an observability startup from ground up. ",(0,a.jsx)("br",{}),"Taylan is tech lead of Cadence team at Uber, based in Seattle. ",(0,a.jsx)("br",{}),"When he is not working, you'll probably find him playing basketball or kickboxing."]}),(0,a.jsx)(h,{name:"Tim Li",githubUrl:"https://github.com/timl3136",children:" "}),(0,a.jsx)(h,{name:"tubignat",githubUrl:"https://github.com/tubignat",children:" "}),(0,a.jsx)(h,{name:"Vinay Kumar Yadav",githubUrl:"https://github.com/vinay116",children:" "}),(0,a.jsx)(h,{name:"Vsevolod Kaloshin",githubUrl:"https://github.com/arzonus",children:" "})]})}const d={},m="Team",u={},b=[{value:"Core Team",id:"core-team",level:2}];function g(e){const i={blockquote:"blockquote",h1:"h1",h2:"h2",header:"header",p:"p",...(0,s.R)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(i.header,{children:(0,a.jsx)(i.h1,{id:"team",children:"Team"})}),"\n","\n",(0,a.jsx)(i.h2,{id:"core-team",children:"Core Team"}),"\n",(0,a.jsxs)(i.blockquote,{children:["\n",(0,a.jsx)(i.p,{children:"The Cadence team develops and maintains the Cadence open source project as well as foundational services for Uber's Platform.\nCurrent members of the Cadence team are listed in alphabetical order below."}),"\n"]}),"\n",(0,a.jsx)(c,{})]})}function p(e={}){const{wrapper:i}={...(0,s.R)(),...e.components};return i?(0,a.jsx)(i,{...e,children:(0,a.jsx)(g,{...e})}):g(e)}},8453:(e,i,n)=>{n.d(i,{R:()=>r,x:()=>o});var t=n(6540);const a={},s=t.createContext(a);function r(e){const i=t.useContext(s);return t.useMemo((function(){return"function"==typeof e?e(i):{...i,...e}}),[i,e])}function o(e){let i;return i=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:r(e.components),t.createElement(s.Provider,{value:i},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/4d0beaf2.78a8e7a9.js b/assets/js/4d0beaf2.78a8e7a9.js new file mode 100644 index 000000000..8555ca88e --- /dev/null +++ b/assets/js/4d0beaf2.78a8e7a9.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[1507],{4950:e=>{e.exports=JSON.parse('{"archive":{"blogPosts":[{"id":"/2024/11/18/cadence-workflows-github-organization","metadata":{"permalink":"/Cadence-Docs/blog/2024/11/18/cadence-workflows-github-organization","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2024-11-18-cadence-workflows-github-organization.md","source":"@site/blog/2024-11-18-cadence-workflows-github-organization.md","title":"Cadence Repositories Have Moved!","description":"Discover the latest update for Cadence Workflow! Our GitHub repositories have moved to the new cadence-workflow organization. Learn more about the migration, including updated links and how this change supports the growing Cadence community","date":"2024-11-18T14:00:00.000Z","tags":[{"inline":false,"label":"Announcement","permalink":"/Cadence-Docs/blog/tags/announcements","description":"Announcement tag description"}],"readingTime":0.6,"hasTruncateMarker":true,"authors":[{"name":"Josu\xe9 Alexander Ibarra","title":"Developer Advocate @ Uber","url":"https://github.com/ibarrajo/","page":{"permalink":"/Cadence-Docs/blog/authors/ibarrajo"},"socials":{"github":"https://github.com/ibarrajo","linkedin":"https://www.linkedin.com/in/elninja/"},"imageURL":"https://github.com/ibarrajo.png","key":"ibarrajo"}],"frontMatter":{"title":"Cadence Repositories Have Moved!","description":"Discover the latest update for Cadence Workflow! Our GitHub repositories have moved to the new cadence-workflow organization. Learn more about the migration, including updated links and how this change supports the growing Cadence community","authors":"ibarrajo","tags":["announcement"],"date":"2024-11-18T14:00"},"unlisted":false,"nextItem":{"title":"Zonal Isolation for Cadence Workflows","permalink":"/Cadence-Docs/blog/zonal-isolation-v1/zonal-isolation-v1"}},"content":"We\u2019re excited to announce that all Cadence GitHub repositories have been consolidated under the [cadence-workflow](https://github.com/cadence-workflow) organization! \ud83c\udf89\\n\\nPreviously, Cadence repositories were distributed across multiple organizations at Uber: [`uber`](https://github.com/uber), [`uber-go`](https://github.com/uber-go), [`uber-common`](https://github.com/uber-common). To improve developer cohesiveness and simplify access, the Cadence Core team has migrated all open-source repositories to the [`cadence-workflow`](https://github.com/cadence-workflow) organization.\\n\\nFor example, our main repository has moved from:\\n\\n\ud83d\udc49 [uber/cadence](https://github.com/cadence-workflow/cadence)\\n\\nTo its new home:\\n\\n\ud83d\udc49 [cadence-workflow/cadence](https://github.com/cadence-workflow/cadence)\\n\\nYou can find the full list of Cadence repositories here \ud83d\udc49 [orgs/cadence-workflow/repositories](https://github.com/orgs/cadence-workflow/repositories)\\n\\n\x3c!-- truncate --\x3e\\n\\nThis move reflects our continued commitment to growing the Cadence community and making the project even more accessible to contributors and users. Please update your bookmarks and links accordingly.\\n\\nThank you for being part of the Cadence journey! \ud83d\ude80"},{"id":"/zonal-isolation-v1/zonal-isolation-v1","metadata":{"permalink":"/Cadence-Docs/blog/zonal-isolation-v1/zonal-isolation-v1","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/zonal-isolation-v1/zonal-isolation-v1.md","source":"@site/blog/zonal-isolation-v1/zonal-isolation-v1.md","title":"Zonal Isolation for Cadence Workflows","description":"At Uber, we want to achieve regional resilience such that losing a zone within a region can be tolerated without requiring a cross-region failover. We also want to make sure that losing a zone only affects a subset of workload, at most, rather than everything. However, in Cadence-based systems, the workload in a region is distributed randomly across all workers in the region at a \u201ctask-level granularity\u201d, which means a workflow may be worked on by any worker in the region where the domain is active. To achieve this goal, we introduced Zonal Isolation for Cadence Workflows - a feature designed to pin workflows to the zone they are started in, so that zonal isolation can be achieved at a workflow-level.","date":"2024-10-14T00:00:00.000Z","tags":[{"inline":false,"label":"Deep Dives","permalink":"/Cadence-Docs/blog/tags/deep-dives","description":"Deep Dives tag description"},{"inline":false,"label":"Cadence Operations","permalink":"/Cadence-Docs/blog/tags/cadence-operations","description":"Cadence Operations tag description"}],"readingTime":7.985,"hasTruncateMarker":true,"authors":[{"name":"Zijian Chen","title":"Software Engineer @ Uber","url":"https://www.linkedin.com/in/zijian-chen-5868938b/","page":{"permalink":"/Cadence-Docs/blog/authors/shaddoll"},"socials":{"linkedin":"https://www.linkedin.com/in/zijian-chen-5868938b/","github":"https://github.com/Shaddoll"},"imageURL":"https://github.com/Shaddoll.png","key":"shaddoll"}],"frontMatter":{"title":"Zonal Isolation for Cadence Workflows","subtitle":"test","date":"2024-10-14T00:00:00.000Z","authors":"shaddoll","tags":["deep-dive","cadence-operations"]},"unlisted":false,"prevItem":{"title":"Cadence Repositories Have Moved!","permalink":"/Cadence-Docs/blog/2024/11/18/cadence-workflows-github-organization"},"nextItem":{"title":"Announcement: Cadence Helm Charts v0 Release","permalink":"/Cadence-Docs/blog/2024/10/01/announcing-cadence-helm-charts-v0"}},"content":"At Uber, we want to achieve regional resilience such that losing a zone within a region can be tolerated without requiring a cross-region failover. We also want to make sure that losing a zone only affects a subset of workload, at most, rather than everything. However, in Cadence-based systems, the workload in a region is distributed randomly across all workers in the region at a \u201ctask-level granularity\u201d, which means a workflow may be worked on by any worker in the region where the domain is active. To achieve this goal, we introduced Zonal Isolation for Cadence Workflows - a feature designed to pin workflows to the zone they are started in, so that zonal isolation can be achieved at a workflow-level.\\n\\n## What is Zonal Isolation for Cadence Workflows?\\nAt high-level, Zonal Isolation for Cadence Workflows can be thought in 2 levels:\\n\\n1. **Task-level isolation:** All decision tasks and activity tasks of a workflow are only processed by workers from the zone where the workflow was started\\n2. **Infrastructure-level isolation:** Within a regional Cadence cluster, workflows are handled by server instances in the same zone where they were started, and the corresponding data is stored in that zone as well.\\n\\nInfrastructure-level isolation is quite challenging to implement as it requires significant changes to the core design of the Cadence server. Due to the complexity involved, support for this feature is not planned for the foreseeable future.\\n\\nAs a result, the focus remains on achieving task-level zonal isolation outside the Cadence server, which offers a more practical and immediate way to improve system resilience. It provides the capability of ensuring that an unhealthy zone (i.e. bad deployment of workers) only affect a subset of workflows (started from a certain zone) rather than every workflow in a Cadence domain.\\n\\n\x3c!-- truncate --\x3e\\n\\n## How Zonal Isolation Works in Cadence?\\n\\n### Architecture\\nHere is what the architecture of a zonally isolated Cadence-based system looks like:\\n![zonal isolation overview](./zone-isolation.png)\\n*

Fig: Workflows started in one zone are only dispatched to workers from the same zone. Colors to emphasize pinning.

*\\n### Implementation\\n\\n#### Determine the zone of a workflow and workers\\n\\nTo ensure that tasks are dispatched to workers in the same zone as the workflows, we must identify the origin zone of both. The zone of a workflow is determined by the origin zone of the StartWorkflowExecution request, while the zone of workers is determined by the origin zone of the PollForDecisionTask and PollForActivityTask requests. There are three possible ways to determine the origin zone for these requests:\\n\\n- **Uber\'s Approach:** Let Cadence SDK set the origin zone in the headers of the requests before sending the request to Cadence.\\n- **Preferred Approach:** Get the origin zone of the requests from headers set by network infrastructure.\\n- Determine the origin zone of the requests from the zone of the cadence-frontend instance receiving the request, if the network layer has already achieved zonal isolation.\\n\\nThe 2nd approach is the ideal one, but Uber\'s network infrastructure doesn\'t provide such headers and the network layer is not ready for zonal isolation. As a result, we adopt the 1st approach. At Uber, we have internal libraries in Go and Java acting as wrappers around Cadence SDK injecting necessary configurations. These libraries have been updated to include the origin zone in the request headers using a header called `cadence-client-isolation-group`.\\n\\n#### How to dispatch tasks to workers from the same zone?\\nTo implement task-level isolation, we introduce a new dimension to the tasklist \u2014 **isolation group**. When a workflow is initiated, the origin zone of the workflow is stored in the database. Each time a decision or activity task is dispatched to cadence-matching, the workflow\'s origin zone is used as the isolation group for that task.\\n\\nWhen a worker sends a `PollForDecisionTask` or `PollForActivityTask` request to cadence-matching, the request is labeled with the worker\'s isolation group (i.e., the worker\'s zone). Tasks are then dispatched only to poller requests that have the same isolation group, ensuring that tasks are processed by workers in the same zone as the workflow\'s origin.\\n#### How to handle workflows from a drained zone?\\nIn the event of an outage, such as a bad deployment, customers may want to drain workers from a specific zone to mitigate the impact. There are two types of drains that can occur:\\n1. **Implicit drain:** Workers from a zone completely stop operating, either due to failures or manual shutdowns.\\n2. **Explicit drain:** Customers explicitly mark workers from a zone as drained.\\n\\nWithin cadence-matching, a list of pollers is maintained for each tasklist, tracking the zone from which the pollers originate. An implicit drain can be detected by checking whether there are any active pollers from a particular zone. If a zone is drained (either explicitly or implicitly), workflows that were started in that zone will be reassigned and spread to workers in the remaining healthy zones.\\n##### How to drain a zone explicitly?\\nExplicitly draining a zone can be done at two levels:\\n1. **Domain-level drain:** This applies to a specific domain, allowing the zone to be drained only for workflows within that domain.\\n2. **Cluster-level drain:** This applies to the entire Cadence cluster, draining the zone for all domains and workflows within the cluster.\\n\\nFor domain-level drain, the draining status is stored in [`domains`](https://github.com/cadence-workflow/cadence/blob/v1.2.13/schema/cassandra/cadence/schema.cql#L412) table. For cluster-level drain, the status is stored in [`cluster_config`](https://github.com/cadence-workflow/cadence/blob/v1.2.13/schema/cassandra/cadence/schema.cql#L498) table.\\n\\n## How to enable Zonal Isolation?\\n### Server Update\\nIn order to enable this feature, please upgrade Cadence server to [v1.2.1](https://github.com/cadence-workflow/cadence/releases/tag/v1.2.1) or later.\\n\\n**NOTE:** If you\'re not using the provided main binary located in `cmd/server`, you must adopt this [middleware](https://github.com/cadence-workflow/cadence/blob/v1.2.1/common/rpc/middleware.go#L188). Depends on the appoach to [determine the origin zone of requests](#determine-the-zone-of-a-workflow-and-workers), you can adopt this [middleware](https://github.com/cadence-workflow/cadence/blob/v1.2.1/common/rpc/middleware.go#L229) or build your own middleware using [`partition.ContextWithConfig`](https://github.com/cadence-workflow/cadence/blob/v1.2.1/common/partition/context.go#L42) function to inject origin zone into the context.\\n\\nThis feature is controlled by 2 dynamic config properties.\\n- `system.allIsolationGroups`: This property provides the list of available zones within a region.\\n- `system.enableTasklistIsolation`: This property enables Zonal Isolation at domain level.\\nIt\u2019s important to note that any update to the `system.allIsolationGroups` property requires a restart of the cadence-matching service for the changes to take effect. This ensures that the new zone configuration is properly loaded and applied. However, the `system.enableTasklistIsolation` property can be updated dynamically without requiring a restart, making it more flexible for enabling or disabling Zonal Isolation on a per-domain basis.\\n\\nAn example configuration using the file based dynamic configuration could look like this:\\n```yaml\\nsystem.allIsolationGroups:\\n- value: []\\n constraints: {}\\n- value: [\\"dca1\\", \\"dca2\\", \\"dca3\\"]\\n constraints:\\n clusterName: prod-dca\\n- value: [\\"phx1\\", \\"phx2\\", \\"phx3\\"]\\n constraints:\\n clusterName: prod-phx\\nsystem.enableTasklistIsolation:\\n- value: false\\n constraints: {}\\n- value: true\\n constraints:\\n domainName: samples-domain\\n```\\nIn this example, the Cadence cluster spans two regions, each containing three zones: `dca1`, `dca2`, `dca3` in the `dca` region and `phx1`, `phx2`, `phx3` in the `phx` region. Zonal isolation is enabled only for the `samples-domain`, while it remains disabled for other domains.\\n\\n### SDK Update\\nNOTE: This update is only necessary if you\'re using the 1st approach to [determine the origin zone of requests](#determine-the-zone-of-a-workflow-and-workers).\\n\\nTo support Zonal Isolation, please upgrade your SDK versions:\\n- **Go SDK:** Upgrade to [v1.0.2](https://github.com/cadence-workflow/cadence-go-client/releases/tag/v1.0.2) or later.\\n- **Java SDK:** Upgrade to [v3.9.0](https://github.com/cadence-workflow/cadence-java-client/releases/tag/v3.9.0) or later.\\n\\n**For Java SDK users**, set the [`isolationGroup`](https://github.com/cadence-workflow/cadence-java-client/blob/v3.9.0/src/main/java/com/uber/cadence/serviceclient/ClientOptions.java#L83) field to the zone of the instance when creating `serviceClient`.\\n\\n**For Go SDK users**, set the [`isolationGroup`](https://github.com/cadence-workflow/cadence-go-client/blob/v1.0.2/internal/worker.go#L132) field to the zone of the instance when creating `Worker`. Additionally, you need to use [this method](https://github.com/cadence-workflow/cadence-go-client/blob/v1.0.2/isolationgroup/wrapper.go#L29C39-L29C70) to wrap `workflowserviceclient.Interface`.\\n## How to drain a zone explicitly?\\nDrains can be done via the [Admin APIs](https://github.com/cadence-workflow/cadence-idl/blob/50a4ee241e50c6baab8e5d47540b176c5ee022a4/proto/cadence-workflow/cadence/admin/v1/service.proto#L125) of cadence-frontend or CLI.\\n\\nYou can check the help message for the CLI by running:\\n```bash\\ncadence admin isolation-groups -h\\n```\\n## Monitoring\\nA new metric is introduced to help detect the leakage of tasks and skewness of traffic.\\n\\n`isolation_task_matches_per_tl`: This is a counter that counts the number of tasks polled by workers. The metric is tagged with the domain, tasklist name, tasklist type, the origin zone of the workflow and the origin zone of the worker polling the task.\\n\\nThis metric can be used in the following ways:\\n\\n**Detecting task leakage:** By grouping tasks based on the origin zones of both the workflows and workers, you can identify tasks that have leaked, i.e., tasks assigned to workers in zones different from the workflow\'s origin zone.\\n\\n**Identifying traffic skewness:** By grouping tasks based solely on the origin zones of workflows, you can determine if traffic is disproportionately distributed among the zones, helping to detect any uneven load or traffic imbalance across zones.\\n\\n## Status at Uber\\n- We launched this feature at Uber in July 2023. More than 100 domains have Zonal Isolation enabled.\\n- However, as of 2024, the rollout of Zonal Isolation is paused due to a traffic skewness issue:\\n - Some customers have highly skewed traffic that some zones have more workflows than other zones, but the number of workers are evenly distributed in all zones. Enabling Zonal Isolation for the customers will decrease the utilization of their workers and may cause high latency for the customers.\\n\\n## Next Step\\nCurrently, Zonal Isolation is implemented as **hard isolation**, where tasks are strictly limited to the same zone as the originating workflow. To address the traffic skewness issue, we are working on iterating this feature to introduce **soft isolation**. This relaxed version will allow for some task leakage between zones if traffic skewness is detected, ensuring better worker utilization and reducing latency.\\n\\nThis enhancement is one of our major ongoing projects, and we plan to share more details in a future blog post once it is launched."},{"id":"/2024/10/01/announcing-cadence-helm-charts-v0","metadata":{"permalink":"/Cadence-Docs/blog/2024/10/01/announcing-cadence-helm-charts-v0","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2024-10-01-announcing-cadence-helm-charts-v0.md","source":"@site/blog/2024-10-01-announcing-cadence-helm-charts-v0.md","title":"Announcement: Cadence Helm Charts v0 Release","description":"We\u2019ve heard your feedback: deploying Cadence has been a challenge, especially with limited documentation on operational aspects. So far, we\u2019ve only provided a few docker compose files to help you get started on a development machine. However, deploying and managing Cadence at scale requires a deep understanding of underlying services, configurations and their dependencies.","date":"2024-10-01T00:00:00.000Z","tags":[{"inline":false,"label":"Announcement","permalink":"/Cadence-Docs/blog/tags/announcements","description":"Announcement tag description"}],"readingTime":2.6,"hasTruncateMarker":true,"authors":[{"name":"Taylan Isikdemir","title":"Sr. Staff Software Engineer @ Uber","url":"https://www.linkedin.com/in/taylan-isikdemir","page":{"permalink":"/Cadence-Docs/blog/authors/taylanisikdemir"},"socials":{"linkedin":"https://www.linkedin.com/in/taylan-isikdemir","github":"https://github.com/taylanisikdemir"},"imageURL":"https://github.com/taylanisikdemir.png","key":"taylanisikdemir"}],"frontMatter":{"title":"Announcement: Cadence Helm Charts v0 Release","date":"2024-10-01T00:00:00.000Z","authors":"taylanisikdemir","tags":["announcement"]},"unlisted":false,"prevItem":{"title":"Zonal Isolation for Cadence Workflows","permalink":"/Cadence-Docs/blog/zonal-isolation-v1/zonal-isolation-v1"},"nextItem":{"title":"Minimizing blast radius in Cadence: Introducing Workflow ID-based Rate Limits","permalink":"/Cadence-Docs/blog/2024/09/05/workflow-specific-rate-limits"}},"content":"We\u2019ve heard your feedback: deploying Cadence has been a challenge, especially with limited documentation on operational aspects. So far, we\u2019ve only provided a few [docker compose files](https://github.com/cadence-workflow/cadence/tree/master/docker) to help you get started on a development machine. However, deploying and managing Cadence at scale requires a deep understanding of underlying services, configurations and their dependencies.\\n\\nTo address these challenges, we\u2019re launching several initiatives to make it easier to deploy and operate Cadence clusters. These include deployment specs for common scenarios, monitoring dashboards, alerts, runbooks, and more comprehensive documentation.\\n\\n\x3c!-- truncate --\x3e\\n\\n## Introducing Cadence Kubernetes Helm Chart v0\\n\\nToday, we are happy to announce the release of [Cadence Kubernetes Helm Chart v0](https://github.com/cadence-workflow/cadence-charts). This will be the starting point for standardizing Cadence deployments on Kubernetes. We chose Kubernetes because it\'s the leading compute platform, but Cadence remains flexible and can run on any infrastructure.\\n\\n## How to Get Started\\n\\n[Helm](https://helm.sh) must be installed to use the charts. Please refer to Helm\'s [documentation](https://helm.sh/docs) to get started.\\n\\nOnce Helm has been set up correctly, add the repo as follows:\\n\\n```bash\\nhelm repo add cadence https://uber.github.io/cadence-charts\\n```\\n\\nIf you had already added this repo earlier, run `helm repo update` to retrieve the latest versions of the packages. You can then run `helm search repo cadence` to see the charts.\\n\\nTo install the cadence chart:\\n```bash\\nhelm install my-cadence cadence/cadence\\n```\\n\\nTo uninstall the chart:\\n```bash\\nhelm delete my-cadence\\n```\\n\\nSee [CONTRIBUTING.md](https://github.com/cadence-workflow/cadence-charts/blob/main/CONTRIBUTING.md) for details on how to validate the deployment by running sample workflows.\\n\\n## Current State of the Chart\\n\\nThere were a few community-created Cadence Helm charts but they were not actively maintained and had a few glitches that Cadence team @Uber wasn\'t able to provide support for. With the introduction of the new official Cadence Helm chart, our team is committed to provide support and evolve it with input from community.\\n\\nThe v0 chart contains only the basics at the moment:\\n- Cadence backend services as separate deployments: frontend, history, matching, worker.\\n- Customizable replica counts and resource limitations.\\n- Customizable dynamic config as a configmap.\\n- A single instance ephemeral Cassandra container. This is included so that no external dependency is required to get started. Ideally you should have your own external (hosted or managed) DB instance that you can specify in values.yaml.\\n- The chart comes with `cadence:master-auto-setup` as the default image and capable of setting up Cassandra DB schema on first installation.\\n\\nWhat is (obviously) missing:\\n- Support for advanced visibility stores like Elasticsearch or Pinot.\\n- Support for persistent plugins configurations besides Cassandra.\\n- Support for fully customizable service config via values.yaml.\\n- Metrics integration with Prometheus (and more out of the box prometheus dashboards)\\n- Custom annotations/lables/tolerations etc.\\n- Support for ingress\\n\\n\\n## Next Steps\\n\\nSince this is an early release, we would love to hear from you. Feel free to start [discussions](https://github.com/cadence-workflow/cadence-charts/discussions) or report [issues](https://github.com/cadence-workflow/cadence-charts/issues).\\n\\nAlso check out the [contribution guideline](https://github.com/cadence-workflow/cadence-charts/blob/main/CONTRIBUTING.md) if you are interested to contribute. Don\'t hesitate to send a PR and ping us over slack if we miss it.\\n\\nP.S. Huge thanks to our summer intern [Nikita Bhardwaj](https://github.com/nikitab7) for kickstarting the Cadence Helm charts initiative."},{"id":"/2024/09/05/workflow-specific-rate-limits","metadata":{"permalink":"/Cadence-Docs/blog/2024/09/05/workflow-specific-rate-limits","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2024-09-05-workflow-specific-rate-limits.md","source":"@site/blog/2024-09-05-workflow-specific-rate-limits.md","title":"Minimizing blast radius in Cadence: Introducing Workflow ID-based Rate Limits","description":"At Uber, we run several big multitenant Cadence clusters with hundreds of domains in each. The clusters being multi-tenant means potential noisy neighbor effects between domains.","date":"2024-09-05T00:00:00.000Z","tags":[{"inline":false,"label":"Deep Dives","permalink":"/Cadence-Docs/blog/tags/deep-dives","description":"Deep Dives tag description"}],"readingTime":6.335,"hasTruncateMarker":true,"authors":[{"name":"Jakob Haahr Taankvist","title":"Software Engineer II @ Uber","url":"https://www.linkedin.com/in/jakob-taankvist/","page":{"permalink":"/Cadence-Docs/blog/authors/jakobht"},"socials":{"linkedin":"https://www.linkedin.com/in/jakob-taankvist/","github":"https://github.com/jakobht"},"imageURL":"https://github.com/jakobht.png","key":"jakobht"}],"frontMatter":{"title":"Minimizing blast radius in Cadence: Introducing Workflow ID-based Rate Limits","date":"2024-09-05T00:00:00.000Z","authors":"jakobht","tags":["deep-dive"]},"unlisted":false,"prevItem":{"title":"Announcement: Cadence Helm Charts v0 Release","permalink":"/Cadence-Docs/blog/2024/10/01/announcing-cadence-helm-charts-v0"},"nextItem":{"title":"2024 Cadence Yearly Roadmap Update","permalink":"/Cadence-Docs/blog/2024/07/11/2024-07-11-yearly-roadmap-update/yearly-roadmap-update"}},"content":"At Uber, we run several big multitenant Cadence clusters with hundreds of domains in each. The clusters being multi-tenant means potential [noisy neighbor](https://en.wikipedia.org/wiki/Cloud_computing_issues#Performance_interference_and_noisy_neighbors) effects between domains.\\n\\nAn essential aspect of avoiding this is managing how workflows interact with our infrastructure to prevent any single workflow from causing instability for the whole cluster. To this end, we are excited to introduce Workflow ID-based rate limits \u2014 a new feature designed to protect our clusters from problematic workflows and ensure stability across the board.\\n\\n## Why Workflow ID-based Rate Limits?\\nWe already have rate limits for how many requests can be sent to a domain. However, since Cadence is sharded on the workflow ID, a user-provided input, an overused workflow with a particular id might overwhelm a shard by making too many requests. There are two main ways this happens:\\n\\n1. A user starts, or signals the same workflow ID too aggressively,\\n2. A workflow starts too many activities over a short period of time (e.g. thousands of activities in seconds).\\n\\n\x3c!-- truncate --\x3e\\n\\nFor example, the following workflow would cause issues for Cadence. It would create huge amounts of traffic to a single shard in a very small time frame:\\n\\n```go\\nfunc Workflow(ctx workflow.Context, input sampleInput) (string, error) {\\n\\t...\\n\\tfor _, elem := range longList {\\n\\t\\terr := workflow.ExecuteActivity(ctx, QuickActivity, elem).Get(ctx, nil)\\n\\t}\\n\\t...\\n}\\n```\\n\\nThis heavy load creates what we call _hot shards_. Hot shards degrade performance not just for the workflow causing the issue, but for all workflows that interact with the affected shard. This can grow to a point where the whole cluster becomes unstable.\\n\\nNow, with Workflow ID-based rate limits, we limit the number of external calls and actions per second for each individual workflow, reducing the blast radius (impact on the cluster) of a badly behaved workflow to an absolute minimum where only the offending workflow is impacted.\\n\\n## Why _not_ Shard Rate Limits?\\n\\nAn obvious question is \u201cwhy don\u2019t we rate limit the requests to the shard?\u201d. After all, the shard is what we want to protect. We have several reasons for choosing to rate limit the workflow ID instead of the shard:\\n\\n- __Hashing__ The workflow ID to shard is random. This means that rate limiting a workflow is a good proxy for rate limiting a shard. The likelihood that many requests from different workflows hit the same shard is very low.\\n- __Communication__ It is easy to explain to a user that their domain is rate limited because they are sending too many requests to a specific workflow ID. Shards are an internal implementation detail that users should not have to worry about.\\n- __Noisy neighbors__ Shards are shared across the different domains in a Cadence cluster. If a user is sending too many requests to a shard, we would choose to rate limit requests to that shard. Since other users in other domains are also using the shard, they will also be rate limited.\\nRate limiting users of a healthy domain because of requests from a completely different domain goes against the isolation the domains are meant to ensure.\\n\\n## How Does It Work?\\nWorkflow ID-based rate limits are set for all workflow IDs in a domain. If the external limit for a domain is e.g. set to 100 it means that any single workflow ID in that domain can at most be signaled 100 times a second. The rate limits are implemented in two main areas:\\n\\n1. __External Calls__ Cadence limits the number of requests per second for each workflow ID, which includes operations like starting, querying, or signaling a workflow. If this limit is exceeded, a ServiceBusyError with message \u201cToo many requests for the workflow ID\u201d is triggered, indicating that the rate limit for the workflow has been reached.\\n\\n2. __Actions Within a Workflow__ This limit controls the number of tasks processed per second within a workflow, focusing on managing decision tasks and activity tasks. When these limits are reached, Cadence slows down task processing without requiring any intervention from the user, though they might notice an increase in task execution time, eventually causing timeouts.\\n\\n### How do I Enable It?\\n\\nThe limits are controlled using six dynamic config properties, three for the internal limits, and a corresponding three for the external limits, all with a domain filter, so the limits can be controlled for each domain.\\n\\n- history.workflowIDCacheInternalEnabled\\\\\\n history.workflowIDCacheExternalEnabled\\n - Controls if the statistics needed to do the rate limiting should be collected. The feature keeps an in-memory record in the history service for each workflow ID.\\n- history.workflowIDInternalRPS\\\\\\n history.workflowIDExternalRPS\\n - Sets the number of requests allowed per second per workflow in a particular domain.\\n- history.workflowIDExternalRateLimitEnabled\\\\\\n history.workflowIDInternalRateLimitEnabled\\n - Set whether rate limiting should happen. Setting this to false allows us to see which domains _would have_ been rate limited and adjust them before enforcing the limits.\\n\\nAn example configuration using the file based dynamic configuration could look like this:\\n\\n```yaml\\nhistory.workflowIDCacheExternalEnabled:\\n- value: true\\n constraints: {}\\nhistory.workflowIDExternalRateLimitEnabled:\\n- value: false\\n constraints:\\n domainName: samples-domain\\n- value: true\\n constraints: {}\\nhistory.workflowIDExternalRPS:\\n- value: 100\\n constraints: {}\\n```\\n\\nHere only the external rate limits are enabled. The internal rate limits have the same structure. We see that \u200cthe rate limiting is enabled for all domains, with a max RPS of 100. The domain samples-domain is however running in shadow mode, so its requests are not rate limited, but metrics and logs are still emitted.\\n\\nThe exact RPS to set for a specific domain and cluster, depends on many things, such as the number of shards, the selected persistent layer, the general load on the cluster etc.\\n\\n## Monitoring and Troubleshooting\\n\\nThe new feature introduces both new metrics and new logs. The new logs help us find workflows that are being rate limited, while the new metrics let us see if domains are being rate limited, and how close to being rate limited they are.\\n\\nThere are four new metrics, two for internal limits and two corresponding metrics for external limits, all emitted from history.\\n\\n- workflow_id_external_requests_ratelimited\\\\\\n workflow_id_internal_requests_ratelimited\\n - This is a counter that counts the number of rate limited requests. The metric is tagged with the domain, so we can track the rate limiting per domain.\\n- workflow_id_external_requests_max_requests_per_second\\\\\\n workflow_id_internal_requests_max_requests_per_second\\n - This is a timer metric. The upper series gives the max number of requests to a single workflow ID. This is again tagged with the domain, so we can for each domain see how close its workflows are to the limit.\\n\\nThese metrics let us monitor and alert on the new rate limits. Additionally, when breaking a rate limit, the history service will emit an info log with the message \u201cRate limiting workflowID\u201d, these logs are tagged with the workflowID that is being limited, so it is easy to find the offending workflow. An example log would look like this:\\n\\n```json\\n{\\n \\"level\\":\\"info\\",\\n \\"ts\\":\\"2024-09-02T08:47:12.843Z\\",\\n \\"msg\\":\\"Rate limiting workflowID\\",\\n \\"service\\":\\"cadence-history\\",\\n \\"request-type\\":\\"external\\",\\n \\"wf-domain-id\\":\\"fc0c7fcb-5796-4c80-b0d7-10bbbc66614e\\",\\n \\"wf-domain-name\\":\\"samples-domain\\",\\n \\"wf-id\\":\\"test\\",\\n \\"logging-call-at\\":\\"cache.go:175\\"\\n}\\n```\\n\\n## Conclusion\\n\\nImplementing these rate limits highly improves the reliability of a Cadence cluster, as users now cannot send too many requests to a single shard. This fine-grained control helps in maintaining optimal performance and enhances the ability to forecast and mitigate potential issues before they impact the service.\\n\\nWorkflow ID-based rate limits are a significant step forward in our ongoing effort to provide a robust and efficient workflow management service. By preventing hot shards and ensuring equitable resource distribution, we can offer more reliable performance, even under peak loads. We encourage all Cadence users to familiarize themselves with these new limits and adjust their workflow configurations to achieve optimal results."},{"id":"/2024/07/11/2024-07-11-yearly-roadmap-update/yearly-roadmap-update","metadata":{"permalink":"/Cadence-Docs/blog/2024/07/11/2024-07-11-yearly-roadmap-update/yearly-roadmap-update","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2024-07-11-yearly-roadmap-update/2024-07-11-yearly-roadmap-update.md","source":"@site/blog/2024-07-11-yearly-roadmap-update/2024-07-11-yearly-roadmap-update.md","title":"2024 Cadence Yearly Roadmap Update","description":"Introduction","date":"2024-07-11T00:00:00.000Z","tags":[{"inline":false,"label":"Roadmap","permalink":"/Cadence-Docs/blog/tags/roadmap","description":"Roadmap tag description"},{"inline":false,"label":"Deep Dives","permalink":"/Cadence-Docs/blog/tags/deep-dives","description":"Deep Dives tag description"}],"readingTime":16.31,"hasTruncateMarker":true,"authors":[{"name":"Ender Demirkaya","title":"Senior Manager at Uber, Cadence. Author of the Software Engineering Handbook","url":"https://www.linkedin.com/in/enderdemirkaya/","page":{"permalink":"/Cadence-Docs/blog/authors/enderdemirkaya"},"socials":{"linkedin":"https://www.linkedin.com/in/enderdemirkaya/","github":"https://github.com/demirkayaender"},"imageURL":"https://github.com/demirkayaender.png","key":"enderdemirkaya"}],"frontMatter":{"title":"2024 Cadence Yearly Roadmap Update","date":"2024-07-11T00:00:00.000Z","authors":"enderdemirkaya","tags":["roadmap","deep-dive"]},"unlisted":false,"prevItem":{"title":"Minimizing blast radius in Cadence: Introducing Workflow ID-based Rate Limits","permalink":"/Cadence-Docs/blog/2024/09/05/workflow-specific-rate-limits"},"nextItem":{"title":"Cadence non-derministic errors common question Q&A (part 1)","permalink":"/Cadence-Docs/blog/2024/02/15/cadence-non-deterministic-common-qa"}},"content":"## Introduction\\n\\nIf you haven\u2019t heard about Cadence, this section is for you. In a short description, Cadence is a code-driven workflow orchestration engine. The definition itself may not tell enough, so it would help splitting it into three parts:\\n\\n* What\u2019s a workflow? (everyone has a different definition)\\n* Why does it matter to be code-driven?\\n* Benefits of Cadence\\n\\n### What is a Workflow?\\n\\n![workflow.png](./2024-yearly-update/workflow.png)\\n\\nIn the simplest definition, it is \u201ca multi-step execution\u201d. Step here represents individual operations that are a little heavier than small in-process function calls. Although they are not limited to those: it could be a separate service call, processing a large dataset, map-reduce, thread sleep, scheduling next run, waiting for an external input, starting a sub workflow etc. It\u2019s anything a user thinks as a single unit of logic in their code. Those steps often have dependencies among themselves. Some steps, including the very first step, might require external triggers (e.g. button click) or schedules. In the more broader meaning, any multi-step function or service is a workflow in principle.\\n\\n\x3c!-- truncate --\x3e\\n\\nWhile the above is a more correct way to define workflows, specialized workflows are more widely known: such as data pipelines, directed acyclic graphs, state machines, cron jobs, (micro)service orchestration, etc. This is why typically everyone has a different workflow meaning in mind. Specialized workflows also have simplified interfaces such as UI, configs or a DSL (domain specific language) to make it easy to express the workflow definition.\\n\\n### Code-Driven Workflows\\n\\nOver time, any workflow interface evolves to support more scenarios. For any non-code (UI, config, DSL) technology, this means more APIs, concepts and tooling. However, eventually, the technology\u2019s capabilities will be limited by its interface itself. Otherwise the interface will get more complicated to operate.\\n\\nWhat happens here is users love the seamless way of creating workflow applications and try to fit more scenarios into it. Natural user tendency is to be able to write any program with such simplicity and confidence.\\n\\nGiven this natural evolution of workflow requirements, it\u2019s better to have a code-driven workflow orchestration engine that can meet any future needs with its powerful expressiveness. On top of this, it is ideal if the interface is seamless, where engineers learn as little as possible and change almost nothing in their local code to write a distributed and durable workflow code. This would virtually remove any limitation and enable implementing any service as a workflow. This is what Cadence aims for.\\n\\n### Benefits\\n\\n![cadence-benefits.png](./2024-yearly-update/cadence-benefits.png)\\n\\nWith Cadence, many overheads that need to be built for any well-supported service come for free. Here are some highlights (see [cadenceworkflow.io](http://cadenceworkflow.io)):\\n\\n* Disaster recovery is supported by default through data replication and failovers\\n* Strong multi tenancy support in Cadence clusters. Capacity and traffic management.\\n* Users can use Cadence APIs to start and interact with their workflows instead of writing new APIs for them\\n* They can schedule their workflows (distributed cron, scheduled start) or any step in their workflows\\n* They have tooling to get updates or cancel their workflows.\\n* Cadence comes with default metrics and logging support so users already get great insights about their workflows without implementing any observability tooling.\\n* Cadence has a web UI where users can list and filter their workflows, inspect workflow/activity inputs and outputs.\\n* They can scale their service just like true stateless services even though their workflows maintain a certain state.\\n* Behavior on failure modes can easily be configured with a few lines, providing high reliability.\\n* With Cadence testing capabilities, they can write unit tests or test against production data to prevent backward incompatibility issues.\\n* \u2026\\n\\n## Project Support\\n\\n### Team\\n\\nToday the Cadence team comprises 26 people. We have people working from Uber\u2019s US offices (Seattle, San Francisco and Sunnyvale) as well as Europe offices (Aarhus-DK and Amsterdam-NL).\\n\\n### Community\\n\\nCadence is an actively built open source project. We invest in both our internal and open source community ([Slack](http://t.uber.com/cadence-slack), [Github](https://github.com/cadence-workflow/cadence/issues)), responding to new features and enhancements.\\n\\n### Scale\\n\\nIt\u2019s one of the most popular platforms at Uber executing ~100K workflow updates per second. There are about 30 different Cadence clusters, several of which serve hundreds of domains. There are ~1000 domains (use cases) varying from tier 0 (most critical) to tier 5 scenarios.\\n\\n### Managed Solutions\\n\\nWhile Uber doesn\u2019t officially sell a managed Cadence solution, there are companies (e.g. [Instaclustr](https://www.instaclustr.com/platform/managed-cadence/)) in our community that we work closely with selling Managed Cadence. Due to efficiency investments and other factors, it\u2019s significantly cheaper than its competitors. It can be run in users\u2019 on-prem machines or their cloud service of choice. Pricing is defined based on allocated hosts instead of number of requests so users can get more with the same resources by utilizing multi-tenant clusters.\\n\\n## After V1 Release\\n\\nLast year, around this time we announced [Cadence V1](https://www.uber.com/blog/announcing-cadence/) and shared our roadmap. In this section we will talk about updates since then. At a high level, you will notice that we continue investing in high reliability and efficiency while also developing new features.\\n\\n### Frequent Releases\\n\\nWe announced plans to make more frequent releases last year and started making more frequent releases. Today we aim to release biweekly and sometimes release as frequently as weekly. About the format, we listened to our community and heard about having too frequent releases potentially being painful. Therefore, we decided to increment the patch version with releases while incrementing the minor version close to quarterly. This helped us ship much more robust releases and improved our reliability. Here are some highlights:\\n\\n### Zonal Isolation\\n\\nCadence clusters have already been regionally isolated until this change. However, in the cloud, inter-zone communications matter as they are more expensive and their latencies are higher. Zones can individually have problems without impacting other cloud zones. In a regional architecture, a single zone problem might impact every request; however, with zonal isolation traffic from a zone with issues can easily be failed over to other zones, eliminating its impact on the whole cluster. Therefore, we implemented zonal isolation keeping domain traffic inside a single zone to help improve efficiency and reliability.\\n\\n### Narrowing Blast Radius\\n\\nWhen there are issues in a Cadence cluster, it\u2019s often from a single misbehaving workflow. When this happens the whole domain or the cluster could have had issues until the specific workflow is addressed. With this change, we are able to contain the issue only to the offending workflow without impacting others. This is the narrowest blast radius possible.\\n\\n### Async APIs\\n\\nAt Uber, there are many batch work streams that run a high number of workflows (thousands to millions) at the same time causing bottlenecks for Cadence clusters, causing noisy neighbor issues. This is because StartWorkflow and SignalWorkflow APIs are synchronous, which means when Cadence acks the user requests are successfully saved in their workflow history.\\n\\nEven after successful initiations, users would then need to deal with high concurrency. This often means constant worker cache thrashing, followed by history rebuilds at every update, increasing workflow execution complexity to O(n^2) from O(n). Alternatively, they would need to quickly scale out and down their service hosts in a very short amount of time to avoid this.\\n\\nWhen we took a step back and analyzed such scenarios, we realized that users simply wanted to \u201ccomplete N workflows (jobs) in K time\u201d. The guarantees around starts and signals were not really important for their use cases. Therefore, we implemented async versions of our sync API, by which we can control the consumption rate, guaranteeing the fastest execution with no disruption in the cluster.\\n\\nLater this year, we plan to expand this feature to cron workflows and timers as well.\\n\\n### Pinot as Visibility Store\\n\\n[Apache Pinot](https://pinot.apache.org/) is becoming popular due to its cost efficient nature. Several teams reported significant savings by changing their observability storage to Pinot. Cadence now has a Pinot plugin for its visibility store. We are still rolling out this change. Latencies and cost savings will be shared later.\\n\\n### Code Coverage\\n\\nWe have received many requests from our community to actively contribute to our codebase, especially after our V1 release. While we have been already collaborating with some companies, this is a challenge with individuals who are just learning about Cadence. One of the main reasons was to avoid bugs that can be introduced.\\n\\nWhile Cadence has many integration tests, its unit test coverage was lower than desired. With better unit test coverage we can catch changes that break previous logic and prevent them getting into the main branch. Our team covered additional 50K+ lines in various Cadence repos. We hope to bring our code coverage to 85%+ by the end of year so we can welcome such inquiries a lot easier.\\n\\n### Replayer Improvements\\n\\nThis is still an ongoing project. As mentioned in our V1 release, we are revisiting some core parts of Cadence where less-than-ideal architectural decisions were made in the past. Replayer/shadower is one of such parts. We have been working on improving its precision, eliminating false negatives and positives.\\n\\n### Global Rate Limiters\\n\\nCadence rate limiters are equally distributed across zones and hosts. However, when the user\'s traffic is skewed, rate limits can get activated even though the user has more capacity. To avoid this, we built global rate limiters. This will make rate limits much more predictable and capacity management a lot easier.\\n\\n### Regular Failover Drills\\n\\nCadence has been performing monthly regional and zonal failover drills to ensure its failover operations are working properly in case we need it. We are failing over hundreds of domains at the same time to validate the scale of this operation, capacity elasticity and correctness of workflows.\\n\\n### Cadence Web v4\\n\\nWe are migrating Cadence web from Vue.js to React.js to use a more modern infrastructure and to have better feature velocity. We are about 70% complete with this migration and hope to release the new version of it soon.\\n\\n### Code Review Time Non-determinism Checks\\n\\n(This is an internal-only feature that we hope to release soon) Cadence non-determinism errors and versioning were common pain points for our customers. There are available tools but they require ongoing effort to validate. We have built a tool that generates a shadower test with a single line command (one time only operation) and continuously validates any code change against production data.\\n\\nThis feature reduced the detect-and-fix time from days/weeks to minutes. Just by launching this feature to the domains with the most non-determinism errors, the number of related incidents reduced by 40%. We have already blocked 500+ diffs that would potentially impact production negatively. This boosted our users\u2019 confidence in using Cadence.\\n\\n### Domain Reports\\n\\n(This is an internal-only feature that we hope to release soon) We are able to detect potential issues (bugs, antipatterns, inefficiencies, failures) with domains upon manual investigation. We have automated this process and now generate reports for each domain. This information can be accessed historically (to see the progression over time) and on-demand (to see the current state). This has already driven domain reliability and efficiency improvements.\\n\\nThis feature and above are at MVP level where we plan to generalize, expand and release for open source soon. In the V1 release, we have mentioned that we would build certain features internally first to be able to have enough velocity, to see where they are going and to make breaking changes until it\u2019s mature.\\n\\n### Client Based Migrations\\n\\nWith 30 clusters and ~1000 domains in production, migrating a domain from a cluster to another became a somewhat frequent operation for Cadence. While this feature is mostly automated, we would like to fully automate it to a level that this would be a single click or command operation. Client based migrations (as opposed to server based ones) give us big flexibility that we can have migrations from many to many environments at the same time. Each migration happens in isolation without impacting any other domain or the cluster.\\n\\nThis is an ongoing project where remaining parts are migrating long running workflows faster and seamless technology to technology migrations even if the \u201cfrom-technology\u201d is not Cadence in the first place. There are many users that migrated from Cadence-like or different technologies to Cadence so we hope to remove the repeating overhead for such users.\\n\\n## Roadmap (Next Year)\\n\\nOur priorities for next year look similar with reliability, efficiency, and new features as our focus. We have seen significant improvements especially in our users\u2019 reliability and efficiency on top of the improvements in our servers. This both reduces operational load on our users and makes Cadence one step closer to being a standard way to build services. Here is a short list of what\'s coming over the next 12 months:\\n\\n### Database efficiency\\n\\nWe are increasing our investment in improving Cadence\u2019s database usage. Even though Cadence\u2019s cost looks a lot better compared to the same family of technologies, it can still be significantly improved by eliminating certain bottlenecks coming from its original design.\\n\\n### Helm Charts\\n\\nWe are grateful to the Cadence community for introducing and maintaining our Helm charts for operating Cadence clusters. We are taking its ownership so it can be officially released and tested. We expect to release this in 2024.\\n\\n### Dashboard Templates\\n\\nDuring our tech talks, demos and user talks, we have received inquiries about what metrics care about. We plan to release templates for our dashboards so our community would look at a similar picture.\\n\\n### Client V2 Modernization\\n\\nAs we announced last year that we plan to make breaking changes to significantly improve our interfaces, we are working on modernizing our client interface.\\n\\n### Higher Parallelization and Prioritization in Task Processing\\n\\nIn an effort to have better domain prioritization in multitenant Cadence clusters, we are improving our task processing with higher parallelization and better prioritization. This is a lot better model than just having domains with defined limits. We expect to provide more resources to high priority domains during their peak hours while allowing low priority domains to consume much bigger resources than allocated during quiet times.\\n\\n### Timer and Cron Burst Handling\\n\\nAfter addressing start and signal burst scenarios, we are continuing with bursty timers and cron jobs. Many users set their schedules and timers for the same second with the intention of being able to finish N jobs within a certain amount of time. Current scheduling design isn\u2019t friendly for such intents and high loads can cause temporary starvation in the cluster. By introducing better batch scheduling support, clusters can continue with no disruption while timers are processed in the most efficient way.\\n\\n### High zonal skew handling\\n\\nFor users operating in their own cloud and having multiple independent zones in every region, zonal skews can be a problem and can create unnecessary bottlenecks when Zonal Isolation feature is enabled. We are working on addressing such issues to improve task matching across zones when skew is detected.\\n\\n### Tasklist Improvements\\n\\nWhen a user scenario grows, there are many knobs that need to be manually adjusted. We would like to automatically partition and smartly forward tasks to improve tasklist efficiency significantly to avoid backlogs, timeouts and hot shards.\\n\\n### Shard Movement/Assignment Improvements\\n\\nCadence shard movements are based on consistent hash and this can be a limiting factor for many different reasons. Certain hosts can end up getting unlucky by having many shards, or having heavy shards. During deployments we might observe a much higher number of shard movements than desired, which reduces the availability. With improved shard movements and assignments we can have more homogenous load among hosts while also having a minimum amount of shard movements during deployments with much better availability.\\n\\n### Worker Heartbeats\\n\\nToday, there\u2019s no worker liveliness tracking in Cadence. Instead, task or activity heartbeat timeouts are used to reassign tasks to different workers. For latency sensitive users this can become a big disruption. For long activities without heartbeats, this can cause big delays. This feature is to eliminate depending on manual timeout or heartbeat configs to reassign tasks by tracking if workers are still healthy. This feature will also enable so many other new efficiency and reliability features we would like to get to in the future.\\n\\n### Domain and Workflow Diagnostics\\n\\nProbably the two most common user questions are \u201cWhat\u2019s wrong with my domain?\u201d and \u201cWhat\u2019s wrong with my workflow?\u201d. Today, diagnosing what happened and what could be wrong isn\u2019t that easy apart from some basic cases. We are working on tools that would run diagnostics on workflows and domains to point out things that might potentially be wrong with public runbook links attached. This feature will not only help diagnose what is wrong with our workflows and domains but will also help fix them.\\n\\n### Self Serve Operations\\n\\nCertain Cadence operations are performed through admin CLI operations. However, these should be able to be done via Cadence UI by users. Admins shouldn\u2019t need to be involved in every step or the checks they validate should be able to be automated. This is what the initiative is about including domain registration, auth/authz onboarding or adding new search attributes but it\u2019s not limited to these operations.\\n\\n### Cost Estimation\\n\\nOne big question we receive when users are onboarding to Cadence is \u201cHow much will this cost me?\u201d. This is not an easy question to answer since data and traffic load can be quite different. We plan to automate this process to help users understand how much resources they will need. Especially in multi-tenant clusters, this will help users understand how much room they still have in their clusters and how much the new scenario will consume.\\n\\n### Domain Reports (continue)\\n\\nWe plan to release this internal feature to open source as soon as possible. On top of presenting this data on built-in Cadence surfaces (web, CLI. etc.) we will create APIs to make it integratable with deployment systems, user service UIs, periodic reports and any other service that would like to consume.\\n\\n### Non-determinism Detection Improvements (continue)\\n\\nWe have seen great reliability improvements and reduction in incidents with this feature on the user side last year. We continue to invest in this feature and make it available in open source as soon as possible.\\n\\n### Domain Migrations (continue)\\n\\nIn the next year, we plan to finish our seamless client based migration to be able to safely migrate domains from one cluster to another, one technology (even if it\u2019s not Cadence) to another and one cloud solution to another. There are only a few features left to achieve this.\\n\\n## Community\\n\\nDo you want to hear more about Cadence? Do you need help with your set-up or usage? Are you evaluating your options? Do you want to contribute? Feel free to join our community and reach out to us.\\n\\nSlack: [https://uber-cadence.slack.com/](https://uber-cadence.slack.com/)\\n\\nGithub: [https://github.com/cadence-workflow/cadence](https://github.com/cadence-workflow/cadence)\\n\\nSince last year, we have been contacted by various companies to take on bigger projects on the Cadence project. As we have been investing in code coverage and refactoring Cadence for a cleaner codebase, this will be a lot easier now. Let us know if you have project ideas to contribute or if you\u2019d like to pick something we already planned.\\n\\nOur monthly community meetings are still ongoing, too. That is the best place to get heard and be involved in our decision-making process. Let us know so we can send you an invite. We are also working on a broader governing model to open up this project to more people. Stay tuned for updates on this topic!"},{"id":"/2024/02/15/cadence-non-deterministic-common-qa","metadata":{"permalink":"/Cadence-Docs/blog/2024/02/15/cadence-non-deterministic-common-qa","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2024-02-15-cadence-non-deterministic-common-qa.md","source":"@site/blog/2024-02-15-cadence-non-deterministic-common-qa.md","title":"Cadence non-derministic errors common question Q&A (part 1)","description":"If I change code logic inside an Cadence activity (for example, my activity is calling database A but now I want it to call database B), will it trigger an non-deterministic error?","date":"2024-03-10T00:00:00.000Z","tags":[{"inline":false,"label":"Deep Dives","permalink":"/Cadence-Docs/blog/tags/deep-dives","description":"Deep Dives tag description"}],"readingTime":2.625,"hasTruncateMarker":true,"authors":[{"name":"Chris Qin","title":"Applications Developer @ Uber","url":"https://www.linkedin.com/in/chrisqin0610/","page":{"permalink":"/Cadence-Docs/blog/authors/chopincode"},"socials":{"linkedin":"https://www.linkedin.com/in/chrisqin0610/","github":"https://github.com/chopincode"},"imageURL":"https://github.com/chopincode.png","key":"chopincode"}],"frontMatter":{"title":"Cadence non-derministic errors common question Q&A (part 1)","date":"2024-03-10T00:00:00.000Z","authors":"chopincode","tags":["deep-dive"]},"unlisted":false,"prevItem":{"title":"2024 Cadence Yearly Roadmap Update","permalink":"/Cadence-Docs/blog/2024/07/11/2024-07-11-yearly-roadmap-update/yearly-roadmap-update"},"nextItem":{"title":"Cadence Community Spotlight Update - November 2023","permalink":"/Cadence-Docs/blog/2023/11/30/community-spotlight-update-november-2023"}},"content":"### If I change code logic inside an Cadence activity (for example, my activity is calling database A but now I want it to call database B), will it trigger an non-deterministic error?\\n\\nNO. This change will not trigger non-deterministic error.\\n\\nAn Activity is the smallest unit of execution for Cadence and what happens inside activities are not recorded as historical events and therefore will not be replayed. In short, this change is deterministic and it is fine to modify logic inside activities.\\n\\n### Does changing the workflow definition trigger non-determinstic errors?\\n\\nYES. This is a very typical non-deterministic error.\\n\\nWhen a new workflow code change is deployed, Cadence will find if it is compatible with\\nCadence history. Changes to workflow definition will fail the replay process of Cadence\\nas it finds the new workflow definition imcompatible with previous historical events.\\n\\nHere is a list of common workflow definition changes.\\n- Changing workflow parameter counts\\n- Changing workflow parameter types\\n- Changing workflow return types\\n\\nThe following changes are not categorized as definition changes and therefore will not\\ntrigger non-deterministic errors.\\n- Changes of workflow return values\\n- Changing workflow parameter names as they are just positional\\n\\n\x3c!-- truncate --\x3e\\n\\n### Does changing activity definitions trigger non-determinstic errors?\\n\\nYES. Similar to workflow definition change, this is also a very typical non-deterministic error.\\n\\nActivities are also recorded and replayed by Cadence. Therefore, changes to activity must also be compatible with Cadence history. The following changes are common ones that trigger non-deterministic errors.\\n- Changing activity parameter counts\\n- Changing activity parameter types\\n- Changing activity return types\\n\\nAs activity paremeters are also positional, these two changes will NOT trigger non-deterministic errors.\\n- Changes of activity return values\\n- Changing activity parameter names\\n\\nActivity return values inside workflows are not recorded and replayed.\\n\\n### What changes inside workflows may potentially trigger non-deterministic errors?\\n\\nCadence records each execution of a workflow and activity execution inside each of them.Therefore, new changes must be compatible with execution orders inside the workflow. The following changes will fail the non-deterministic check.\\n\\n- Append another activity\\n- Delete an existing activity\\n- Reordering activities\\n\\nIf you really need to change the activity implementation based on new business requirements, you may consider using versioning your workflow.\\n\\n### Are Cadence signals replayed? If definition of signal is changed, will it trigger non-deterministic errors?\\n\\nYes. If a signal is used in a workflow, it becomes a critical component of your workflow. Because signals also involve I/O to your workflow, it is also recorded and replayed. Modifications on signal definitions or usage may yield to non-deterministic errors, for instance, changing return type of a signal.\\n\\n### If I have new business requirement and really need to change the definition of a workflow, what should I do?\\n\\nYou may introduce a new workflow registered to your worker and divert traffic to it or use versioning for your workflow. Check out [Cadence website](https://cadenceworkflow.io/docs/go-client/workflow-versioning/) for more information about versioning.\\n\\n### Does changes to local activities\' definition trigger non-deterministic errors?\\n\\nYes. Local activities are recorded and therefore replayed by Cadence. Imcompatible changes on local activity definitions will yield to non-deterministic errors."},{"id":"/2023/11/30/community-spotlight-update-november-2023","metadata":{"permalink":"/Cadence-Docs/blog/2023/11/30/community-spotlight-update-november-2023","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2023-11-30-community-spotlight-update-november-2023.md","source":"@site/blog/2023-11-30-community-spotlight-update-november-2023.md","title":"Cadence Community Spotlight Update - November 2023","description":"Welcome to the latest of our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!","date":"2023-11-30T00:00:00.000Z","tags":[{"inline":false,"label":"Community Spotlight","permalink":"/Cadence-Docs/blog/tags/community-spotlights","description":"Community Spotlight tag description"},{"inline":false,"label":"Announcement","permalink":"/Cadence-Docs/blog/tags/announcements","description":"Announcement tag description"}],"readingTime":3.46,"hasTruncateMarker":true,"authors":[{"name":"Sharan Foga","title":"Director of Operations & Customer Success @ Encube Technologies","url":"https://www.linkedin.com/in/sfoga/","page":{"permalink":"/Cadence-Docs/blog/authors/sharanf"},"socials":{"linkedin":"https://www.linkedin.com/in/sfoga/","github":"https://github.com/sharanf"},"imageURL":"https://github.com/sharanf.png","key":"sharanf"}],"frontMatter":{"title":"Cadence Community Spotlight Update - November 2023","date":"2023-11-30T00:00:00.000Z","authors":"sharanf","tags":["community-spotlight","announcement"]},"unlisted":false,"prevItem":{"title":"Cadence non-derministic errors common question Q&A (part 1)","permalink":"/Cadence-Docs/blog/2024/02/15/cadence-non-deterministic-common-qa"},"nextItem":{"title":"Cadence Community Spotlight Update - August 2023","permalink":"/Cadence-Docs/blog/2023/08/31/community-spotlight-august-2023"}},"content":"Welcome to the latest of our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!\\n\\nIt\'s been a couple of months since our last update so we have a lot of updates to share with you.\\n\\nPlease see below for a roundup of the highlights:\\n\\n\x3c!-- truncate --\x3e\\n\\n## Proposal for Cadence Native Authentication ##\\n\\nCommunity member [Mantas Sidlauskas](https://lt.linkedin.com/in/mantassidlauskas) has drafted a proposal around Cadence native authentication and is asking for community feedback. If you are interested in reviewing the current proposal and providing comments or feedback then please find the proposal details at the link below:\\n\\n- [Cadence Native Authentication Proposal](https://docs.google.com/document/d/13GxRBZfQkLyhDCrpFaZmRcw7DJJG-zdy0_mPXy3CcWw/edit#heading=h.c8u99ansg7ma)\\n\\n This is a great example of how we can focus on collaborating together to find a collective solution. A big thank you to Mantas for initiating this work and we hope to see the results of the community input soon!\\n\\n## iWF Deep Dive and More! ##\\n\\nDuring the last few months community member [Quanzheng Long](https://www.linkedin.com/in/prclqz/) has continued to share his thoughts about [iWF](https://github.com/indeedeng/iwf), a layer implemented on top of Cadence. Since our last update iWF now has a[Python SDK](https://github.com/indeedeng/iwf-python-sdk). Long has been busy writing articles to share iWF tips and tricks as well as some general ideas about workflows and processes. Links to Long\'s articles can be found below:\\n\\n- [iWF Deep Dive: workflowState+Durable Timer#1](https://medium.com/@qlong/iwf-deep-dive-workflowstate-durable-timer-1-0bb89e6d6fd4)\\n\\n- [Gotchas About SignalWithStart in Cadence/Temporal](https://medium.com/@qlong/gotchas-about-signalwithstart-in-cadence-temporal-c3783fe1cc2e)\\n\\n- [\\"Workflow\\" could be \\"Process\\" in WorkflowAsCode frameworks](https://medium.com/@qlong/workflow-could-be-process-in-workflowascode-frameworks-63dcb632c248)\\n\\n## New Go Samples for Cadence ##\\n\\nThe Cadence core team is deprecating the old samples for Go and replacing them with new version 2 (V2) samples. They have received a lot of feedback from the community that people are having trouble with old samples, so are in the process of publishing a completely new set of samples for Go.\\n\\nHere are some major changes to the new samples:\\n\\n- Easy to use the read - the new samples will be completely based on CLIs instead of running a binary. (This is consistent with current Cadence use experience)\\n- Simple and transparent worker configuration - the old samples did not provide user a clear demonstration about the relationship between the worker and workflow themselves\\n- The new samples will help you bootstrap your Cadence workflow faster and easier.\\n- More vivid and self-explanatory - instead of the traditional \\"HelloWorld\\" type of samples, we want to make it more interesting and engaging. (Each sample will try to simulate a real-life use case to make them more understandable and fun to learn!)\\n\\nWe hope the community will enjoy these changes. If you have any questions or have new an idea for a new sample then please reach out to [Chris Qin](https://www.linkedin.com/in/chrisqin0610).\\n\\nThe new Go samples can be found at:\\n- https://github.com/cadence-workflow/cadence-samples/tree/master/new_samples.\\n\\nNote that the old samples will be removed once the new samples are fully refreshed.\\n\\n## Cadence Retrospective ##\\n\\nWe are nearly at the end of another year and yes it has gone so fast! Over this year Cadence and the community have evolved and grown. This is a good time to reflect about all the things that have happened in the project over the year and think about a possible roadmap for the future.\\n\\nIf you have any feedback, or comments about the project or ideas about what features you\'d like to see in the roadmap then please feel free to begin a discussion in the #community [Slack](http://t.uber.com/cadence-slack) channel.\\n\\n## Cadence in the News!\\n\\nBelow are a selection of Cadence related articles, blogs and whitepapers.\\nPlease take a look and feel free to share via your own social media channels.\\n\\n- [How to Throttle Cadence](https://www.instaclustr.com/blog/how-to-throttle-cadence/)\\n\\n- [iWF Deep Dive: workflowState+Durable Timer#1](https://medium.com/@qlong/iwf-deep-dive-workflowstate-durable-timer-1-0bb89e6d6fd4)\\n\\n- [Gotchas About SignalWithStart in Cadence/Temporal](https://medium.com/@qlong/gotchas-about-signalwithstart-in-cadence-temporal-c3783fe1cc2e)\\n\\n- [\\"Workflow\\" could be \\"Process\\" in WorkflowAsCode frameworks](https://medium.com/@qlong/workflow-could-be-process-in-workflowascode-frameworks-63dcb632c248)\\n\\n## Upcoming Events\\n\\n- [On Demand Webinar: Building With Cadence:Quantifiable Efficiency](https://netapp.zoom.us/webinar/register/WN_jT5fxSldRhuzV0NSllBd7g#/registration)\\n\\nIf you have any news or topics you\'d like us to include in our next update then please join our [Slack](http://t.uber.com/cadence-slack) #community channel.\\n\\nPlease remember that this update is for you - so if you have any comments or feedback that could help us improve it then please share it with us in the #community [Slack](http://t.uber.com/cadence-slack) channel."},{"id":"/2023/08/31/community-spotlight-august-2023","metadata":{"permalink":"/Cadence-Docs/blog/2023/08/31/community-spotlight-august-2023","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2023-08-31-community-spotlight-august-2023.md","source":"@site/blog/2023-08-31-community-spotlight-august-2023.md","title":"Cadence Community Spotlight Update - August 2023","description":"Welcome to the latest of our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!","date":"2023-08-31T00:00:00.000Z","tags":[{"inline":false,"label":"Introduction to Cadence","permalink":"/Cadence-Docs/blog/tags/introduction-to-cadence","description":"Introduction to Cadence tag description"},{"inline":false,"label":"Community Spotlight","permalink":"/Cadence-Docs/blog/tags/community-spotlights","description":"Community Spotlight tag description"}],"readingTime":2.955,"hasTruncateMarker":true,"authors":[{"name":"Sharan Foga","title":"Director of Operations & Customer Success @ Encube Technologies","url":"https://www.linkedin.com/in/sfoga/","page":{"permalink":"/Cadence-Docs/blog/authors/sharanf"},"socials":{"linkedin":"https://www.linkedin.com/in/sfoga/","github":"https://github.com/sharanf"},"imageURL":"https://github.com/sharanf.png","key":"sharanf"}],"frontMatter":{"title":"Cadence Community Spotlight Update - August 2023","date":"2023-08-31T00:00:00.000Z","authors":"sharanf","tags":["introduction-to-cadence","community-spotlight"]},"unlisted":false,"prevItem":{"title":"Cadence Community Spotlight Update - November 2023","permalink":"/Cadence-Docs/blog/2023/11/30/community-spotlight-update-november-2023"},"nextItem":{"title":"Non-deterministic errors, replayers and shadowers","permalink":"/Cadence-Docs/blog/2023/08/28/nondeterministic-errors-replayers-shadowers"}},"content":"Welcome to the latest of our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!\\n\\nPlease see below for a roundup of the highlights:\\n\\n## More Cadence How To\'s ##\\n\\nYou might have noticed that we have had a few more contributions to our blog from [Chris Qin](https://www.linkedin.com/in/chrisqin0610). Chris has been busy sharing insights, and tips on a few important Cadence topics. The objective is to help the community with any potential problems.\\n\\nHere are the latest topics:\\n\\n- [Bad Practices and Anti-Patterns with Cadence - Part 1](https://cadenceworkflow.io/blog/2023/07/10/cadence-bad-practices-part-1/)\\n\\n- [Non-Determistic Errors, Replayers and Shadowers](https://cadenceworkflow.io/blog/2023/08/27/nondeterministic-errors-replayers-shadowers/)\\n\\nEven if you have not encountered these use cases - it is good to be prepared and have a solution ready.Please take a look and let us have your feedback.\\n\\nChris is also going to take a look at the [Cadence Samples](https://cadenceworkflow.io/docs/java-client/client-overview/#samples) to make sure they are all working and if not - he\'s going to re-write them so that they do!\\n\\nThanks very much Chris for all the work you are doing to help improve the project!\\n\\n\x3c!-- truncate --\x3e\\n\\n## More iWF Examaples ##\\n\\nCommunity member [Quanzheng Long](https://www.linkedin.com/in/prclqz/) has also been busy writing this month. In previous blogs Long has told us about [iWF](https://github.com/indeedeng/iwf) that is a layer implemented over of Cadence.\\n\\nDuring August Long has published a couple of articles on using the \'ContinueAsNew\' functionality in iWF. Links to Part 1 and Part are below:\\n\\n- [Guide to ContinueAsNew in Cadence/Temporal Workflow Using iWF as an example - Part 1](https://medium.com/@qlong/guide-to-continueasnew-in-cadence-temporal-workflow-using-iwf-as-an-example-part-2-cedabd732bec)\\n\\n- [Guide to ContinueAsNew in Cadence/Temporal Workflow Using iWF as an example - Part 2](https://medium.com/@qlong/guide-to-continueasnew-in-cadence-temporal-workflow-using-iwf-as-an-example-part-1-c24ae5266f07)\\n\\nPlease take a look and if you\'ve enjoyed reading them then let Long and us know!\\n\\n## Cadence At the Helm! ##\\n\\nLast month we mentioned the Cadence Helm charts and all the previous work that had been done by [Mark Sagi-Kazar](https://www.linkedin.com/in/sagikazarmark/). We were looking to ensure they are maintained.\\n\\nSo a special thanks goes out this month to [Edmondo](ttps://github.com/edmondop ) for contributing some work on the [Cadence Helm Chart](https://github.com/edmondop/cadence-helm-chart/).\\n\\n## Community Support! ##\\n\\nOur [Slack](http://t.uber.com/cadence-slack) channel continues to be the main place where people are asking for help and support with Cadence. During August (which is supposed to be holiday season), we still had 9 questions raised around various topics.\\n\\nHuge thanks to the following community members who took time to respond and help others: David, Edmondo, Chris Qin, Rony Rahman and Ben Slater.\\n\\nIt\'s good to see that we are continuing to support each other - doing exactly what communities do!\\n\\n## Cadence in the News!\\n\\nBelow are a selection of Cadence related articles, blogs and whitepapers.\\nPlease take a look and feel free to share via your own social media channels.\\n\\n\\n- [Guide to ContinueAsNew in Cadence/Temporal Workflow Using iWF as an example - Part 1](https://medium.com/@qlong/guide-to-continueasnew-in-cadence-temporal-workflow-using-iwf-as-an-example-part-2-cedabd732bec)\\n\\n- [Guide to ContinueAsNew in Cadence/Temporal Workflow Using iWF as an example - Part 2](https://medium.com/@qlong/guide-to-continueasnew-in-cadence-temporal-workflow-using-iwf-as-an-example-part-1-c24ae5266f07)\\n\\n- [AWS PrivateLink Connectivity is now Available with Instaclustr for Cadence](https://www.instaclustr.com/blog/aws-privatelink-for-cadence-on-instaclustr-by-netapp/)\\n\\n## Upcoming Events\\n\\n- [Webinar: Introducing the Cadence Workflow HTTP API - 21st September 2023 ](https://netapp.zoom.us/webinar/register/WN_Uh9Y6ruiQSS5EiylNlsMug#/registration)\\n\\n- [On Demand Webinar: Microservices - A Modern Orchestration Approach with Cadence](https://netapp.zoom.us/webinar/register/WN_Hv9lO9QtSqyPPWkSAIRj5g#/registration)\\n\\n- [On Demand Webinar: Spinning Your Drones with Cadence and Apache Kafka](https://www.instaclustr.com/events/spinning-your-drones-with-cadence-and-apache-kafka/)\\n\\nIf you have any news or topics you\'d like us to include in our next update then please join our [Slack](http://t.uber.com/cadence-slack) #community channel.\\n\\nPlease remember that this update is for you - so if you have any comments or feedback that could help us improve it then please share it with us in the #community [Slack](http://t.uber.com/cadence-slack) channel."},{"id":"/2023/08/28/nondeterministic-errors-replayers-shadowers","metadata":{"permalink":"/Cadence-Docs/blog/2023/08/28/nondeterministic-errors-replayers-shadowers","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2023-08-28-nondeterministic-errors-replayers-shadowers.md","source":"@site/blog/2023-08-28-nondeterministic-errors-replayers-shadowers.md","title":"Non-deterministic errors, replayers and shadowers","description":"It is conceivable that developers constantly update their Cadence workflow code based upon new business use cases and needs. However,","date":"2023-08-27T00:00:00.000Z","tags":[{"inline":false,"label":"Deep Dives","permalink":"/Cadence-Docs/blog/tags/deep-dives","description":"Deep Dives tag description"},{"inline":false,"label":"Testing","permalink":"/Cadence-Docs/blog/tags/testing","description":"Testing tag description"}],"readingTime":2.305,"hasTruncateMarker":true,"authors":[{"name":"Chris Qin","title":"Applications Developer @ Uber","url":"https://www.linkedin.com/in/chrisqin0610/","page":{"permalink":"/Cadence-Docs/blog/authors/chopincode"},"socials":{"linkedin":"https://www.linkedin.com/in/chrisqin0610/","github":"https://github.com/chopincode"},"imageURL":"https://github.com/chopincode.png","key":"chopincode"}],"frontMatter":{"title":"Non-deterministic errors, replayers and shadowers","date":"2023-08-27T00:00:00.000Z","authors":"chopincode","tags":["deep-dive","testing"]},"unlisted":false,"prevItem":{"title":"Cadence Community Spotlight Update - August 2023","permalink":"/Cadence-Docs/blog/2023/08/31/community-spotlight-august-2023"},"nextItem":{"title":"Cadence Community Spotlight Update - July 2023","permalink":"/Cadence-Docs/blog/2023/07/31/community-spotlight-july-2023"}},"content":"It is conceivable that developers constantly update their Cadence workflow code based upon new business use cases and needs. However,\\nthe definition of a Cadence workflow must be deterministic because behind the scenes cadence uses event sourcing to construct\\nthe workflow state by replaying the historical events stored for this specific workflow. Introducing components that are not compatible\\nwith an existing running workflow will yield to non-deterministic errors and sometimes developers find it tricky to debug. Consider the\\nfollowing workflow that executes two activities.\\n\\n```go\\nfunc SampleWorkflow(ctx workflow.Context, data string) (string, error) {\\n ao := workflow.ActivityOptions{\\n ScheduleToStartTimeout: time.Minute,\\n StartToCloseTimeout: time.Minute,\\n }\\n ctx = workflow.WithActivityOptions(ctx, ao)\\n var result1 string\\n err := workflow.ExecuteActivity(ctx, ActivityA, data).Get(ctx, &result1)\\n if err != nil {\\n return \\"\\", err\\n }\\n var result2 string\\n err = workflow.ExecuteActivity(ctx, ActivityB, result1).Get(ctx, &result2)\\n return result2, err\\n}\\n\\n```\\n\\n\x3c!-- truncate --\x3e\\n\\nIn this example, the workflow will execute ActivityA and Activity B in sequence. These activities may have other logics in background, such as polling long running operations or manipulate database reads or writes. Now if the developer replaces ActivityA with another activity ActivityC, a non-deterministic error could happen for an existing workflow. It is because the workflow expects results from ActivityA but since the definition of the workflow has been changed to use results from ActivityC, the workflow will fail due to failure of identifying history data of ActivityA. Such issues can be detected by introducing replayers and shadowers to the workflow unit tests.\\n\\nCadence workflow replayer is a testing component for replaying existing workflow histories against a workflow definition. You may think of replayer as a mock which will rerun your workflow with exactly the same history as your real workflow. The replaying logic is the same as the one used for processing workflow tasks. If it detects any incompatible changes, the replay test will fail.\\nWorkflow Replayer works well when verifying the compatibility against a small number of workflow histories. If there are lots of workflows in production that need to be verified, dumping all histories manually clearly won\'t work. Directly fetching histories from the cadence server might be a solution, but the time to replay all workflow histories might be too long for a test.\\n\\nWorkflow Shadower is built on top of Workflow Replayer to address this problem. The basic idea of shadowing is: scan workflows based on the filters you defined, fetch history for each workflow in the scan result from Cadence server and run the replay test. It can be run either as a test to serve local development purposes or as a workflow in your worker to continuously replay production workflows.\\n\\nYou may find detailed instructions on how to use replayers and shadowers on [our website](https://cadenceworkflow.io/docs/go-client/workflow-replay-shadowing/). We will introduce versioning in the next coming blogs."},{"id":"/2023/07/31/community-spotlight-july-2023","metadata":{"permalink":"/Cadence-Docs/blog/2023/07/31/community-spotlight-july-2023","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2023-07-31-community-spotlight-july-2023.md","source":"@site/blog/2023-07-31-community-spotlight-july-2023.md","title":"Cadence Community Spotlight Update - July 2023","description":"Welcome to the latest of our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!","date":"2023-07-31T00:00:00.000Z","tags":[{"inline":false,"label":"Releases","permalink":"/Cadence-Docs/blog/tags/releases","description":"Releases tag description"},{"inline":false,"label":"Announcement","permalink":"/Cadence-Docs/blog/tags/announcements","description":"Announcement tag description"},{"inline":false,"label":"Community Spotlight","permalink":"/Cadence-Docs/blog/tags/community-spotlights","description":"Community Spotlight tag description"}],"readingTime":2.49,"hasTruncateMarker":true,"authors":[{"name":"Sharan Foga","title":"Director of Operations & Customer Success @ Encube Technologies","url":"https://www.linkedin.com/in/sfoga/","page":{"permalink":"/Cadence-Docs/blog/authors/sharanf"},"socials":{"linkedin":"https://www.linkedin.com/in/sfoga/","github":"https://github.com/sharanf"},"imageURL":"https://github.com/sharanf.png","key":"sharanf"}],"frontMatter":{"title":"Cadence Community Spotlight Update - July 2023","date":"2023-07-31T00:00:00.000Z","authors":"sharanf","tags":["release","announcement","community-spotlight"]},"unlisted":false,"prevItem":{"title":"Non-deterministic errors, replayers and shadowers","permalink":"/Cadence-Docs/blog/2023/08/28/nondeterministic-errors-replayers-shadowers"},"nextItem":{"title":"Write your first workflow with Cadence","permalink":"/Cadence-Docs/blog/2023/07/16/2023-07-16-write-your-first-workflow-with-cadence/write-your-first-workflow-with-cadence"}},"content":"Welcome to the latest of our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!\\n\\nPlease see below for a roundup of the highlights:\\n\\n## Getting Started with Cadence ##\\n\\nAre you new to Cadence and want to understand the basic concepts and architecture? Well we have some great information for you!\\n\\nCommunity member [Chris Qin](https://www.linkedin.com/in/chrisqin0610/) has written a [short blog post](https://cadenceworkflow.io/blog/2023/07/01/components-of-cadence-application-setup/) that takes you through the the three main components that make up a Cadence application. Please take a look and feel free to give us your comments and feedback.\\n\\nThanks Chris for sharing your knowledge and helping others to get started.\\n\\n## Cadence Go Client v1.0 Released ##\\n\\nThis month saw the release of [v1.0 of the Cadence Go Client](https://github.com/cadence-workflow/cadence-go-client/releases/tag/v1.0.0). Note that the work done on this release was as a result of community feedback asking for it - so we are listening and responding to community needs.\\n\\nThanks very much to everyone who worked hard to get this release out!\\n\\n\x3c!-- truncate --\x3e\\n\\n## Cadence Release Strategy ##\\n\\nA recent discussion on the Cadence Release strategy was posted in [Cadence Github Discussions](https://github.com/cadence-workflow/cadence/discussions/5362) (and also our #general channel on our [Slack](http://t.uber.com/cadence-slack) about the approach we\'d like to take for future releases. As a community we want to ensure code stability and to not burden people with having to upgrade frequently.\\n\\nBased on feedback from the community we will be introducing quarterly release cycles but also give people the ability to make use of patches and minor releases. We will be communicating the intention to make a release at least a month beforehand so that the community has time to finalise any features they want to be included in the upcoming release.\\n\\nFor those of you wanting to keep up to date or try out new features in between releases, the core team at Uber will continue to make patch and minor version updates available to the community.\\n\\nAs always we welcome your feedback so please feel free to add your thoughts and comments to the discussion.\\n\\n## Cadence Helm Charts ##\\n\\nCommunity member [Mark Sagi-Kazar](https://www.linkedin.com/in/sagikazarmark/) has been maintaining the Banzai Cloud Cadence Helm Charts for the community. As the Helm Charts are a key tool for the community we are planning to take over the maintenance of them.\\n\\nOur plan is to move the charts into the Cadence repository and to maintain an official and supported Kubernetes solution with Cadence.\\n\\nHuge thanks to Mark for all the work you have done and it\'s great to see the task being handed over and made into a community effort.\\n\\n## Upcoming Events\\n\\n- None\\n\\nIf you have any news or topics you\'d like us to include in our next update then please join our [Slack](http://t.uber.com/cadence-slack) #community channel.\\n\\nPlease remember that this update is for you - so if you have any comments or feedback that could help us improve it then please share it with us in the #community [Slack](http://t.uber.com/cadence-slack) channel."},{"id":"/2023/07/16/2023-07-16-write-your-first-workflow-with-cadence/write-your-first-workflow-with-cadence","metadata":{"permalink":"/Cadence-Docs/blog/2023/07/16/2023-07-16-write-your-first-workflow-with-cadence/write-your-first-workflow-with-cadence","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2023-07-16-write-your-first-workflow-with-cadence/2023-07-16-write-your-first-workflow-with-cadence.md","source":"@site/blog/2023-07-16-write-your-first-workflow-with-cadence/2023-07-16-write-your-first-workflow-with-cadence.md","title":"Write your first workflow with Cadence","description":"We have covered basic components of Cadence and how to implement a Cadence worker on local environment in previous blogs. In this blog, let\'s write your very first HelloWorld workflow with Cadence. I\'ve started the Cadence backend server in background and registered a domain named test-domain. You may use the code snippet for the worker service in this blog Let\'s first write a activity, which takes a single string argument and print a log in the console.","date":"2023-07-16T00:00:00.000Z","tags":[{"inline":false,"label":"Deep Dives","permalink":"/Cadence-Docs/blog/tags/deep-dives","description":"Deep Dives tag description"},{"inline":false,"label":"Introduction to Cadence","permalink":"/Cadence-Docs/blog/tags/introduction-to-cadence","description":"Introduction to Cadence tag description"}],"readingTime":2.075,"hasTruncateMarker":true,"authors":[{"name":"Chris Qin","title":"Applications Developer @ Uber","url":"https://www.linkedin.com/in/chrisqin0610/","page":{"permalink":"/Cadence-Docs/blog/authors/chopincode"},"socials":{"linkedin":"https://www.linkedin.com/in/chrisqin0610/","github":"https://github.com/chopincode"},"imageURL":"https://github.com/chopincode.png","key":"chopincode"}],"frontMatter":{"title":"Write your first workflow with Cadence","date":"2023-07-16T00:00:00.000Z","authors":"chopincode","tags":["deep-dive","introduction-to-cadence"]},"unlisted":false,"prevItem":{"title":"Cadence Community Spotlight Update - July 2023","permalink":"/Cadence-Docs/blog/2023/07/31/community-spotlight-july-2023"},"nextItem":{"title":"Bad practices and Anti-patterns with Cadence (Part 1)","permalink":"/Cadence-Docs/blog/2023/07/10/cadence-bad-practices-part-1"}},"content":"We have covered [basic components of Cadence](/blog/2023-06-28-components-of-cadence-application-setup.md) and [how to implement a Cadence worker on local environment](/blog/2023-07-05-implement-cadence-worker-from-scratch.md) in previous blogs. In this blog, let\'s write your very first HelloWorld workflow with Cadence. I\'ve started the Cadence backend server in background and registered a domain named `test-domain`. You may use the code snippet for the worker service in [this blog](/blog/2023-07-05-implement-cadence-worker-from-scratch.md) Let\'s first write a activity, which takes a single string argument and print a log in the console.\\n\\n```go\\nfunc helloWorldActivity(ctx context.Context, name string) (string, error) {\\n\\tlogger := activity.GetLogger(ctx)\\n\\tlogger.Info(\\"helloworld activity started\\")\\n\\treturn \\"Hello \\" + name + \\"!\\", nil\\n}\\n```\\n\\n\x3c!-- truncate --\x3e\\n\\nThen let\'s write a workflow that invokes this activity\\n```go\\nfunc helloWorldWorkflow(ctx workflow.Context, name string) error {\\n\\tao := workflow.ActivityOptions{\\n\\t\\tScheduleToStartTimeout: time.Minute,\\n\\t\\tStartToCloseTimeout: time.Minute,\\n\\t\\tHeartbeatTimeout: time.Second * 20,\\n\\t}\\n\\tctx = workflow.WithActivityOptions(ctx, ao)\\n\\n\\tlogger := workflow.GetLogger(ctx)\\n\\tlogger.Info(\\"helloworld workflow started\\")\\n\\tvar helloworldResult string\\n\\terr := workflow.ExecuteActivity(ctx, helloWorldActivity, name).Get(ctx, &helloworldResult)\\n\\tif err != nil {\\n\\t\\tlogger.Error(\\"Activity failed.\\", zap.Error(err))\\n\\t\\treturn err\\n\\t}\\n\\n\\tlogger.Info(\\"Workflow completed.\\", zap.String(\\"Result\\", helloworldResult))\\n\\n\\treturn nil\\n}\\n```\\n\\nDon\'t forget to register your workflow and activity to your worker in the `init` function.\\n```go\\nfunc init() {\\n workflow.Register(helloWorldWorkflow)\\n activity.Register(helloWorldActivity)\\n}\\n```\\n\\nNow restart your worker and you will only see logs like\\n```bash\\n2023-07-16T12:07:33.165-0700 INFO internal/internal_worker.go:834 Started Workflow Worker {\\"Domain\\": \\"test-domain\\", \\"TaskList\\": \\"test-worker\\", \\"WorkerID\\": \\"13585@uber-C02F18EQMD6R@test-worker@42f8a76f-cc42-4a0d-a001-7f7959d5d623\\"}\\n2023-07-16T12:07:33.175-0700 INFO internal/internal_worker.go:859 Started Activity Worker {\\"Domain\\": \\"test-domain\\", \\"TaskList\\": \\"test-worker\\", \\"WorkerID\\": \\"13585@uber-C02F18EQMD6R@test-worker@42f8a76f-cc42-4a0d-a001-7f7959d5d623\\"}\\n2023-07-16T12:07:33.175-0700 INFO cadence-worker/code.go:84 Started Worker. {\\"worker\\": \\"test-worker\\"}\\n```\\n\\nLet\'s try to run a Cadence workflow using Cadence CLI.\\n```bash\\ncadence --env development --domain test-domain workflow start --et 60 --tl test-worker --workflow_type main.helloWorldWorkflow --input \'\\"World\\"\'\\n```\\n\\nYou should see the Hello World log such like\\n```bash\\n2023-07-16T12:09:11.858-0700 INFO cadence-worker/code.go:104 Workflow completed. {\\"Domain\\": \\"test-domain\\", \\"TaskList\\": \\"test-worker\\", \\"WorkerID\\": \\"13585@uber-C02F18EQMD6R@test-worker@42f8a76f-cc42-4a0d-a001-7f7959d5d623\\", \\"WorkflowType\\": \\"main.helloWorldWorkflow\\", \\"WorkflowID\\": \\"8cb7fb2a-243b-43f8-82d9-48d758c9d62f\\", \\"RunID\\": \\"3c070007-89c3-4e00-a039-19a86b2f9224\\", \\"Result\\": \\"Hello World!\\"}\\n```\\n\\nCongratulations, you have successfully run your very first Cadence workflow.\\n\\nFor a bonus point, the Cadence team has also developed a demonstrative web dashboard to visualize the history of all workflows you have run when you start the Cadence server. Check http://localhost:8088 to see the dashboard like this.\\n\\n![cadencde-ui](./cadence_ui.png)\\n\\nThis web portal persists all historical workflow you have run recently. Search for the domain you used for this tutorial. In our case, type `test-domain` and hit enter. You may see a list of workflows with detailed information. Feel free to explore the web UI and raise your suggestions to our [Github repo](https://github.com/cadence-workflow/cadence-web).\\n\\n![cadence-ui-detailed](./cadence_ui_detailed.png)\\n\\nFor the incoming blogs, we will cover more advanced topics and use cases with Cadence."},{"id":"/2023/07/10/cadence-bad-practices-part-1","metadata":{"permalink":"/Cadence-Docs/blog/2023/07/10/cadence-bad-practices-part-1","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2023-07-10-cadence-bad-practices-part-1.md","source":"@site/blog/2023-07-10-cadence-bad-practices-part-1.md","title":"Bad practices and Anti-patterns with Cadence (Part 1)","description":"In the upcoming blog series, we will delve into a discussion about common bad practices and anti-patterns related to Cadence. As diverse teams often encounter distinct business use cases, it becomes imperative to address the most frequently reported issues in Cadence workflows. To provide valuable insights and guidance, the Cadence team has meticulously compiled these common challenges based on customer feedback.","date":"2023-07-10T00:00:00.000Z","tags":[{"inline":false,"label":"Introduction to Cadence","permalink":"/Cadence-Docs/blog/tags/introduction-to-cadence","description":"Introduction to Cadence tag description"},{"inline":false,"label":"Deep Dives","permalink":"/Cadence-Docs/blog/tags/deep-dives","description":"Deep Dives tag description"}],"readingTime":2.065,"hasTruncateMarker":true,"authors":[{"name":"Chris Qin","title":"Applications Developer @ Uber","url":"https://www.linkedin.com/in/chrisqin0610/","page":{"permalink":"/Cadence-Docs/blog/authors/chopincode"},"socials":{"linkedin":"https://www.linkedin.com/in/chrisqin0610/","github":"https://github.com/chopincode"},"imageURL":"https://github.com/chopincode.png","key":"chopincode"}],"frontMatter":{"title":"Bad practices and Anti-patterns with Cadence (Part 1)","date":"2023-07-10T00:00:00.000Z","authors":"chopincode","tags":["introduction-to-cadence","deep-dive"]},"unlisted":false,"prevItem":{"title":"Write your first workflow with Cadence","permalink":"/Cadence-Docs/blog/2023/07/16/2023-07-16-write-your-first-workflow-with-cadence/write-your-first-workflow-with-cadence"},"nextItem":{"title":"Implement a Cadence worker service from scratch","permalink":"/Cadence-Docs/blog/2023/07/05/implement-cadence-worker-from-scratch"}},"content":"In the upcoming blog series, we will delve into a discussion about common bad practices and anti-patterns related to Cadence. As diverse teams often encounter distinct business use cases, it becomes imperative to address the most frequently reported issues in Cadence workflows. To provide valuable insights and guidance, the Cadence team has meticulously compiled these common challenges based on customer feedback.\\n\\n* Reusing the same workflow ID for very active/continuous running workflows\\n\\nCadence organizes workflows based on their unique IDs, using a process called partitioning. If a workflow receives a large number of updates in a short period of time or frequently starts new runs using the `continueAsNew` function, all these updates will be directed to the same shard. Unfortunately, the Cadence backend is not equipped to handle this concentrated workload efficiently. As a result, a situation known as a \\"hot shard\\" arises, overloading the Cadence backend and worsening the problem.\\n\\nSolution:\\nWell, the best way to avoid this is simply just design your workflow in the way such that each workflow owns a uniformly distributed workflow ID across your Cadence domain. This will make sure that Cadence backend is able to evenly distribute the traffic with proper partition on your workflowIDs.\\n\\n\x3c!-- truncate --\x3e\\n\\n* Excessive batch jobs or an enormous number of timers triggered at the same time\\n\\nCadence has the capability to handle a large number of concurrent tasks initiated simultaneously, but tampering with this feature can lead to issues within the Cadence system. Consider a scenario where millions of jobs are scheduled to start at the same time and are expected to finish within a specific time interval. Cadence faces the challenge of understanding the desired behavior of customers in such cases. It is uncertain whether the intention is to complete all jobs simultaneously, provide progressive updates in parallel, or finish all jobs before a given deadline. This ambiguity arises due to the independent nature of each job and the difficulty in predicting their outcomes.\\n\\nMoreover, Cadence workers utilize a sticky cache by default to optimize the runtime of workflows. However, when an overwhelming number of parallel workflows cannot fit into the cache, it can result in cache thrashing. This, in turn, leads to a quadratic increase in runtime complexity, specifically O(n^2), exacerbating the overall performance of the system.\\n\\nSolution:\\nThere are multiple ways to address this issue. Customers can either run jobs in a smaller batch or use start workflow jitter to randomly distribute timers within certain timeframe."},{"id":"/2023/07/05/implement-cadence-worker-from-scratch","metadata":{"permalink":"/Cadence-Docs/blog/2023/07/05/implement-cadence-worker-from-scratch","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2023-07-05-implement-cadence-worker-from-scratch.md","source":"@site/blog/2023-07-05-implement-cadence-worker-from-scratch.md","title":"Implement a Cadence worker service from scratch","description":"In the previous blog, we have introduced three critical components for a Cadence application: the Cadence backend, domain, and worker. Among these, the worker service is the most crucial focus for developers as it hosts the activities and workflows of a Cadence application. In this blog, I will provide a short tutorial on how to implement a simple worker service from scratch in Go.","date":"2023-07-05T00:00:00.000Z","tags":[{"inline":false,"label":"Deep Dives","permalink":"/Cadence-Docs/blog/tags/deep-dives","description":"Deep Dives tag description"},{"inline":false,"label":"Introduction to Cadence","permalink":"/Cadence-Docs/blog/tags/introduction-to-cadence","description":"Introduction to Cadence tag description"}],"readingTime":3.69,"hasTruncateMarker":true,"authors":[{"name":"Chris Qin","title":"Applications Developer @ Uber","url":"https://www.linkedin.com/in/chrisqin0610/","page":{"permalink":"/Cadence-Docs/blog/authors/chopincode"},"socials":{"linkedin":"https://www.linkedin.com/in/chrisqin0610/","github":"https://github.com/chopincode"},"imageURL":"https://github.com/chopincode.png","key":"chopincode"}],"frontMatter":{"title":"Implement a Cadence worker service from scratch","date":"2023-07-05T00:00:00.000Z","authors":"chopincode","tags":["deep-dive","introduction-to-cadence"]},"unlisted":false,"prevItem":{"title":"Bad practices and Anti-patterns with Cadence (Part 1)","permalink":"/Cadence-Docs/blog/2023/07/10/cadence-bad-practices-part-1"},"nextItem":{"title":"Understanding components of Cadence application","permalink":"/Cadence-Docs/blog/2023/06/28/components-of-cadence-application-setup"}},"content":"In the previous [blog](/blog/2023-06-28-components-of-cadence-application-setup.md), we have introduced three critical components for a Cadence application: the Cadence backend, domain, and worker. Among these, the worker service is the most crucial focus for developers as it hosts the activities and workflows of a Cadence application. In this blog, I will provide a short tutorial on how to implement a simple worker service from scratch in Go.\\n\\nTo finish this tutorial, there are two prerequisites you need to finish first\\n1. Register a Cadence domain for your worker. For this tutorial, I\'ve already registered a domain named `test-domain`\\n2. Start the Cadence backend server in background.\\n\\nTo get started, let\'s simply use the native HTTP package built in Go to start a process listening to port 3000. You may customize the port for your worker, but the port you choose should not conflict with existing port for your Cadence backend.\\n\\n```go\\npackage main\\n\\nimport (\\n\\t\\"fmt\\"\\n\\t\\"net/http\\"\\n)\\n\\nfunc main(){\\n\\tfmt.Println(\\"Cadence worker started at port 3000\\")\\n\\thttp.ListenAndServe(\\":3000\\", nil)\\n}\\n```\\n\x3c!-- truncate --\x3e\\n\\nNext, let\'s define some basic configurations for the worker. In real production environment, you may need to implement them in configurational languages, but in this tutorial, let\'s just hard code them for now.\\n\\n```go\\nvar HostPort = \\"127.0.0.1:7933\\"\\nvar Domain = \\"test-domain\\"\\nvar TaskListName = \\"test-worker\\"\\nvar ClientName = \\"test-worker\\"\\nvar CadenceService = \\"cadence-frontend\\"\\n```\\n\\nNote that the domain is what we\'ve already registered in advance. We will need to use this domain to interact with Cadence CLI tool.\\n\\nThen let\'s write a simple function to build a Cadence client on gRPC in your worker, which will communicate with the Cadence backend continuously.\\n\\n```go\\nfunc buildCadenceClient() workflowserviceclient.Interface {\\n dispatcher := yarpc.NewDispatcher(yarpc.Config{\\n\\t\\tName: ClientName,\\n\\t\\tOutbounds: yarpc.Outbounds{\\n\\t\\t CadenceService: {Unary: grpc.NewTransport().NewSingleOutbound(HostPort)},\\n\\t\\t},\\n\\t })\\n\\t if err := dispatcher.Start(); err != nil {\\n\\t\\tpanic(\\"Failed to start dispatcher\\")\\n\\t }\\n\\n\\t clientConfig := dispatcher.ClientConfig(CadenceService)\\n\\n\\t return compatibility.NewThrift2ProtoAdapter(\\n\\t\\tapiv1.NewDomainAPIYARPCClient(clientConfig),\\n\\t\\tapiv1.NewWorkflowAPIYARPCClient(clientConfig),\\n\\t\\tapiv1.NewWorkerAPIYARPCClient(clientConfig),\\n\\t\\tapiv1.NewVisibilityAPIYARPCClient(clientConfig),\\n\\t )\\n}\\n```\\n\\nLet\'s also build a logger to help us debug our application\\n\\n```go\\nfunc buildLogger() *zap.Logger {\\n config := zap.NewDevelopmentConfig()\\n config.Level.SetLevel(zapcore.InfoLevel)\\n\\n var err error\\n logger, err := config.Build()\\n if err != nil {\\n panic(\\"Failed to setup logger\\")\\n }\\n\\n return logger\\n}\\n```\\n\\nWith both client and logger helper function ready, let\'s write the function that starts our worker.\\n\\n```go\\nfunc startWorker(logger *zap.Logger, service workflowserviceclient.Interface) {\\n // TaskListName identifies set of client workflows, activities, and workers.\\n // It could be your group or client or application name.\\n workerOptions := worker.Options{\\n Logger: logger,\\n MetricsScope: tally.NewTestScope(TaskListName, map[string]string{}),\\n }\\n\\n worker := worker.New(\\n service,\\n Domain,\\n TaskListName,\\n workerOptions)\\n err := worker.Start()\\n if err != nil {\\n panic(\\"Failed to start worker\\")\\n }\\n\\n logger.Info(\\"Started Worker.\\", zap.String(\\"worker\\", TaskListName))\\n}\\n```\\n\\nNow we have all components ready for the worker, let\'s put them together.\\n\\n```Go\\nimport (\\n \\"net/http\\"\\n \\"go.uber.org/cadence/.gen/go/cadence/workflowserviceclient\\"\\n \\"go.uber.org/cadence/compatibility\\"\\n \\"go.uber.org/cadence/worker\\"\\n\\n apiv1 \\"github.com/cadence-workflow/cadence-idl/go/proto/api/v1\\"\\n \\"github.com/uber-go/tally\\"\\n \\"go.uber.org/zap\\"\\n \\"go.uber.org/zap/zapcore\\"\\n \\"go.uber.org/yarpc\\"\\n \\"go.uber.org/yarpc/transport/grpc\\"\\n)\\n\\nvar HostPort = \\"127.0.0.1:7933\\"\\nvar Domain = \\"test-domain\\"\\nvar TaskListName = \\"test-worker\\"\\nvar ClientName = \\"test-worker\\"\\nvar CadenceService = \\"cadence-frontend\\"\\n\\nfunc main() {\\n startWorker(buildLogger(), buildCadenceClient())\\n http.ListenAndServe(\\":3000\\", nil)\\n}\\n\\nfunc buildLogger() *zap.Logger {\\n config := zap.NewDevelopmentConfig()\\n config.Level.SetLevel(zapcore.InfoLevel)\\n\\n var err error\\n logger, err := config.Build()\\n if err != nil {\\n panic(\\"Failed to setup logger\\")\\n }\\n\\n return logger\\n}\\n\\nfunc buildCadenceClient() workflowserviceclient.Interface {\\n dispatcher := yarpc.NewDispatcher(yarpc.Config{\\n\\t\\tName: ClientName,\\n\\t\\tOutbounds: yarpc.Outbounds{\\n\\t\\t CadenceService: {Unary: grpc.NewTransport().NewSingleOutbound(HostPort)},\\n\\t\\t},\\n\\t })\\n\\t if err := dispatcher.Start(); err != nil {\\n\\t\\tpanic(\\"Failed to start dispatcher\\")\\n\\t }\\n\\n\\t clientConfig := dispatcher.ClientConfig(CadenceService)\\n\\n\\t return compatibility.NewThrift2ProtoAdapter(\\n\\t\\tapiv1.NewDomainAPIYARPCClient(clientConfig),\\n\\t\\tapiv1.NewWorkflowAPIYARPCClient(clientConfig),\\n\\t\\tapiv1.NewWorkerAPIYARPCClient(clientConfig),\\n\\t\\tapiv1.NewVisibilityAPIYARPCClient(clientConfig),\\n\\t )\\n}\\n\\nfunc startWorker(logger *zap.Logger, service workflowserviceclient.Interface) {\\n // TaskListName identifies set of client workflows, activities, and workers.\\n // It could be your group or client or application name.\\n workerOptions := worker.Options{\\n Logger: logger,\\n MetricsScope: tally.NewTestScope(TaskListName, map[string]string{}),\\n }\\n\\n worker := worker.New(\\n service,\\n Domain,\\n TaskListName,\\n workerOptions)\\n err := worker.Start()\\n if err != nil {\\n panic(\\"Failed to start worker\\")\\n }\\n\\n logger.Info(\\"Started Worker.\\", zap.String(\\"worker\\", TaskListName))\\n}\\n```\\n\\nOpen a new terminal and start this server, you should see logs like\\n```shell\\n2023-07-03T11:46:46.266-0700 INFO internal/internal_worker.go:826 Worker has no workflows registered, so workflow worker will not be started. {\\"Domain\\": \\"test-domain\\", \\"TaskList\\": \\"test-worker\\", \\"WorkerID\\": \\"35987@uber-C02F18EQMD6R@test-worker@90c0260e-ba5c-4652-9f10-c6d1f9e29c1d\\"}\\n2023-07-03T11:46:46.267-0700 INFO internal/internal_worker.go:834 Started Workflow Worker {\\"Domain\\": \\"test-domain\\", \\"TaskList\\": \\"test-worker\\", \\"WorkerID\\": \\"35987@uber-C02F18EQMD6R@test-worker@90c0260e-ba5c-4652-9f10-c6d1f9e29c1d\\"}\\n2023-07-03T11:46:46.267-0700 INFO internal/internal_worker.go:838 Worker has no activities registered, so activity worker will not be started. {\\"Domain\\": \\"test-domain\\", \\"TaskList\\": \\"test-worker\\", \\"WorkerID\\": \\"35987@uber-C02F18EQMD6R@test-worker@90c0260e-ba5c-4652-9f10-c6d1f9e29c1d\\"}\\n2023-07-03T11:46:46.267-0700 INFO cadence-worker/main.go:75 Started Worker. {\\"worker\\": \\"test-worker\\"}\\n```\\n\\nYou may see these logs because your worker is successfully running but we haven\'t registered any workflows or activities to the worker. In the next tutorial, we will learn how to write a simple hello world workflow for your Cadence application."},{"id":"/2023/06/28/components-of-cadence-application-setup","metadata":{"permalink":"/Cadence-Docs/blog/2023/06/28/components-of-cadence-application-setup","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2023-06-28-components-of-cadence-application-setup.md","source":"@site/blog/2023-06-28-components-of-cadence-application-setup.md","title":"Understanding components of Cadence application","description":"Cadence is a powerful, scalable, and fault-tolerant workflow orchestration framework that helps developers implement and manage complex workflow tasks. In most cases, developers contribute activities and workflows directly to their codebases, and they may not have a full understanding of the components behind a running Cadence application. We receive numerous inquiries about setting up Cadence in a local environment from scratch for testing. Therefore, in this article, we will explore the components that power a Cadence cluster.","date":"2023-07-01T00:00:00.000Z","tags":[{"inline":false,"label":"Deep Dives","permalink":"/Cadence-Docs/blog/tags/deep-dives","description":"Deep Dives tag description"},{"inline":false,"label":"Introduction to Cadence","permalink":"/Cadence-Docs/blog/tags/introduction-to-cadence","description":"Introduction to Cadence tag description"}],"readingTime":1.615,"hasTruncateMarker":true,"authors":[{"name":"Chris Qin","title":"Applications Developer @ Uber","url":"https://www.linkedin.com/in/chrisqin0610/","page":{"permalink":"/Cadence-Docs/blog/authors/chopincode"},"socials":{"linkedin":"https://www.linkedin.com/in/chrisqin0610/","github":"https://github.com/chopincode"},"imageURL":"https://github.com/chopincode.png","key":"chopincode"}],"frontMatter":{"title":"Understanding components of Cadence application","date":"2023-07-01T00:00:00.000Z","authors":"chopincode","tags":["deep-dive","introduction-to-cadence"]},"unlisted":false,"prevItem":{"title":"Implement a Cadence worker service from scratch","permalink":"/Cadence-Docs/blog/2023/07/05/implement-cadence-worker-from-scratch"},"nextItem":{"title":"Cadence Community Spotlight Update - June 2023","permalink":"/Cadence-Docs/blog/2023/06/30/community-spotlight-june-2023"}},"content":"Cadence is a powerful, scalable, and fault-tolerant workflow orchestration framework that helps developers implement and manage complex workflow tasks. In most cases, developers contribute activities and workflows directly to their codebases, and they may not have a full understanding of the components behind a running Cadence application. We receive numerous inquiries about setting up Cadence in a local environment from scratch for testing. Therefore, in this article, we will explore the components that power a Cadence cluster.\\n\\nThere are three critical components that are essential for any Cadence application:\\n1. A running Cadence backend server.\\n2. A registered Cadence domain.\\n3. A running Cadence worker that registers all workflows and activities.\\n\\nLet\'s go over these components in more details.\\n\\n\x3c!-- truncate --\x3e\\n\\nThe Cadence backend serves as the heart of your Cadence application. It is responsible for processing and scheduling your workflows and activities. While the backend relies on various dependencies, our team has conveniently packaged them into a single Docker image. You can follow the instructions provided [here](/docs/get-started/server-installation).\\n\\nThe Cadence domain functions as the namespace for your Cadence workflows. It helps segregate your workflows into manageable groups. When running workflows, you must specify the domain on which you want to execute them.\\n\\nThe Cadence worker, also known as the worker service, is a separate binary process that you need to implement in order to host your workflows and activities. When developing a worker, ensure that all your workflows and activities are properly registered with it. The worker is an actively running application, and you have the freedom to choose the hosting technologies that best suit your needs, such as a simple HTTP or gRPC application.\\n\\nUltimately, you will need to set up two running processes on your local machine: the Cadence server and the worker. Additionally, you must register the Cadence domain as a resource. Our team has packaged all these components into user-friendly tools, which you can find on our website."},{"id":"/2023/06/30/community-spotlight-june-2023","metadata":{"permalink":"/Cadence-Docs/blog/2023/06/30/community-spotlight-june-2023","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2023-06-30-community-spotlight-june-2023.md","source":"@site/blog/2023-06-30-community-spotlight-june-2023.md","title":"Cadence Community Spotlight Update - June 2023","description":"We\'ve had a short break but now we are back. Welcome to the latest of our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!","date":"2023-06-30T00:00:00.000Z","tags":[{"inline":false,"label":"Community Spotlight","permalink":"/Cadence-Docs/blog/tags/community-spotlights","description":"Community Spotlight tag description"},{"inline":false,"label":"Releases","permalink":"/Cadence-Docs/blog/tags/releases","description":"Releases tag description"}],"readingTime":2.725,"hasTruncateMarker":true,"authors":[{"name":"Sharan Foga","title":"Director of Operations & Customer Success @ Encube Technologies","url":"https://www.linkedin.com/in/sfoga/","page":{"permalink":"/Cadence-Docs/blog/authors/sharanf"},"socials":{"linkedin":"https://www.linkedin.com/in/sfoga/","github":"https://github.com/sharanf"},"imageURL":"https://github.com/sharanf.png","key":"sharanf"}],"frontMatter":{"title":"Cadence Community Spotlight Update - June 2023","date":"2023-06-30T00:00:00.000Z","authors":"sharanf","tags":["community-spotlight","release"]},"unlisted":false,"prevItem":{"title":"Understanding components of Cadence application","permalink":"/Cadence-Docs/blog/2023/06/28/components-of-cadence-application-setup"},"nextItem":{"title":"2023 Cadence Community Survey Results","permalink":"/Cadence-Docs/blog/2023/06/08/2023-06-08-survey-results/survey-results"}},"content":"We\'ve had a short break but now we are back. Welcome to the latest of our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!\\n\\nPlease see below for a roundup of the highlights:\\n\\n## Cadence Release 1.0 ##\\n\\nJust in case you missed it - at the end of April [Cadence v1.0](https://github.com/cadence-workflow/cadence/releases/tag/v1.0.0) was officially released. This release is a significant milestone for the project and the community. It indicates that we are confident in the stability of the code that we can recommend it and promote it widely to more users. Kudos to everyone that worked together to make this release happen.\\n\\nAnd the Uber team also gave Cadence a writeup on the [Uber Engineering Blog](https://www.uber.com/en-SE/blog/announcing-cadence/) so please take a look.\\n\\n\x3c!-- truncate --\x3e\\n\\n## Community Survey Results ##\\n\\nThe results of our Community Survey have been published and you can find [the details right here on our blog](https://cadenceworkflow.io/blog/2023/06/08/survey-results/). From the results we can see that:\\n\\n- our community is a good mix of people using, evaluating, testing or thinking about migrating to Cadence\\n- Software Engineers featured highly as a community user profile\\n- Europe seems to be the most common community timezone\\n- People prefer using our Slack channel for questions\\n- Debugging is what most people need help with\\n\\nThank you to Ender for compiling the data and to everyone who participated.\\n\\n## Cadence Video Open Source Summit, North America ##\\nIn May [Ender Demirkaya](https://www.linkedin.com/in/enderdemirkaya/) gave a talk called on Cadence at the Linux Foundation\'s [Open Source Summit, North America](https://events.linuxfoundation.org/open-source-summit-north-america/) in Vancouver. The presentation attracted a sizeable audience and was very well received. There was also a lot of questions from the audience which is a sign that Cadence sounded potentially useful to them.\\n\\nA recording of the talk [Cadence: The New Open Source Project for Building Complex Distributed Applications](https://www.youtube.com/watch?v=vFPJlE6d4xs) is now available.\\n\\n## Overcoming Potential Workflow Versioning Maintenance Challenges ##\\n\\nCommunity member [Quanzheng Long](https://www.linkedin.com/in/prclqz/) has written a [detailed article on Medium](https://medium.com/@qlong/how-to-overcome-some-maintenance-challenges-of-temporal-cadence-workflow-versioning-f893815dd18d) about some of the potential maintenance challenges of workflow versioning. It\'s a short read and has some good examples that explains the potential problems and identifies some approaches for dealing with them.\\n\\nThanks Long for sharing this knowledge with the community!\\n\\n## Cadence in the News!\\n\\nBelow are a selection of Cadence related articles, blogs and whitepapers. Please take a look and feel free to share via your own social media channels.\\n\\n- [Announcing Cadence 1.0: The Powerful Workflow Platform Built for Scale and Reliability](https://www.uber.com/en-SE/blog/announcing-cadence/)\\n\\n- [Cadence 1.0 Released on the Instaclustr Managed Platform](https://www.instaclustr.com/blog/cadence-1-0-released-on-the-instaclustr-managed-platform/)\\n\\n- [How to Overcome Some Maintenance Challenges of Temporal/Cadence Workflow Versioning](https://medium.com/@qlong/how-to-overcome-some-maintenance-challenges-of-temporal-cadence-workflow-versioning-f893815dd18d)\\n\\n- [Video: Cadence - The New Open Source Project for Building Complex Distributed Applications](https://www.youtube.com/watch?v=vFPJlE6d4xs)\\n\\n- [Instaclustr Releases Multi-Region Cadence Workflow](https://www.instaclustr.com/blog/instaclustr-releases-multi-region-cadence-workflow-2/)\\n\\n- [Understanding Components of Cadence Application](https://cadenceworkflow.io/blog/2023/07/01/components-of-cadence-application-setup/)\\n\\n- [Improving the Reliability of Cadence Search Queries That Use OpenSearch/Elasticsearch](https://www.instaclustr.com/blog/improving-the-reliability-of-cadence-search-queries/)\\n\\n- [Instaclustr Cadence Workflow Developer Offering Hits General Availability](https://www.instaclustr.com/blog/instaclustr-cadence-workflow-developer/)\\n\\n## Upcoming Events\\n\\n- None\\n\\nIf you have any news or topics you\'d like us to include in our next update then please join our [Slack](http://t.uber.com/cadence-slack)#community channel.\\n\\nPlease remember that this update is for you - so if you have any comments or feedback that could help us improve it then please share it with us in the #community [Slack](http://t.uber.com/cadence-slack) channel."},{"id":"/2023/06/08/2023-06-08-survey-results/survey-results","metadata":{"permalink":"/Cadence-Docs/blog/2023/06/08/2023-06-08-survey-results/survey-results","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2023-06-08-survey-results/2023-06-08-survey-results.md","source":"@site/blog/2023-06-08-survey-results/2023-06-08-survey-results.md","title":"2023 Cadence Community Survey Results","description":"We released a user survey earlier this year to learn about who our users are, how they use Cadence, and how we can help them. It was shared from our Slack workspace, cadenceworkflow.io Blog and LinkedIn. After collecting the feedback, we wanted to share the results with our community. Thank you everyone for filling it out! Your feedback is invaluable and it helps us shape our roadmap for the future.","date":"2023-06-08T00:00:00.000Z","tags":[{"inline":false,"label":"Announcement","permalink":"/Cadence-Docs/blog/tags/announcements","description":"Announcement tag description"}],"readingTime":3.255,"hasTruncateMarker":true,"authors":[{"name":"Ender Demirkaya","title":"Senior Manager at Uber, Cadence. Author of the Software Engineering Handbook","url":"https://www.linkedin.com/in/enderdemirkaya/","page":{"permalink":"/Cadence-Docs/blog/authors/enderdemirkaya"},"socials":{"linkedin":"https://www.linkedin.com/in/enderdemirkaya/","github":"https://github.com/demirkayaender"},"imageURL":"https://github.com/demirkayaender.png","key":"enderdemirkaya"}],"frontMatter":{"title":"2023 Cadence Community Survey Results","date":"2023-06-08T00:00:00.000Z","authors":"enderdemirkaya","tags":["announcement"]},"unlisted":false,"prevItem":{"title":"Cadence Community Spotlight Update - June 2023","permalink":"/Cadence-Docs/blog/2023/06/30/community-spotlight-june-2023"},"nextItem":{"title":"Cadence Community Spotlight Update - March 2023","permalink":"/Cadence-Docs/blog/2023/03/31/community-spotlight-march-2023"}},"content":"We released a user survey earlier this year to learn about who our users are, how they use Cadence, and how we can help them. It was shared from our [Slack workspace](https://uber-cadence.slack.com/), [cadenceworkflow.io](https://cadenceworkflow.io) Blog and [LinkedIn](https://www.linkedin.com/company/cadenceworkflow/). After collecting the feedback, we wanted to share the results with our community. Thank you everyone for filling it out! Your feedback is invaluable and it helps us shape our roadmap for the future.\\n\\n\\nHere are some highlights in text and you can check out the visuals to get more details:\\n\\n![using.png](./2023-survey-results/using.png)\\n\\n![job_role.png](./2023-survey-results/job_role.png)\\n\\nMost of the people who replied to our survey were engineers who were already using Cadence, actively evaluating, or migrating from a similar technology. This was exciting to hear! Some of you have contacted us to learn more about benchmarks, scale, and ideal use cases. We will share more guidelines about this but until then, feel free to contact us over our Slack workspace for guidance.\\n\\n\x3c!-- truncate --\x3e\\n\\n![scale.png](./2023-survey-results/scale.png)\\n\\nThe scale our users operating Cadence varies from thousands to billions of workflows per month. It was exciting to see it being used in both small and large scale companies.\\n\\n![time_zone.png](./2023-survey-results/time_zone.png)\\n\\nMost survey responders were from Europe compared to any other place. This is in-line with the Cadence team growing its presence in Europe. Users from different places also contacted us to contribute to Cadence as a follow up to the survey. We will start putting up-for-grabs and new-starter tasks on Github. Several of them wanted to meet with a Zoom call and to discuss their use cases and best practices. As the Cadence team has presence in both the EU and the US, we welcome all our users to contact us anytime. Slack is the fastest way to reach us.\\n\\n![following.png](./2023-survey-results/following.png)\\n\\n![channels.png](./2023-survey-results/channels.png)\\n\\nCadence is followed in [Slack](https://uber-cadence.slack.com/) the most, then [Github](https://github.com/cadence-workflow/cadence) and [LinkedIn](https://www.linkedin.com/company/cadenceworkflow/). We are the most active in Slack and we plan to be more active in other mediums as well.\\n\\n![scenarios.png](./2023-survey-results/scenarios.png)\\nAll of our main use cases were used across the board. While we mentioned the most common cases, several others were mentioned as a comment: enhanced timers, leader election etc.\\n\\nWe found out that Cadence has been used in several science communities. Some of them were using community built clients and were asking if we are going to support more languages. We are planning to take ownership of the Python and Javascript/Typescript clients and support them officially.\\n\\n![improvement.png](./2023-survey-results/improvement.png)\\n\\nDocumentation is by far what our users wanted improvements on. We are revamping our documentation soon and there will be major changes on our website soon.\\n\\n![help_stage.png](./2023-survey-results/help_stage.png)\\n\\nOther requests were about observability, debuggability, operability, and usability. These areas have been our main focus this year and we are planning to release updates and blogs about them.\\n\\n![support.png](./2023-survey-results/support.png)\\n\\nWe noticed most of our users need help once a month or more. While we welcome questions and discussions over the mediums mentioned above, we plan to make more public posts about the common issues using our blog, StackOverflow, LinkedIn, or Twitter.\\n\\nMany users wanted to hear more from Cadence about the roadmap and its growth. Our posts about these will be released soon. Expect more posts about upcoming features, investments, scale, and community updates. Follow us at [LinkedIn](https://www.linkedin.com/company/cadenceworkflow/) for such updates.\\n\\nOur users are interested in learning more about guidelines, capacity expectations in on-prem and in managed solutions. While we have been providing feedback per user basis before, we plan to release more generic guidelines with our observability updates mentioned above.\\n\\nWe also would like to thank our community for the increased interest and engagement with us! Cadence has been more active in different mediums (LinkedIn, Slack, blog, etc.) this year. In the first quarter, we observed that our user base and activities has almost doubled (+96% and +90% respectively) through both new and returning users. Based on such immediate positive reactions, we will keep increasing our community investments in different channels."},{"id":"/2023/03/31/community-spotlight-march-2023","metadata":{"permalink":"/Cadence-Docs/blog/2023/03/31/community-spotlight-march-2023","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2023-03-31-community-spotlight-march-2023.md","source":"@site/blog/2023-03-31-community-spotlight-march-2023.md","title":"Cadence Community Spotlight Update - March 2023","description":"Welcome to the latest of our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!","date":"2023-03-31T00:00:00.000Z","tags":[{"inline":false,"label":"Community Spotlight","permalink":"/Cadence-Docs/blog/tags/community-spotlights","description":"Community Spotlight tag description"}],"readingTime":1.885,"hasTruncateMarker":true,"authors":[{"name":"Sharan Foga","title":"Director of Operations & Customer Success @ Encube Technologies","url":"https://www.linkedin.com/in/sfoga/","page":{"permalink":"/Cadence-Docs/blog/authors/sharanf"},"socials":{"linkedin":"https://www.linkedin.com/in/sfoga/","github":"https://github.com/sharanf"},"imageURL":"https://github.com/sharanf.png","key":"sharanf"}],"frontMatter":{"title":"Cadence Community Spotlight Update - March 2023","date":"2023-03-31T00:00:00.000Z","authors":"sharanf","tags":["community-spotlight"]},"unlisted":false,"prevItem":{"title":"2023 Cadence Community Survey Results","permalink":"/Cadence-Docs/blog/2023/06/08/2023-06-08-survey-results/survey-results"},"nextItem":{"title":"Cadence Community Spotlight Update - March 2024","permalink":"/Cadence-Docs/blog/2024/3/11/community-spotlight-update-march-2024"}},"content":"Welcome to the latest of our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!\\n\\nPlease see below for a roundup of the highlights:\\n\\n## Cadence at Open Source Summit, North America ##\\nWe are very pleased to let you know that a talk on Cadence has been accepted for the Linux Foundation\'s [Open Source Summit, North America](https://events.linuxfoundation.org/open-source-summit-north-america/) in Vancouver on 10th - 12th May 2023.\\n\\nThe talk called [Cadence: The New Open Source Project for Building Complex Distributed Applications](https://ossna2023.sched.com/event/1K5B1) will be given by [Ender Demirkaya](https://www.linkedin.com/in/enderdemirkaya/) and [Emrah Seker](https://www.linkedin.com/in/emrahseker/) If you are planning to attend the Open Source Summit then please don\'t forget to attend the talk and take time catch up with Ender and Emrah!\\n\\n## Community Activity ##\\nOur Slack #support channel has been very active over the last few months as we continue to get an continual stream of questions. Here are the stats:\\n\\n- February 2023 : 16 questions asked\\n- March 2023 : 12 questions asked\\n\\nAll of these questions are being answered collaboratively by the community. Thanks everyone for sharing your knowledge and we are looking forward to receiving more of your questions!\\n\\n\x3c!-- truncate --\x3e\\n\\n## Cadence Developer Advocate ##\\nPlease welcome Yizhe Qin - the new Cadence Developer Advocate from Uber team that will be working to help support the community.\\n\\nYizhe\'s role will involve responding to support questions, organising documentation and anything else that will help keep the community running smoothly.\\n\\nPlease feel free to say Hi to Yizhe on the Slack channel!\\n\\n## Cadence in the News!\\n\\nBelow are a selection of Cadence related articles, blogs and whitepapers. Please take a look and feel free to share via your own social media channels.\\n\\n- [Instaclustr Cadence Developer Offering - General Availability](https://www.instaclustr.com/blog/instaclustr-cadence-workflow-developer/)\\n\\n- [Improving Reliability of Cadence Search Queries That Use OpenSearch/Elasticsearch](https://www.instaclustr.com/blog/improving-the-reliability-of-cadence-search-queries/)\\n\\n## Upcoming Events\\n\\n- [Webinar: Microservices - A Modern Orchestration Approach with Cadence](https://netapp.zoom.us/webinar/register/WN__5fuwxmNQuWeZ6DiI5wUqg)\\n\\nIf you have any news or topics you\'d like us to include in our next update then please join our [Slack](http://t.uber.com/cadence-slack)#community channel.\\n\\nPlease remember that this update is for you - so if you have any comments or feedback that could help us improve it then please share it with us in the #community [Slack](http://t.uber.com/cadence-slack) channel."},{"id":"/2024/3/11/community-spotlight-update-march-2024","metadata":{"permalink":"/Cadence-Docs/blog/2024/3/11/community-spotlight-update-march-2024","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2024-3-11-community-spotlight-update-march-2024.md","source":"@site/blog/2024-3-11-community-spotlight-update-march-2024.md","title":"Cadence Community Spotlight Update - March 2024","description":"Welcome back to the latest in our regular Cadence community spotlight updates where we aim to deliver you news from in and around the Cadence community!","date":"2023-03-11T00:00:00.000Z","tags":[{"inline":false,"label":"Community Spotlight","permalink":"/Cadence-Docs/blog/tags/community-spotlights","description":"Community Spotlight tag description"}],"readingTime":2.91,"hasTruncateMarker":true,"authors":[{"name":"Kevin Corbett","title":"Open Source Community Manager | @instaclustr @NetApp","url":"https://github.com/kcorbett-netapp","page":{"permalink":"/Cadence-Docs/blog/authors/kcorbett-netapp"},"socials":{"linkedin":"https://www.linkedin.com/in/kcorb95/","github":"https://github.com/kcorbett-netapp"},"imageURL":"https://github.com/kcorbett-netapp.png","key":"kcorbett-netapp"}],"frontMatter":{"title":"Cadence Community Spotlight Update - March 2024","date":"2023-03-11T00:00:00.000Z","authors":"kcorbett-netapp","tags":["community-spotlight"]},"unlisted":false,"prevItem":{"title":"Cadence Community Spotlight Update - March 2023","permalink":"/Cadence-Docs/blog/2023/03/31/community-spotlight-march-2023"},"nextItem":{"title":"Cadence Community Spotlight Update - February 2023","permalink":"/Cadence-Docs/blog/2023/02/28/community-spotlight-february"}},"content":"Welcome back to the latest in our regular Cadence community spotlight updates where we aim to deliver you news from in and around the Cadence community!\\nIt\u2019s been a few months since our [last update](https://cadenceworkflow.io/blog/2023/11/30/community-spotlight-update-november-2023/), so I have a bunch of exciting updates to share.\\n\\nLet\u2019s get started!\\n\\n## Proposal for Cadence Plugin System ##\\nCommunity member [Mantas Sidlauskas](https://lt.linkedin.com/in/mantassidlauskas) drafted a thorough proposal around putting together a plugin system in Cadence. Aimed at enhancing the flexibility of integrating various components like storage, document search, and archival, this system encourages the use of external plugins, promoting innovation and reducing dependency complications. Your insights and feedback are crucial; learn more and contribute your thoughts at the link below:\\n\\n- [Cadence Plugin System Proposal](https://github.com/cadence-workflow/cadence/issues/5593)\\n\\nA huge thank you to Mantas for initiating this work. This is an excellent example of how we can collaborate together to bring about new features that benefit us all.\\n\\n\x3c!-- truncate --\x3e\\n\\n## Admin API Permissions Rethinking ##\\nThe community is deliberating on the permission requirements for the Admin API DescribeCluster endpoint. This vital discussion aims to ensure Cadence web\'s accessibility across different user levels. We\'re exploring various solutions and your participation would greatly influence the decision-making process. Feel free to chime in [here](https://github.com/cadence-workflow/cadence/issues/5683)!\\n\\n## New Java Samples for Cadence: Signal Workflow Interactions ##\\nIn some exciting news for Java enthusiasts, a new sample has been added to the Cadence Java Samples repository, demonstrating how to initiate and interact with a signal workflow using the Cadence client. This practical example is a huge win for developers looking to deepen their understanding of workflow signaling in Java. Explore the new sample and expand your Cadence toolkit [here](https://github.com/cadence-workflow/cadence-java-samples/pull/78).\\n\\n## New GoLang client & Cadence Web Enhancements ##\\nUpdates to the Cadence GoLang Client and Cadence Web have been rolled out, bringing new features and improvements that streamline user experiences. Highlights include upgraded Cassandra images, refined workflow interceptors, and more intuitive Cadence Web interfaces. Discover the full scope of updates on our GitHub repositories.\\n\\n- [GoLang Client Releases](https://github.com/cadence-workflow/cadence-go-client/releases)\\n- [Cadence Web Releases](https://github.com/cadence-workflow/cadence-web/releases)\\n\\n## Release Updates: v1.2.6 & v1.2.7 ##\\nCadence recently saw the release of versions v1.2.6 and v1.2.7, featuring significant improvements and fixes that enhance the overall Cadence experience. These updates reflect a commitment to respond to the community\'s valuable feedback. Check out the detailed release notes on the [GitHub releases page](https://github.com/cadence-workflow/cadence/releases)!\\n\\n## Cadence in the News! ##\\nBelow is a selection of Cadence related articles and blogs. Take a look and feel free to share your own with us via your own social media channels!\\n\\n- [How to Avoid \u201cDomain update too frequent\u201d Error in Multi-Region Cadence](https://www.instaclustr.com/blog/how-to-avoid-domain-update-too-frequent-error-in-multi-region-cadence/)\\n- [Build a Digital Collectibles Portal Using Flow and Cadence (Part 1)](https://levelup.gitconnected.com/build-a-digital-collectibles-portal-using-flow-and-cadence-part-1-2783f2902ef6)\\n\\n## Recent Events ##\\nCheck out this recent webinar, \\"Building with Cadence: Quantifiable Efficiency,\\" available on-demand now. Discover the robust features of Cadence and how it can streamline the development of distributed applications through an engaging demonstration by [John Del Castillo](https://au.linkedin.com/in/john-del-castillo-28b87b90?trk=people-guest_people_search-card).\\n\\n- [On Demand: Building with Cadence: Quantifiable Efficiency](https://netapp.zoom.us/webinar/register/WN_jT5fxSldRhuzV0NSllBd7g#/registration)\\n\\n\\n\\\\\\n\\\\\\n\\\\\\nThat\u2019s all for this month!\\n\\nYour engagement and contributions are what make the Cadence community thrive. Whether you have innovative ideas, insightful feedback, or just want to chat about Cadence, we encourage you to join our [Slack #community channel](http://t.uber.com/cadence-slack).\\n\\nWe\'re committed to making this update as useful and informative as possible, so please share any feedback or suggestions you might have. Let\u2019s keep building a vibrant and collaborative Cadence community together!\\n\\nLooking forward to sharing more exciting updates next month!"},{"id":"/2023/02/28/community-spotlight-february","metadata":{"permalink":"/Cadence-Docs/blog/2023/02/28/community-spotlight-february","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2023-02-28-community-spotlight-february.md","source":"@site/blog/2023-02-28-community-spotlight-february.md","title":"Cadence Community Spotlight Update - February 2023","description":"Here\u2019s the latest in our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!","date":"2023-02-28T00:00:00.000Z","tags":[{"inline":false,"label":"Community Spotlight","permalink":"/Cadence-Docs/blog/tags/community-spotlights","description":"Community Spotlight tag description"}],"readingTime":1.875,"hasTruncateMarker":true,"authors":[{"name":"Sharan Foga","title":"Director of Operations & Customer Success @ Encube Technologies","url":"https://www.linkedin.com/in/sfoga/","page":{"permalink":"/Cadence-Docs/blog/authors/sharanf"},"socials":{"linkedin":"https://www.linkedin.com/in/sfoga/","github":"https://github.com/sharanf"},"imageURL":"https://github.com/sharanf.png","key":"sharanf"}],"frontMatter":{"title":"Cadence Community Spotlight Update - February 2023","date":"2023-02-28T00:00:00.000Z","authors":"sharanf","tags":["community-spotlight"]},"unlisted":false,"prevItem":{"title":"Cadence Community Spotlight Update - March 2024","permalink":"/Cadence-Docs/blog/2024/3/11/community-spotlight-update-march-2024"},"nextItem":{"title":"Cadence Community Spotlight Update - January 2023","permalink":"/Cadence-Docs/blog/2023/01/31/community-spotlight-january-2023"}},"content":"Here\u2019s the latest in our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!\\n\\nPlease see below for a roundup of the highlights:\\n\\n## Community Survey ##\\nWe\'ve been talking about doing a community survey for a while and during February we sent it out. We are still collating the results so it\'s not too late to send in your response.\\n\\nThe survey takes 5 minutes and is your opportunity to provide feedback to the project and highlight areas you think we need to focus on.\\n\\nUse this [Survey Link](https://uber.surveymonkey.com/r/ZS83WJW)\\n\\nPlease take a few minutes to give us your opinion.\\n\\n\x3c!-- truncate --\x3e\\n\\n## Cadence and Temporal ##\\nDuring user surveys we\'ve had a few queries about whether Cadence and [Temporal](https://temporal.io/) are the same project. The answer is No - they are not the same project but they do share the same origin. At a high level Temporal is a fork of the Cadence project. Both Temporal and Cadence are now being developed by different communities so are independent.\\n\\n## Cadence at DoorDash ##\\nAlthough published a few months ago we missed including an article by [DoorDash](https://doordash.engineering/) about how they are using Cadence to build real time event processing with [Apache Flink](https://flink.apache.org/) and [Apache Kafka](https://kafka.apache.org/).\\n\\nHere is the link to the article: [Building Scalable Real Time Event Processing with Kafka and Flink](https://doordash.engineering/2022/08/02/building-scalable-real-time-event-processing-with-kafka-and-flink/)\\n\\nRemember to let us know if you have news, articles or blog posts about Cadence that you\'d like us to include in these monthly updates.\\n\\n## Cadence in the News!\\n\\nBelow are a selection of Cadence related articles, blogs and whitepapers. Please take a look and feel free to share via your own social media channels.\\n\\n- [Getting Started with Cadence, an Open Source Workflow Engine](https://opensource.com/article/22/6/cadence-open-source-workflow-engine)\\n\\n- [Meet Cadence: Workflow Engine for Taming Complex Processes](https://thenewstack.io/meet-cadence-workflow-engine-for-taming-complex-processes/)\\n\\n## Upcoming Events\\n\\n- [On Demand Webinar: Spinning Your Drones with Cadence and Apache Kafka](https://info.instaclustr.com/webinar-spinning-drones-cadence-kafka.html)\\n\\nIf you have any news or topics you\'d like us to include in our next update then please join our [Slack](http://t.uber.com/cadence-slack)#community channel.\\n\\nPlease remember that this update is for you - so if you have any comments or feedback that could help us improve it then please share it with us in the #community [Slack](http://t.uber.com/cadence-slack) channel."},{"id":"/2023/01/31/community-spotlight-january-2023","metadata":{"permalink":"/Cadence-Docs/blog/2023/01/31/community-spotlight-january-2023","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2023-01-31-community-spotlight-january-2023.md","source":"@site/blog/2023-01-31-community-spotlight-january-2023.md","title":"Cadence Community Spotlight Update - January 2023","description":"Happy New Year everyone! Here\u2019s the latest in our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!","date":"2023-01-31T00:00:00.000Z","tags":[{"inline":false,"label":"Community Spotlight","permalink":"/Cadence-Docs/blog/tags/community-spotlights","description":"Community Spotlight tag description"}],"readingTime":2.06,"hasTruncateMarker":true,"authors":[{"name":"Sharan Foga","title":"Director of Operations & Customer Success @ Encube Technologies","url":"https://www.linkedin.com/in/sfoga/","page":{"permalink":"/Cadence-Docs/blog/authors/sharanf"},"socials":{"linkedin":"https://www.linkedin.com/in/sfoga/","github":"https://github.com/sharanf"},"imageURL":"https://github.com/sharanf.png","key":"sharanf"}],"frontMatter":{"title":"Cadence Community Spotlight Update - January 2023","date":"2023-01-31T00:00:00.000Z","authors":"sharanf","tags":["community-spotlight"]},"unlisted":false,"prevItem":{"title":"Cadence Community Spotlight Update - February 2023","permalink":"/Cadence-Docs/blog/2023/02/28/community-spotlight-february"},"nextItem":{"title":"Cadence Community Spotlight Update - December 2022","permalink":"/Cadence-Docs/blog/2022/12/23/community-spotlight-december-2022"}},"content":"Happy New Year everyone! Here\u2019s the latest in our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!\\n\\nPlease see below for a roundup of the highlights:\\n\\n## Closing Down Cadence Office Hours ##\\nWe have been running Office Hours sessions every month since May last year. The aim was to give the community an opportunity to speak directly with some of the Cadence core developers and experts to answer questions on particular issues you may be having. We have found that the most preferred method for community questions has been the support Slack channel so have decided to stop this monthly call.\\n\\nThanks very much to [Ender Demirkaya](https://www.linkedin.com/in/enderdemirkaya/)and the Uber team for making themselves available for these sessions.\\n\\nPlease remember that if you have question about Cadence or are facing a specific issue then you can post your question in our #support [Slack](http://t.uber.com/cadence-slack) channel. If you also post the details on StackOverflow with the cadence workflow tag then there will be a searchable history for others who encounter the same issue to find a solution.\\n\\n\x3c!-- truncate --\x3e\\n\\n## Update on iWF Support for Cadence ##\\nLast October we featured an update in our monthly blog about [iWF - Interpreter for Workflow](https://github.com/indeedeng/iwf), a project built on top of Cadence by community member [Quanzheng Long](https://www.linkedin.com/in/prclqz/). It was announced recently that iWF has released a [Golang SDK](https://github.com/iworkflowio/iwf-golang-sdk) and updated versions of the [Java SDK and server](https://github.com/indeedeng/iwf).\\n\\nLong is really keen to get feedback so please take a look at iWF, try them out and presented him any feedback.\\nLong has also created a couple of blog posts about iWF that we have featured in the Cadence in the News section below so please take a look.\\n\\n## Cadence in the News!\\n\\nBelow are a selection of Cadence related articles, blogs and whitepapers. Please take a look and feel free to share via your own social media channels.\\n\\n- [A Letter to Cadence/Temporal and Workflow Tech Community](https://medium.com/@qlong/a-letter-to-cadence-temporal-and-workflow-tech-community-b32e9fa97a0c)\\n\\n- [iWF vs Cadence/Temporal](https://medium.com/@qlong/iwf-vs-cadence-temporal-1e11b35960fe)\\n\\n- [AWS PrivateLink Connectivity Is Now Available with Instaclustr for Cadence](https://www.instaclustr.com/blog/aws-privatelink-for-cadence-on-instaclustr-by-netapp/)\\n\\n## Upcoming Events\\n\\nNo upcoming events at the moment.\\n\\nIf you have any news or topics you\'d like us to include in our next update then please join our [Slack](http://t.uber.com/cadence-slack)#community channel.\\n\\nPlease remember that this update is for you - so if you have any comments or feedback that could help us improve it then please share it with us in the #community [Slack](http://t.uber.com/cadence-slack) channel."},{"id":"/2022/12/23/community-spotlight-december-2022","metadata":{"permalink":"/Cadence-Docs/blog/2022/12/23/community-spotlight-december-2022","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2022-12-23-community-spotlight-december-2022.md","source":"@site/blog/2022-12-23-community-spotlight-december-2022.md","title":"Cadence Community Spotlight Update - December 2022","description":"I know we are a little early this month as many people will be taking some time out for holidays.","date":"2022-12-23T00:00:00.000Z","tags":[{"inline":false,"label":"Community Spotlight","permalink":"/Cadence-Docs/blog/tags/community-spotlights","description":"Community Spotlight tag description"}],"readingTime":1.08,"hasTruncateMarker":true,"authors":[{"name":"Sharan Foga","title":"Director of Operations & Customer Success @ Encube Technologies","url":"https://www.linkedin.com/in/sfoga/","page":{"permalink":"/Cadence-Docs/blog/authors/sharanf"},"socials":{"linkedin":"https://www.linkedin.com/in/sfoga/","github":"https://github.com/sharanf"},"imageURL":"https://github.com/sharanf.png","key":"sharanf"}],"frontMatter":{"title":"Cadence Community Spotlight Update - December 2022","date":"2022-12-23T00:00:00.000Z","authors":"sharanf","tags":["community-spotlight"]},"unlisted":false,"prevItem":{"title":"Cadence Community Spotlight Update - January 2023","permalink":"/Cadence-Docs/blog/2023/01/31/community-spotlight-january-2023"},"nextItem":{"title":"Cadence Community Spotlight Update - November 2022","permalink":"/Cadence-Docs/blog/2022/11/30/community-spotlight-november-2022"}},"content":"I know we are a little early this month as many people will be taking some time out for holidays.\\n\\n## Happy Holidays ##\\n\\nWe\'d like to wish everyone happy holidays and to thank you for being part of the Cadence community. It\'s been a busy year for Cadence as we have continued to build a strong, active community that works together to solve issues and generally support each other.\\n\\nLet\'s keep going!...This is a great way to build a sustainable community.\\n\\nWe are sure that 2023 will be even more exciting as we continue to develop Cadence.\\n\\n## Cadence in the News!\\n\\nBelow are a selection of Cadence related articles, blogs and whitepapers. Please take a look and feel free to share via your own social media channels.\\n\\n- [Cadence iWF](https://www.instaclustr.com/blog/cadence-iwf)\\n\\n- [Child Workflow Cookbook](https://github.com/instaclustr/cadence-cookbooks-instafood/blob/main/cookbooks/child-workflows/child-workflows-megafood.md)\\n\\n- [Cadence Connection Examples Using TLS](https://www.instaclustr.com/blog/cadence-connection-examples-using-tls/)\\n\\n\x3c!-- truncate --\x3e\\n\\n## Upcoming Events\\n\\n- [Cadence Technical Office Hours - 30th January 2023 @ 9am PT](https://calendar.google.com/calendar/u/0/embed?src=e6r40gp3c2r01054id7e99dlac@group.calendar.google.com&ctz=America/Los_Angeles)\\n\\nIf you have any news or topics you\'d like us to include in our next update then please join our [Slack](http://t.uber.com/cadence-slack)#community channel.\\n\\nPlease remember that this update is for you - so if you have any comments or feedback that could help us improve it then please share it with us in the #community [Slack](http://t.uber.com/cadence-slack) channel."},{"id":"/2022/11/30/community-spotlight-november-2022","metadata":{"permalink":"/Cadence-Docs/blog/2022/11/30/community-spotlight-november-2022","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2022-11-30-community-spotlight-november-2022.md","source":"@site/blog/2022-11-30-community-spotlight-november-2022.md","title":"Cadence Community Spotlight Update - November 2022","description":"Here\u2019s the latest in our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!","date":"2022-11-30T00:00:00.000Z","tags":[{"inline":false,"label":"Community Spotlight","permalink":"/Cadence-Docs/blog/tags/community-spotlights","description":"Community Spotlight tag description"}],"readingTime":1.91,"hasTruncateMarker":true,"authors":[{"name":"Sharan Foga","title":"Director of Operations & Customer Success @ Encube Technologies","url":"https://www.linkedin.com/in/sfoga/","page":{"permalink":"/Cadence-Docs/blog/authors/sharanf"},"socials":{"linkedin":"https://www.linkedin.com/in/sfoga/","github":"https://github.com/sharanf"},"imageURL":"https://github.com/sharanf.png","key":"sharanf"}],"frontMatter":{"title":"Cadence Community Spotlight Update - November 2022","date":"2022-11-30T00:00:00.000Z","authors":"sharanf","tags":["community-spotlight"]},"unlisted":false,"prevItem":{"title":"Cadence Community Spotlight Update - December 2022","permalink":"/Cadence-Docs/blog/2022/12/23/community-spotlight-december-2022"},"nextItem":{"title":"Cadence Community Spotlight Update - October 2022","permalink":"/Cadence-Docs/blog/2022/10/31/community-spotlight-october-2022"}},"content":"Here\u2019s the latest in our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!\\n\\nPlease see below for a roundup of the highlights:\\n\\n## Cadence @ Uber ##\\n\\nThis month Uber Engineering published a really nice article on one of the ways they are using Cadence. The article is called [How Uber Optimizes the Timing of Push Notifications using ML and Linear Programming](https://www.uber.com/en-US/blog/how-uber-optimizes-push-notifications-using-ml/).\\n\\nThe Uber team take you through the details of the problem that they are looking to solve, so you can understand the scope limitations and depedencies - so please take a look.\\n\\n## Cadence @ DeveloperWeek Enterprise ##\\n\\nDevNetwork run a series of conferences and during November Cadence was featured in at [DeveloperWeek Enterprise](https://www.developerweek.com/global/conference/enterprise/). [Ender Demirkaya](https://www.linkedin.com/in/enderdemirkaya/) and [Ben Slater](https://www.linkedin.com/in/ben-slater-2720562/) presented a talk called [Espress Complex Business Logic as Code with Open Source Cadence!](https://embed.emamo.com/event/developerweek-enterprise-2022/s/express-complex-business-logic-as-code-with-open-source-cadence-WKLMvo).\\n\\nIt is good to see that we are finding new channels for us to present the benefits of using Cadence. Huge hanks to Ben and Ender for the presentation and to everyone that attended.\\n\\n\x3c!-- truncate --\x3e\\n\\n## Cadence at W-JAX ##\\n\\nIt must be presentation month as we have had yet another Cadence presentation! Earlier this month a Cadence talk was featured at the [W-JAX Conference](https://jax.de/munich/) in Munich, Germany. [Merlin Walter](https://www.linkedin.com/in/merlin-walter/) presented a talk called [Microservices - Modern Orchestration with Cadence](https://jax.de/microservices/microservices-modern-orchestration-approach-with-cadence/)\\n\\nSession feedback received was very positive and it\'s great to see that new audiences are interested in learning more about Cadence and seeing how it works.\\n\\n## Cadence in the News!\\n\\nBelow are a selection of Cadence related articles, blogs and whitepapers. Please take a look and feel free to share via your own social media channels.\\n\\n- [How Uber Optimizes the Timing of Push Notifications using ML and Linear Programming](https://www.uber.com/en-US/blog/how-uber-optimizes-push-notifications-using-ml/)\\n\\n- [Building with Cadence: Quantifiable Efficiency](https://www.instaclustr.com/blog/building-with-cadence-quantifiable-efficiency/)\\n\\n## Upcoming Events\\n\\n**PLEASE NOTE:** No Office Hours on 26th December 2022\\n\\n- [Cadence Technical Office Hours - 30th January 2023 @ 9am PT](https://calendar.google.com/calendar/u/0/embed?src=e6r40gp3c2r01054id7e99dlac@group.calendar.google.com&ctz=America/Los_Angeles)\\n\\nIf you have any news or topics you\'d like us to include in our next update then please join our [Slack](http://t.uber.com/cadence-slack)#community channel.\\n\\nPlease remember that this update is for you - so if you have any comments or feedback that could help us improve it then please share it with us in the #community [Slack](http://t.uber.com/cadence-slack) channel."},{"id":"/2022/10/31/community-spotlight-october-2022","metadata":{"permalink":"/Cadence-Docs/blog/2022/10/31/community-spotlight-october-2022","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2022-10-31-community-spotlight-october-2022.md","source":"@site/blog/2022-10-31-community-spotlight-october-2022.md","title":"Cadence Community Spotlight Update - October 2022","description":"Here\u2019s the latest in our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!","date":"2022-10-31T00:00:00.000Z","tags":[{"inline":false,"label":"Community Spotlight","permalink":"/Cadence-Docs/blog/tags/community-spotlights","description":"Community Spotlight tag description"}],"readingTime":1.93,"hasTruncateMarker":true,"authors":[{"name":"Sharan Foga","title":"Director of Operations & Customer Success @ Encube Technologies","url":"https://www.linkedin.com/in/sfoga/","page":{"permalink":"/Cadence-Docs/blog/authors/sharanf"},"socials":{"linkedin":"https://www.linkedin.com/in/sfoga/","github":"https://github.com/sharanf"},"imageURL":"https://github.com/sharanf.png","key":"sharanf"}],"frontMatter":{"title":"Cadence Community Spotlight Update - October 2022","date":"2022-10-31T00:00:00.000Z","authors":"sharanf","tags":["community-spotlight"]},"unlisted":false,"prevItem":{"title":"Cadence Community Spotlight Update - November 2022","permalink":"/Cadence-Docs/blog/2022/11/30/community-spotlight-november-2022"},"nextItem":{"title":"Cadence Community Spotlight Update - September 2022","permalink":"/Cadence-Docs/blog/2022/09/30/community-spotlight-september-2022"}},"content":"Here\u2019s the latest in our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!\\n\\nPlease see below for a roundup of the highlights:\\n\\n## Cadence Meetup Postponed ##\\n\\nIt\'s always great to get the community together and we had planned to run another Cadence Meetup in early November. Unfortunately we didn\'t have enough time to get things organised so we\'ve decided to postpone it. So please watch out for an announcement for the new Cadence meetup date.\\n\\n## Doordash Technnical Showcase Featuring Cadence\\n\\nWe have had some great feedback from people who attended Technical Showcase that was run this month by Doordash. It featured their financial products but also highlighted some of the key technologies they use...and guess what Cadence is one of them!\\n\\nIf you missed the session then you will be happy to know that it was recorded and we\'ve inlcuded a link to the [the recording on Youtube](https://www.youtube.com/watch?v=uNwbdQyLpns).\\n\\nThanks to the Doordash team for running the session and helping support Cadence by sharing their knowledge.\\n\\n\x3c!-- truncate --\x3e\\n\\n## iWF Support for Cadence ##\\n\\nCommunity member [Quanzheng Long](https://www.linkedin.com/in/prclqz/) has been busy working on a new project that has been built on top of Cadence. The project is called [iWF - Interpreter for Workflow](https://github.com/indeedeng/iwf). It\'s great to see that Cadence is now growing it\'s own ecosystem!\\n\\nPlease feel free to take a look and let Long know what you think!\\n\\n## Cadence in the News!\\n\\nBelow are a selection of Cadence related articles, blogs and whitepapers. Please take a look and feel free to share via your own social media channels.\\n\\n\\n- [Apache Airflow vs Cadence: A Side by Side Comparison](https://www.instaclustr.com/blog/airflow-vs-cadence-a-side-to-side-comparison/)\\n\\n- [Managing Custom Search Attributes for Advance Visibility Cadence](https://www.instaclustr.com/blog/managing-custom-search-attributes-for-advanced-visibility-cadence/)\\n\\n## Upcoming Events\\n\\n- [Webinar: Spinning Your Drones with Cadence and Apache Kafka - 15th November 2022](https://info.instaclustr.com/webinar-spinning-drones-cadence-kafka.html)\\n\\n- [Webinar: Fitting Cadence in Your Corporate Architecture - 24th November 2022](https://info.instaclustr.com/webinar-emea-fitting-cadence.html)\\n\\n- [Cadence Technical Office Hours - 28th November 2022 @ 9am PT](https://calendar.google.com/calendar/u/0/embed?src=e6r40gp3c2r01054id7e99dlac@group.calendar.google.com&ctz=America/Los_Angeles)\\n\\n\\nIf you have any news or topics you\'d like us to include in our next update then please join our [Slack](http://t.uber.com/cadence-slack)#community channel.\\n\\nPlease remember that this update is for you - so if you have any comments or feedback that could help us improve it then please share it with us in the #community [Slack](http://t.uber.com/cadence-slack) channel."},{"id":"/2022/09/30/community-spotlight-september-2022","metadata":{"permalink":"/Cadence-Docs/blog/2022/09/30/community-spotlight-september-2022","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2022-09-30-community-spotlight-september-2022.md","source":"@site/blog/2022-09-30-community-spotlight-september-2022.md","title":"Cadence Community Spotlight Update - September 2022","description":"Here\u2019s the latest in our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!","date":"2022-10-11T00:00:00.000Z","tags":[{"inline":false,"label":"Community Spotlight","permalink":"/Cadence-Docs/blog/tags/community-spotlights","description":"Community Spotlight tag description"}],"readingTime":1.585,"hasTruncateMarker":true,"authors":[{"name":"Sharan Foga","title":"Director of Operations & Customer Success @ Encube Technologies","url":"https://www.linkedin.com/in/sfoga/","page":{"permalink":"/Cadence-Docs/blog/authors/sharanf"},"socials":{"linkedin":"https://www.linkedin.com/in/sfoga/","github":"https://github.com/sharanf"},"imageURL":"https://github.com/sharanf.png","key":"sharanf"}],"frontMatter":{"title":"Cadence Community Spotlight Update - September 2022","date":"2022-10-11T00:00:00.000Z","authors":"sharanf","tags":["community-spotlight"]},"unlisted":false,"prevItem":{"title":"Cadence Community Spotlight Update - October 2022","permalink":"/Cadence-Docs/blog/2022/10/31/community-spotlight-october-2022"},"nextItem":{"title":"Cadence Community Spotlight Update - August 2022","permalink":"/Cadence-Docs/blog/2022/08/31/community-spotlight-august-2022"}},"content":"Here\u2019s the latest in our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!\\n\\nPlease see below for a roundup of the highlights:\\n\\n# Cadence at Developer Week\\n\\nA Cadence talk by [Ender Demirkaya](https://www.linkedin.com/in/enderdemirkaya/) and [Ben Slater](https://www.linkedin.com/in/ben-slater-2720562/) has been accepted for [Developer Week Enterprise](https://www.developerweek.com/global/conference/enterprise/).\\n\\nThe talk is scheduled to for 16th November so please make a note in your calendars.\\n\\n# Sharing Knowledge\\n\\nOver the last few months we have had a continual stream of Cadence questions in our [Slack](http://t.uber.com/cadence-slack) #support channel or on [StackOverflow](https://stackoverflow.com/questions/tagged/cadence-workflow). As a result of the increased interest some members from the Cadence core team have decided to spend some time each day responding to your questions.\\n\\nRemember that if you have received a response that has solved your problem especially on StackOverflow then please don\'t forget to accept answer!\\n\\n\x3c!-- truncate --\x3e\\n\\n## Cadence in the News!\\n\\nBelow are a selection of Cadence related articles, blogs and whitepapers. Please take a look and feel free to share via your own social media channels.\\n\\n- [Technical Showcase Event: DoorDash\'s Financial Products and Platforms\\n](https://www.youtube.com/watch?v=uNwbdQyLpns)\\n\\n- [Airflow vs Cadence: A Side by Side Comparison](https://www.instaclustr.com/blog/airflow-vs-cadence-a-side-to-side-comparison/)\\n\\n- [New Offering for Cadence Developers](https://www.instaclustr.com/blog/new-instaclustr-offering-for-cadence-developers/)\\n\\n- [Open Source Cadence Is Built for the Developer Experience \u2013 Here\u2019s How to Take Advantage](https://devm.io/open-source/open-source-cadence)\\n\\n## Upcoming Events\\n\\n- [Fitting Cadence in Your Corporate Architecture - 18th October 2022 @ 10am PT](https://info.instaclustr.com/webinar-fitting-cadence-in-corporate-architecture.html)\\n\\n- [Migrating Your Workflow Solution from Temporal to Cadence - 25th October 2022 @ 10am PT](https://info.instaclustr.com/webinar-fitting-cadence-in-corporate-architecture.html)\\n\\n- [Cadence Technical Office Hours - 31st October 2022 @ 9am PT](https://calendar.google.com/calendar/u/0/embed?src=e6r40gp3c2r01054id7e99dlac@group.calendar.google.com&ctz=America/Los_Angeles)\\n\\n\\nIf you have any news or topics you\'d like us to include in our next update then please join our [Slack](http://t.uber.com/cadence-slack)#community channel.\\n\\nPlease remember that this update is for you - so if you have any comments or feedback that could help us improve it then please share it with us in the #community [Slack](http://t.uber.com/cadence-slack) channel."},{"id":"/2022/08/31/community-spotlight-august-2022","metadata":{"permalink":"/Cadence-Docs/blog/2022/08/31/community-spotlight-august-2022","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2022-08-31-community-spotlight-august-2022.md","source":"@site/blog/2022-08-31-community-spotlight-august-2022.md","title":"Cadence Community Spotlight Update - August 2022","description":"Here\u2019s the latest in our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!","date":"2022-08-31T00:00:00.000Z","tags":[{"inline":false,"label":"Community Spotlight","permalink":"/Cadence-Docs/blog/tags/community-spotlights","description":"Community Spotlight tag description"}],"readingTime":2.83,"hasTruncateMarker":true,"authors":[{"name":"Sharan Foga","title":"Director of Operations & Customer Success @ Encube Technologies","url":"https://www.linkedin.com/in/sfoga/","page":{"permalink":"/Cadence-Docs/blog/authors/sharanf"},"socials":{"linkedin":"https://www.linkedin.com/in/sfoga/","github":"https://github.com/sharanf"},"imageURL":"https://github.com/sharanf.png","key":"sharanf"}],"frontMatter":{"title":"Cadence Community Spotlight Update - August 2022","date":"2022-08-31T00:00:00.000Z","authors":"sharanf","tags":["community-spotlight"]},"unlisted":false,"prevItem":{"title":"Cadence Community Spotlight Update - September 2022","permalink":"/Cadence-Docs/blog/2022/09/30/community-spotlight-september-2022"},"nextItem":{"title":"Cadence Community Spotlight Update - July 2022","permalink":"/Cadence-Docs/blog/2022/07/31/community-spotlight-update-july-2022"}},"content":"Here\u2019s the latest in our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!\\n\\nPlease see below for a roundup of the highlights:\\n\\n## Community Survey\\n\\nWe are working on putting together our first community survey to find out a bit more about our community. We would like to get your feedback about on a few things such as:\\n\\n- how you are using Cadence\\n- any specific experiences you have had where you\'d like to see new features\\n- any special use cases not yet covered\\n- and of course whatever other feedback you\'d like to give us\\n\\nSo please watch out for the survey which will be coming out to you via the Slack channel soon!\\n\\n\x3c!-- truncate --\x3e\\n\\n## Support Activity\\n\\nWe have noticed that community activity is increasing and that we are continuing to respond to questions in our Slack #support channel. Eight questions have been posted in the channel this month and another seven questions have been posted on StackOverflow. We encourage people to post their questions on StackOverflow so that the response can be shared. You can also post a link to the StackOverflow question in the support channel to be extra sure it gets seen by our community members.\\n\\nWe are looking always forward to receiving more of your questions!\\n\\n## GitHub Activity\\n\\nDo you remember our GitHub Statistics from last month? Don\'t worry if you don\'t! In July we had 28 pull requests (PRs) merged into the code repository. This month we have had 43 PRs merged (nearly double!)- so you can see the level of activity is also increasing in terms of the project code.\\n\\nIf you are interested in contributing to Cadence then please take a look at our [Contribution Guidelines](https://github.com/cadence-workflow/cadence/blob/86f645da952e15d7a7415cdf9fcd2726f28063a6/CONTRIBUTING.md) and also our list of [good first issues](https://github.com/cadence-workflow/cadence/contribute) to work on.\\n\\n## Come Along to Our Next Cadence Meetup!\\n\\nIt\'s been a while since we had a Cadence meetup so we have decided to organise another one. This time we are planning to do an in-person meetup in the San Francisco Bay area in early November. We are looking for any companies using Cadence to come along and speak about how they are using it. We\'d also like to hear about any interesting use cases that you have used Cadence for.\\n\\nIf you are interested in speaking at our next meetup then please contact [Ender Demirkaya](https://www.linkedin.com/in/enderdemirkaya/)\\n\\n## Looking for a Cadence Role?\\n\\nThe Cadence teeam at Uber are recruiting for a Fullstack Engineer. If you are interested then please contact [Ender Demirkaya](https://www.linkedin.com/in/enderdemirkaya/) for more details.\\n\\n## Cadence in the News!\\n\\nBelow are a selection of Cadence related articles, blogs and whitepapers. Please take a look and feel free to share via your own social media channels.\\n\\n- [Cadence Advanced Visibility: Enhance Your Workflows with Searchability](https://www.instaclustr.com/blog/cadence-advanced-visibility-enhance-your-workflows-with-searchability/)\\n\\n- [New Features for Instaclustr Managed Cadence](https://www.instaclustr.com/blog/new-features-for-instaclustr-managed-cadence/)\\n\\n## Upcoming Events\\n\\n- [Webinar: Building Your First Cadence Workflow with Java and Go - 1st September 2022](https://info.instaclustr.com/webinar-emea-building-cadence-workflow.html)\\n\\n- [Cadence Technical Office Hours - 26th September 2022 @ 9am PT](https://calendar.google.com/calendar/u/0/embed?src=e6r40gp3c2r01054id7e99dlac@group.calendar.google.com&ctz=America/Los_Angeles)\\n\\n\\nIf you have any news or topics you\'d like us to include in our next update then please join our [Slack](http://t.uber.com/cadence-slack)#community channel.\\n\\nPlease remember that this update is for you - so if you have any comments or feedback that could help us improve it then please share it with us in the #community [Slack](http://t.uber.com/cadence-slack) channel."},{"id":"/2022/07/31/community-spotlight-update-july-2022","metadata":{"permalink":"/Cadence-Docs/blog/2022/07/31/community-spotlight-update-july-2022","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2022-07-31-community-spotlight-update-july-2022.md","source":"@site/blog/2022-07-31-community-spotlight-update-july-2022.md","title":"Cadence Community Spotlight Update - July 2022","description":"Here\u2019s our monthly Community Spotlight update that gives you news from in and around the Cadence community!","date":"2022-07-31T00:00:00.000Z","tags":[{"inline":false,"label":"Community Spotlight","permalink":"/Cadence-Docs/blog/tags/community-spotlights","description":"Community Spotlight tag description"}],"readingTime":1.885,"hasTruncateMarker":true,"authors":[{"name":"Sharan Foga","title":"Director of Operations & Customer Success @ Encube Technologies","url":"https://www.linkedin.com/in/sfoga/","page":{"permalink":"/Cadence-Docs/blog/authors/sharanf"},"socials":{"linkedin":"https://www.linkedin.com/in/sfoga/","github":"https://github.com/sharanf"},"imageURL":"https://github.com/sharanf.png","key":"sharanf"}],"frontMatter":{"title":"Cadence Community Spotlight Update - July 2022","date":"2022-07-31T00:00:00.000Z","authors":"sharanf","tags":["community-spotlight"]},"unlisted":false,"prevItem":{"title":"Cadence Community Spotlight Update - August 2022","permalink":"/Cadence-Docs/blog/2022/08/31/community-spotlight-august-2022"},"nextItem":{"title":"Cadence Community Spotlight Update - June 2022","permalink":"/Cadence-Docs/blog/2022/06/30/community-spotlight-update-june-2022"}},"content":"Here\u2019s our monthly Community Spotlight update that gives you news from in and around the Cadence community!\\n\\nPlease see below for a roundup of the highlights:\\n\\n## Flying Drones with Cadence\\n\\nCommunity member [Paul Brebner](https://www.linkedin.com/in/paul-brebner-0a547b4/) has released [another blog](https://www.instaclustr.com/blog/spinning-your-drones-with-cadence-and-apache-kafka-how-many-drones-can-we-fly/) in the series of using Cadence to manage a drone delivery service. You can see a [simulated view of it in action](https://www.youtube.com/watch?v=YgQeFSqzprk)\\n\\nDon\u2019t forget to try out the code yourself and remember if you have used Cadence to do something interesting then please let us know so we can feature it in our next update.\\n\\n## GitHub Statistics\\n\\nDuring July the main Cadence branch had 28 pull requests (PRs) merged. There were 214 files changed by 11 different authors. You can find more details [here](https://github.com/cadence-workflow/cadence/pulse/monthly)\\n\\nThe Cadence documentation repository was not as busy with only 2 PRs merged in July, 5 commits and 3 authors active. More details can be found [here](https://github.com/cadence-workflow/Cadence-Docs/pulse/monthly )\\n\\n\x3c!-- truncate --\x3e\\n\\n## Cadence Roadmap\\n\\nThe Cadence Core team has been busy this month looking at the various community feedback for potential improvements and features for Cadence. Planning is already in place for a development roadmap and it is still a little too early to say what will be included so please watch out for future updates. All I know is that it\u2019s going to be exciting!\\n\\n## Cadence in the News!\\n\\nBelow are a selection of Cadence related articles, blogs and whitepapers. Please take a look and feel free to share via your own social media channels.\\n\\n- [Migrate to Cadence From Temporal](https://www.instaclustr.com/blog/migrate-to-cadence-from-temporal/)\\n\\n- [Spinning Your Drones With Cadence and Apache Kafka\xae: How Many Drones Can We Fly?](https://www.instaclustr.com/blog/spinning-your-drones-with-cadence-and-apache-kafka-how-many-drones-can-we-fly/)\\n\\n## Upcoming Events\\n\\n- [Cadence Technical Office Hours - 29th August 2022 @ 9am PT](https://calendar.google.com/calendar/u/0/embed?src=e6r40gp3c2r01054id7e99dlac@group.calendar.google.com&ctz=America/Los_Angeles)\\n\\n- [Webinar: Cadence Fundamentals: Event Sourcing - Two sessions one on 16th and one on 18th August 2022\\n](https://info.instaclustr.com/webinar-cadence-fundamentals-event-sourcing/)\\n\\n- [Webinar: Building Your First Cadence Workflow with Java and Go - 1st September 2022](https://info.instaclustr.com/webinar-emea-building-cadence-workflow.html)\\n\\nIf you have any news or topics you\'d like us to include in our next update then please join our [Slack](http://t.uber.com/cadence-slack)#community channel.\\n\\nPlease remember that this update is for you - so if you have any comments or feedback that could help us improve it then please share it with us in the #community [Slack](http://t.uber.com/cadence-slack) channel."},{"id":"/2022/06/30/community-spotlight-update-june-2022","metadata":{"permalink":"/Cadence-Docs/blog/2022/06/30/community-spotlight-update-june-2022","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2022-06-30-community-spotlight-update-june-2022.md","source":"@site/blog/2022-06-30-community-spotlight-update-june-2022.md","title":"Cadence Community Spotlight Update - June 2022","description":"It\u2019s time for our monthly Cadence Community Spotlight update with news from in and around the Cadence community!","date":"2022-06-30T00:00:00.000Z","tags":[{"inline":false,"label":"Community Spotlight","permalink":"/Cadence-Docs/blog/tags/community-spotlights","description":"Community Spotlight tag description"}],"readingTime":2.285,"hasTruncateMarker":true,"authors":[{"name":"Sharan Foga","title":"Director of Operations & Customer Success @ Encube Technologies","url":"https://www.linkedin.com/in/sfoga/","page":{"permalink":"/Cadence-Docs/blog/authors/sharanf"},"socials":{"linkedin":"https://www.linkedin.com/in/sfoga/","github":"https://github.com/sharanf"},"imageURL":"https://github.com/sharanf.png","key":"sharanf"}],"frontMatter":{"title":"Cadence Community Spotlight Update - June 2022","date":"2022-06-30T00:00:00.000Z","authors":"sharanf","tags":["community-spotlight"]},"unlisted":false,"prevItem":{"title":"Cadence Community Spotlight Update - July 2022","permalink":"/Cadence-Docs/blog/2022/07/31/community-spotlight-update-july-2022"},"nextItem":{"title":"Cadence Community Spotlight Update - May 2022","permalink":"/Cadence-Docs/blog/2022/05/31/community-spotlight-update-may-2022"}},"content":"It\u2019s time for our monthly Cadence Community Spotlight update with news from in and around the Cadence community!\\n\\nPlease see below for a roundup of the highlights:\\n\\n## Knowledge Sharing and Support\\n\\nOur Slack #support channel has been busy this month with 13 questions asked this month by 12 different community members. Six community members took time to respond to those questions which clearly shows our community is growing, collaborating and keen to share knowledge.\\n\\nPlease don\u2019t forget that we encourage everyone to post questions on StackOverflow using the **cadence-workflow** and **uber-cadence** tags so that others with similar questions or issues can easily search for and find an answer.\\n\\n## Improving Technical Office Hours\\n\\nOver the last few months we have been holding regular monthly Office Hours meetings but they have not attracted as many participants as we would like. We would like to understand if there is something preventing people from attending (e.g perhaps the timing or dates are not convenient) so we are planning to send out a short community survey.\\n\\nIf you have any ideas or comments about how we can improve our community office hours sessions then please include this in your feedback or contact us in the #community Slack channel.\\n\\n\x3c!-- truncate --\x3e\\n\\n## Cadence Stability Improvements\\n\\nIs Cadence getting better? Yes it is! Many of you may have noticed that Cadence is improving.That is because of the amount of work being done behind the scenes. The Cadence core team has been doing a lot of work to stabilise Cadence functionality. Keep watching out for even more improvements!\\n\\n## Sprechen Sie Deutsch?\\n\\nDo you speak German? If you do speak then we have some good news for you. A couple of Cadence blog posts have been translated into German to help promote it to a wider audience. The links are as below and we hope you find them useful!\\n\\n- [Workflows mit Cadence optimieren!](https://www.credativ.de/blog/howtos/workflows-mit-cadence-optimieren/)\\n- [Apache Kafka\xae Microservices mit Cadence-Workflows optimieren](https://www.credativ.de/blog/howtos/apache-kafka-microservices-mit-cadence-workflows-optimieren/)\\n\\n## Cadence in the News!\\n\\nBelow are a selection of Cadence related articles, blogs and whitepapers. Please take a look and feel free to share via your own social media channels.\\n\\n- [Workflow Comparison: Uber Cadence vs Netflix Conductor](https://www.instaclustr.com/blog/workflow-comparison-uber-cadence-vs-netflix-conductor/)\\n\\n- [Securing Cadence Web Using NGINX](https://www.instaclustr.com/blog/securing-cadence-web-using-nginx/)\\n\\n## Upcoming Events\\n\\n- [Cadence Technical Office Hours - 25th July 2022 @ 9am PT](https://calendar.google.com/calendar/u/0/embed?src=e6r40gp3c2r01054id7e99dlac@group.calendar.google.com&ctz=America/Los_Angeles)\\n\\n- [Webinar: Building Your First Cadence Workflow with Java and Go - 19th July 2022](https://info.instaclustr.com/webinar-building-cadence-workflow)\\n\\nIf you have any news or topics you\'d like us to include in our next update then please join our [Slack](http://t.uber.com/cadence-slack)#community channel.\\n\\nPlease remember that this update is for you - so if you have any comments or feedback that could help us improve it then please share it with us in the #community [Slack](http://t.uber.com/cadence-slack) channel."},{"id":"/2022/05/31/community-spotlight-update-may-2022","metadata":{"permalink":"/Cadence-Docs/blog/2022/05/31/community-spotlight-update-may-2022","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2022-05-31-community-spotlight-update-may-2022.md","source":"@site/blog/2022-05-31-community-spotlight-update-may-2022.md","title":"Cadence Community Spotlight Update - May 2022","description":"Welcome to our regular Cadence Community Spotlight update!","date":"2022-05-31T00:00:00.000Z","tags":[{"inline":false,"label":"Community Spotlight","permalink":"/Cadence-Docs/blog/tags/community-spotlights","description":"Community Spotlight tag description"}],"readingTime":2.905,"hasTruncateMarker":true,"authors":[{"name":"Sharan Foga","title":"Director of Operations & Customer Success @ Encube Technologies","url":"https://www.linkedin.com/in/sfoga/","page":{"permalink":"/Cadence-Docs/blog/authors/sharanf"},"socials":{"linkedin":"https://www.linkedin.com/in/sfoga/","github":"https://github.com/sharanf"},"imageURL":"https://github.com/sharanf.png","key":"sharanf"}],"frontMatter":{"title":"Cadence Community Spotlight Update - May 2022","date":"2022-05-31T00:00:00.000Z","authors":"sharanf","tags":["community-spotlight"]},"unlisted":false,"prevItem":{"title":"Cadence Community Spotlight Update - June 2022","permalink":"/Cadence-Docs/blog/2022/06/30/community-spotlight-update-june-2022"},"nextItem":{"title":"Cadence Community Spotlight Update - April 2022","permalink":"/Cadence-Docs/blog/2022/04/30/community-spotlight-update-april-2022"}},"content":"Welcome to our regular Cadence Community Spotlight update!\\n\\nThis is our monthly blog post series focused on news from in and around the Cadence community.\\n\\nPlease see below for a short activity roundup of what has happened recently in the community.\\n\\n## Cadence Polling Cookbook\\n\\nDo you want to understand polling work and have an example of how to set it up in Cadence? Well a brand new [Cadence Polling cookbook](https://info.instaclustr.com/rs/620-JHM-287/images/Cadence_Cookbook.pdf) is now available that gives you all the details you need. The cookbook was created by several members of the [Instaclustr](https://www.instaclustr.com/) team and they are keen to share it with the community. The pdf version of the cookbook can found on the Cadence website under the *Polling an external API for a specific resource to become available* section of the [Polling Use cases](https://cadenceworkflow.io/docs/use-cases/polling/).\\n\\nA [Github repository](https://github.com/instaclustr/cadence-cookbooks-instafood) has also been created with the sample cookbook code for you to try out for yourself.\\n\\nSo please go ahead and try out the cookbook and don\u2019t forget to let us have your feedback.\\n\\n\x3c!-- truncate --\x3e\\n\\n## Congratulations to a First Time Contributor\\n\\nWe are always looking for ways to encourage project participation. It doesn\'t matter how large the contribution is or whether it is coding or non coding related. This month one of our community members had [their first PR merged](https://github.com/cadence-workflow/Cadence-Docs/pull/107)- so congratulations and many thanks for the contribution [tonyxrandall](https://github.com/tonyxrandall)!\\n\\n## Share Your News!\\n\\nOur #support [Slack](http://t.uber.com/cadence-slack) channel is always full of questions and activity so we know that there are are lot of people out there exploring, trying out and setting up Cadence. We are always interested in hearing about what the community are doing so if you have something to you want to share as a blog post or part of this montly update then please contact us in the #community [Slack](http://t.uber.com/cadence-slack) channel.\\n\\n## Next Cadence Technical Office Hours: 3rd and 27th June 2022\\n\\nWe will be having two Technical Office Hours sessions this month. As 30th May was a US holiday we have moved May\u2019s Technical Office Hours to Friday 3rd June at 11am PT. And we will be having our June call on 27th.\\n\\nRemember that in these Zoom sessions you can speak directly with some of our Cadence experts so if you have a question about Cadence or are facing a particular issue getting it setup then please come along and chat to one of our experts!\\n\\n## Cadence in the News!\\n\\nBelow are a selection of Cadence related articles, blogs and whitepapers. Please take a look and feel free to share via your own social media channels.\\n\\n- [Spinning Your Drones With Cadence and Apache Kafka \u2013 Integration Patterns and New Cadence Features](https://www.instaclustr.com/blog/spinning-your-drones-with-cadence-and-apache-kafka-integration-patterns-and-new-cadence-features/)\\n\\n- [Enabling Faster Financial Partnership Integrations Using Cadence](https://doordash.engineering/2022/05/18/enabling-faster-financial-partnership-integrations-using-cadence/)\\n\\n- [Spinning Your Drones With Cadence and Apache Kafka\xae \u2013 Architecture, Order and Delivery Workflows](https://www.instaclustr.com/blog/spinning-your-drones-with-cadence-and-apache-kafka-architecture-order-and-delivery-workflows/)\\n\\n## Upcoming Events\\n\\n- [Cadence Technical Office Hours - 3rd June 2022 @ 11am PT](https://calendar.google.com/calendar/u/0/embed?src=e6r40gp3c2r01054id7e99dlac@group.calendar.google.com&ctz=America/Los_Angeles)\\n\\n- [Webinar : Spinning up Your Workflows with Cadence : 20th June](https://info.instaclustr.com/webinar-emea-spinning-workflows-cadence.html)\\n\\n- [Cadence Technical Office Hours - 27th June 2022 @ 9am PT](https://calendar.google.com/calendar/u/0/embed?src=e6r40gp3c2r01054id7e99dlac@group.calendar.google.com&ctz=America/Los_Angeles)\\n\\n- [Webinar: Building Your First Cadence Workflow with Java and Go - 19th July 2022](https://info.instaclustr.com/webinar-building-cadence-workflow)\\n\\nIf you have any news or topics you\'d like us to include in our next update then please join our [Slack](http://t.uber.com/cadence-slack)#community channel.\\n\\nPlease remember that this update is for you - so if you have any comments or feedback that could help us improve it then please share it with us in the #community [Slack](http://t.uber.com/cadence-slack) channel."},{"id":"/2022/04/30/community-spotlight-update-april-2022","metadata":{"permalink":"/Cadence-Docs/blog/2022/04/30/community-spotlight-update-april-2022","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2022-04-30-community-spotlight-update-april-2022.md","source":"@site/blog/2022-04-30-community-spotlight-update-april-2022.md","title":"Cadence Community Spotlight Update - April 2022","description":"Welcome to our Cadence Community Spotlight update!","date":"2022-04-30T00:00:00.000Z","tags":[{"inline":false,"label":"Community Spotlight","permalink":"/Cadence-Docs/blog/tags/community-spotlights","description":"Community Spotlight tag description"}],"readingTime":2.955,"hasTruncateMarker":true,"authors":[{"name":"Sharan Foga","title":"Director of Operations & Customer Success @ Encube Technologies","url":"https://www.linkedin.com/in/sfoga/","page":{"permalink":"/Cadence-Docs/blog/authors/sharanf"},"socials":{"linkedin":"https://www.linkedin.com/in/sfoga/","github":"https://github.com/sharanf"},"imageURL":"https://github.com/sharanf.png","key":"sharanf"}],"frontMatter":{"title":"Cadence Community Spotlight Update - April 2022","date":"2022-04-30T00:00:00.000Z","authors":"sharanf","tags":["community-spotlight"]},"unlisted":false,"prevItem":{"title":"Cadence Community Spotlight Update - May 2022","permalink":"/Cadence-Docs/blog/2022/05/31/community-spotlight-update-may-2022"},"nextItem":{"title":"Cadence Community Spotlight Update - March 2022","permalink":"/Cadence-Docs/blog/2022/03/31/community-spotlight-update-march-2022"}},"content":"Welcome to our Cadence Community Spotlight update!\\n\\nThis is our monthly blog post series focused on news from in and around the Cadence community.\\n\\nPlease see below for a short activity roundup of what has happened recently in the community.\\n\\n## SD Times Names Cadence Open Source Project of the Week\\n\\nIn April Cadence was named as open source project of the week by the SD Times. Being named gives the project some great publicity and means the project is getting noticed. You can find a link to the article in the *Cadence in the News* section below.\\n\\n## Follow Us on LinkedIn and Twitter!\\n\\nWe have now set up Cadence accounts on [LinkedIn](https://www.linkedin.com/company/cadenceworkflow/) and [Twitter](https://twitter.com/cadenceworkflow) where you can keep up to date with what is happening in the community. We will be using these social media accounts to share news, articles, stories and links related to Cadence - so please follow us!\\n\\nAnd don\u2019t forget to share your news with us. We are looking forward to receiving your feedback and comments. The more we interact - the more we build our community!\\n\\n\x3c!-- truncate --\x3e\\n\\n## Proposal to Change the Way We Write Workflows\\n\\nIf you haven\u2019t seen the proposal from community member [Quanzheng Long](https://www.linkedin.com/in/prclqz/) about creating a new way to write Cadence workflows then please take a look:[https://github.com/cadence-workflow/cadence/issues/4785](https://github.com/cadence-workflow/cadence/issues/4785). He has already received some initial feedback and is currently working on putting together a proof of concept demo to show the community. As soon as we have more news about it - we will let you know!\\n\\n\\n## Help Us Improve Cadence\\n\\nDo you want to help us improve Cadence? We are always looking for contributors so any contribution you can make - however small is welcome. If you would like to start contributing then please take a look at the list of [Cadence Issues on Github](https://github.com/cadence-workflow/cadence/issues). We have some issues flagged with a tag of *\u2018good first issue\'* that would be a great place to start.\\n\\nRemember that we are not only looking for code contributions but also non coding ones such as documentation improvements so please take a look and select something to work on.\\n\\n## Next Cadence Technical Office Hours: 30th May 2022\\n\\nEvery month we hold a Technical Office Hours session via Zoom where you can speak directly with some of our Cadence experts. If you have a question about Cadence or are facing a particular issue getting it setup then please come along and chat to one of our experts!\\n\\nMeetings are held on the last Monday of every month so please make sure you mark the dates in your calendars. Our next session will be on the 30th May at 9am PT so hope to see you there!\\n\\n## Cadence in the News!\\n\\nBelow are a selection of Cadence related articles, blogs and whitepapers. Please take a look and feel free to share via your own social media channels.\\n\\n- [SD Times Open Source Project of the Week : Cadence](https://sdtimes.com/softwaredev/sd-times-open-source-project-of-the-week-cadence/)\\n\\n- [The New Stack Interview: Meet Cadence: The Open-Source Orchestration Workflow Engine](https://www.youtube.com/watch?v=-f1m5EI4cRo)\\n\\n- [The New Stack: Instaclustr Adds Managed Cadence to Its Platform](https://thenewstack.io/instaclustr-adds-managed-cadence-to-its-platform/)\\n\\n## Upcoming Events\\n\\n- [Cadence Technical Office Hours - 30th May 2022 @ 9am PT](https://calendar.google.com/calendar/u/0/embed?src=e6r40gp3c2r01054id7e99dlac@group.calendar.google.com&ctz=America/Los_Angeles)\\n\\n\\nIf you have any news or topics you\'d like us to include in our next update then please join our [Slack](http://t.uber.com/cadence-slack)#community channel.\\n\\nPlease remember that this update is for you - so if you have any comments or feedback that could help us improve it then please share it with us in the #community [Slack](http://t.uber.com/cadence-slack) channel."},{"id":"/2022/03/31/community-spotlight-update-march-2022","metadata":{"permalink":"/Cadence-Docs/blog/2022/03/31/community-spotlight-update-march-2022","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2022-03-31-community-spotlight-update-march-2022.md","source":"@site/blog/2022-03-31-community-spotlight-update-march-2022.md","title":"Cadence Community Spotlight Update - March 2022","description":"Welcome to our Cadence Community Spotlight update!","date":"2022-03-31T00:00:00.000Z","tags":[{"inline":false,"label":"Community Spotlight","permalink":"/Cadence-Docs/blog/tags/community-spotlights","description":"Community Spotlight tag description"}],"readingTime":3.235,"hasTruncateMarker":true,"authors":[{"name":"Sharan Foga","title":"Director of Operations & Customer Success @ Encube Technologies","url":"https://www.linkedin.com/in/sfoga/","page":{"permalink":"/Cadence-Docs/blog/authors/sharanf"},"socials":{"linkedin":"https://www.linkedin.com/in/sfoga/","github":"https://github.com/sharanf"},"imageURL":"https://github.com/sharanf.png","key":"sharanf"}],"frontMatter":{"title":"Cadence Community Spotlight Update - March 2022","date":"2022-03-31T00:00:00.000Z","authors":"sharanf","tags":["community-spotlight"]},"unlisted":false,"prevItem":{"title":"Cadence Community Spotlight Update - April 2022","permalink":"/Cadence-Docs/blog/2022/04/30/community-spotlight-update-april-2022"},"nextItem":{"title":"Cadence Community Spotlight Update - February 2022","permalink":"/Cadence-Docs/blog/2022/02/28/community-spotlight-february-2022"}},"content":"Welcome to our Cadence Community Spotlight update!\\n\\nThis is the latest in our series of monthly blog posts focused on the Cadence community and news about what you have been doing with Cadence.\\n\\nPlease see below for a short activity roundup of what has happened recently in the community.\\n\\n## Updated Cadence Topology Diagram\\n\\nDid you know that we have an updated Cadence Service diagram on the website? Well we do - and you can find it on our [Deployment Topology](https://cadenceworkflow.io/docs/concepts/topology/#overview) page. We are always looking for information that helps makes it easier for people to understand how Cadence works.\\n\\nSpecial thanks to Ben Slater for updating the diagram and also to Ender, Emrah and Long for helping review it.\\n\\n\x3c!-- truncate --\x3e\\n\\n## Monthly Cadence Technical Office Hours\\n\\nEvery month we hold a Technical Office Hours session via Zoom where you can speak directly with some of our Cadence experts. If you have a question about Cadence or are facing a particular issue getting it setup then please come along and chat to one of our experts!\\n\\nMeetings are held on the last Monday of every month so make sure you mark the dates in your calendars. Our next session will be on the 25th April at 9am PT so hope to see you there!\\n\\nThe [Cadence Community Calendar](https://calendar.google.com/calendar/u/0/embed?src=e6r40gp3c2r01054id7e99dlac@group.calendar.google.com&ctz=America/Los_Angeles) contains the Zoom link for the meeting and details of any other events planned so please check it regularly.\\n\\n## Some Cadence Statistics\\n\\nThis month we thought it would be interesting to post some statistics about the Cadence community.\\n\\n- 1722 - the number of members in our #general Slack channel\\n- 24 - the number of questions asked in our #support Slack channel during the month\\n- 5 - the number of questions asked about Cadence in StackOverflow during the month\\n- 105 - the number of contributors to the Cadence git repo\\n- 9 - the number of community members who responded to a question during the month\\n\\n## Using StackOverflow to Respond to Support Questions\\n\\nWe have over 1700 members in our #support channel on our Cadence Slack where some of you have been asking questions about Cadence. The community has been responding and provided some great answers that we don\u2019t want to lose!\\n\\nIt can be difficult searching the Slack #support channel for a specific problem and we want to make sure that we capture all these great answers so that they can help others in the community.\\n\\nSo if possible we would like you to start posting your Cadence questions on [StackOverflow](https://stackoverflow.com/).\\n\\n- Create your question in StackOverflow\\n- Post the StackOverflow question link in the Cadence Slack #support channel\\n- A response to your question will be posted to StackOverflow\\n\\nOther community members will be able to search StackOverflow for the details of the your question and see the response. We hope that this will make it easier for people to find answers to common questions.\\n\\n## Cadence in the News!\\n\\nBelow are a selection of Cadence related articles, blogs and whitepapers. Please take a look and feel free to share via your own social media channels.\\n\\n- [Create Distributed, Scalable, Durable, and Highly Available Software\u2014 With Cadence](https://betterprogramming.pub/create-distributed-scalable-durable-and-highly-available-software-with-cadence-9f4fa6b1376b)\\n\\n- [Spinning Your Drones with Cadence - Introduction](https://www.instaclustr.com/blog/spinning-your-drones-with-cadence-introduction/)\\n\\n- [Instaclustr Announces General Availability of Managed Cadence](https://www.globenewswire.com/news-release/2022/04/04/2415472/0/en/Instaclustr-Announces-General-Availability-of-Instaclustr-Managed-Cadence.html)\\n\\n- [Introducing Managed Cadence on the Instaclustr Platform](https://www.youtube.com/watch?v=Vzc_LWmJ8lE&feature=youtu.be)\\n\\n- [Whitepaper: Understanding Cadence for Ops and SREs](https://info.instaclustr.com/rs/620-JHM-287/images/Understanding_Cadence_for%20Ops_and_SRE_WhitePaper.pdf)\\n\\n## Upcoming Events\\n\\n- [Cadence Technical Office Hours - 25th April 2022 @ 9am PT\\n](https://calendar.google.com/calendar/u/0/embed?src=e6r40gp3c2r01054id7e99dlac@group.calendar.google.com&ctz=America/Los_Angeles)\\n\\n- [Webinar : Spinning up Your Workflows with Cadence](https://info.instaclustr.com/webinar-spinning-workflows-cadence.html)\\n\\nIf you have any news or topics you\'d like us to include in our next update then please join our [Slack](http://t.uber.com/cadence-slack)#community channel.\\n\\nPlease remember that this update is for you - so if you have any comments or feedback that could help us improve it then please share it with us in the #community [Slack](http://t.uber.com/cadence-slack) channel."},{"id":"/2022/02/28/community-spotlight-february-2022","metadata":{"permalink":"/Cadence-Docs/blog/2022/02/28/community-spotlight-february-2022","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2022-02-28-community-spotlight-february-2022.md","source":"@site/blog/2022-02-28-community-spotlight-february-2022.md","title":"Cadence Community Spotlight Update - February 2022","description":"Welcome to the Cadence Community Spotlight update!","date":"2022-02-28T00:00:00.000Z","tags":[{"inline":false,"label":"Community Spotlight","permalink":"/Cadence-Docs/blog/tags/community-spotlights","description":"Community Spotlight tag description"}],"readingTime":2.99,"hasTruncateMarker":true,"authors":[{"name":"Sharan Foga","title":"Director of Operations & Customer Success @ Encube Technologies","url":"https://www.linkedin.com/in/sfoga/","page":{"permalink":"/Cadence-Docs/blog/authors/sharanf"},"socials":{"linkedin":"https://www.linkedin.com/in/sfoga/","github":"https://github.com/sharanf"},"imageURL":"https://github.com/sharanf.png","key":"sharanf"}],"frontMatter":{"title":"Cadence Community Spotlight Update - February 2022","date":"2022-02-28T00:00:00.000Z","authors":"sharanf","tags":["community-spotlight"]},"unlisted":false,"prevItem":{"title":"Cadence Community Spotlight Update - March 2022","permalink":"/Cadence-Docs/blog/2022/03/31/community-spotlight-update-march-2022"},"nextItem":{"title":"Cadence Community Spotlight Update - January 2022","permalink":"/Cadence-Docs/blog/2022/01/31/community-spotlight-january-2022"}},"content":"Welcome to the Cadence Community Spotlight update!\\n\\nThis is the second in our series of monthly updates focused on the Cadence community and news about what you have been doing with Cadence. We hope that you enjoyed last month\'s update and are keen to find out what has been happening.\\n\\nPlease see below for a short activity roundup of what has happened recently in the community.\\n\\n## Announcements\\n\\nJust in case you missed it the alpha version of the Cadence notification service has been released. Details can be found at the following link:\\n[Cadence Notification Service](https://github.com/cadence-oss/cadence-notification/releases/tag/v0.0.1)\\n\\nThanks very much to everyone that worked on this!\\n\\n\x3c!-- truncate --\x3e\\n\\n## Community Supporting the Community\\n\\nDuring February 16 questions were posted in the Cadence #support [Slack](http://t.uber.com/cadence-slack) channel from new Cadence users and existing community members looking for help and guidance. A very big thank you to the following community members who took the time to help others: Ali, David, Tamas Weisz, Liang Mei, Quanzheng Long, peaceChoi, Emrah Seker, Ben Slater and Sathyaraju Sekaran.\\n\\nIt\u2019s great to see that we are supporting each other - and that is exactly what communities do!\\n\\n\\n## Please Subscribe to our Youtube Channel\\n\\nDid you know that we have a Youtube channel where you can find Cadence related videos and even the recording of our last meetup? Well we do and you can find it here:\\n[Cadence Youtube](https://www.youtube.com/channel/UC6H9Jsq4ZQ74g8coDgJu9ZA/videos)\\nPlease subscribe and let us know what other videos you\u2019d like to see there.\\n\\n## Help us to Make Cadence even better\\n\\nAre you interested in helping us improve Cadence? We are always looking for contributors to help share the workload. If you\u2019d like to help then you can start by taking a look at our list of [open issues](https://github.com/cadence-workflow/cadence/issues) on Github. We currently have 320 of them that need to be worked on so if you want to learn more about Cadence and solve some of the reported issues then please take a look and volunteer to fix it.\\n\\nIf you are new to Cadence or you\u2019d like to try something simple then we have some issues labelled as \u2018good first issue\u2019. These are a great place to start to get more Cadence experience.\\n\\n## Cadence Calendar\\n\\nWe have created a [Cadence public calendar](https://calendar.google.com/calendar/embed?src=e6r40gp3c2r01054id7e99dlac%40group.calendar.google.com&ctz=America%2FLos_Angeles) where we can highlight events, meetings, webinars etc that are planned around Cadence. The calendar will soon be available on the [Cadence website](https://cadenceworkflow.io/) so please make sure that you check it regularly.\\nThis means that you can easily find out if there are any Cadence events planned that you would like to attend.\\n\\n## Cadence Technical Office Hours\\n\\nOur second Technical Office Hours event took place on February 28th, Monday at 9AM PST. The main objective was provide Cadence support, respond to any questions about and to share any knowledge that you have learned. We always encourage community members to come along - and thanks very much to everyone who participated.\\n\\n## Cadence in the News!\\n\\nBelow are a selection of Cadence related articles, blogs and whitepapers. Please take a look and feel free to share via your own social media channels.\\n\\n- [Spinning Apache Kafka\xae Microservices With Cadence Workflows](https://www.instaclustr.com/blog/spinning-apache-kafka-microservices-with-cadence-workflows/)\\n\\n## Upcoming Events\\n\\n- [Webinar : What is Cadence? And is it right for you? (APAC)](https://info.instaclustr.com/webinar-apac-what-is-cadence.html)\\n\\nIf you have any news or topics you\'d like us to include in our next update then please join our [Slack](http://t.uber.com/cadence-slack)#community channel.\\n\\nPlease remember that this update is for you - so if you have any comments or feedback that could help us improve it then please share it with us in the #community [Slack](http://t.uber.com/cadence-slack) channel."},{"id":"/2022/01/31/community-spotlight-january-2022","metadata":{"permalink":"/Cadence-Docs/blog/2022/01/31/community-spotlight-january-2022","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2022-01-31-community-spotlight-january-2022.md","source":"@site/blog/2022-01-31-community-spotlight-january-2022.md","title":"Cadence Community Spotlight Update - January 2022","description":"Welcome to our very first Cadence Community Spotlight update!","date":"2022-01-31T00:00:00.000Z","tags":[{"inline":false,"label":"Community Spotlight","permalink":"/Cadence-Docs/blog/tags/community-spotlights","description":"Community Spotlight tag description"},{"inline":false,"label":"Roadmap","permalink":"/Cadence-Docs/blog/tags/roadmap","description":"Roadmap tag description"}],"readingTime":2.04,"hasTruncateMarker":true,"authors":[{"name":"Sharan Foga","title":"Director of Operations & Customer Success @ Encube Technologies","url":"https://www.linkedin.com/in/sfoga/","page":{"permalink":"/Cadence-Docs/blog/authors/sharanf"},"socials":{"linkedin":"https://www.linkedin.com/in/sfoga/","github":"https://github.com/sharanf"},"imageURL":"https://github.com/sharanf.png","key":"sharanf"}],"frontMatter":{"title":"Cadence Community Spotlight Update - January 2022","date":"2022-01-31T00:00:00.000Z","authors":"sharanf","tags":["community-spotlight","roadmap"]},"unlisted":false,"prevItem":{"title":"Cadence Community Spotlight Update - February 2022","permalink":"/Cadence-Docs/blog/2022/02/28/community-spotlight-february-2022"},"nextItem":{"title":"Moving to gRPC","permalink":"/Cadence-Docs/blog/2021/10/19/2021-10-19-moving-to-grpc/moving-to-grpc"}},"content":"Welcome to our very first Cadence Community Spotlight update!\\n\\nThis monthly update focuses on news from the wider Cadence community and is all about what you have been doing with Cadence. Do you have an interesting project that uses Cadence? If so then we want to hear from you. Also if you have any news items, blogs, articles, videos or events where Cadence has been mentioned then that is good too. We want to showcase that our community is active and is doing exciting and interesting things.\\n\\nPlease see below for a short round up of things that have happened recently in the community.\\n\\n\x3c!-- truncate --\x3e\\n\\n## Community Related Office Hours\\n\\nOn the 12th January 2022 we held our first Cadence Community Related Office Hours. This session was focused on discussing how we plan and organise things for the community. This includes things such as Code of Conduct, managing social media and making sure we regularly communicate project news and events.\\n\\nAnd you can see that this monthly update is the result of the feedback from that session! We are happy to get any feedback for comments you may have. Please remember that this update is for you so getting your feedback will help us improve it.\\n\\nWe will be planning other Community Related Office Hour sessions so please watch out for updates.\\n\\n## Adopting a Cadence Community Code of Conduct\\n\\nSome of you may already know that our community has adopted this version of the [Contributor Covenant](https://github.com/uber/.github/blob/dcd96c52f2d1d839208315a2572cf37f48e52e96/CODE_OF_CONDUCT.md) as our Code of Conduct. We want our community to be an open, welcoming and supportive place where everyone can collaborate.\\n\\n## Recording from Cadence Meetup Available\\n\\nPlease don\'t worry if you missed our online [November Cadence meetup](https://www.meetup.com/UberEvents/events/281975343/) because the recording is now available. You can find out more details about the meetup and get access to recordings [here](https://www.youtube.com/watch?v=pXgCd1BilLQ)\\n\\n## Cadence in the News!\\n\\nBelow are a selection of Cadence related articles, blogs and whitepapers. Please take a look and feel free to share via your own social media channels.\\n\\n- [Meet Cadence: Workflow Engine for Taming Complex Processes](https://thenewstack.io/meet-cadence-workflow-engine-for-taming-complex-processes/)\\n- [Spinning Your Workflows with Cadence](https://www.instaclustr.com/blog/spinning-your-workflows-with-cadence/)\\n- [Instaclustr Joins the Engineering Team at Uber in Supporting Cadence, the Powerful Open Source Orchestration Engine](https://www.globenewswire.com/news-release/2021/12/07/2347314/0/en/Instaclustr-Joins-the-Engineering-Team-at-Uber-in-Supporting-Cadence-the-Powerful-Open-Source-Orchestration-Engine.html)\\n\\n## Upcoming Events\\n\\n- [Webinar : What is Cadence? And is it right for you?](https://info.instaclustr.com/webinar-emea-what-is-cadence.html?_ga=2.191041518.510582234.1643223308-2138855655.1638190316)\\n\\nIf you have any news or topics you\'d like us to include in our next update then please join our [slack](http://t.uber.com/cadence-slack)#community channel."},{"id":"/2021/10/19/2021-10-19-moving-to-grpc/moving-to-grpc","metadata":{"permalink":"/Cadence-Docs/blog/2021/10/19/2021-10-19-moving-to-grpc/moving-to-grpc","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2021-10-19-moving-to-grpc/2021-10-19-moving-to-grpc.md","source":"@site/blog/2021-10-19-moving-to-grpc/2021-10-19-moving-to-grpc.md","title":"Moving to gRPC","description":"Background","date":"2021-10-19T00:00:00.000Z","tags":[{"inline":false,"label":"Deep Dives","permalink":"/Cadence-Docs/blog/tags/deep-dives","description":"Deep Dives tag description"},{"inline":false,"label":"Cadence Operations","permalink":"/Cadence-Docs/blog/tags/cadence-operations","description":"Cadence Operations tag description"}],"readingTime":4.795,"hasTruncateMarker":true,"authors":[{"name":"Vytautas Karpavicius","title":"Software Engineer @ Uber","url":"https://www.linkedin.com/in/vytautas-karpavicius","page":{"permalink":"/Cadence-Docs/blog/authors/vytautas-karpavicius"},"socials":{"linkedin":"https://www.linkedin.com/in/vytautas-karpavicius","github":"https://github.com/vytautas-karpavicius"},"imageURL":"https://github.com/vytautas-karpavicius.png","key":"vytautas-karpavicius"}],"frontMatter":{"title":"Moving to gRPC","date":"2021-10-19T00:00:00.000Z","authors":"vytautas-karpavicius","tags":["deep-dive","cadence-operations"]},"unlisted":false,"prevItem":{"title":"Cadence Community Spotlight Update - January 2022","permalink":"/Cadence-Docs/blog/2022/01/31/community-spotlight-january-2022"},"nextItem":{"title":"Announcing Cadence OSS office hours and community sync up","permalink":"/Cadence-Docs/blog/2021/10/13/announcing-cadence-oss-office-hours-and-community-sync-up"}},"content":"## Background\\nCadence historically has been using TChannel transport with Thrift encoding for both internal RPC calls and communication with client SDKs. gRPC is becoming a de-facto industry standard with much better adoption and community support. It offers features such as authentication and streaming that are very relevant for Cadence. Moreover, TChannel is being deprecated within Uber itself, pushing an effort for this migration. During the last year we\u2019ve implemented multiple changes in server and SDK that allows users to use gRPC in Cadence, as well as to upgrade their existing Cadence cluster in a backward compatible way. This post tracks the completed work items and our future plans.\\n\\n## Our Approach\\nWith ~500 services using Cadence at Uber and many more open source customers around the world, we had to think about the gRPC transition in a backwards compatible way. We couldn\u2019t simply flip transport and encoding everywhere. Instead we needed to support both protocols as an intermediate step to ensure a smooth transition for our users.\\n\\nCadence was using Thrift/TChannel not just for the API with client SDKs. They were also used for RPC calls between internal Cadence server components and also between different data centers. When starting this migration we had a choice of either starting with public APIs first or all the internal things within the server. We chose the latter one, so that we could gain experience and iterate faster within the server without disruption to the clients. With server side done and listening for both protocols, dynamic config flag was exposed to switch traffic internally. It allowed gradual deployment and provided an option to rollback if needed.\\n\\n\x3c!-- truncate --\x3e\\n\\nThe next step - client migration. We have more users for the Go SDK at Uber, that is why we started with it. Current version of SDK exposes Thrift types via public API, therefore we can not remove them without breaking changes. While we have plans for revamped v2 SDK, current users are able to use gRPC as well - with the help of a [translation adapter](https://github.com/cadence-workflow/cadence-go-client/blob/v0.18.2/compatibility/thrift2proto.go). Migration is underway starting with [cadence canary service](https://github.com/cadence-workflow/cadence/tree/master/canary), and then onboarding user services one by one.\\n\\nWe plan to support TChannel for a few more releases and then eventually drop it in a future.\\n\\n## System overview\\n![gRPC migration overview](./grpc-migration.svg)\\n\\n1. The frontend of [Cadence Server](https://github.com/cadence-workflow/cadence) exposes two inbounds for both gRPC and TChannel starting [v0.21.0 release](https://github.com/cadence-workflow/cadence/releases/tag/v0.21.0). gRPC traffic is being served on a different port that can be configured [here](https://github.com/cadence-workflow/cadence/blob/v0.21.0/config/development.yaml#L25). For gRPC API we introduced [proto IDL](https://github.com/cadence-workflow/cadence-idl/tree/master/proto/cadence-workflow/cadence/api/v1) definitions. We will keep TChannel open on frontend for some time to allow gradual client migration.\\n2. Starting with [v0.21.0](https://github.com/cadence-workflow/cadence/releases/tag/v0.21.0) internal components of Cadence Server (history & matching) also started accepting gRPC traffic. Sending traffic via gRPC is off by default and could be enabled with a flag in [dynamic config](https://github.com/cadence-workflow/cadence/blob/v0.21.0/config/dynamicconfig/development.yaml#L10). Planned for v0.24.0 it will be enabled by default, with an option to opt-out.\\n3. Starting with v0.23.0 communication between different Cadence clusters can be switched to gRPC via this [configuration](https://github.com/cadence-workflow/cadence/blob/0.23.x/config/development_active.yaml#L82). It is used for replication and request redirection to different DC.\\n4. [Go SDK](https://github.com/cadence-workflow/cadence-go-client) has exposed generated Thrift types via its public API. This complicated migration, because switching them to proto types (or rpc agnostic types) means breaking changes. Because of this we are pursuing two alternatives:\\n 1. (A) Short term: starting with [v0.18.2](https://github.com/cadence-workflow/cadence-go-client/releases/tag/v0.18.2) a [compatibility layer](https://github.com/cadence-workflow/cadence-go-client/blob/v0.18.2/compatibility/thrift2proto.go) is available which makes translation between thrift-proto types underneath. It allows using gRPC communication while still using Thrift based API. [Usage example](https://github.com/cadence-workflow/cadence-samples/pull/52).\\n 2. (B) Long term: we are currently designing v2 SDK that will support gRPC directly. Its API will be RPC agnostic and will include other usability improvements. You can check some ideas that are being considered [here](https://github.com/cadence-workflow/cadence-go-client/issues/1133).\\n5. [Java SDK](https://github.com/cadence-workflow/cadence-java-client) is currently on TChannel only. Move to gRPC is planned for 2022 H1.\\n6. It is now possible to communicate with gRPC from other languages as well. Use [proto IDLs](https://github.com/cadence-workflow/cadence-idl/tree/master/proto/cadence-workflow/cadence/api/v1) to generate bindings for your preferred language. [Minimal example](https://github.com/vytautas-karpavicius/cadence-python) for doing it in python.\\n7. WebUI and CLI are currently on TChannel. They are planned to be switched to gRPC for 2022 H1.\\n\\n## Migration steps\\n### Upgrading Cadence server\\nIn order to start using gRPC please upgrade Cadence server to **[v0.22.0](https://github.com/cadence-workflow/cadence/releases/tag/v0.22.0) or later**.\\n1. If you are using an older version (before v0.21.0), make sure to disable internal gRPC communication at first. Needed to ensure that all nodes in the cluster are ready to accept gRPC traffic, before switching it on. This is controlled by the [system.enableGRPCOutbound](https://github.com/cadence-workflow/cadence/blob/v0.21.0/config/dynamicconfig/development.yaml#L10) flag in dynamic config.\\n2. Once deployed, flip system.enableGRPCOutbound to true. It will require a cluster restart for setting to take effect.\\n3. If you are operating in more than one DC - recommended server version to upgrade to is v0.23.0 or newer. Once individual clusters with gRPC support are deployed, please update [config](https://github.com/cadence-workflow/cadence/blob/0.23.x/config/development_active.yaml#L82) to switch cross DC traffic to gRPC. Don\u2019t forget to update ports as well. We also recommend increasing [grpcMaxMsgSize](https://github.com/cadence-workflow/cadence/blob/0.23.x/config/development.yaml#L29) to 32MB which is needed to ensure smooth replication. After config change you will need a restart for setting to take effect.\\n4. Do not forget that gRPC runs on a different port, therefore you might need to open it on docker containers, firewalls, etc.\\n\\n### Upgrading clients\\n1. GoSDK - Follow an [example](https://github.com/cadence-workflow/cadence-samples/pull/52) to inject Thrift-to-proto adapter during client initialization and update your config to use the gRPC port.\\n\\n### Status at Uber\\n* All clusters run gRPC traffic internally for 4 months without any issues.\\n* Cross DC traffic has been switched to gRPC this month.\\n* With internal tooling updated, we are starting to onboard services to use the Go SDK gRPC compatibility layer.\\n\\n---\\nDo not hesitate to reach out to us ([cadence-oss@googlegroups.com](mailto:cadence-oss@googlegroups.com)\xa0or\xa0[slack](http://t.uber.com/cadence-slack)) if you have any questions.\\n\\nThe Uber Cadence team"},{"id":"/2021/10/13/announcing-cadence-oss-office-hours-and-community-sync-up","metadata":{"permalink":"/Cadence-Docs/blog/2021/10/13/announcing-cadence-oss-office-hours-and-community-sync-up","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2021-10-13-announcing-cadence-oss-office-hours-and-community-sync-up.md","source":"@site/blog/2021-10-13-announcing-cadence-oss-office-hours-and-community-sync-up.md","title":"Announcing Cadence OSS office hours and community sync up","description":"Are you a current Cadence user, do you operate Cadence services, or are you interested in learning about workflow technologies and wonder what problems Cadence could solve for you? We would like to talk to you!","date":"2021-10-13T00:00:00.000Z","tags":[{"inline":false,"label":"Announcement","permalink":"/Cadence-Docs/blog/tags/announcements","description":"Announcement tag description"},{"inline":false,"label":"Roadmap","permalink":"/Cadence-Docs/blog/tags/roadmap","description":"Roadmap tag description"}],"readingTime":1.83,"hasTruncateMarker":true,"authors":[{"name":"Liang Mei","title":"Engineering Manager @ Uber","url":"https://www.linkedin.com/in/meiliang86/","page":{"permalink":"/Cadence-Docs/blog/authors/meiliang-86"},"socials":{"linkedin":"https://www.linkedin.com/in/meiliang86/","github":"https://github.com/meiliang86"},"imageURL":"https://github.com/meiliang86.png","key":"meiliang86"}],"frontMatter":{"title":"Announcing Cadence OSS office hours and community sync up","date":"2021-10-13T00:00:00.000Z","authors":"meiliang86","tags":["announcement","roadmap"]},"unlisted":false,"prevItem":{"title":"Moving to gRPC","permalink":"/Cadence-Docs/blog/2021/10/19/2021-10-19-moving-to-grpc/moving-to-grpc"},"nextItem":{"title":"Long-term commitment and support for the Cadence project, and its community","permalink":"/Cadence-Docs/blog/2021/09/30/long-term-commitment-and-support-for-the-cadence-project-and-its-community"}},"content":"Are you a current Cadence user, do you operate Cadence services, or are you interested in learning about workflow technologies and wonder what problems Cadence could solve for you? We would like to talk to you!\\n\\n\\nOur team has spent a significant amount of time working with users and partner teams at Uber to design, scale and operate their workflows. This helps our users understand the technology better, smooth their learning curve and ramp up experience, and at the same time allows us to get fast and direct feedback so we can improve the developer experience and close feature gaps. As our product and community grows, we would like to expand this practice to our users in the OSS community. **For the first time ever, members of the Cadence team along with core contributors from the community will host bi-weekly office hours to answer any questions you have about Cadence, or workflow technology in general.** We can also dedicate future sessions to specific topics that have a common interest. Please don\u2019t hesitate to let us know your thoughts.\\n\\n\\nPlease join a session if you would like to talk about any of the following topics:\\n
    \\n
  1. Understand what Cadence is and why it might be useful for you and your company
  2. \\n
  3. Guidance about running Cadence services and workers in production
  4. \\n
  5. Workflow design and operation consultation
  6. \\n
  7. Product update, future roadmaps as well as collaboration opportunities
  8. \\n
\\n\\n\\nBuilding and maintaining a healthy and growing community is the key to the success of Cadence, and one of the top priorities for our team. We would like to use the office hours as an opportunity to understand and help our customers, seek feedback, and forge partnerships. We look forward to seeing you in one of the meetings.\\n\\n\\n**Upcoming Office Hours**\\n\\n\\nAs we have a geo-distributed userbase, we are still trying to figure out a time that works for most of the people. In the meanwhile, we will manually schedule the first few instances of the meeting until we settle on a fixed schedule. Our next office hours will take place on **Thursday, October 21 2pm-3pm PT/5pm-6pm EST/9pm-10pm GMT**. Please join via [this zoom link](https://uber.zoom.us/j/92356466350?pwd=RFVTc2pwV0xoVTdlK3VxN3N2eU5UZz09).\\n\\n\x3c!-- truncate --\x3e\\n\\nThe Uber Cadence team"},{"id":"/2021/09/30/long-term-commitment-and-support-for-the-cadence-project-and-its-community","metadata":{"permalink":"/Cadence-Docs/blog/2021/09/30/long-term-commitment-and-support-for-the-cadence-project-and-its-community","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2021-09-30-long-term-commitment-and-support-for-the-cadence-project-and-its-community.md","source":"@site/blog/2021-09-30-long-term-commitment-and-support-for-the-cadence-project-and-its-community.md","title":"Long-term commitment and support for the Cadence project, and its community","description":"Dear valued Cadence users and developers,","date":"2021-09-30T00:00:00.000Z","tags":[{"inline":false,"label":"Announcement","permalink":"/Cadence-Docs/blog/tags/announcements","description":"Announcement tag description"}],"readingTime":2.545,"hasTruncateMarker":true,"authors":[{"name":"Liang Mei","title":"Engineering Manager @ Uber","url":"https://www.linkedin.com/in/meiliang86/","page":{"permalink":"/Cadence-Docs/blog/authors/meiliang-86"},"socials":{"linkedin":"https://www.linkedin.com/in/meiliang86/","github":"https://github.com/meiliang86"},"imageURL":"https://github.com/meiliang86.png","key":"meiliang86"}],"frontMatter":{"title":"Long-term commitment and support for the Cadence project, and its community","date":"2021-09-30T00:00:00.000Z","authors":"meiliang86","tags":["announcement"]},"unlisted":false,"prevItem":{"title":"Announcing Cadence OSS office hours and community sync up","permalink":"/Cadence-Docs/blog/2021/10/13/announcing-cadence-oss-office-hours-and-community-sync-up"}},"content":"Dear valued Cadence users and developers,\\n\\n\\nSome of you might have read Temporal\u2019s recent announcement about their decision to drop the support for the Cadence project. This message caused some confusion in the community, so we would like to take this opportunity to clear things out.\\n\\n\\nFirst of all, **Uber is committed to the long-term success of the Cadence project**. Since its inception 5 years ago, use cases built on Cadence and their scale have grown significantly at Uber. Today, Cadence powers a variety of our most business-critical use cases (some public stories are available [here](https://eng.uber.com/hadoop-container-blog/) and [here](https://eng.uber.com/meet-sao-paulo-tech/)). At the same time, the Cadence development team at Uber has enjoyed rapid growth with the product and has been driving innovations of workflow technology across the board, from new features (e.g. [graceful failover](https://github.com/cadence-workflow/cadence/pulls?q=is%3Apr+graceful+failover), [workflow shadowing](https://cadenceworkflow.io/docs/java-client/workflow-replay-shadowing/#workflow-replayer), [UI improvements](https://github.com/cadence-workflow/cadence-web/commits/master)) to better engineering foundations (e.g. [gRPC support](https://github.com/cadence-workflow/cadence/pulls?q=is%3Apr+grpc), [multi-tenancy support](https://github.com/cadence-workflow/cadence/pulls?q=is%3Apr+label%3A%22cadence+multi-tenancy%22+)), all in a backwards compatible manner. Neither Uber\u2019s use nor support of Cadence is going to change with Temporal\u2019s announcement. We have a long list of features and exciting roadmaps ahead of us, and we will share more details in our next meetup in November \u201821. As always we will continue to push the boundaries of scale and reliability as our usage within Uber grows.\\n\\n\x3c!-- truncate --\x3e\\n\\nSecondly, **we are committed to maintaining and growing a healthy and collaborative community**. Cadence continues to attract attention as a [popular open source platform](https://star-history.t9t.io/#cadence-workflow/cadence), with more than 100 contributors to our project, and more than 1500 developers in our [open source Slack support channel](https://t.uber.com/cadence-slack). The Uber Cadence team, along with our open source partners like [Long](https://www.linkedin.com/in/prclqz/) from Indeed, have been behind the management and support of the Cadence open source community for the past 2 years. Moving forward, we are going to work even more closely with our community, through a series of online and offline channels including meetups, office hours, tech deep dives, and design consultations. We would also like to scale the way we operate, by creating a **Cadence OSS Committee** that allows us to maintain a closer relationship with its members, so that we can learn from each other\'s Cadence experiences and grow together. Please definitely let us know your suggestions on the type of engagements that you would like to see with the core team.\\n\\n\\n**About Temporal and its \u201cEOL announcement\u201d**\\n\\nTemporal is a startup that was started 2 years ago based on a Cadence fork by some of the original Cadence team members. We are always grateful for their original contribution to the Cadence project and wish them the best of luck in their future endeavours. That said the announcement from Temporal only means that their team will focus on Temporal (which has always been the case for the last 2 years), and not an official stance on Cadence since they have not been involved with the project for quite some time now.\\n\\n\\nFeel free to reach out to us ([cadence-oss@googlegroups.com](mailto:cadence-oss@googlegroups.com) or [slack](http://t.uber.com/cadence-slack)) if you have any questions. And we look forward to your contribution and collaboration.\\n\\n\\nThe Uber Cadence team"}]}}')}}]); \ No newline at end of file diff --git a/assets/js/4d332630.09e4bd50.js b/assets/js/4d332630.22650505.js similarity index 50% rename from assets/js/4d332630.09e4bd50.js rename to assets/js/4d332630.22650505.js index 412f4e49b..1329f5953 100644 --- a/assets/js/4d332630.09e4bd50.js +++ b/assets/js/4d332630.22650505.js @@ -1 +1 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[7748],{434:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>r,contentTitle:()=>u,default:()=>m,frontMatter:()=>a,metadata:()=>o,toc:()=>l});var o=n(8143),i=n(4848),s=n(8453);const a={title:"Cadence Community Spotlight Update - August 2022",date:new Date("2022-08-31T00:00:00.000Z"),authors:"sharanf",tags:["community-spotlight"]},u=void 0,r={authorsImageUrls:[void 0]},l=[{value:"Community Survey",id:"community-survey",level:2}];function c(e){const t={h2:"h2",li:"li",p:"p",ul:"ul",...(0,s.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(t.p,{children:"Here\u2019s the latest in our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!"}),"\n",(0,i.jsx)(t.p,{children:"Please see below for a roundup of the highlights:"}),"\n",(0,i.jsx)(t.h2,{id:"community-survey",children:"Community Survey"}),"\n",(0,i.jsx)(t.p,{children:"We are working on putting together our first community survey to find out a bit more about our community. We would like to get your feedback about on a few things such as:"}),"\n",(0,i.jsxs)(t.ul,{children:["\n",(0,i.jsx)(t.li,{children:"how you are using Cadence"}),"\n",(0,i.jsx)(t.li,{children:"any specific experiences you have had where you'd like to see new features"}),"\n",(0,i.jsx)(t.li,{children:"any special use cases not yet covered"}),"\n",(0,i.jsx)(t.li,{children:"and of course whatever other feedback you'd like to give us"}),"\n"]}),"\n",(0,i.jsx)(t.p,{children:"So please watch out for the survey which will be coming out to you via the Slack channel soon!"})]})}function m(e={}){const{wrapper:t}={...(0,s.R)(),...e.components};return t?(0,i.jsx)(t,{...e,children:(0,i.jsx)(c,{...e})}):c(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>a,x:()=>u});var o=n(6540);const i={},s=o.createContext(i);function a(e){const t=o.useContext(s);return o.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function u(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:a(e.components),o.createElement(s.Provider,{value:t},e.children)}},8143:e=>{e.exports=JSON.parse('{"permalink":"/blog/2022/08/31/community-spotlight-august-2022","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2022-08-31-community-spotlight-august-2022.md","source":"@site/blog/2022-08-31-community-spotlight-august-2022.md","title":"Cadence Community Spotlight Update - August 2022","description":"Here\u2019s the latest in our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!","date":"2022-08-31T00:00:00.000Z","tags":[{"inline":false,"label":"Community Spotlight","permalink":"/blog/tags/community-spotlights","description":"Community Spotlight tag description"}],"readingTime":2.83,"hasTruncateMarker":true,"authors":[{"name":"Sharan Foga","title":"Director of Operations & Customer Success @ Encube Technologies","url":"https://www.linkedin.com/in/sfoga/","page":{"permalink":"/blog/authors/sharanf"},"socials":{"linkedin":"https://www.linkedin.com/in/sfoga/","github":"https://github.com/sharanf"},"imageURL":"https://github.com/sharanf.png","key":"sharanf"}],"frontMatter":{"title":"Cadence Community Spotlight Update - August 2022","date":"2022-08-31T00:00:00.000Z","authors":"sharanf","tags":["community-spotlight"]},"unlisted":false,"prevItem":{"title":"Cadence Community Spotlight Update - September 2022","permalink":"/blog/2022/09/30/community-spotlight-september-2022"},"nextItem":{"title":"Cadence Community Spotlight Update - July 2022","permalink":"/blog/2022/07/31/community-spotlight-update-july-2022"}}')}}]); \ No newline at end of file +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[7748],{434:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>r,contentTitle:()=>u,default:()=>m,frontMatter:()=>a,metadata:()=>o,toc:()=>c});var o=n(8143),i=n(4848),s=n(8453);const a={title:"Cadence Community Spotlight Update - August 2022",date:new Date("2022-08-31T00:00:00.000Z"),authors:"sharanf",tags:["community-spotlight"]},u=void 0,r={authorsImageUrls:[void 0]},c=[{value:"Community Survey",id:"community-survey",level:2}];function l(e){const t={h2:"h2",li:"li",p:"p",ul:"ul",...(0,s.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(t.p,{children:"Here\u2019s the latest in our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!"}),"\n",(0,i.jsx)(t.p,{children:"Please see below for a roundup of the highlights:"}),"\n",(0,i.jsx)(t.h2,{id:"community-survey",children:"Community Survey"}),"\n",(0,i.jsx)(t.p,{children:"We are working on putting together our first community survey to find out a bit more about our community. We would like to get your feedback about on a few things such as:"}),"\n",(0,i.jsxs)(t.ul,{children:["\n",(0,i.jsx)(t.li,{children:"how you are using Cadence"}),"\n",(0,i.jsx)(t.li,{children:"any specific experiences you have had where you'd like to see new features"}),"\n",(0,i.jsx)(t.li,{children:"any special use cases not yet covered"}),"\n",(0,i.jsx)(t.li,{children:"and of course whatever other feedback you'd like to give us"}),"\n"]}),"\n",(0,i.jsx)(t.p,{children:"So please watch out for the survey which will be coming out to you via the Slack channel soon!"})]})}function m(e={}){const{wrapper:t}={...(0,s.R)(),...e.components};return t?(0,i.jsx)(t,{...e,children:(0,i.jsx)(l,{...e})}):l(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>a,x:()=>u});var o=n(6540);const i={},s=o.createContext(i);function a(e){const t=o.useContext(s);return o.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function u(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:a(e.components),o.createElement(s.Provider,{value:t},e.children)}},8143:e=>{e.exports=JSON.parse('{"permalink":"/Cadence-Docs/blog/2022/08/31/community-spotlight-august-2022","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2022-08-31-community-spotlight-august-2022.md","source":"@site/blog/2022-08-31-community-spotlight-august-2022.md","title":"Cadence Community Spotlight Update - August 2022","description":"Here\u2019s the latest in our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!","date":"2022-08-31T00:00:00.000Z","tags":[{"inline":false,"label":"Community Spotlight","permalink":"/Cadence-Docs/blog/tags/community-spotlights","description":"Community Spotlight tag description"}],"readingTime":2.83,"hasTruncateMarker":true,"authors":[{"name":"Sharan Foga","title":"Director of Operations & Customer Success @ Encube Technologies","url":"https://www.linkedin.com/in/sfoga/","page":{"permalink":"/Cadence-Docs/blog/authors/sharanf"},"socials":{"linkedin":"https://www.linkedin.com/in/sfoga/","github":"https://github.com/sharanf"},"imageURL":"https://github.com/sharanf.png","key":"sharanf"}],"frontMatter":{"title":"Cadence Community Spotlight Update - August 2022","date":"2022-08-31T00:00:00.000Z","authors":"sharanf","tags":["community-spotlight"]},"unlisted":false,"prevItem":{"title":"Cadence Community Spotlight Update - September 2022","permalink":"/Cadence-Docs/blog/2022/09/30/community-spotlight-september-2022"},"nextItem":{"title":"Cadence Community Spotlight Update - July 2022","permalink":"/Cadence-Docs/blog/2022/07/31/community-spotlight-update-july-2022"}}')}}]); \ No newline at end of file diff --git a/assets/js/4d8144ae.8e3b6910.js b/assets/js/4d8144ae.8e3b6910.js new file mode 100644 index 000000000..71992836e --- /dev/null +++ b/assets/js/4d8144ae.8e3b6910.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[6076],{1065:e=>{e.exports=JSON.parse('{"tag":{"label":"Testing","permalink":"/Cadence-Docs/blog/tags/testing","description":"Testing tag description","allTagsPath":"/Cadence-Docs/blog/tags","count":1,"unlisted":false},"listMetadata":{"permalink":"/Cadence-Docs/blog/tags/testing","page":1,"postsPerPage":10,"totalPages":1,"totalCount":1,"blogDescription":"The latest news and updates from the Cadence team","blogTitle":"Cadence Blog"}}')}}]); \ No newline at end of file diff --git a/assets/js/4f20e2dc.09c92d90.js b/assets/js/4f20e2dc.09c92d90.js new file mode 100644 index 000000000..13eaf58a2 --- /dev/null +++ b/assets/js/4f20e2dc.09c92d90.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[4973],{7145:e=>{e.exports=JSON.parse('{"author":{"name":"Chris Qin","title":"Applications Developer @ Uber","url":"https://www.linkedin.com/in/chrisqin0610/","page":{"permalink":"/Cadence-Docs/blog/authors/chopincode"},"socials":{"linkedin":"https://www.linkedin.com/in/chrisqin0610/","github":"https://github.com/chopincode"},"imageURL":"https://github.com/chopincode.png","key":"chopincode","count":6},"listMetadata":{"permalink":"/Cadence-Docs/blog/authors/chopincode","page":1,"postsPerPage":10,"totalPages":1,"totalCount":6,"blogDescription":"The latest news and updates from the Cadence team","blogTitle":"Cadence Blog"}}')}}]); \ No newline at end of file diff --git a/assets/js/528620f0.cde2c83a.js b/assets/js/528620f0.b0244194.js similarity index 55% rename from assets/js/528620f0.cde2c83a.js rename to assets/js/528620f0.b0244194.js index 704e38040..1bee4dd6c 100644 --- a/assets/js/528620f0.cde2c83a.js +++ b/assets/js/528620f0.b0244194.js @@ -1 +1 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[7600],{5506:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>c,contentTitle:()=>s,default:()=>h,frontMatter:()=>a,metadata:()=>o,toc:()=>l});var o=n(5386),i=n(4848),r=n(8453);const a={title:"Cadence Community Spotlight Update - November 2022",date:new Date("2022-11-30T00:00:00.000Z"),authors:"sharanf",tags:["community-spotlight"]},s=void 0,c={authorsImageUrls:[void 0]},l=[{value:"Cadence @ Uber",id:"cadence--uber",level:2},{value:"Cadence @ DeveloperWeek Enterprise",id:"cadence--developerweek-enterprise",level:2}];function d(e){const t={a:"a",h2:"h2",p:"p",...(0,r.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(t.p,{children:"Here\u2019s the latest in our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!"}),"\n",(0,i.jsx)(t.p,{children:"Please see below for a roundup of the highlights:"}),"\n",(0,i.jsx)(t.h2,{id:"cadence--uber",children:"Cadence @ Uber"}),"\n",(0,i.jsxs)(t.p,{children:["This month Uber Engineering published a really nice article on one of the ways they are using Cadence. The article is called ",(0,i.jsx)(t.a,{href:"https://www.uber.com/en-US/blog/how-uber-optimizes-push-notifications-using-ml/",children:"How Uber Optimizes the Timing of Push Notifications using ML and Linear Programming"}),"."]}),"\n",(0,i.jsx)(t.p,{children:"The Uber team take you through the details of the problem that they are looking to solve, so you can understand the scope limitations and depedencies - so please take a look."}),"\n",(0,i.jsx)(t.h2,{id:"cadence--developerweek-enterprise",children:"Cadence @ DeveloperWeek Enterprise"}),"\n",(0,i.jsxs)(t.p,{children:["DevNetwork run a series of conferences and during November Cadence was featured in at ",(0,i.jsx)(t.a,{href:"https://www.developerweek.com/global/conference/enterprise/",children:"DeveloperWeek Enterprise"}),". ",(0,i.jsx)(t.a,{href:"https://www.linkedin.com/in/enderdemirkaya/",children:"Ender Demirkaya"})," and ",(0,i.jsx)(t.a,{href:"https://www.linkedin.com/in/ben-slater-2720562/",children:"Ben Slater"})," presented a talk called ",(0,i.jsx)(t.a,{href:"https://embed.emamo.com/event/developerweek-enterprise-2022/s/express-complex-business-logic-as-code-with-open-source-cadence-WKLMvo",children:"Espress Complex Business Logic as Code with Open Source Cadence!"}),"."]}),"\n",(0,i.jsx)(t.p,{children:"It is good to see that we are finding new channels for us to present the benefits of using Cadence. Huge hanks to Ben and Ender for the presentation and to everyone that attended."})]})}function h(e={}){const{wrapper:t}={...(0,r.R)(),...e.components};return t?(0,i.jsx)(t,{...e,children:(0,i.jsx)(d,{...e})}):d(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>a,x:()=>s});var o=n(6540);const i={},r=o.createContext(i);function a(e){const t=o.useContext(r);return o.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function s(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:a(e.components),o.createElement(r.Provider,{value:t},e.children)}},5386:e=>{e.exports=JSON.parse('{"permalink":"/blog/2022/11/30/community-spotlight-november-2022","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2022-11-30-community-spotlight-november-2022.md","source":"@site/blog/2022-11-30-community-spotlight-november-2022.md","title":"Cadence Community Spotlight Update - November 2022","description":"Here\u2019s the latest in our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!","date":"2022-11-30T00:00:00.000Z","tags":[{"inline":false,"label":"Community Spotlight","permalink":"/blog/tags/community-spotlights","description":"Community Spotlight tag description"}],"readingTime":1.91,"hasTruncateMarker":true,"authors":[{"name":"Sharan Foga","title":"Director of Operations & Customer Success @ Encube Technologies","url":"https://www.linkedin.com/in/sfoga/","page":{"permalink":"/blog/authors/sharanf"},"socials":{"linkedin":"https://www.linkedin.com/in/sfoga/","github":"https://github.com/sharanf"},"imageURL":"https://github.com/sharanf.png","key":"sharanf"}],"frontMatter":{"title":"Cadence Community Spotlight Update - November 2022","date":"2022-11-30T00:00:00.000Z","authors":"sharanf","tags":["community-spotlight"]},"unlisted":false,"prevItem":{"title":"Cadence Community Spotlight Update - December 2022","permalink":"/blog/2022/12/23/community-spotlight-december-2022"},"nextItem":{"title":"Cadence Community Spotlight Update - October 2022","permalink":"/blog/2022/10/31/community-spotlight-october-2022"}}')}}]); \ No newline at end of file +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[7600],{5506:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>c,contentTitle:()=>s,default:()=>h,frontMatter:()=>r,metadata:()=>o,toc:()=>l});var o=n(5386),i=n(4848),a=n(8453);const r={title:"Cadence Community Spotlight Update - November 2022",date:new Date("2022-11-30T00:00:00.000Z"),authors:"sharanf",tags:["community-spotlight"]},s=void 0,c={authorsImageUrls:[void 0]},l=[{value:"Cadence @ Uber",id:"cadence--uber",level:2},{value:"Cadence @ DeveloperWeek Enterprise",id:"cadence--developerweek-enterprise",level:2}];function d(e){const t={a:"a",h2:"h2",p:"p",...(0,a.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(t.p,{children:"Here\u2019s the latest in our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!"}),"\n",(0,i.jsx)(t.p,{children:"Please see below for a roundup of the highlights:"}),"\n",(0,i.jsx)(t.h2,{id:"cadence--uber",children:"Cadence @ Uber"}),"\n",(0,i.jsxs)(t.p,{children:["This month Uber Engineering published a really nice article on one of the ways they are using Cadence. The article is called ",(0,i.jsx)(t.a,{href:"https://www.uber.com/en-US/blog/how-uber-optimizes-push-notifications-using-ml/",children:"How Uber Optimizes the Timing of Push Notifications using ML and Linear Programming"}),"."]}),"\n",(0,i.jsx)(t.p,{children:"The Uber team take you through the details of the problem that they are looking to solve, so you can understand the scope limitations and depedencies - so please take a look."}),"\n",(0,i.jsx)(t.h2,{id:"cadence--developerweek-enterprise",children:"Cadence @ DeveloperWeek Enterprise"}),"\n",(0,i.jsxs)(t.p,{children:["DevNetwork run a series of conferences and during November Cadence was featured in at ",(0,i.jsx)(t.a,{href:"https://www.developerweek.com/global/conference/enterprise/",children:"DeveloperWeek Enterprise"}),". ",(0,i.jsx)(t.a,{href:"https://www.linkedin.com/in/enderdemirkaya/",children:"Ender Demirkaya"})," and ",(0,i.jsx)(t.a,{href:"https://www.linkedin.com/in/ben-slater-2720562/",children:"Ben Slater"})," presented a talk called ",(0,i.jsx)(t.a,{href:"https://embed.emamo.com/event/developerweek-enterprise-2022/s/express-complex-business-logic-as-code-with-open-source-cadence-WKLMvo",children:"Espress Complex Business Logic as Code with Open Source Cadence!"}),"."]}),"\n",(0,i.jsx)(t.p,{children:"It is good to see that we are finding new channels for us to present the benefits of using Cadence. Huge hanks to Ben and Ender for the presentation and to everyone that attended."})]})}function h(e={}){const{wrapper:t}={...(0,a.R)(),...e.components};return t?(0,i.jsx)(t,{...e,children:(0,i.jsx)(d,{...e})}):d(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>r,x:()=>s});var o=n(6540);const i={},a=o.createContext(i);function r(e){const t=o.useContext(a);return o.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function s(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:r(e.components),o.createElement(a.Provider,{value:t},e.children)}},5386:e=>{e.exports=JSON.parse('{"permalink":"/Cadence-Docs/blog/2022/11/30/community-spotlight-november-2022","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2022-11-30-community-spotlight-november-2022.md","source":"@site/blog/2022-11-30-community-spotlight-november-2022.md","title":"Cadence Community Spotlight Update - November 2022","description":"Here\u2019s the latest in our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!","date":"2022-11-30T00:00:00.000Z","tags":[{"inline":false,"label":"Community Spotlight","permalink":"/Cadence-Docs/blog/tags/community-spotlights","description":"Community Spotlight tag description"}],"readingTime":1.91,"hasTruncateMarker":true,"authors":[{"name":"Sharan Foga","title":"Director of Operations & Customer Success @ Encube Technologies","url":"https://www.linkedin.com/in/sfoga/","page":{"permalink":"/Cadence-Docs/blog/authors/sharanf"},"socials":{"linkedin":"https://www.linkedin.com/in/sfoga/","github":"https://github.com/sharanf"},"imageURL":"https://github.com/sharanf.png","key":"sharanf"}],"frontMatter":{"title":"Cadence Community Spotlight Update - November 2022","date":"2022-11-30T00:00:00.000Z","authors":"sharanf","tags":["community-spotlight"]},"unlisted":false,"prevItem":{"title":"Cadence Community Spotlight Update - December 2022","permalink":"/Cadence-Docs/blog/2022/12/23/community-spotlight-december-2022"},"nextItem":{"title":"Cadence Community Spotlight Update - October 2022","permalink":"/Cadence-Docs/blog/2022/10/31/community-spotlight-october-2022"}}')}}]); \ No newline at end of file diff --git a/assets/js/533eb95b.32408520.js b/assets/js/533eb95b.32408520.js new file mode 100644 index 000000000..6d4d121f5 --- /dev/null +++ b/assets/js/533eb95b.32408520.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[5541],{8878:e=>{e.exports=JSON.parse('{"metadata":{"permalink":"/Cadence-Docs/blog/page/4","page":4,"postsPerPage":10,"totalPages":4,"totalCount":35,"previousPage":"/Cadence-Docs/blog/page/3","blogDescription":"The latest news and updates from the Cadence team","blogTitle":"Cadence Blog"}}')}}]); \ No newline at end of file diff --git a/assets/js/534a6068.76f8e63d.js b/assets/js/534a6068.90692c0c.js similarity index 50% rename from assets/js/534a6068.76f8e63d.js rename to assets/js/534a6068.90692c0c.js index cb8da8b59..64f068e3d 100644 --- a/assets/js/534a6068.76f8e63d.js +++ b/assets/js/534a6068.90692c0c.js @@ -1 +1 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[862],{3340:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>c,contentTitle:()=>r,default:()=>u,frontMatter:()=>a,metadata:()=>o,toc:()=>d});var o=n(1230),i=n(4848),s=n(8453);const a={title:"Bad practices and Anti-patterns with Cadence (Part 1)",date:new Date("2023-07-10T00:00:00.000Z"),authors:"chopincode",tags:["introduction-to-cadence","deep-dive"]},r=void 0,c={authorsImageUrls:[void 0]},d=[];function l(e){const t={code:"code",li:"li",p:"p",ul:"ul",...(0,s.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(t.p,{children:"In the upcoming blog series, we will delve into a discussion about common bad practices and anti-patterns related to Cadence. As diverse teams often encounter distinct business use cases, it becomes imperative to address the most frequently reported issues in Cadence workflows. To provide valuable insights and guidance, the Cadence team has meticulously compiled these common challenges based on customer feedback."}),"\n",(0,i.jsxs)(t.ul,{children:["\n",(0,i.jsx)(t.li,{children:"Reusing the same workflow ID for very active/continuous running workflows"}),"\n"]}),"\n",(0,i.jsxs)(t.p,{children:["Cadence organizes workflows based on their unique IDs, using a process called ",(0,i.jsx)("b",{children:"partitioning"}),". If a workflow receives a large number of updates in a short period of time or frequently starts new runs using the ",(0,i.jsx)(t.code,{children:"continueAsNew"}),' function, all these updates will be directed to the same shard. Unfortunately, the Cadence backend is not equipped to handle this concentrated workload efficiently. As a result, a situation known as a "hot shard" arises, overloading the Cadence backend and worsening the problem.']}),"\n",(0,i.jsx)(t.p,{children:"Solution:\nWell, the best way to avoid this is simply just design your workflow in the way such that each workflow owns a uniformly distributed workflow ID across your Cadence domain. This will make sure that Cadence backend is able to evenly distribute the traffic with proper partition on your workflowIDs."})]})}function u(e={}){const{wrapper:t}={...(0,s.R)(),...e.components};return t?(0,i.jsx)(t,{...e,children:(0,i.jsx)(l,{...e})}):l(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>a,x:()=>r});var o=n(6540);const i={},s=o.createContext(i);function a(e){const t=o.useContext(s);return o.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function r(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:a(e.components),o.createElement(s.Provider,{value:t},e.children)}},1230:e=>{e.exports=JSON.parse('{"permalink":"/blog/2023/07/10/cadence-bad-practices-part-1","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2023-07-10-cadence-bad-practices-part-1.md","source":"@site/blog/2023-07-10-cadence-bad-practices-part-1.md","title":"Bad practices and Anti-patterns with Cadence (Part 1)","description":"In the upcoming blog series, we will delve into a discussion about common bad practices and anti-patterns related to Cadence. As diverse teams often encounter distinct business use cases, it becomes imperative to address the most frequently reported issues in Cadence workflows. To provide valuable insights and guidance, the Cadence team has meticulously compiled these common challenges based on customer feedback.","date":"2023-07-10T00:00:00.000Z","tags":[{"inline":false,"label":"Introduction to Cadence","permalink":"/blog/tags/introduction-to-cadence","description":"Introduction to Cadence tag description"},{"inline":false,"label":"Deep Dives","permalink":"/blog/tags/deep-dives","description":"Deep Dives tag description"}],"readingTime":2.065,"hasTruncateMarker":true,"authors":[{"name":"Chris Qin","title":"Applications Developer @ Uber","url":"https://www.linkedin.com/in/chrisqin0610/","page":{"permalink":"/blog/authors/chopincode"},"socials":{"linkedin":"https://www.linkedin.com/in/chrisqin0610/","github":"https://github.com/chopincode"},"imageURL":"https://github.com/chopincode.png","key":"chopincode"}],"frontMatter":{"title":"Bad practices and Anti-patterns with Cadence (Part 1)","date":"2023-07-10T00:00:00.000Z","authors":"chopincode","tags":["introduction-to-cadence","deep-dive"]},"unlisted":false,"prevItem":{"title":"Write your first workflow with Cadence","permalink":"/blog/2023/07/16/2023-07-16-write-your-first-workflow-with-cadence/write-your-first-workflow-with-cadence"},"nextItem":{"title":"Implement a Cadence worker service from scratch","permalink":"/blog/2023/07/05/implement-cadence-worker-from-scratch"}}')}}]); \ No newline at end of file +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[862],{3340:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>r,contentTitle:()=>c,default:()=>u,frontMatter:()=>a,metadata:()=>o,toc:()=>d});var o=n(1230),i=n(4848),s=n(8453);const a={title:"Bad practices and Anti-patterns with Cadence (Part 1)",date:new Date("2023-07-10T00:00:00.000Z"),authors:"chopincode",tags:["introduction-to-cadence","deep-dive"]},c=void 0,r={authorsImageUrls:[void 0]},d=[];function l(e){const t={code:"code",li:"li",p:"p",ul:"ul",...(0,s.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(t.p,{children:"In the upcoming blog series, we will delve into a discussion about common bad practices and anti-patterns related to Cadence. As diverse teams often encounter distinct business use cases, it becomes imperative to address the most frequently reported issues in Cadence workflows. To provide valuable insights and guidance, the Cadence team has meticulously compiled these common challenges based on customer feedback."}),"\n",(0,i.jsxs)(t.ul,{children:["\n",(0,i.jsx)(t.li,{children:"Reusing the same workflow ID for very active/continuous running workflows"}),"\n"]}),"\n",(0,i.jsxs)(t.p,{children:["Cadence organizes workflows based on their unique IDs, using a process called ",(0,i.jsx)("b",{children:"partitioning"}),". If a workflow receives a large number of updates in a short period of time or frequently starts new runs using the ",(0,i.jsx)(t.code,{children:"continueAsNew"}),' function, all these updates will be directed to the same shard. Unfortunately, the Cadence backend is not equipped to handle this concentrated workload efficiently. As a result, a situation known as a "hot shard" arises, overloading the Cadence backend and worsening the problem.']}),"\n",(0,i.jsx)(t.p,{children:"Solution:\nWell, the best way to avoid this is simply just design your workflow in the way such that each workflow owns a uniformly distributed workflow ID across your Cadence domain. This will make sure that Cadence backend is able to evenly distribute the traffic with proper partition on your workflowIDs."})]})}function u(e={}){const{wrapper:t}={...(0,s.R)(),...e.components};return t?(0,i.jsx)(t,{...e,children:(0,i.jsx)(l,{...e})}):l(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>a,x:()=>c});var o=n(6540);const i={},s=o.createContext(i);function a(e){const t=o.useContext(s);return o.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function c(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:a(e.components),o.createElement(s.Provider,{value:t},e.children)}},1230:e=>{e.exports=JSON.parse('{"permalink":"/Cadence-Docs/blog/2023/07/10/cadence-bad-practices-part-1","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2023-07-10-cadence-bad-practices-part-1.md","source":"@site/blog/2023-07-10-cadence-bad-practices-part-1.md","title":"Bad practices and Anti-patterns with Cadence (Part 1)","description":"In the upcoming blog series, we will delve into a discussion about common bad practices and anti-patterns related to Cadence. As diverse teams often encounter distinct business use cases, it becomes imperative to address the most frequently reported issues in Cadence workflows. To provide valuable insights and guidance, the Cadence team has meticulously compiled these common challenges based on customer feedback.","date":"2023-07-10T00:00:00.000Z","tags":[{"inline":false,"label":"Introduction to Cadence","permalink":"/Cadence-Docs/blog/tags/introduction-to-cadence","description":"Introduction to Cadence tag description"},{"inline":false,"label":"Deep Dives","permalink":"/Cadence-Docs/blog/tags/deep-dives","description":"Deep Dives tag description"}],"readingTime":2.065,"hasTruncateMarker":true,"authors":[{"name":"Chris Qin","title":"Applications Developer @ Uber","url":"https://www.linkedin.com/in/chrisqin0610/","page":{"permalink":"/Cadence-Docs/blog/authors/chopincode"},"socials":{"linkedin":"https://www.linkedin.com/in/chrisqin0610/","github":"https://github.com/chopincode"},"imageURL":"https://github.com/chopincode.png","key":"chopincode"}],"frontMatter":{"title":"Bad practices and Anti-patterns with Cadence (Part 1)","date":"2023-07-10T00:00:00.000Z","authors":"chopincode","tags":["introduction-to-cadence","deep-dive"]},"unlisted":false,"prevItem":{"title":"Write your first workflow with Cadence","permalink":"/Cadence-Docs/blog/2023/07/16/2023-07-16-write-your-first-workflow-with-cadence/write-your-first-workflow-with-cadence"},"nextItem":{"title":"Implement a Cadence worker service from scratch","permalink":"/Cadence-Docs/blog/2023/07/05/implement-cadence-worker-from-scratch"}}')}}]); \ No newline at end of file diff --git a/assets/js/5450051a.2ee40998.js b/assets/js/5450051a.2ee40998.js new file mode 100644 index 000000000..4f2e45941 --- /dev/null +++ b/assets/js/5450051a.2ee40998.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[9528],{8781:(e,t,s)=>{s.r(t),s.d(t,{assets:()=>l,contentTitle:()=>r,default:()=>h,frontMatter:()=>o,metadata:()=>n,toc:()=>c});const n=JSON.parse('{"id":"operation-guide/maintain","title":"Cluster Maintenance","description":"This includes how to use and maintain a Cadence cluster for both clients and server clusters.","source":"@site/docs/07-operation-guide/02-maintain.md","sourceDirName":"07-operation-guide","slug":"/operation-guide/maintain","permalink":"/Cadence-Docs/docs/operation-guide/maintain","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/07-operation-guide/02-maintain.md","tags":[],"version":"current","sidebarPosition":2,"frontMatter":{"layout":"default","title":"Cluster Maintenance","permalink":"/docs/operation-guide/maintain"},"sidebar":"docsSidebar","previous":{"title":"Cluster Configuration","permalink":"/Cadence-Docs/docs/operation-guide/setup"},"next":{"title":"Cluster Monitoring","permalink":"/Cadence-Docs/docs/operation-guide/monitoring"}}');var a=s(4848),i=s(8453);const o={layout:"default",title:"Cluster Maintenance",permalink:"/docs/operation-guide/maintain"},r="Cluster Maintenance",l={},c=[{value:"Scale up & down Cluster",id:"scale-up--down-cluster",level:2},{value:"Scale up a tasklist using Scalable tasklist feature",id:"scale-up-a-tasklist-using-scalable-tasklist-feature",level:2},{value:"Restarting Cluster",id:"restarting-cluster",level:2},{value:"Optimize SQL Persistence",id:"optimize-sql-persistence",level:2},{value:"Upgrading Server",id:"upgrading-server",level:2},{value:"How to upgrade:",id:"how-to-upgrade",level:3},{value:"How to apply DB schema changes",id:"how-to-apply-db-schema-changes",level:3}];function d(e){const t={a:"a",code:"code",h1:"h1",h2:"h2",h3:"h3",header:"header",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,i.R)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(t.header,{children:(0,a.jsx)(t.h1,{id:"cluster-maintenance",children:"Cluster Maintenance"})}),"\n",(0,a.jsx)(t.p,{children:"This includes how to use and maintain a Cadence cluster for both clients and server clusters."}),"\n",(0,a.jsx)(t.h2,{id:"scale-up--down-cluster",children:"Scale up & down Cluster"}),"\n",(0,a.jsxs)(t.ul,{children:["\n",(0,a.jsx)(t.li,{children:"When CPU/Memory is getting bottleneck on Cadence instances, you may scale up or add more instances."}),"\n",(0,a.jsxs)(t.li,{children:["Watch ",(0,a.jsx)(t.a,{href:"/docs/operation-guide/monitoring/",children:"Cadence metrics"}),"\n",(0,a.jsxs)(t.ul,{children:["\n",(0,a.jsx)(t.li,{children:"See if the external traffic to frontend is normal"}),"\n",(0,a.jsxs)(t.li,{children:["If the slowness is due to too many tasks on a tasklist, you may need to ",(0,a.jsx)(t.a,{href:"/docs/operation-guide/maintain/#scale-up-a-tasklist-using-scalable-tasklist-feature",children:"scale up the tasklist"})]}),"\n",(0,a.jsx)(t.li,{children:"If persistence latency is getting too high, try scale up your DB instance"}),"\n"]}),"\n"]}),"\n",(0,a.jsxs)(t.li,{children:["Never change the ",(0,a.jsxs)(t.a,{href:"/docs/operation-guide/setup/#static-configuration",children:[(0,a.jsx)(t.code,{children:"numOfShards"})," of a cluster"]}),". If you need that because the current one is too small, follow the instructions to ",(0,a.jsx)(t.a,{href:"migration",children:"migrate your cluster to a new one"}),"."]}),"\n"]}),"\n",(0,a.jsxs)(t.h2,{id:"scale-up-a-tasklist-using-scalable-tasklist-feature",children:["Scale up a tasklist using ",(0,a.jsx)(t.code,{children:"Scalable tasklist"})," feature"]}),"\n",(0,a.jsx)(t.p,{children:"By default a tasklist is not scalable enough to support hundreds of tasks per second. That\u2019s mainly because each tasklist is assigned to a Matching service node, and dispatching tasks in a tasklist is in sequence."}),"\n",(0,a.jsx)(t.p,{children:"In the past, Cadence recommended using multiple tasklists to start workflow/activity. You need to make a list of tasklists and randomly pick one when starting workflows. And then when starting workers, let them listen to all the tasklists."}),"\n",(0,a.jsx)(t.p,{children:"Nowadays, Cadence has a feature called \u201cScalable tasklist\u201d. It will divide a tasklist into multiple logical partitions, which can distribute tasks to multiple Matching service nodes. By default this feature is not enabled because there is some performance penalty on the server side, plus it\u2019s not common that a tasklist needs to support more than hundreds tasks per second."}),"\n",(0,a.jsx)(t.p,{children:"You must make a dynamic configuration change in Cadence server to use this feature:"}),"\n",(0,a.jsx)(t.p,{children:(0,a.jsx)(t.strong,{children:"matching.numTasklistWritePartitions"})}),"\n",(0,a.jsx)(t.p,{children:"and"}),"\n",(0,a.jsx)(t.p,{children:(0,a.jsx)(t.strong,{children:"matching.numTasklistReadPartitions"})}),"\n",(0,a.jsx)(t.p,{children:"matching.numTasklistWritePartitions is the number of partitions when a Cadence server sends a task to the tasklist.\nmatching.numTasklistReadPartitions is the number of partitions when your worker accepts a task from the tasklist."}),"\n",(0,a.jsx)(t.p,{children:"There are a few things to know when using this feature:"}),"\n",(0,a.jsxs)(t.ul,{children:["\n",(0,a.jsxs)(t.li,{children:["Always make sure ",(0,a.jsx)(t.code,{children:"matching.numTasklistWritePartitions <= matching.numTasklistReadPartitions"})," . Otherwise there may be some tasks that are sent to a tasklist partition but no poller(worker) will be able to pick up."]}),"\n",(0,a.jsx)(t.li,{children:"Because of above, when scaling down the number of partitions, you must decrease the WritePartitions first, to wait for a certain time to ensure that tasks are drained, and then decrease ReadPartitions."}),"\n",(0,a.jsxs)(t.li,{children:["Both domain names and taskListName should be specified in the dynamic config. An example of using this feature. See more details about dynamic config format using file based ",(0,a.jsx)(t.a,{href:"/docs/operation-guide/setup/#static-configuration",children:"dynamic config"}),"."]}),"\n"]}),"\n",(0,a.jsx)(t.pre,{children:(0,a.jsx)(t.code,{className:"language-yaml",children:'matching.numTasklistWritePartitions:\n - value: 10\n constraints:\n domainName: "samples-domain"\n taskListName: "aScalableTasklistName"\nmatching.numTasklistReadPartitions:\n - value: 10\n constraints:\n domainName: "samples-domain"\n taskListName: "aScalableTasklistName"\n'})}),"\n",(0,a.jsx)(t.p,{children:"NOTE: the value must be integer without double quotes."}),"\n",(0,a.jsx)(t.h2,{id:"restarting-cluster",children:"Restarting Cluster"}),"\n",(0,a.jsx)(t.p,{children:"Make sure rolling restart to keep high availability."}),"\n",(0,a.jsx)(t.h2,{id:"optimize-sql-persistence",children:"Optimize SQL Persistence"}),"\n",(0,a.jsxs)(t.ul,{children:["\n",(0,a.jsx)(t.li,{children:"Connection is shared within a Cadence server host"}),"\n",(0,a.jsx)(t.li,{children:"For each host, The max number of connections it will consume is maxConn of defaultStore + maxConn of visibilityStore."}),"\n",(0,a.jsx)(t.li,{children:"The total max number of connections your Cadence cluster will consume is the summary from all hosts(from Frontend/Matching/History/SysWorker services)"}),"\n",(0,a.jsx)(t.li,{children:"Frontend and history nodes need both default and visibility Stores, but matching and sys workers only need default Stores, they don't need to talk to visibility DBs."}),"\n",(0,a.jsx)(t.li,{children:"For default Stores, history service will take the most connection, then Frontend/Matching. SysWorker will use much less than others"}),"\n",(0,a.jsx)(t.li,{children:"Default Stores is for Cadence\u2019 core data model, which requires strong consistency. So it cannot use replicas. VisibilityStore is not for core data models. It\u2019s recommended to use a separate DB for visibility store if using DB based visibility."}),"\n",(0,a.jsx)(t.li,{children:"Visibility Stores usually take much less connection as the workload is much lightweight(less QPS and no explicit transactions)."}),"\n",(0,a.jsx)(t.li,{children:"Visibility Stores require eventual consistency for read. So it can use replicas."}),"\n",(0,a.jsx)(t.li,{children:"MaxIdelConns should be less than MaxConns, so that the connections can be distributed better across hosts."}),"\n"]}),"\n",(0,a.jsx)(t.h2,{id:"upgrading-server",children:"Upgrading Server"}),"\n",(0,a.jsxs)(t.p,{children:["To get notified about release, please subscribe the release of project by : Go to ",(0,a.jsx)(t.a,{href:"https://github.com/cadence-workflow/cadence",children:"https://github.com/cadence-workflow/cadence"}),' -> Click the right top "Watch" button -> Custom -> "Release".']}),"\n",(0,a.jsx)(t.p,{children:"It's recommended to upgrade one minor version at a time. E.g, if you are at 0.10, you should upgrade to 0.11, stabilize it with running some normal workload to make sure that the upgraded server is happy with the schema changes. After ~1 hour, then upgrade to 0.12. then 0.13. etc."}),"\n",(0,a.jsx)(t.p,{children:"The reason is that for each minor upgrade, you should be able to follow the release notes about what you should do for upgrading. The release notes may require you to run some commands. This will also help to narrow down the cause when something goes wrong."}),"\n",(0,a.jsx)(t.h3,{id:"how-to-upgrade",children:"How to upgrade:"}),"\n",(0,a.jsx)(t.p,{children:"Things that you may need to do for upgrading a minor version(patch version upgrades should not need it):"}),"\n",(0,a.jsxs)(t.ul,{children:["\n",(0,a.jsx)(t.li,{children:"Schema(DB/ElasticSearch) changes"}),"\n",(0,a.jsx)(t.li,{children:"Configuration format/layout changes"}),"\n",(0,a.jsxs)(t.li,{children:["Data migration -- this is very rare. For example, ",(0,a.jsx)(t.a,{href:"https://github.com/cadence-workflow/cadence/releases/tag/v0.16.0",children:"upgrading from 0.15.x to 0.16.0 requires a data migration"}),"."]}),"\n"]}),"\n",(0,a.jsx)(t.p,{children:"You should read through the release instruction for each minor release to understand what needs to be done."}),"\n",(0,a.jsxs)(t.ul,{children:["\n",(0,a.jsxs)(t.li,{children:["Schema changes need to be applied before upgrading server","\n",(0,a.jsxs)(t.ul,{children:["\n",(0,a.jsx)(t.li,{children:"Upgrade MySQL/Postgres schema if applicable"}),"\n",(0,a.jsx)(t.li,{children:"Upgrade Cassandra schema if applicable"}),"\n",(0,a.jsx)(t.li,{children:"Upgrade ElasticSearch schema if applicable"}),"\n"]}),"\n"]}),"\n",(0,a.jsx)(t.li,{children:"Usually schema change is backward compatible. So rolling back usually is not a problem. It also means that Cadence allows running a mixed version of schema, as long as they are all greater than or equal to the required version of the server.\nOther requirements for upgrading should be found in the release notes. It may contain information about config changes, or special rollback instructions if normal rollback may cause problems."}),"\n",(0,a.jsx)(t.li,{children:"Similarly, data migration should be done before upgrading the server binary."}),"\n"]}),"\n",(0,a.jsx)(t.p,{children:"NOTE: Do not use \u201cauto-setup\u201d images to upgrade your schema. It's mainly for development. At most for initial setup only."}),"\n",(0,a.jsx)(t.h3,{id:"how-to-apply-db-schema-changes",children:"How to apply DB schema changes"}),"\n",(0,a.jsxs)(t.p,{children:["For how to apply database schema, refer to this doc: ",(0,a.jsx)(t.a,{href:"https://github.com/cadence-workflow/cadence/tree/master/tools/sql",children:"SQL tool README"}),"\n",(0,a.jsx)(t.a,{href:"https://github.com/cadence-workflow/cadence/tree/master/tools/cassandra",children:"Cassandra tool README"})]}),"\n",(0,a.jsx)(t.p,{children:"The tool makes use of a table called \u201cschema_versions\u201d to keep track of upgrading History. But there is no transaction guarantee for cross table operations. So in case of some error, you may need to fix or apply schema change manually.\nAlso, the schema tool by default will upgrade schema to the latest, so no manual is required. ( you can also specify to let it upgrade to any place, like 0.14)."}),"\n",(0,a.jsxs)(t.p,{children:["Database schema changes are versioned in the folders: ",(0,a.jsx)(t.a,{href:"https://github.com/cadence-workflow/cadence/tree/master/schema/mysql/v57/cadence/versioned",children:"Versioned Schema Changes"})," for Default Store\nand ",(0,a.jsx)(t.a,{href:"https://github.com/cadence-workflow/cadence/tree/master/schema/mysql/v57/visibility/versioned",children:"Versioned Schema Changes"})," for Visibility Store if you use database for basic visibility instead of ElasticSearch."]}),"\n",(0,a.jsxs)(t.p,{children:["If you use homebrew, the schema files are located at ",(0,a.jsx)(t.code,{children:"/usr/local/etc/cadence/schema/"}),"."]}),"\n",(0,a.jsxs)(t.p,{children:["Alternatively, you can checkout the ",(0,a.jsx)(t.a,{href:"https://github.com/cadence-workflow/cadence",children:"repo"})," and the release tag. E.g. ",(0,a.jsx)(t.code,{children:"git checkout v0.21.0"})," and then the schema files is at ",(0,a.jsx)(t.code,{children:"./schema/"})]})]})}function h(e={}){const{wrapper:t}={...(0,i.R)(),...e.components};return t?(0,a.jsx)(t,{...e,children:(0,a.jsx)(d,{...e})}):d(e)}},8453:(e,t,s)=>{s.d(t,{R:()=>o,x:()=>r});var n=s(6540);const a={},i=n.createContext(a);function o(e){const t=n.useContext(i);return n.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function r(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:o(e.components),n.createElement(i.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/5450051a.fbb1dd55.js b/assets/js/5450051a.fbb1dd55.js deleted file mode 100644 index d3b0d9e34..000000000 --- a/assets/js/5450051a.fbb1dd55.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[9528],{8781:(e,t,s)=>{s.r(t),s.d(t,{assets:()=>l,contentTitle:()=>r,default:()=>h,frontMatter:()=>o,metadata:()=>n,toc:()=>c});const n=JSON.parse('{"id":"operation-guide/maintain","title":"Cluster Maintenance","description":"This includes how to use and maintain a Cadence cluster for both clients and server clusters.","source":"@site/docs/07-operation-guide/02-maintain.md","sourceDirName":"07-operation-guide","slug":"/operation-guide/maintain","permalink":"/docs/operation-guide/maintain","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/07-operation-guide/02-maintain.md","tags":[],"version":"current","sidebarPosition":2,"frontMatter":{"layout":"default","title":"Cluster Maintenance","permalink":"/docs/operation-guide/maintain"},"sidebar":"docsSidebar","previous":{"title":"Cluster Configuration","permalink":"/docs/operation-guide/setup"},"next":{"title":"Cluster Monitoring","permalink":"/docs/operation-guide/monitoring"}}');var a=s(4848),i=s(8453);const o={layout:"default",title:"Cluster Maintenance",permalink:"/docs/operation-guide/maintain"},r="Cluster Maintenance",l={},c=[{value:"Scale up & down Cluster",id:"scale-up--down-cluster",level:2},{value:"Scale up a tasklist using Scalable tasklist feature",id:"scale-up-a-tasklist-using-scalable-tasklist-feature",level:2},{value:"Restarting Cluster",id:"restarting-cluster",level:2},{value:"Optimize SQL Persistence",id:"optimize-sql-persistence",level:2},{value:"Upgrading Server",id:"upgrading-server",level:2},{value:"How to upgrade:",id:"how-to-upgrade",level:3},{value:"How to apply DB schema changes",id:"how-to-apply-db-schema-changes",level:3}];function d(e){const t={a:"a",code:"code",h1:"h1",h2:"h2",h3:"h3",header:"header",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,i.R)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(t.header,{children:(0,a.jsx)(t.h1,{id:"cluster-maintenance",children:"Cluster Maintenance"})}),"\n",(0,a.jsx)(t.p,{children:"This includes how to use and maintain a Cadence cluster for both clients and server clusters."}),"\n",(0,a.jsx)(t.h2,{id:"scale-up--down-cluster",children:"Scale up & down Cluster"}),"\n",(0,a.jsxs)(t.ul,{children:["\n",(0,a.jsx)(t.li,{children:"When CPU/Memory is getting bottleneck on Cadence instances, you may scale up or add more instances."}),"\n",(0,a.jsxs)(t.li,{children:["Watch ",(0,a.jsx)(t.a,{href:"/docs/operation-guide/monitoring/",children:"Cadence metrics"}),"\n",(0,a.jsxs)(t.ul,{children:["\n",(0,a.jsx)(t.li,{children:"See if the external traffic to frontend is normal"}),"\n",(0,a.jsxs)(t.li,{children:["If the slowness is due to too many tasks on a tasklist, you may need to ",(0,a.jsx)(t.a,{href:"/docs/operation-guide/maintain/#scale-up-a-tasklist-using-scalable-tasklist-feature",children:"scale up the tasklist"})]}),"\n",(0,a.jsx)(t.li,{children:"If persistence latency is getting too high, try scale up your DB instance"}),"\n"]}),"\n"]}),"\n",(0,a.jsxs)(t.li,{children:["Never change the ",(0,a.jsxs)(t.a,{href:"/docs/operation-guide/setup/#static-configuration",children:[(0,a.jsx)(t.code,{children:"numOfShards"})," of a cluster"]}),". If you need that because the current one is too small, follow the instructions to ",(0,a.jsx)(t.a,{href:"migration",children:"migrate your cluster to a new one"}),"."]}),"\n"]}),"\n",(0,a.jsxs)(t.h2,{id:"scale-up-a-tasklist-using-scalable-tasklist-feature",children:["Scale up a tasklist using ",(0,a.jsx)(t.code,{children:"Scalable tasklist"})," feature"]}),"\n",(0,a.jsx)(t.p,{children:"By default a tasklist is not scalable enough to support hundreds of tasks per second. That\u2019s mainly because each tasklist is assigned to a Matching service node, and dispatching tasks in a tasklist is in sequence."}),"\n",(0,a.jsx)(t.p,{children:"In the past, Cadence recommended using multiple tasklists to start workflow/activity. You need to make a list of tasklists and randomly pick one when starting workflows. And then when starting workers, let them listen to all the tasklists."}),"\n",(0,a.jsx)(t.p,{children:"Nowadays, Cadence has a feature called \u201cScalable tasklist\u201d. It will divide a tasklist into multiple logical partitions, which can distribute tasks to multiple Matching service nodes. By default this feature is not enabled because there is some performance penalty on the server side, plus it\u2019s not common that a tasklist needs to support more than hundreds tasks per second."}),"\n",(0,a.jsx)(t.p,{children:"You must make a dynamic configuration change in Cadence server to use this feature:"}),"\n",(0,a.jsx)(t.p,{children:(0,a.jsx)(t.strong,{children:"matching.numTasklistWritePartitions"})}),"\n",(0,a.jsx)(t.p,{children:"and"}),"\n",(0,a.jsx)(t.p,{children:(0,a.jsx)(t.strong,{children:"matching.numTasklistReadPartitions"})}),"\n",(0,a.jsx)(t.p,{children:"matching.numTasklistWritePartitions is the number of partitions when a Cadence server sends a task to the tasklist.\nmatching.numTasklistReadPartitions is the number of partitions when your worker accepts a task from the tasklist."}),"\n",(0,a.jsx)(t.p,{children:"There are a few things to know when using this feature:"}),"\n",(0,a.jsxs)(t.ul,{children:["\n",(0,a.jsxs)(t.li,{children:["Always make sure ",(0,a.jsx)(t.code,{children:"matching.numTasklistWritePartitions <= matching.numTasklistReadPartitions"})," . Otherwise there may be some tasks that are sent to a tasklist partition but no poller(worker) will be able to pick up."]}),"\n",(0,a.jsx)(t.li,{children:"Because of above, when scaling down the number of partitions, you must decrease the WritePartitions first, to wait for a certain time to ensure that tasks are drained, and then decrease ReadPartitions."}),"\n",(0,a.jsxs)(t.li,{children:["Both domain names and taskListName should be specified in the dynamic config. An example of using this feature. See more details about dynamic config format using file based ",(0,a.jsx)(t.a,{href:"/docs/operation-guide/setup/#static-configuration",children:"dynamic config"}),"."]}),"\n"]}),"\n",(0,a.jsx)(t.pre,{children:(0,a.jsx)(t.code,{className:"language-yaml",children:'matching.numTasklistWritePartitions:\n - value: 10\n constraints:\n domainName: "samples-domain"\n taskListName: "aScalableTasklistName"\nmatching.numTasklistReadPartitions:\n - value: 10\n constraints:\n domainName: "samples-domain"\n taskListName: "aScalableTasklistName"\n'})}),"\n",(0,a.jsx)(t.p,{children:"NOTE: the value must be integer without double quotes."}),"\n",(0,a.jsx)(t.h2,{id:"restarting-cluster",children:"Restarting Cluster"}),"\n",(0,a.jsx)(t.p,{children:"Make sure rolling restart to keep high availability."}),"\n",(0,a.jsx)(t.h2,{id:"optimize-sql-persistence",children:"Optimize SQL Persistence"}),"\n",(0,a.jsxs)(t.ul,{children:["\n",(0,a.jsx)(t.li,{children:"Connection is shared within a Cadence server host"}),"\n",(0,a.jsx)(t.li,{children:"For each host, The max number of connections it will consume is maxConn of defaultStore + maxConn of visibilityStore."}),"\n",(0,a.jsx)(t.li,{children:"The total max number of connections your Cadence cluster will consume is the summary from all hosts(from Frontend/Matching/History/SysWorker services)"}),"\n",(0,a.jsx)(t.li,{children:"Frontend and history nodes need both default and visibility Stores, but matching and sys workers only need default Stores, they don't need to talk to visibility DBs."}),"\n",(0,a.jsx)(t.li,{children:"For default Stores, history service will take the most connection, then Frontend/Matching. SysWorker will use much less than others"}),"\n",(0,a.jsx)(t.li,{children:"Default Stores is for Cadence\u2019 core data model, which requires strong consistency. So it cannot use replicas. VisibilityStore is not for core data models. It\u2019s recommended to use a separate DB for visibility store if using DB based visibility."}),"\n",(0,a.jsx)(t.li,{children:"Visibility Stores usually take much less connection as the workload is much lightweight(less QPS and no explicit transactions)."}),"\n",(0,a.jsx)(t.li,{children:"Visibility Stores require eventual consistency for read. So it can use replicas."}),"\n",(0,a.jsx)(t.li,{children:"MaxIdelConns should be less than MaxConns, so that the connections can be distributed better across hosts."}),"\n"]}),"\n",(0,a.jsx)(t.h2,{id:"upgrading-server",children:"Upgrading Server"}),"\n",(0,a.jsxs)(t.p,{children:["To get notified about release, please subscribe the release of project by : Go to ",(0,a.jsx)(t.a,{href:"https://github.com/cadence-workflow/cadence",children:"https://github.com/cadence-workflow/cadence"}),' -> Click the right top "Watch" button -> Custom -> "Release".']}),"\n",(0,a.jsx)(t.p,{children:"It's recommended to upgrade one minor version at a time. E.g, if you are at 0.10, you should upgrade to 0.11, stabilize it with running some normal workload to make sure that the upgraded server is happy with the schema changes. After ~1 hour, then upgrade to 0.12. then 0.13. etc."}),"\n",(0,a.jsx)(t.p,{children:"The reason is that for each minor upgrade, you should be able to follow the release notes about what you should do for upgrading. The release notes may require you to run some commands. This will also help to narrow down the cause when something goes wrong."}),"\n",(0,a.jsx)(t.h3,{id:"how-to-upgrade",children:"How to upgrade:"}),"\n",(0,a.jsx)(t.p,{children:"Things that you may need to do for upgrading a minor version(patch version upgrades should not need it):"}),"\n",(0,a.jsxs)(t.ul,{children:["\n",(0,a.jsx)(t.li,{children:"Schema(DB/ElasticSearch) changes"}),"\n",(0,a.jsx)(t.li,{children:"Configuration format/layout changes"}),"\n",(0,a.jsxs)(t.li,{children:["Data migration -- this is very rare. For example, ",(0,a.jsx)(t.a,{href:"https://github.com/cadence-workflow/cadence/releases/tag/v0.16.0",children:"upgrading from 0.15.x to 0.16.0 requires a data migration"}),"."]}),"\n"]}),"\n",(0,a.jsx)(t.p,{children:"You should read through the release instruction for each minor release to understand what needs to be done."}),"\n",(0,a.jsxs)(t.ul,{children:["\n",(0,a.jsxs)(t.li,{children:["Schema changes need to be applied before upgrading server","\n",(0,a.jsxs)(t.ul,{children:["\n",(0,a.jsx)(t.li,{children:"Upgrade MySQL/Postgres schema if applicable"}),"\n",(0,a.jsx)(t.li,{children:"Upgrade Cassandra schema if applicable"}),"\n",(0,a.jsx)(t.li,{children:"Upgrade ElasticSearch schema if applicable"}),"\n"]}),"\n"]}),"\n",(0,a.jsx)(t.li,{children:"Usually schema change is backward compatible. So rolling back usually is not a problem. It also means that Cadence allows running a mixed version of schema, as long as they are all greater than or equal to the required version of the server.\nOther requirements for upgrading should be found in the release notes. It may contain information about config changes, or special rollback instructions if normal rollback may cause problems."}),"\n",(0,a.jsx)(t.li,{children:"Similarly, data migration should be done before upgrading the server binary."}),"\n"]}),"\n",(0,a.jsx)(t.p,{children:"NOTE: Do not use \u201cauto-setup\u201d images to upgrade your schema. It's mainly for development. At most for initial setup only."}),"\n",(0,a.jsx)(t.h3,{id:"how-to-apply-db-schema-changes",children:"How to apply DB schema changes"}),"\n",(0,a.jsxs)(t.p,{children:["For how to apply database schema, refer to this doc: ",(0,a.jsx)(t.a,{href:"https://github.com/cadence-workflow/cadence/tree/master/tools/sql",children:"SQL tool README"}),"\n",(0,a.jsx)(t.a,{href:"https://github.com/cadence-workflow/cadence/tree/master/tools/cassandra",children:"Cassandra tool README"})]}),"\n",(0,a.jsx)(t.p,{children:"The tool makes use of a table called \u201cschema_versions\u201d to keep track of upgrading History. But there is no transaction guarantee for cross table operations. So in case of some error, you may need to fix or apply schema change manually.\nAlso, the schema tool by default will upgrade schema to the latest, so no manual is required. ( you can also specify to let it upgrade to any place, like 0.14)."}),"\n",(0,a.jsxs)(t.p,{children:["Database schema changes are versioned in the folders: ",(0,a.jsx)(t.a,{href:"https://github.com/cadence-workflow/cadence/tree/master/schema/mysql/v57/cadence/versioned",children:"Versioned Schema Changes"})," for Default Store\nand ",(0,a.jsx)(t.a,{href:"https://github.com/cadence-workflow/cadence/tree/master/schema/mysql/v57/visibility/versioned",children:"Versioned Schema Changes"})," for Visibility Store if you use database for basic visibility instead of ElasticSearch."]}),"\n",(0,a.jsxs)(t.p,{children:["If you use homebrew, the schema files are located at ",(0,a.jsx)(t.code,{children:"/usr/local/etc/cadence/schema/"}),"."]}),"\n",(0,a.jsxs)(t.p,{children:["Alternatively, you can checkout the ",(0,a.jsx)(t.a,{href:"https://github.com/cadence-workflow/cadence",children:"repo"})," and the release tag. E.g. ",(0,a.jsx)(t.code,{children:"git checkout v0.21.0"})," and then the schema files is at ",(0,a.jsx)(t.code,{children:"./schema/"})]})]})}function h(e={}){const{wrapper:t}={...(0,i.R)(),...e.components};return t?(0,a.jsx)(t,{...e,children:(0,a.jsx)(d,{...e})}):d(e)}},8453:(e,t,s)=>{s.d(t,{R:()=>o,x:()=>r});var n=s(6540);const a={},i=n.createContext(a);function o(e){const t=n.useContext(i);return n.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function r(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:o(e.components),n.createElement(i.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/55db2bea.b7e4e4a4.js b/assets/js/55db2bea.b7e4e4a4.js new file mode 100644 index 000000000..abb621aa1 --- /dev/null +++ b/assets/js/55db2bea.b7e4e4a4.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[573],{7919:(e,n,i)=>{i.r(n),i.d(n,{assets:()=>a,contentTitle:()=>c,default:()=>h,frontMatter:()=>r,metadata:()=>o,toc:()=>d});const o=JSON.parse('{"id":"operation-guide/setup","title":"Cluster Configuration","description":"This section will help to understand what you need for setting up a Cadence cluster.","source":"@site/docs/07-operation-guide/01-setup.md","sourceDirName":"07-operation-guide","slug":"/operation-guide/setup","permalink":"/Cadence-Docs/docs/operation-guide/setup","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/07-operation-guide/01-setup.md","tags":[],"version":"current","sidebarPosition":1,"frontMatter":{"layout":"default","title":"Cluster Configuration","permalink":"/docs/operation-guide/setup"},"sidebar":"docsSidebar","previous":{"title":"Overview","permalink":"/Cadence-Docs/docs/operation-guide/"},"next":{"title":"Cluster Maintenance","permalink":"/Cadence-Docs/docs/operation-guide/maintain"}}');var t=i(4848),s=i(8453);const r={layout:"default",title:"Cluster Configuration",permalink:"/docs/operation-guide/setup"},c="Cluster Configuration",a={},d=[{value:"Static configuration",id:"static-configuration",level:2},{value:"Configuration Directory and Files",id:"configuration-directory-and-files",level:3},{value:"Combining Configuration Files",id:"combining-configuration-files",level:4},{value:"Using Environment Variables",id:"using-environment-variables",level:4},{value:"Understand the basic static configuration",id:"understand-the-basic-static-configuration",level:3},{value:"The full list of static configuration",id:"the-full-list-of-static-configuration",level:3},{value:"Dynamic Configuration",id:"dynamic-configuration",level:2},{value:"How to update Dynamic Configuration",id:"how-to-update-dynamic-configuration",level:3},{value:"File-based client",id:"file-based-client",level:4},{value:"Config store client",id:"config-store-client",level:4},{value:"Other Advanced Features",id:"other-advanced-features",level:2},{value:"Deployment & Release",id:"deployment--release",level:2},{value:"Stress/Bench Test a cluster",id:"stressbench-test-a-cluster",level:2}];function l(e){const n={a:"a",code:"code",h1:"h1",h2:"h2",h3:"h3",h4:"h4",header:"header",li:"li",p:"p",pre:"pre",strong:"strong",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",ul:"ul",...(0,s.R)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.header,{children:(0,t.jsx)(n.h1,{id:"cluster-configuration",children:"Cluster Configuration"})}),"\n",(0,t.jsx)(n.p,{children:"This section will help to understand what you need for setting up a Cadence cluster."}),"\n",(0,t.jsx)(n.p,{children:"You should understand some basic static configuration of Cadence cluster."}),"\n",(0,t.jsx)(n.p,{children:'There are also many other configuration called "Dynamic Configuration" for fine tuning the cluster. The default values are good to go for small clusters.'}),"\n",(0,t.jsx)(n.p,{children:"Cadence\u2019s minimum dependency is a database(Cassandra or SQL based like MySQL/Postgres). Cadence uses it for persistence. All instances of Cadence clusters are stateless."}),"\n",(0,t.jsx)(n.p,{children:"For production you also need a metric server(Prometheus/Statsd/M3/etc)."}),"\n",(0,t.jsxs)(n.p,{children:["For ",(0,t.jsx)(n.a,{href:"/docs/operation-guide/setup/#other-advanced-features",children:"advanced features"})," Cadence depends on others like Elastisearch/OpenSearch+Kafka if you need ",(0,t.jsx)(n.a,{href:"/docs/concepts/search-workflows/",children:"Advanced visibility feature to search workflows"}),". Cadence will depends on a blob store like S3 if you need to enable ",(0,t.jsx)(n.a,{href:"/docs/concepts/archival/",children:"archival feature"}),"."]}),"\n",(0,t.jsx)(n.h2,{id:"static-configuration",children:"Static configuration"}),"\n",(0,t.jsx)(n.h3,{id:"configuration-directory-and-files",children:"Configuration Directory and Files"}),"\n",(0,t.jsxs)(n.p,{children:["The default directory for configuration files is named ",(0,t.jsx)(n.strong,{children:"config/"}),". This directory contains various configuration files, but not all files will necessarily be used in every scenario."]}),"\n",(0,t.jsx)(n.h4,{id:"combining-configuration-files",children:"Combining Configuration Files"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:["Base Configuration: The ",(0,t.jsx)(n.code,{children:"base.yaml"})," file is always loaded first, providing a common configuration that applies to all environments."]}),"\n",(0,t.jsxs)(n.li,{children:["Runtime Environment File: The second file to be loaded is specific to the runtime environment. The environment name can be specified through the ",(0,t.jsx)(n.code,{children:"$CADENCE_ENVIRONMENT"})," environment variable or passed as a command-line argument. If neither option is specified, ",(0,t.jsx)(n.code,{children:"development.yaml"})," is used by default."]}),"\n",(0,t.jsxs)(n.li,{children:["Availability Zone File: If an availability zone is specified (either through the ",(0,t.jsx)(n.code,{children:"$CADENCE_AVAILABILITY_ZONE"}),' environment variable or as a command-line argument), a file named after the zone will be merged. For example, if you specify "az1" as the zone, ',(0,t.jsx)(n.code,{children:"production_az1.yaml"})," will be used as well."]}),"\n"]}),"\n",(0,t.jsxs)(n.p,{children:["To merge ",(0,t.jsx)(n.code,{children:"base.yaml"}),", ",(0,t.jsx)(n.code,{children:"production.yaml"}),", and ",(0,t.jsx)(n.code,{children:"production_az1.yaml"}),' files, you need to specify "production" as the runtime environment and "az1" as the zone.']}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-log",children:"// base.yaml -> production.yaml -> production_az1.yaml = final configuration\n"})}),"\n",(0,t.jsx)(n.h4,{id:"using-environment-variables",children:"Using Environment Variables"}),"\n",(0,t.jsxs)(n.p,{children:["Configuration values can be provided using environment variables with a specific syntax.\n",(0,t.jsx)(n.code,{children:"$VAR"}),": This notation will be replaced with the value of the specified environment variable. If the environment variable is not set, the value will be left blank.\nYou can declare a default value using the syntax ",(0,t.jsx)(n.code,{children:"{$VAR:default}"}),". This means that if the environment variable VAR is not set, the default value will be used instead."]}),"\n",(0,t.jsxs)(n.p,{children:["Note: If you want to include the ",(0,t.jsx)(n.code,{children:"$"})," symbol literally in your configuration file (without interpreting it as an environment variable substitution), escape it by using $$. This will prevent it from being replaced by an environment variable value."]}),"\n",(0,t.jsx)(n.h3,{id:"understand-the-basic-static-configuration",children:"Understand the basic static configuration"}),"\n",(0,t.jsx)(n.p,{children:"There are quite many configs in Cadence. Here are the most basic configuration that you should understand."}),"\n",(0,t.jsxs)(n.table,{children:[(0,t.jsx)(n.thead,{children:(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.th,{children:"Config name"}),(0,t.jsx)(n.th,{children:"Explanation"}),(0,t.jsx)(n.th,{children:"Recommended value"})]})}),(0,t.jsxs)(n.tbody,{children:[(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"numHistoryShards"}),(0,t.jsxs)(n.td,{children:["This is the most important one in Cadence config.It will be a fixed number in the cluster forever. The only way to change it is to migrate to another cluster. Refer to Migrate cluster section. ",(0,t.jsx)("br",{})," ",(0,t.jsx)("br",{})," Some facts about it: ",(0,t.jsx)("br",{})," 1. Each workflow will be mapped to a single shard. Within a shard, all the workflow creation/updates are serialized. ",(0,t.jsx)("br",{})," 2. Each shard will be assigned to only one History node to own the shard, using a Consistent Hashing Ring. Each shard will consume a small amount of memory/CPU to do background processing. Therefore, a single History node cannot own too many shards. You may need to figure out a good number range based on your instance size(memory/CPU). ",(0,t.jsx)("br",{})," 3. Also, you can\u2019t add an infinite number of nodes to a cluster because this config is fixed. When the number of History nodes is closed or equal to numHistoryShards, there will be some History nodes that have no shards assigned to it. This will be wasting resources. ",(0,t.jsx)("br",{})," ",(0,t.jsx)("br",{})," Based on above, you don\u2019t want to have a small number of shards which will limit the maximum size of your cluster. You also don\u2019t want to have a too big number, which will require you to have a quite big initial size of the cluster. ",(0,t.jsx)("br",{})," Also, typically a production cluster will start with a smaller number and then we add more nodes/hosts to it. But to keep high availability, it\u2019s recommended to use at least 4 nodes for each service(Frontend/History/Matching) at the beginning."]}),(0,t.jsxs)(n.td,{children:["1K~16K depending on the size ranges of the cluster you expect to run, and the instance size. ",(0,t.jsx)(n.strong,{children:"Typically 2K for SQL based persistence, and 8K for Cassandra based."})]})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"ringpop"}),(0,t.jsxs)(n.td,{children:["This is the config to let all nodes of all services connected to each other. ALL the bootstrap nodes MUST be reachable by ringpop when a service is starting up, within a MaxJoinDuration. defaultMaxJoinDuration is 2 minutes. ",(0,t.jsx)("br",{}),(0,t.jsx)("br",{})," It\u2019s not required that bootstrap nodes need to be Frontend/History or Matching. In fact, it can be running none of them as long as it runs Ringpop protocol."]}),(0,t.jsxs)(n.td,{children:["For dns mode: Recommended to put the DNS of Frontend service ",(0,t.jsx)("br",{}),(0,t.jsx)("br",{})," For hosts or hostfile mode: A list of Frontend service node addresses if using hosts mode. Make sure all the bootstrap nodes are reachable at startup."]})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"publicClient"}),(0,t.jsxs)(n.td,{children:["The Cadence Frontend service addresses that internal Cadence system(like system workflows) need to talk to. ",(0,t.jsx)("br",{}),(0,t.jsx)("br",{})," After connected, all nodes in Ringpop will form a ring with identifiers of what service they serve. Ideally Cadence should be able to get Frontend address from there. But Ringpop doesn\u2019t expose this API yet."]}),(0,t.jsxs)(n.td,{children:["Recommended be DNS of Frontend service, so that requests will be distributed to all Frontend nodes. ",(0,t.jsx)("br",{}),(0,t.jsx)("br",{}),"Using localhost+Port or local container IP address+Port will not work if the IP/container is not running frontend"]})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"services.NAME.rpc"}),(0,t.jsxs)(n.td,{children:["Configuration of how to listen to network ports and serve traffic. ",(0,t.jsx)("br",{}),(0,t.jsx)("br",{})," bindOnLocalHost",":true"," will bind on 127.0.0.1. It\u2019s mostly for local development. In production usually you have to specify the IP that containers will use by using bindOnIP ",(0,t.jsx)("br",{}),(0,t.jsx)("br",{})," NAME is the matter for the \u201c--services\u201d option in the server startup command."]}),(0,t.jsx)(n.td,{children:"Name: Use as recommended in development.yaml. bindOnIP : an IP address that the container will serve the traffic with"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"services.NAME.pprof"}),(0,t.jsx)(n.td,{children:"Golang profiling service , will bind on the same IP as RPC"}),(0,t.jsx)(n.td,{children:"a port that you want to serve pprof request"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"services.Name.metrics"}),(0,t.jsx)(n.td,{children:"See Metrics&Logging section"}),(0,t.jsx)(n.td,{children:"cc"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"clusterMetadata"}),(0,t.jsxs)(n.td,{children:["Cadence cluster configuration. ",(0,t.jsx)("br",{}),(0,t.jsx)("br",{}),"enableGlobalDomain\uff1atrue will enable Cadence Cross datacenter replication(aka XDC) feature.",(0,t.jsx)("br",{}),(0,t.jsx)("br",{}),"failoverVersionIncrement: This decides the maximum clusters that you will have replicated to each other at the same time. For example 10 is sufficient for most cases.",(0,t.jsx)("br",{}),(0,t.jsx)("br",{}),"masterClusterName: a master cluster must be one of the enabled clusters, usually the very first cluster to start. It is only meaningful for internal purposes.",(0,t.jsx)("br",{}),(0,t.jsx)("br",{}),"currentClusterName: current cluster name using this config file. ",(0,t.jsx)("br",{}),(0,t.jsx)("br",{}),"clusterInformation is a map from clusterName to the cluster configure ",(0,t.jsx)("br",{}),(0,t.jsx)("br",{}),"initialFailoverVersion: each cluster must use a different value from 0 to failoverVersionIncrement-1. ",(0,t.jsx)("br",{}),(0,t.jsx)("br",{}),"rpcName: must be \u201ccadence-frontend\u201d. Can be improved in this issue. ",(0,t.jsx)("br",{}),(0,t.jsx)("br",{}),"rpcAddress: the address to talk to the Frontend of the cluster for inter-cluster replication. ",(0,t.jsx)("br",{}),(0,t.jsx)("br",{}),"Note that even if you don\u2019t need XDC replication right now, if you want to migrate data stores in the future, you should enable xdc from every beginning. You just need to use the same name of cluster for both masterClusterName and currentClusterName. ",(0,t.jsx)("br",{}),(0,t.jsx)("br",{})," Go to ",(0,t.jsx)(n.a,{href:"/docs/concepts/cross-dc-replication/#running-in-production",children:"cross dc replication"})," for how to configure replication in production"]}),(0,t.jsx)(n.td,{children:"As explanation."})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"dcRedirectionPolicy"}),(0,t.jsx)(n.td,{children:"For allowing forwarding frontend requests from passive cluster to active clusters."}),(0,t.jsx)(n.td,{children:"\u201cselected-apis-forwarding\u201d"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"archival"}),(0,t.jsxs)(n.td,{children:["This is for archival history feature, skip if you don\u2019t need it. Go to ",(0,t.jsx)(n.a,{href:"/docs/concepts/archival/#running-in-production",children:"workflow archival"})," for how to configure archival in production"]}),(0,t.jsx)(n.td,{children:"N/A"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"blobstore"}),(0,t.jsx)(n.td,{children:"This is also for archival history feature Default cadence server is using file based blob store implementation."}),(0,t.jsx)(n.td,{children:"N/A"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"domainDefaults"}),(0,t.jsx)(n.td,{children:"default config for each domain. Right now only being used for Archival feature."}),(0,t.jsx)(n.td,{children:"N/A"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"dynamicconfig (previously known as dynamicConfigClient)"}),(0,t.jsxs)(n.td,{children:["Dynamic config is a config manager that enables you to change configs without restarting servers. It\u2019s a good way for Cadence to keep high availability and make things easy to configure. ",(0,t.jsx)("br",{}),(0,t.jsx)("br",{}),"By default Cadence server uses ",(0,t.jsx)(n.code,{children:"filebased"})," client which allows you to override default configs using a YAML file. However, this approach can be cumbersome in production environment because it's the operator's responsibility to sync the YAML files across Cadence nodes. ",(0,t.jsx)("br",{}),(0,t.jsx)("br",{}),"Therefore, we provide another option, ",(0,t.jsx)(n.code,{children:"configstore"})," client, that stores config changes in the persistent data store for Cadence (e.g., Cassandra database) rather than the YAML file. This approach shifts the responsibility of syncing config changes from the operator to Cadence service. You can use Cadence CLI commands to list/get/update/restore config changes. ",(0,t.jsx)("br",{}),(0,t.jsx)("br",{}),"You can also implement the dynamic config interface if you have a better way to manage configs."]}),(0,t.jsx)(n.td,{children:"Same as the sample development config"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"persistence"}),(0,t.jsxs)(n.td,{children:["Configuration for data store / persistence layer. ",(0,t.jsx)("br",{}),(0,t.jsx)("br",{}),"Values of DefaultStore VisibilityStore AdvancedVisibilityStore should be keys of map DataStores. ",(0,t.jsx)("br",{}),(0,t.jsx)("br",{}),"DefaultStore is for core Cadence functionality. ",(0,t.jsx)("br",{}),(0,t.jsx)("br",{}),"VisibilityStore is for basic visibility feature ",(0,t.jsx)("br",{}),(0,t.jsx)("br",{}),"AdvancedVisibilityStore is for advanced visibility",(0,t.jsx)("br",{}),(0,t.jsx)("br",{})," Go to ",(0,t.jsx)(n.a,{href:"/docs/concepts/search-workflows/#running-in-production",children:"advanced visibility"})," for detailed configuration of advanced visibility. See ",(0,t.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence/blob/master/docs/persistence.md",children:"persistence documentation"})," about using different database for Cadence"]}),(0,t.jsx)(n.td,{children:"As explanation"})]})]})]}),"\n",(0,t.jsx)(n.h3,{id:"the-full-list-of-static-configuration",children:"The full list of static configuration"}),"\n",(0,t.jsx)(n.p,{children:"Starting from v0.21.0, all the static configuration are defined by GoDocs in details."}),"\n",(0,t.jsxs)(n.table,{children:[(0,t.jsx)(n.thead,{children:(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.th,{children:"Version"}),(0,t.jsx)(n.th,{children:"GoDocs Link"}),(0,t.jsx)(n.th,{children:"Github Link"})]})}),(0,t.jsxs)(n.tbody,{children:[(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"v0.21.0"}),(0,t.jsx)(n.td,{children:(0,t.jsx)(n.a,{href:"https://pkg.go.dev/github.com/cadence-workflow/cadence@v0.21.0/common/config#Config",children:"Configuration Docs"})}),(0,t.jsx)(n.td,{children:(0,t.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence/blob/v0.21.0/common/config/config.go#L37",children:"Configuration"})})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsxs)(n.td,{children:["...",(0,t.jsx)(n.a,{href:"https://pkg.go.dev/github.com/cadence-workflow/cadence@v0.21.0?tab=versions",children:"other higher versions"})]}),(0,t.jsx)(n.td,{children:"...Replace the version in the URL of v0.21.0"}),(0,t.jsx)(n.td,{children:"...Replace the version in the URL of v0.21.0"})]})]})]}),"\n",(0,t.jsx)(n.p,{children:"For earlier versions, you can find all the configurations similarly:"}),"\n",(0,t.jsxs)(n.table,{children:[(0,t.jsx)(n.thead,{children:(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.th,{children:"Version"}),(0,t.jsx)(n.th,{children:"GoDocs Link"}),(0,t.jsx)(n.th,{children:"Github Link"})]})}),(0,t.jsxs)(n.tbody,{children:[(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"v0.20.0"}),(0,t.jsx)(n.td,{children:(0,t.jsx)(n.a,{href:"https://pkg.go.dev/github.com/cadence-workflow/cadence@v0.20.0/common/service/config#Config",children:"Configuration Docs"})}),(0,t.jsx)(n.td,{children:(0,t.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence/blob/v0.20.0/common/service/config/config.go#L37",children:"Configuration"})})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"v0.19.2"}),(0,t.jsx)(n.td,{children:(0,t.jsx)(n.a,{href:"https://pkg.go.dev/github.com/cadence-workflow/cadence@v0.19.2/common/service/config#Config",children:"Configuration Docs"})}),(0,t.jsx)(n.td,{children:(0,t.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence/blob/v0.19.2/common/service/config/config.go#L37",children:"Configuration"})})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"v0.18.2"}),(0,t.jsx)(n.td,{children:(0,t.jsx)(n.a,{href:"https://pkg.go.dev/github.com/cadence-workflow/cadence@v0.18.2/common/service/config#Config",children:"Configuration Docs"})}),(0,t.jsx)(n.td,{children:(0,t.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence/blob/v0.18.2/common/service/config/config.go#L37",children:"Configuration"})})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"v0.17.0"}),(0,t.jsx)(n.td,{children:(0,t.jsx)(n.a,{href:"https://pkg.go.dev/github.com/cadence-workflow/cadence@v0.17.0/common/service/config#Config",children:"Configuration Docs"})}),(0,t.jsx)(n.td,{children:(0,t.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence/blob/v0.17.0/common/service/config/config.go#L37",children:"Configuration"})})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsxs)(n.td,{children:["...",(0,t.jsx)(n.a,{href:"https://pkg.go.dev/github.com/cadence-workflow/cadence@v0.20.0?tab=versions",children:"other lower versions"})]}),(0,t.jsx)(n.td,{children:"...Replace the version in the URL of v0.20.0"}),(0,t.jsx)(n.td,{children:"...Replace the version in the URL of v0.20.0"})]})]})]}),"\n",(0,t.jsx)(n.h2,{id:"dynamic-configuration",children:"Dynamic Configuration"}),"\n",(0,t.jsx)(n.p,{children:"Dynamic configuration is for fine tuning a Cadence cluster."}),"\n",(0,t.jsx)(n.p,{children:"There are a lot more dynamic configurations than static configurations. Most of the default values are good for small clusters. As a cluster is scaled up, you may look for tuning it for the optimal performance."}),"\n",(0,t.jsxs)(n.p,{children:["Starting from v0.21.0 with this ",(0,t.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence/pull/4156/files",children:"change"}),", all the dynamic configuration are well defined by GoDocs."]}),"\n",(0,t.jsxs)(n.table,{children:[(0,t.jsx)(n.thead,{children:(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.th,{children:"Version"}),(0,t.jsx)(n.th,{children:"GoDocs Link"}),(0,t.jsx)(n.th,{children:"Github Link"})]})}),(0,t.jsxs)(n.tbody,{children:[(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"v0.21.0"}),(0,t.jsx)(n.td,{children:(0,t.jsx)(n.a,{href:"https://pkg.go.dev/github.com/cadence-workflow/cadence@v0.21.0/common/dynamicconfig#Key",children:"Dynamic Configuration Docs"})}),(0,t.jsx)(n.td,{children:(0,t.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence/blob/v0.21.0/common/dynamicconfig/constants.go#L58",children:"Dynamic Configuration"})})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsxs)(n.td,{children:["...",(0,t.jsx)(n.a,{href:"https://pkg.go.dev/github.com/cadence-workflow/cadence@v0.21.0?tab=versions",children:"other higher versions"})]}),(0,t.jsx)(n.td,{children:"...Replace the version in the URL of v0.21.0"}),(0,t.jsx)(n.td,{children:"...Replace the version in the URL of v0.21.0"})]})]})]}),"\n",(0,t.jsx)(n.p,{children:"For earlier versions, you can find all the configurations similarly:"}),"\n",(0,t.jsxs)(n.table,{children:[(0,t.jsx)(n.thead,{children:(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.th,{children:"Version"}),(0,t.jsx)(n.th,{children:"GoDocs Link"}),(0,t.jsx)(n.th,{children:"Github Link"})]})}),(0,t.jsxs)(n.tbody,{children:[(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"v0.20.0"}),(0,t.jsx)(n.td,{children:(0,t.jsx)(n.a,{href:"https://pkg.go.dev/github.com/cadence-workflow/cadence@v0.20.0/common/service/dynamicconfig#Key",children:"Dynamic Configuration Docs"})}),(0,t.jsx)(n.td,{children:(0,t.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence/blob/v0.20.0/common/service/dynamicconfig/constants.go#L53",children:"Dynamic Configuration"})})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"v0.19.2"}),(0,t.jsx)(n.td,{children:(0,t.jsx)(n.a,{href:"https://pkg.go.dev/github.com/cadence-workflow/cadence@v0.19.2/common/service/dynamicconfig#Key",children:"Dynamic Configuration Docs"})}),(0,t.jsx)(n.td,{children:(0,t.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence/blob/v0.19.2/common/service/dynamicconfig/constants.go#L53",children:"Dynamic Configuration"})})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"v0.18.2"}),(0,t.jsx)(n.td,{children:(0,t.jsx)(n.a,{href:"https://pkg.go.dev/github.com/cadence-workflow/cadence@v0.18.2/common/service/dynamicconfig#Key",children:"Dynamic Configuration Docs"})}),(0,t.jsx)(n.td,{children:(0,t.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence/blob/v0.18.2/common/service/dynamicconfig/constants.go#L53",children:"Dynamic Configuration"})})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"v0.17.0"}),(0,t.jsx)(n.td,{children:(0,t.jsx)(n.a,{href:"https://pkg.go.dev/github.com/cadence-workflow/cadence@v0.17.0/common/service/dynamicconfig#Key",children:"Dynamic Configuration Docs"})}),(0,t.jsx)(n.td,{children:(0,t.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence/blob/v0.17.0/common/service/dynamicconfig/constants.go#L53",children:"Dynamic Configuration"})})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsxs)(n.td,{children:["...",(0,t.jsx)(n.a,{href:"https://pkg.go.dev/github.com/cadence-workflow/cadence@v0.20.0?tab=versions",children:"other lower versions"})]}),(0,t.jsx)(n.td,{children:"...Replace the version in the URL of v0.20.0"}),(0,t.jsx)(n.td,{children:"...Replace the version in the URL of v0.20.0"})]})]})]}),"\n",(0,t.jsxs)(n.p,{children:['However, the GoDocs in earlier versions don\'t contain detailed information. You need to look it up the newer version of GoDocs.\nFor example, search for "EnableGlobalDomain" in Dynamic Configuration ',(0,t.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence/blob/667b7c68e67682a8d23f4b8f93e91a791313d8d6/common/dynamicconfig/constants.go",children:"Comments in v0.21.0"})," or ",(0,t.jsx)(n.a,{href:"https://pkg.go.dev/github.com/cadence-workflow/cadence@v0.21.0/common/dynamicconfig#Key",children:"Docs of v0.21.0"}),", as the usage of DynamicConfiguration never changes."]}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.strong,{children:"KeyName"})," is the key that you will use in the dynamicconfig yaml content"]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.strong,{children:"Default value"})," is the default value"]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.strong,{children:"Value type"})," indicates the type that you should change the yaml value of:","\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"Int should be integer like 123"}),"\n",(0,t.jsx)(n.li,{children:"Float should be number like 123.4"}),"\n",(0,t.jsx)(n.li,{children:"Duration should be Golang duration like: 10s, 2m, 5h for 10 seconds, 2 minutes and 5 hours."}),"\n",(0,t.jsx)(n.li,{children:"Bool should be true or false"}),"\n",(0,t.jsx)(n.li,{children:"Map should be map of yaml"}),"\n"]}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.strong,{children:"Allowed filters"})," indicates what kinds of filters you can set as constraints with the dynamic configuration.","\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"DomainName"})," can be used with ",(0,t.jsx)(n.code,{children:"domainName"})]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"N/A"})," means no filters can be set. The config will be global."]}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,t.jsx)(n.p,{children:"For example, if you want to change the ratelimiting for List API, below is the config:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-clike",children:"// FrontendVisibilityListMaxQPS is max qps frontend can list open/close workflows\n// KeyName: frontend.visibilityListMaxQPS\n// Value type: Int\n// Default value: 10\n// Allowed filters: DomainName\nFrontendVisibilityListMaxQPS\n"})}),"\n",(0,t.jsx)(n.p,{children:"Then you can add the config like:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-yaml",children:'frontend.visibilityListMaxQPS:\n - value: 1000\n constraints:\n domainName: "domainA"\n - value: 2000\n constraints:\n domainName: "domainB"\n'})}),"\n",(0,t.jsxs)(n.p,{children:["You will expect to see ",(0,t.jsx)(n.code,{children:"domainA"})," will be able to perform 1K List operation per second, while ",(0,t.jsx)(n.code,{children:"domainB"})," can perform 2K per second."]}),"\n",(0,t.jsx)(n.p,{children:"NOTE 1: the size related configuration numbers are based on byte."}),"\n",(0,t.jsxs)(n.p,{children:["NOTE 2: for ",(0,t.jsx)(n.code,{children:".persistenceMaxQPS"})," versus ",(0,t.jsx)(n.code,{children:".persistenceGlobalMaxQPS"})," --- persistenceMaxQPS is local for single node while persistenceGlobalMaxQPS is global for all node. persistenceGlobalMaxQPS is preferred if set as greater than zero. But by default it is zero so persistenceMaxQPS is being used."]}),"\n",(0,t.jsx)(n.h3,{id:"how-to-update-dynamic-configuration",children:"How to update Dynamic Configuration"}),"\n",(0,t.jsx)(n.h4,{id:"file-based-client",children:"File-based client"}),"\n",(0,t.jsx)(n.p,{children:"By default, Cadence uses file-based client to manage dynamic configurations. Following are the approaches to changing dynamic configs using a yaml file."}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:["Local docker-compose by mounting volume: 1. Change the dynamic configs in ",(0,t.jsx)(n.code,{children:"cadence/config/dynamicconfig/development.yaml"}),". 2. Update the ",(0,t.jsx)(n.code,{children:"cadence"})," section in the docker compose file and mount ",(0,t.jsx)(n.code,{children:"dynamicconfig"})," folder to host machine like the following:"]}),"\n"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-yaml",children:'cadence:\n image: ubercadence/server:master-auto-setup\n ports:\n # ...(don\'t change anything here)\n environment:\n # ...(don\'t change anything here)\n - "DYNAMIC_CONFIG_FILE_PATH=/etc/custom-dynamicconfig/development.yaml"\n volumes:\n - "/Users//cadence/config/dynamicconfig:/etc/custom-dynamicconfig"\n'})}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsxs)(n.p,{children:["Local docker-compose by logging into the container: run ",(0,t.jsx)(n.code,{children:"docker exec -it docker_cadence_1 /bin/bash"})," to login your container. Then ",(0,t.jsx)(n.code,{children:"vi config/dynamicconfig/development.yaml"})," to make any change. After you changed the config, use ",(0,t.jsx)(n.code,{children:"docker restart docker_cadence_1"})," to restart the cadence instance. Note that you can also use this approach to change static config, but it must be changed through ",(0,t.jsx)(n.code,{children:"config/config_template.yaml"})," instead of ",(0,t.jsx)(n.code,{children:"config/docker.yaml"})," because ",(0,t.jsx)(n.code,{children:"config/docker.yaml"})," is generated on startup."]}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsxs)(n.p,{children:["In production cluster: Follow this example of Helm Chart to deploy Cadence, update dynamic config ",(0,t.jsx)(n.a,{href:"https://github.com/banzaicloud/banzai-charts/blob/be57e81c107fd2ccdfc6cf95dccf6cbab226920c/cadence/templates/server-configmap.yaml#L170",children:"here"})," and restart the cluster."]}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsxs)(n.p,{children:["DEBUG: How to make sure your updates on dynamicconfig is loaded? for example, if you added the following to ",(0,t.jsx)(n.code,{children:"development.yaml"})]}),"\n"]}),"\n"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-yaml",children:"frontend.visibilityListMaxQPS:\n - value: 10000\n"})}),"\n",(0,t.jsxs)(n.p,{children:["After restarting Cadence instances, execute a command like this to let Cadence load the config(it's lazy loading when using it).\n",(0,t.jsx)(n.code,{children:"cadence --domain <> workflow list"})]}),"\n",(0,t.jsx)(n.p,{children:"Then you should see the logs like below"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-log",children:'cadence_1 | {"level":"info","ts":"2021-05-07T18:43:07.869Z","msg":"First loading dynamic config","service":"cadence-frontend","key":"frontend.visibilityListMaxQPS,domainName:sample,clusterName:primary","value":"10000","default-value":"10","logging-call-at":"config.go:93"}\n'})}),"\n",(0,t.jsx)(n.h4,{id:"config-store-client",children:"Config store client"}),"\n",(0,t.jsxs)(n.p,{children:["You can set the ",(0,t.jsx)(n.code,{children:"dynamicconfig"})," client in the static configuration to ",(0,t.jsx)(n.code,{children:"configstore"})," in order to store config changes in a database, as shown below."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-yaml",children:'dynamicconfig:\n client: configstore\n configstore:\n pollInterval: "10s"\n updateRetryAttempts: 2\n FetchTimeout: "2s"\n UpdateTimeout: "2s"\n'})}),"\n",(0,t.jsxs)(n.p,{children:["If you are still using the deprecated config ",(0,t.jsx)(n.code,{children:"dynamicConfigClient"})," like below, you need to replace it with the new ",(0,t.jsx)(n.code,{children:"dynamicconfig"})," as shown above to use ",(0,t.jsx)(n.code,{children:"configstore"})," client."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-yaml",children:'dynamicConfigClient:\n filepath: "/etc/cadence/config/dynamicconfig/config.yaml"\n pollInterval: "10s"\n'})}),"\n",(0,t.jsxs)(n.p,{children:["After changing the client to ",(0,t.jsx)(n.code,{children:"configstore"})," and restarting Cadence, you can manage dynamic configs using ",(0,t.jsx)(n.code,{children:"cadence admin config"})," CLI commands. You may need to set your custom dynamic configs again as the previous configs are not automatically migrated from the YAML file to the database."]}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"cadence admin config listdc"})," lists all dynamic config overrides"]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"cadence admin config getdc --dynamic_config_name "})," gets the value of a specific dynamic config"]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"cadence admin config updc --dynamic_config_name --dynamic_config_value '{\"Value\": }'"})," updates the value of a specific dynamic config"]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"cadence admin config resdc --dynamic_config_name "})," restores a specific dynamic config to its default value"]}),"\n"]}),"\n",(0,t.jsx)(n.h2,{id:"other-advanced-features",children:"Other Advanced Features"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsxs)(n.p,{children:["Go to ",(0,t.jsx)(n.a,{href:"/docs/concepts/search-workflows/#running-in-production",children:"advanced visibility"})," for how to configure advanced visibility in production."]}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsxs)(n.p,{children:["Go to ",(0,t.jsx)(n.a,{href:"/docs/concepts/archival/#running-in-production",children:"workflow archival"})," for how to configure archival in production."]}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsxs)(n.p,{children:["Go to ",(0,t.jsx)(n.a,{href:"/docs/concepts/cross-dc-replication/#running-in-production",children:"cross dc replication"})," for how to configure replication in production."]}),"\n"]}),"\n"]}),"\n",(0,t.jsx)(n.h2,{id:"deployment--release",children:"Deployment & Release"}),"\n",(0,t.jsxs)(n.p,{children:["Kubernetes is the most popular way to deploy Cadence cluster. And easiest way is to use ",(0,t.jsx)(n.a,{href:"https://github.com/banzaicloud/banzai-charts/tree/master/cadence",children:"Cadence Helm Charts"})," that maintained by a community project."]}),"\n",(0,t.jsxs)(n.p,{children:["If you are looking for deploying Cadence using other technologies, then it's reccomended to use Cadence docker images. You can use offical ones, or you may customize it based on what you need. See ",(0,t.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence/tree/master/docker#using-docker-image-for-production",children:"Cadence docker package"})," for how to run the images."]}),"\n",(0,t.jsxs)(n.p,{children:["It's always recommended to use the latest release. See ",(0,t.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence/releases",children:"Cadence release pages"}),"."]}),"\n",(0,t.jsx)(n.p,{children:"Please subscribe the release of project by :"}),"\n",(0,t.jsxs)(n.p,{children:["Go to ",(0,t.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence",children:"https://github.com/cadence-workflow/cadence"}),' -> Click the right top "Watch" button -> Custom -> "Release".']}),"\n",(0,t.jsxs)(n.p,{children:["And see ",(0,t.jsx)(n.a,{href:"/docs/operation-guide/maintain/#upgrading-server",children:"how to upgrade a Cadence cluster"})]}),"\n",(0,t.jsx)(n.h2,{id:"stressbench-test-a-cluster",children:"Stress/Bench Test a cluster"}),"\n",(0,t.jsxs)(n.p,{children:["It's recommended to run bench test on your cluster following this ",(0,t.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence/tree/master/bench",children:"package"})," to see the maximum throughput that it can take, whenever you change some setup."]})]})}function h(e={}){const{wrapper:n}={...(0,s.R)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(l,{...e})}):l(e)}},8453:(e,n,i)=>{i.d(n,{R:()=>r,x:()=>c});var o=i(6540);const t={},s=o.createContext(t);function r(e){const n=o.useContext(s);return o.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function c(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(t):e.components||t:r(e.components),o.createElement(s.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/55db2bea.ee4deac8.js b/assets/js/55db2bea.ee4deac8.js deleted file mode 100644 index d35851d89..000000000 --- a/assets/js/55db2bea.ee4deac8.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[573],{7919:(e,n,i)=>{i.r(n),i.d(n,{assets:()=>a,contentTitle:()=>c,default:()=>h,frontMatter:()=>r,metadata:()=>o,toc:()=>d});const o=JSON.parse('{"id":"operation-guide/setup","title":"Cluster Configuration","description":"This section will help to understand what you need for setting up a Cadence cluster.","source":"@site/docs/07-operation-guide/01-setup.md","sourceDirName":"07-operation-guide","slug":"/operation-guide/setup","permalink":"/docs/operation-guide/setup","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/07-operation-guide/01-setup.md","tags":[],"version":"current","sidebarPosition":1,"frontMatter":{"layout":"default","title":"Cluster Configuration","permalink":"/docs/operation-guide/setup"},"sidebar":"docsSidebar","previous":{"title":"Overview","permalink":"/docs/operation-guide/"},"next":{"title":"Cluster Maintenance","permalink":"/docs/operation-guide/maintain"}}');var t=i(4848),s=i(8453);const r={layout:"default",title:"Cluster Configuration",permalink:"/docs/operation-guide/setup"},c="Cluster Configuration",a={},d=[{value:"Static configuration",id:"static-configuration",level:2},{value:"Configuration Directory and Files",id:"configuration-directory-and-files",level:3},{value:"Combining Configuration Files",id:"combining-configuration-files",level:4},{value:"Using Environment Variables",id:"using-environment-variables",level:4},{value:"Understand the basic static configuration",id:"understand-the-basic-static-configuration",level:3},{value:"The full list of static configuration",id:"the-full-list-of-static-configuration",level:3},{value:"Dynamic Configuration",id:"dynamic-configuration",level:2},{value:"How to update Dynamic Configuration",id:"how-to-update-dynamic-configuration",level:3},{value:"File-based client",id:"file-based-client",level:4},{value:"Config store client",id:"config-store-client",level:4},{value:"Other Advanced Features",id:"other-advanced-features",level:2},{value:"Deployment & Release",id:"deployment--release",level:2},{value:"Stress/Bench Test a cluster",id:"stressbench-test-a-cluster",level:2}];function l(e){const n={a:"a",code:"code",h1:"h1",h2:"h2",h3:"h3",h4:"h4",header:"header",li:"li",p:"p",pre:"pre",strong:"strong",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",ul:"ul",...(0,s.R)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.header,{children:(0,t.jsx)(n.h1,{id:"cluster-configuration",children:"Cluster Configuration"})}),"\n",(0,t.jsx)(n.p,{children:"This section will help to understand what you need for setting up a Cadence cluster."}),"\n",(0,t.jsx)(n.p,{children:"You should understand some basic static configuration of Cadence cluster."}),"\n",(0,t.jsx)(n.p,{children:'There are also many other configuration called "Dynamic Configuration" for fine tuning the cluster. The default values are good to go for small clusters.'}),"\n",(0,t.jsx)(n.p,{children:"Cadence\u2019s minimum dependency is a database(Cassandra or SQL based like MySQL/Postgres). Cadence uses it for persistence. All instances of Cadence clusters are stateless."}),"\n",(0,t.jsx)(n.p,{children:"For production you also need a metric server(Prometheus/Statsd/M3/etc)."}),"\n",(0,t.jsxs)(n.p,{children:["For ",(0,t.jsx)(n.a,{href:"/docs/operation-guide/setup/#other-advanced-features",children:"advanced features"})," Cadence depends on others like Elastisearch/OpenSearch+Kafka if you need ",(0,t.jsx)(n.a,{href:"/docs/concepts/search-workflows/",children:"Advanced visibility feature to search workflows"}),". Cadence will depends on a blob store like S3 if you need to enable ",(0,t.jsx)(n.a,{href:"/docs/concepts/archival/",children:"archival feature"}),"."]}),"\n",(0,t.jsx)(n.h2,{id:"static-configuration",children:"Static configuration"}),"\n",(0,t.jsx)(n.h3,{id:"configuration-directory-and-files",children:"Configuration Directory and Files"}),"\n",(0,t.jsxs)(n.p,{children:["The default directory for configuration files is named ",(0,t.jsx)(n.strong,{children:"config/"}),". This directory contains various configuration files, but not all files will necessarily be used in every scenario."]}),"\n",(0,t.jsx)(n.h4,{id:"combining-configuration-files",children:"Combining Configuration Files"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:["Base Configuration: The ",(0,t.jsx)(n.code,{children:"base.yaml"})," file is always loaded first, providing a common configuration that applies to all environments."]}),"\n",(0,t.jsxs)(n.li,{children:["Runtime Environment File: The second file to be loaded is specific to the runtime environment. The environment name can be specified through the ",(0,t.jsx)(n.code,{children:"$CADENCE_ENVIRONMENT"})," environment variable or passed as a command-line argument. If neither option is specified, ",(0,t.jsx)(n.code,{children:"development.yaml"})," is used by default."]}),"\n",(0,t.jsxs)(n.li,{children:["Availability Zone File: If an availability zone is specified (either through the ",(0,t.jsx)(n.code,{children:"$CADENCE_AVAILABILITY_ZONE"}),' environment variable or as a command-line argument), a file named after the zone will be merged. For example, if you specify "az1" as the zone, ',(0,t.jsx)(n.code,{children:"production_az1.yaml"})," will be used as well."]}),"\n"]}),"\n",(0,t.jsxs)(n.p,{children:["To merge ",(0,t.jsx)(n.code,{children:"base.yaml"}),", ",(0,t.jsx)(n.code,{children:"production.yaml"}),", and ",(0,t.jsx)(n.code,{children:"production_az1.yaml"}),' files, you need to specify "production" as the runtime environment and "az1" as the zone.']}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-log",children:"// base.yaml -> production.yaml -> production_az1.yaml = final configuration\n"})}),"\n",(0,t.jsx)(n.h4,{id:"using-environment-variables",children:"Using Environment Variables"}),"\n",(0,t.jsxs)(n.p,{children:["Configuration values can be provided using environment variables with a specific syntax.\n",(0,t.jsx)(n.code,{children:"$VAR"}),": This notation will be replaced with the value of the specified environment variable. If the environment variable is not set, the value will be left blank.\nYou can declare a default value using the syntax ",(0,t.jsx)(n.code,{children:"{$VAR:default}"}),". This means that if the environment variable VAR is not set, the default value will be used instead."]}),"\n",(0,t.jsxs)(n.p,{children:["Note: If you want to include the ",(0,t.jsx)(n.code,{children:"$"})," symbol literally in your configuration file (without interpreting it as an environment variable substitution), escape it by using $$. This will prevent it from being replaced by an environment variable value."]}),"\n",(0,t.jsx)(n.h3,{id:"understand-the-basic-static-configuration",children:"Understand the basic static configuration"}),"\n",(0,t.jsx)(n.p,{children:"There are quite many configs in Cadence. Here are the most basic configuration that you should understand."}),"\n",(0,t.jsxs)(n.table,{children:[(0,t.jsx)(n.thead,{children:(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.th,{children:"Config name"}),(0,t.jsx)(n.th,{children:"Explanation"}),(0,t.jsx)(n.th,{children:"Recommended value"})]})}),(0,t.jsxs)(n.tbody,{children:[(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"numHistoryShards"}),(0,t.jsxs)(n.td,{children:["This is the most important one in Cadence config.It will be a fixed number in the cluster forever. The only way to change it is to migrate to another cluster. Refer to Migrate cluster section. ",(0,t.jsx)("br",{})," ",(0,t.jsx)("br",{})," Some facts about it: ",(0,t.jsx)("br",{})," 1. Each workflow will be mapped to a single shard. Within a shard, all the workflow creation/updates are serialized. ",(0,t.jsx)("br",{})," 2. Each shard will be assigned to only one History node to own the shard, using a Consistent Hashing Ring. Each shard will consume a small amount of memory/CPU to do background processing. Therefore, a single History node cannot own too many shards. You may need to figure out a good number range based on your instance size(memory/CPU). ",(0,t.jsx)("br",{})," 3. Also, you can\u2019t add an infinite number of nodes to a cluster because this config is fixed. When the number of History nodes is closed or equal to numHistoryShards, there will be some History nodes that have no shards assigned to it. This will be wasting resources. ",(0,t.jsx)("br",{})," ",(0,t.jsx)("br",{})," Based on above, you don\u2019t want to have a small number of shards which will limit the maximum size of your cluster. You also don\u2019t want to have a too big number, which will require you to have a quite big initial size of the cluster. ",(0,t.jsx)("br",{})," Also, typically a production cluster will start with a smaller number and then we add more nodes/hosts to it. But to keep high availability, it\u2019s recommended to use at least 4 nodes for each service(Frontend/History/Matching) at the beginning."]}),(0,t.jsxs)(n.td,{children:["1K~16K depending on the size ranges of the cluster you expect to run, and the instance size. ",(0,t.jsx)(n.strong,{children:"Typically 2K for SQL based persistence, and 8K for Cassandra based."})]})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"ringpop"}),(0,t.jsxs)(n.td,{children:["This is the config to let all nodes of all services connected to each other. ALL the bootstrap nodes MUST be reachable by ringpop when a service is starting up, within a MaxJoinDuration. defaultMaxJoinDuration is 2 minutes. ",(0,t.jsx)("br",{}),(0,t.jsx)("br",{})," It\u2019s not required that bootstrap nodes need to be Frontend/History or Matching. In fact, it can be running none of them as long as it runs Ringpop protocol."]}),(0,t.jsxs)(n.td,{children:["For dns mode: Recommended to put the DNS of Frontend service ",(0,t.jsx)("br",{}),(0,t.jsx)("br",{})," For hosts or hostfile mode: A list of Frontend service node addresses if using hosts mode. Make sure all the bootstrap nodes are reachable at startup."]})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"publicClient"}),(0,t.jsxs)(n.td,{children:["The Cadence Frontend service addresses that internal Cadence system(like system workflows) need to talk to. ",(0,t.jsx)("br",{}),(0,t.jsx)("br",{})," After connected, all nodes in Ringpop will form a ring with identifiers of what service they serve. Ideally Cadence should be able to get Frontend address from there. But Ringpop doesn\u2019t expose this API yet."]}),(0,t.jsxs)(n.td,{children:["Recommended be DNS of Frontend service, so that requests will be distributed to all Frontend nodes. ",(0,t.jsx)("br",{}),(0,t.jsx)("br",{}),"Using localhost+Port or local container IP address+Port will not work if the IP/container is not running frontend"]})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"services.NAME.rpc"}),(0,t.jsxs)(n.td,{children:["Configuration of how to listen to network ports and serve traffic. ",(0,t.jsx)("br",{}),(0,t.jsx)("br",{})," bindOnLocalHost",":true"," will bind on 127.0.0.1. It\u2019s mostly for local development. In production usually you have to specify the IP that containers will use by using bindOnIP ",(0,t.jsx)("br",{}),(0,t.jsx)("br",{})," NAME is the matter for the \u201c--services\u201d option in the server startup command."]}),(0,t.jsx)(n.td,{children:"Name: Use as recommended in development.yaml. bindOnIP : an IP address that the container will serve the traffic with"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"services.NAME.pprof"}),(0,t.jsx)(n.td,{children:"Golang profiling service , will bind on the same IP as RPC"}),(0,t.jsx)(n.td,{children:"a port that you want to serve pprof request"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"services.Name.metrics"}),(0,t.jsx)(n.td,{children:"See Metrics&Logging section"}),(0,t.jsx)(n.td,{children:"cc"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"clusterMetadata"}),(0,t.jsxs)(n.td,{children:["Cadence cluster configuration. ",(0,t.jsx)("br",{}),(0,t.jsx)("br",{}),"enableGlobalDomain\uff1atrue will enable Cadence Cross datacenter replication(aka XDC) feature.",(0,t.jsx)("br",{}),(0,t.jsx)("br",{}),"failoverVersionIncrement: This decides the maximum clusters that you will have replicated to each other at the same time. For example 10 is sufficient for most cases.",(0,t.jsx)("br",{}),(0,t.jsx)("br",{}),"masterClusterName: a master cluster must be one of the enabled clusters, usually the very first cluster to start. It is only meaningful for internal purposes.",(0,t.jsx)("br",{}),(0,t.jsx)("br",{}),"currentClusterName: current cluster name using this config file. ",(0,t.jsx)("br",{}),(0,t.jsx)("br",{}),"clusterInformation is a map from clusterName to the cluster configure ",(0,t.jsx)("br",{}),(0,t.jsx)("br",{}),"initialFailoverVersion: each cluster must use a different value from 0 to failoverVersionIncrement-1. ",(0,t.jsx)("br",{}),(0,t.jsx)("br",{}),"rpcName: must be \u201ccadence-frontend\u201d. Can be improved in this issue. ",(0,t.jsx)("br",{}),(0,t.jsx)("br",{}),"rpcAddress: the address to talk to the Frontend of the cluster for inter-cluster replication. ",(0,t.jsx)("br",{}),(0,t.jsx)("br",{}),"Note that even if you don\u2019t need XDC replication right now, if you want to migrate data stores in the future, you should enable xdc from every beginning. You just need to use the same name of cluster for both masterClusterName and currentClusterName. ",(0,t.jsx)("br",{}),(0,t.jsx)("br",{})," Go to ",(0,t.jsx)(n.a,{href:"/docs/concepts/cross-dc-replication/#running-in-production",children:"cross dc replication"})," for how to configure replication in production"]}),(0,t.jsx)(n.td,{children:"As explanation."})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"dcRedirectionPolicy"}),(0,t.jsx)(n.td,{children:"For allowing forwarding frontend requests from passive cluster to active clusters."}),(0,t.jsx)(n.td,{children:"\u201cselected-apis-forwarding\u201d"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"archival"}),(0,t.jsxs)(n.td,{children:["This is for archival history feature, skip if you don\u2019t need it. Go to ",(0,t.jsx)(n.a,{href:"/docs/concepts/archival/#running-in-production",children:"workflow archival"})," for how to configure archival in production"]}),(0,t.jsx)(n.td,{children:"N/A"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"blobstore"}),(0,t.jsx)(n.td,{children:"This is also for archival history feature Default cadence server is using file based blob store implementation."}),(0,t.jsx)(n.td,{children:"N/A"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"domainDefaults"}),(0,t.jsx)(n.td,{children:"default config for each domain. Right now only being used for Archival feature."}),(0,t.jsx)(n.td,{children:"N/A"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"dynamicconfig (previously known as dynamicConfigClient)"}),(0,t.jsxs)(n.td,{children:["Dynamic config is a config manager that enables you to change configs without restarting servers. It\u2019s a good way for Cadence to keep high availability and make things easy to configure. ",(0,t.jsx)("br",{}),(0,t.jsx)("br",{}),"By default Cadence server uses ",(0,t.jsx)(n.code,{children:"filebased"})," client which allows you to override default configs using a YAML file. However, this approach can be cumbersome in production environment because it's the operator's responsibility to sync the YAML files across Cadence nodes. ",(0,t.jsx)("br",{}),(0,t.jsx)("br",{}),"Therefore, we provide another option, ",(0,t.jsx)(n.code,{children:"configstore"})," client, that stores config changes in the persistent data store for Cadence (e.g., Cassandra database) rather than the YAML file. This approach shifts the responsibility of syncing config changes from the operator to Cadence service. You can use Cadence CLI commands to list/get/update/restore config changes. ",(0,t.jsx)("br",{}),(0,t.jsx)("br",{}),"You can also implement the dynamic config interface if you have a better way to manage configs."]}),(0,t.jsx)(n.td,{children:"Same as the sample development config"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"persistence"}),(0,t.jsxs)(n.td,{children:["Configuration for data store / persistence layer. ",(0,t.jsx)("br",{}),(0,t.jsx)("br",{}),"Values of DefaultStore VisibilityStore AdvancedVisibilityStore should be keys of map DataStores. ",(0,t.jsx)("br",{}),(0,t.jsx)("br",{}),"DefaultStore is for core Cadence functionality. ",(0,t.jsx)("br",{}),(0,t.jsx)("br",{}),"VisibilityStore is for basic visibility feature ",(0,t.jsx)("br",{}),(0,t.jsx)("br",{}),"AdvancedVisibilityStore is for advanced visibility",(0,t.jsx)("br",{}),(0,t.jsx)("br",{})," Go to ",(0,t.jsx)(n.a,{href:"/docs/concepts/search-workflows/#running-in-production",children:"advanced visibility"})," for detailed configuration of advanced visibility. See ",(0,t.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence/blob/master/docs/persistence.md",children:"persistence documentation"})," about using different database for Cadence"]}),(0,t.jsx)(n.td,{children:"As explanation"})]})]})]}),"\n",(0,t.jsx)(n.h3,{id:"the-full-list-of-static-configuration",children:"The full list of static configuration"}),"\n",(0,t.jsx)(n.p,{children:"Starting from v0.21.0, all the static configuration are defined by GoDocs in details."}),"\n",(0,t.jsxs)(n.table,{children:[(0,t.jsx)(n.thead,{children:(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.th,{children:"Version"}),(0,t.jsx)(n.th,{children:"GoDocs Link"}),(0,t.jsx)(n.th,{children:"Github Link"})]})}),(0,t.jsxs)(n.tbody,{children:[(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"v0.21.0"}),(0,t.jsx)(n.td,{children:(0,t.jsx)(n.a,{href:"https://pkg.go.dev/github.com/cadence-workflow/cadence@v0.21.0/common/config#Config",children:"Configuration Docs"})}),(0,t.jsx)(n.td,{children:(0,t.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence/blob/v0.21.0/common/config/config.go#L37",children:"Configuration"})})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsxs)(n.td,{children:["...",(0,t.jsx)(n.a,{href:"https://pkg.go.dev/github.com/cadence-workflow/cadence@v0.21.0?tab=versions",children:"other higher versions"})]}),(0,t.jsx)(n.td,{children:"...Replace the version in the URL of v0.21.0"}),(0,t.jsx)(n.td,{children:"...Replace the version in the URL of v0.21.0"})]})]})]}),"\n",(0,t.jsx)(n.p,{children:"For earlier versions, you can find all the configurations similarly:"}),"\n",(0,t.jsxs)(n.table,{children:[(0,t.jsx)(n.thead,{children:(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.th,{children:"Version"}),(0,t.jsx)(n.th,{children:"GoDocs Link"}),(0,t.jsx)(n.th,{children:"Github Link"})]})}),(0,t.jsxs)(n.tbody,{children:[(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"v0.20.0"}),(0,t.jsx)(n.td,{children:(0,t.jsx)(n.a,{href:"https://pkg.go.dev/github.com/cadence-workflow/cadence@v0.20.0/common/service/config#Config",children:"Configuration Docs"})}),(0,t.jsx)(n.td,{children:(0,t.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence/blob/v0.20.0/common/service/config/config.go#L37",children:"Configuration"})})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"v0.19.2"}),(0,t.jsx)(n.td,{children:(0,t.jsx)(n.a,{href:"https://pkg.go.dev/github.com/cadence-workflow/cadence@v0.19.2/common/service/config#Config",children:"Configuration Docs"})}),(0,t.jsx)(n.td,{children:(0,t.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence/blob/v0.19.2/common/service/config/config.go#L37",children:"Configuration"})})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"v0.18.2"}),(0,t.jsx)(n.td,{children:(0,t.jsx)(n.a,{href:"https://pkg.go.dev/github.com/cadence-workflow/cadence@v0.18.2/common/service/config#Config",children:"Configuration Docs"})}),(0,t.jsx)(n.td,{children:(0,t.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence/blob/v0.18.2/common/service/config/config.go#L37",children:"Configuration"})})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"v0.17.0"}),(0,t.jsx)(n.td,{children:(0,t.jsx)(n.a,{href:"https://pkg.go.dev/github.com/cadence-workflow/cadence@v0.17.0/common/service/config#Config",children:"Configuration Docs"})}),(0,t.jsx)(n.td,{children:(0,t.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence/blob/v0.17.0/common/service/config/config.go#L37",children:"Configuration"})})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsxs)(n.td,{children:["...",(0,t.jsx)(n.a,{href:"https://pkg.go.dev/github.com/cadence-workflow/cadence@v0.20.0?tab=versions",children:"other lower versions"})]}),(0,t.jsx)(n.td,{children:"...Replace the version in the URL of v0.20.0"}),(0,t.jsx)(n.td,{children:"...Replace the version in the URL of v0.20.0"})]})]})]}),"\n",(0,t.jsx)(n.h2,{id:"dynamic-configuration",children:"Dynamic Configuration"}),"\n",(0,t.jsx)(n.p,{children:"Dynamic configuration is for fine tuning a Cadence cluster."}),"\n",(0,t.jsx)(n.p,{children:"There are a lot more dynamic configurations than static configurations. Most of the default values are good for small clusters. As a cluster is scaled up, you may look for tuning it for the optimal performance."}),"\n",(0,t.jsxs)(n.p,{children:["Starting from v0.21.0 with this ",(0,t.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence/pull/4156/files",children:"change"}),", all the dynamic configuration are well defined by GoDocs."]}),"\n",(0,t.jsxs)(n.table,{children:[(0,t.jsx)(n.thead,{children:(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.th,{children:"Version"}),(0,t.jsx)(n.th,{children:"GoDocs Link"}),(0,t.jsx)(n.th,{children:"Github Link"})]})}),(0,t.jsxs)(n.tbody,{children:[(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"v0.21.0"}),(0,t.jsx)(n.td,{children:(0,t.jsx)(n.a,{href:"https://pkg.go.dev/github.com/cadence-workflow/cadence@v0.21.0/common/dynamicconfig#Key",children:"Dynamic Configuration Docs"})}),(0,t.jsx)(n.td,{children:(0,t.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence/blob/v0.21.0/common/dynamicconfig/constants.go#L58",children:"Dynamic Configuration"})})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsxs)(n.td,{children:["...",(0,t.jsx)(n.a,{href:"https://pkg.go.dev/github.com/cadence-workflow/cadence@v0.21.0?tab=versions",children:"other higher versions"})]}),(0,t.jsx)(n.td,{children:"...Replace the version in the URL of v0.21.0"}),(0,t.jsx)(n.td,{children:"...Replace the version in the URL of v0.21.0"})]})]})]}),"\n",(0,t.jsx)(n.p,{children:"For earlier versions, you can find all the configurations similarly:"}),"\n",(0,t.jsxs)(n.table,{children:[(0,t.jsx)(n.thead,{children:(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.th,{children:"Version"}),(0,t.jsx)(n.th,{children:"GoDocs Link"}),(0,t.jsx)(n.th,{children:"Github Link"})]})}),(0,t.jsxs)(n.tbody,{children:[(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"v0.20.0"}),(0,t.jsx)(n.td,{children:(0,t.jsx)(n.a,{href:"https://pkg.go.dev/github.com/cadence-workflow/cadence@v0.20.0/common/service/dynamicconfig#Key",children:"Dynamic Configuration Docs"})}),(0,t.jsx)(n.td,{children:(0,t.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence/blob/v0.20.0/common/service/dynamicconfig/constants.go#L53",children:"Dynamic Configuration"})})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"v0.19.2"}),(0,t.jsx)(n.td,{children:(0,t.jsx)(n.a,{href:"https://pkg.go.dev/github.com/cadence-workflow/cadence@v0.19.2/common/service/dynamicconfig#Key",children:"Dynamic Configuration Docs"})}),(0,t.jsx)(n.td,{children:(0,t.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence/blob/v0.19.2/common/service/dynamicconfig/constants.go#L53",children:"Dynamic Configuration"})})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"v0.18.2"}),(0,t.jsx)(n.td,{children:(0,t.jsx)(n.a,{href:"https://pkg.go.dev/github.com/cadence-workflow/cadence@v0.18.2/common/service/dynamicconfig#Key",children:"Dynamic Configuration Docs"})}),(0,t.jsx)(n.td,{children:(0,t.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence/blob/v0.18.2/common/service/dynamicconfig/constants.go#L53",children:"Dynamic Configuration"})})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"v0.17.0"}),(0,t.jsx)(n.td,{children:(0,t.jsx)(n.a,{href:"https://pkg.go.dev/github.com/cadence-workflow/cadence@v0.17.0/common/service/dynamicconfig#Key",children:"Dynamic Configuration Docs"})}),(0,t.jsx)(n.td,{children:(0,t.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence/blob/v0.17.0/common/service/dynamicconfig/constants.go#L53",children:"Dynamic Configuration"})})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsxs)(n.td,{children:["...",(0,t.jsx)(n.a,{href:"https://pkg.go.dev/github.com/cadence-workflow/cadence@v0.20.0?tab=versions",children:"other lower versions"})]}),(0,t.jsx)(n.td,{children:"...Replace the version in the URL of v0.20.0"}),(0,t.jsx)(n.td,{children:"...Replace the version in the URL of v0.20.0"})]})]})]}),"\n",(0,t.jsxs)(n.p,{children:['However, the GoDocs in earlier versions don\'t contain detailed information. You need to look it up the newer version of GoDocs.\nFor example, search for "EnableGlobalDomain" in Dynamic Configuration ',(0,t.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence/blob/667b7c68e67682a8d23f4b8f93e91a791313d8d6/common/dynamicconfig/constants.go",children:"Comments in v0.21.0"})," or ",(0,t.jsx)(n.a,{href:"https://pkg.go.dev/github.com/cadence-workflow/cadence@v0.21.0/common/dynamicconfig#Key",children:"Docs of v0.21.0"}),", as the usage of DynamicConfiguration never changes."]}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.strong,{children:"KeyName"})," is the key that you will use in the dynamicconfig yaml content"]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.strong,{children:"Default value"})," is the default value"]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.strong,{children:"Value type"})," indicates the type that you should change the yaml value of:","\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"Int should be integer like 123"}),"\n",(0,t.jsx)(n.li,{children:"Float should be number like 123.4"}),"\n",(0,t.jsx)(n.li,{children:"Duration should be Golang duration like: 10s, 2m, 5h for 10 seconds, 2 minutes and 5 hours."}),"\n",(0,t.jsx)(n.li,{children:"Bool should be true or false"}),"\n",(0,t.jsx)(n.li,{children:"Map should be map of yaml"}),"\n"]}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.strong,{children:"Allowed filters"})," indicates what kinds of filters you can set as constraints with the dynamic configuration.","\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"DomainName"})," can be used with ",(0,t.jsx)(n.code,{children:"domainName"})]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"N/A"})," means no filters can be set. The config will be global."]}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,t.jsx)(n.p,{children:"For example, if you want to change the ratelimiting for List API, below is the config:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-clike",children:"// FrontendVisibilityListMaxQPS is max qps frontend can list open/close workflows\n// KeyName: frontend.visibilityListMaxQPS\n// Value type: Int\n// Default value: 10\n// Allowed filters: DomainName\nFrontendVisibilityListMaxQPS\n"})}),"\n",(0,t.jsx)(n.p,{children:"Then you can add the config like:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-yaml",children:'frontend.visibilityListMaxQPS:\n - value: 1000\n constraints:\n domainName: "domainA"\n - value: 2000\n constraints:\n domainName: "domainB"\n'})}),"\n",(0,t.jsxs)(n.p,{children:["You will expect to see ",(0,t.jsx)(n.code,{children:"domainA"})," will be able to perform 1K List operation per second, while ",(0,t.jsx)(n.code,{children:"domainB"})," can perform 2K per second."]}),"\n",(0,t.jsx)(n.p,{children:"NOTE 1: the size related configuration numbers are based on byte."}),"\n",(0,t.jsxs)(n.p,{children:["NOTE 2: for ",(0,t.jsx)(n.code,{children:".persistenceMaxQPS"})," versus ",(0,t.jsx)(n.code,{children:".persistenceGlobalMaxQPS"})," --- persistenceMaxQPS is local for single node while persistenceGlobalMaxQPS is global for all node. persistenceGlobalMaxQPS is preferred if set as greater than zero. But by default it is zero so persistenceMaxQPS is being used."]}),"\n",(0,t.jsx)(n.h3,{id:"how-to-update-dynamic-configuration",children:"How to update Dynamic Configuration"}),"\n",(0,t.jsx)(n.h4,{id:"file-based-client",children:"File-based client"}),"\n",(0,t.jsx)(n.p,{children:"By default, Cadence uses file-based client to manage dynamic configurations. Following are the approaches to changing dynamic configs using a yaml file."}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:["Local docker-compose by mounting volume: 1. Change the dynamic configs in ",(0,t.jsx)(n.code,{children:"cadence/config/dynamicconfig/development.yaml"}),". 2. Update the ",(0,t.jsx)(n.code,{children:"cadence"})," section in the docker compose file and mount ",(0,t.jsx)(n.code,{children:"dynamicconfig"})," folder to host machine like the following:"]}),"\n"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-yaml",children:'cadence:\n image: ubercadence/server:master-auto-setup\n ports:\n # ...(don\'t change anything here)\n environment:\n # ...(don\'t change anything here)\n - "DYNAMIC_CONFIG_FILE_PATH=/etc/custom-dynamicconfig/development.yaml"\n volumes:\n - "/Users//cadence/config/dynamicconfig:/etc/custom-dynamicconfig"\n'})}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsxs)(n.p,{children:["Local docker-compose by logging into the container: run ",(0,t.jsx)(n.code,{children:"docker exec -it docker_cadence_1 /bin/bash"})," to login your container. Then ",(0,t.jsx)(n.code,{children:"vi config/dynamicconfig/development.yaml"})," to make any change. After you changed the config, use ",(0,t.jsx)(n.code,{children:"docker restart docker_cadence_1"})," to restart the cadence instance. Note that you can also use this approach to change static config, but it must be changed through ",(0,t.jsx)(n.code,{children:"config/config_template.yaml"})," instead of ",(0,t.jsx)(n.code,{children:"config/docker.yaml"})," because ",(0,t.jsx)(n.code,{children:"config/docker.yaml"})," is generated on startup."]}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsxs)(n.p,{children:["In production cluster: Follow this example of Helm Chart to deploy Cadence, update dynamic config ",(0,t.jsx)(n.a,{href:"https://github.com/banzaicloud/banzai-charts/blob/be57e81c107fd2ccdfc6cf95dccf6cbab226920c/cadence/templates/server-configmap.yaml#L170",children:"here"})," and restart the cluster."]}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsxs)(n.p,{children:["DEBUG: How to make sure your updates on dynamicconfig is loaded? for example, if you added the following to ",(0,t.jsx)(n.code,{children:"development.yaml"})]}),"\n"]}),"\n"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-yaml",children:"frontend.visibilityListMaxQPS:\n - value: 10000\n"})}),"\n",(0,t.jsxs)(n.p,{children:["After restarting Cadence instances, execute a command like this to let Cadence load the config(it's lazy loading when using it).\n",(0,t.jsx)(n.code,{children:"cadence --domain <> workflow list"})]}),"\n",(0,t.jsx)(n.p,{children:"Then you should see the logs like below"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-log",children:'cadence_1 | {"level":"info","ts":"2021-05-07T18:43:07.869Z","msg":"First loading dynamic config","service":"cadence-frontend","key":"frontend.visibilityListMaxQPS,domainName:sample,clusterName:primary","value":"10000","default-value":"10","logging-call-at":"config.go:93"}\n'})}),"\n",(0,t.jsx)(n.h4,{id:"config-store-client",children:"Config store client"}),"\n",(0,t.jsxs)(n.p,{children:["You can set the ",(0,t.jsx)(n.code,{children:"dynamicconfig"})," client in the static configuration to ",(0,t.jsx)(n.code,{children:"configstore"})," in order to store config changes in a database, as shown below."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-yaml",children:'dynamicconfig:\n client: configstore\n configstore:\n pollInterval: "10s"\n updateRetryAttempts: 2\n FetchTimeout: "2s"\n UpdateTimeout: "2s"\n'})}),"\n",(0,t.jsxs)(n.p,{children:["If you are still using the deprecated config ",(0,t.jsx)(n.code,{children:"dynamicConfigClient"})," like below, you need to replace it with the new ",(0,t.jsx)(n.code,{children:"dynamicconfig"})," as shown above to use ",(0,t.jsx)(n.code,{children:"configstore"})," client."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-yaml",children:'dynamicConfigClient:\n filepath: "/etc/cadence/config/dynamicconfig/config.yaml"\n pollInterval: "10s"\n'})}),"\n",(0,t.jsxs)(n.p,{children:["After changing the client to ",(0,t.jsx)(n.code,{children:"configstore"})," and restarting Cadence, you can manage dynamic configs using ",(0,t.jsx)(n.code,{children:"cadence admin config"})," CLI commands. You may need to set your custom dynamic configs again as the previous configs are not automatically migrated from the YAML file to the database."]}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"cadence admin config listdc"})," lists all dynamic config overrides"]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"cadence admin config getdc --dynamic_config_name "})," gets the value of a specific dynamic config"]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"cadence admin config updc --dynamic_config_name --dynamic_config_value '{\"Value\": }'"})," updates the value of a specific dynamic config"]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"cadence admin config resdc --dynamic_config_name "})," restores a specific dynamic config to its default value"]}),"\n"]}),"\n",(0,t.jsx)(n.h2,{id:"other-advanced-features",children:"Other Advanced Features"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsxs)(n.p,{children:["Go to ",(0,t.jsx)(n.a,{href:"/docs/concepts/search-workflows/#running-in-production",children:"advanced visibility"})," for how to configure advanced visibility in production."]}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsxs)(n.p,{children:["Go to ",(0,t.jsx)(n.a,{href:"/docs/concepts/archival/#running-in-production",children:"workflow archival"})," for how to configure archival in production."]}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsxs)(n.p,{children:["Go to ",(0,t.jsx)(n.a,{href:"/docs/concepts/cross-dc-replication/#running-in-production",children:"cross dc replication"})," for how to configure replication in production."]}),"\n"]}),"\n"]}),"\n",(0,t.jsx)(n.h2,{id:"deployment--release",children:"Deployment & Release"}),"\n",(0,t.jsxs)(n.p,{children:["Kubernetes is the most popular way to deploy Cadence cluster. And easiest way is to use ",(0,t.jsx)(n.a,{href:"https://github.com/banzaicloud/banzai-charts/tree/master/cadence",children:"Cadence Helm Charts"})," that maintained by a community project."]}),"\n",(0,t.jsxs)(n.p,{children:["If you are looking for deploying Cadence using other technologies, then it's reccomended to use Cadence docker images. You can use offical ones, or you may customize it based on what you need. See ",(0,t.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence/tree/master/docker#using-docker-image-for-production",children:"Cadence docker package"})," for how to run the images."]}),"\n",(0,t.jsxs)(n.p,{children:["It's always recommended to use the latest release. See ",(0,t.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence/releases",children:"Cadence release pages"}),"."]}),"\n",(0,t.jsx)(n.p,{children:"Please subscribe the release of project by :"}),"\n",(0,t.jsxs)(n.p,{children:["Go to ",(0,t.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence",children:"https://github.com/cadence-workflow/cadence"}),' -> Click the right top "Watch" button -> Custom -> "Release".']}),"\n",(0,t.jsxs)(n.p,{children:["And see ",(0,t.jsx)(n.a,{href:"/docs/operation-guide/maintain/#upgrading-server",children:"how to upgrade a Cadence cluster"})]}),"\n",(0,t.jsx)(n.h2,{id:"stressbench-test-a-cluster",children:"Stress/Bench Test a cluster"}),"\n",(0,t.jsxs)(n.p,{children:["It's recommended to run bench test on your cluster following this ",(0,t.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence/tree/master/bench",children:"package"})," to see the maximum throughput that it can take, whenever you change some setup."]})]})}function h(e={}){const{wrapper:n}={...(0,s.R)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(l,{...e})}):l(e)}},8453:(e,n,i)=>{i.d(n,{R:()=>r,x:()=>c});var o=i(6540);const t={},s=o.createContext(t);function r(e){const n=o.useContext(s);return o.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function c(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(t):e.components||t:r(e.components),o.createElement(s.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/5806acc5.05ca9dd1.js b/assets/js/5806acc5.05ca9dd1.js deleted file mode 100644 index 6575aed53..000000000 --- a/assets/js/5806acc5.05ca9dd1.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[9306],{4639:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>c,contentTitle:()=>r,default:()=>m,frontMatter:()=>s,metadata:()=>a,toc:()=>l});var a=t(375),i=t(4848),o=t(8453);const s={title:"Announcement: Cadence Helm Charts v0 Release",date:new Date("2024-10-01T00:00:00.000Z"),authors:"taylanisikdemir",tags:["announcement"]},r=void 0,c={authorsImageUrls:[void 0]},l=[];function d(e){const n={a:"a",p:"p",...(0,o.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsxs)(n.p,{children:["We\u2019ve heard your feedback: deploying Cadence has been a challenge, especially with limited documentation on operational aspects. So far, we\u2019ve only provided a few ",(0,i.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence/tree/master/docker",children:"docker compose files"})," to help you get started on a development machine. However, deploying and managing Cadence at scale requires a deep understanding of underlying services, configurations and their dependencies."]}),"\n",(0,i.jsx)(n.p,{children:"To address these challenges, we\u2019re launching several initiatives to make it easier to deploy and operate Cadence clusters. These include deployment specs for common scenarios, monitoring dashboards, alerts, runbooks, and more comprehensive documentation."})]})}function m(e={}){const{wrapper:n}={...(0,o.R)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(d,{...e})}):d(e)}},8453:(e,n,t)=>{t.d(n,{R:()=>s,x:()=>r});var a=t(6540);const i={},o=a.createContext(i);function s(e){const n=a.useContext(o);return a.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function r(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:s(e.components),a.createElement(o.Provider,{value:n},e.children)}},375:e=>{e.exports=JSON.parse('{"permalink":"/blog/2024/10/01/announcing-cadence-helm-charts-v0","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2024-10-01-announcing-cadence-helm-charts-v0.md","source":"@site/blog/2024-10-01-announcing-cadence-helm-charts-v0.md","title":"Announcement: Cadence Helm Charts v0 Release","description":"We\u2019ve heard your feedback: deploying Cadence has been a challenge, especially with limited documentation on operational aspects. So far, we\u2019ve only provided a few docker compose files to help you get started on a development machine. However, deploying and managing Cadence at scale requires a deep understanding of underlying services, configurations and their dependencies.","date":"2024-10-01T00:00:00.000Z","tags":[{"inline":false,"label":"Announcement","permalink":"/blog/tags/announcements","description":"Announcement tag description"}],"readingTime":2.6,"hasTruncateMarker":true,"authors":[{"name":"Taylan Isikdemir","title":"Sr. Staff Software Engineer @ Uber","url":"https://www.linkedin.com/in/taylan-isikdemir","page":{"permalink":"/blog/authors/taylanisikdemir"},"socials":{"linkedin":"https://www.linkedin.com/in/taylan-isikdemir","github":"https://github.com/taylanisikdemir"},"imageURL":"https://github.com/taylanisikdemir.png","key":"taylanisikdemir"}],"frontMatter":{"title":"Announcement: Cadence Helm Charts v0 Release","date":"2024-10-01T00:00:00.000Z","authors":"taylanisikdemir","tags":["announcement"]},"unlisted":false,"prevItem":{"title":"Zonal Isolation for Cadence Workflows","permalink":"/blog/zonal-isolation-v1/zonal-isolation-v1"},"nextItem":{"title":"Minimizing blast radius in Cadence: Introducing Workflow ID-based Rate Limits","permalink":"/blog/2024/09/05/workflow-specific-rate-limits"}}')}}]); \ No newline at end of file diff --git a/assets/js/5806acc5.f7c50722.js b/assets/js/5806acc5.f7c50722.js new file mode 100644 index 000000000..a3765e941 --- /dev/null +++ b/assets/js/5806acc5.f7c50722.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[9306],{4639:(e,n,a)=>{a.r(n),a.d(n,{assets:()=>c,contentTitle:()=>r,default:()=>m,frontMatter:()=>s,metadata:()=>t,toc:()=>d});var t=a(375),o=a(4848),i=a(8453);const s={title:"Announcement: Cadence Helm Charts v0 Release",date:new Date("2024-10-01T00:00:00.000Z"),authors:"taylanisikdemir",tags:["announcement"]},r=void 0,c={authorsImageUrls:[void 0]},d=[];function l(e){const n={a:"a",p:"p",...(0,i.R)(),...e.components};return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsxs)(n.p,{children:["We\u2019ve heard your feedback: deploying Cadence has been a challenge, especially with limited documentation on operational aspects. So far, we\u2019ve only provided a few ",(0,o.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence/tree/master/docker",children:"docker compose files"})," to help you get started on a development machine. However, deploying and managing Cadence at scale requires a deep understanding of underlying services, configurations and their dependencies."]}),"\n",(0,o.jsx)(n.p,{children:"To address these challenges, we\u2019re launching several initiatives to make it easier to deploy and operate Cadence clusters. These include deployment specs for common scenarios, monitoring dashboards, alerts, runbooks, and more comprehensive documentation."})]})}function m(e={}){const{wrapper:n}={...(0,i.R)(),...e.components};return n?(0,o.jsx)(n,{...e,children:(0,o.jsx)(l,{...e})}):l(e)}},8453:(e,n,a)=>{a.d(n,{R:()=>s,x:()=>r});var t=a(6540);const o={},i=t.createContext(o);function s(e){const n=t.useContext(i);return t.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function r(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:s(e.components),t.createElement(i.Provider,{value:n},e.children)}},375:e=>{e.exports=JSON.parse('{"permalink":"/Cadence-Docs/blog/2024/10/01/announcing-cadence-helm-charts-v0","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2024-10-01-announcing-cadence-helm-charts-v0.md","source":"@site/blog/2024-10-01-announcing-cadence-helm-charts-v0.md","title":"Announcement: Cadence Helm Charts v0 Release","description":"We\u2019ve heard your feedback: deploying Cadence has been a challenge, especially with limited documentation on operational aspects. So far, we\u2019ve only provided a few docker compose files to help you get started on a development machine. However, deploying and managing Cadence at scale requires a deep understanding of underlying services, configurations and their dependencies.","date":"2024-10-01T00:00:00.000Z","tags":[{"inline":false,"label":"Announcement","permalink":"/Cadence-Docs/blog/tags/announcements","description":"Announcement tag description"}],"readingTime":2.6,"hasTruncateMarker":true,"authors":[{"name":"Taylan Isikdemir","title":"Sr. Staff Software Engineer @ Uber","url":"https://www.linkedin.com/in/taylan-isikdemir","page":{"permalink":"/Cadence-Docs/blog/authors/taylanisikdemir"},"socials":{"linkedin":"https://www.linkedin.com/in/taylan-isikdemir","github":"https://github.com/taylanisikdemir"},"imageURL":"https://github.com/taylanisikdemir.png","key":"taylanisikdemir"}],"frontMatter":{"title":"Announcement: Cadence Helm Charts v0 Release","date":"2024-10-01T00:00:00.000Z","authors":"taylanisikdemir","tags":["announcement"]},"unlisted":false,"prevItem":{"title":"Zonal Isolation for Cadence Workflows","permalink":"/Cadence-Docs/blog/zonal-isolation-v1/zonal-isolation-v1"},"nextItem":{"title":"Minimizing blast radius in Cadence: Introducing Workflow ID-based Rate Limits","permalink":"/Cadence-Docs/blog/2024/09/05/workflow-specific-rate-limits"}}')}}]); \ No newline at end of file diff --git a/assets/js/580cfca3.2bebdbfb.js b/assets/js/580cfca3.76026c4c.js similarity index 83% rename from assets/js/580cfca3.2bebdbfb.js rename to assets/js/580cfca3.76026c4c.js index d27bdec0a..eba39d4b8 100644 --- a/assets/js/580cfca3.2bebdbfb.js +++ b/assets/js/580cfca3.76026c4c.js @@ -1 +1 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[7770],{3800:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>l,contentTitle:()=>r,default:()=>d,frontMatter:()=>s,metadata:()=>o,toc:()=>c});var o=t(586),a=t(4848),i=t(8453);const s={title:"Cadence Community Spotlight Update - November 2023",date:new Date("2023-11-30T00:00:00.000Z"),authors:"sharanf",tags:["community-spotlight","announcement"]},r=void 0,l={authorsImageUrls:[void 0]},c=[{value:"Proposal for Cadence Native Authentication",id:"proposal-for-cadence-native-authentication",level:2},{value:"iWF Deep Dive and More!",id:"iwf-deep-dive-and-more",level:2},{value:"New Go Samples for Cadence",id:"new-go-samples-for-cadence",level:2},{value:"Cadence Retrospective",id:"cadence-retrospective",level:2},{value:"Cadence in the News!",id:"cadence-in-the-news",level:2},{value:"Upcoming Events",id:"upcoming-events",level:2}];function h(e){const n={a:"a",h2:"h2",li:"li",p:"p",ul:"ul",...(0,i.R)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(n.p,{children:"Welcome to the latest of our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!"}),"\n",(0,a.jsx)(n.p,{children:"It's been a couple of months since our last update so we have a lot of updates to share with you."}),"\n",(0,a.jsx)(n.p,{children:"Please see below for a roundup of the highlights:"}),"\n",(0,a.jsx)(n.h2,{id:"proposal-for-cadence-native-authentication",children:"Proposal for Cadence Native Authentication"}),"\n",(0,a.jsxs)(n.p,{children:["Community member ",(0,a.jsx)(n.a,{href:"https://lt.linkedin.com/in/mantassidlauskas",children:"Mantas Sidlauskas"})," has drafted a proposal around Cadence native authentication and is asking for community feedback. If you are interested in reviewing the current proposal and providing comments or feedback then please find the proposal details at the link below:"]}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsx)(n.li,{children:(0,a.jsx)(n.a,{href:"https://docs.google.com/document/d/13GxRBZfQkLyhDCrpFaZmRcw7DJJG-zdy0_mPXy3CcWw/edit#heading=h.c8u99ansg7ma",children:"Cadence Native Authentication Proposal"})}),"\n"]}),"\n",(0,a.jsx)(n.p,{children:"This is a great example of how we can focus on collaborating together to find a collective solution. A big thank you to Mantas for initiating this work and we hope to see the results of the community input soon!"}),"\n",(0,a.jsx)(n.h2,{id:"iwf-deep-dive-and-more",children:"iWF Deep Dive and More!"}),"\n",(0,a.jsxs)(n.p,{children:["During the last few months community member ",(0,a.jsx)(n.a,{href:"https://www.linkedin.com/in/prclqz/",children:"Quanzheng Long"})," has continued to share his thoughts about ",(0,a.jsx)(n.a,{href:"https://github.com/indeedeng/iwf",children:"iWF"}),", a layer implemented on top of Cadence. Since our last update iWF now has a",(0,a.jsx)(n.a,{href:"https://github.com/indeedeng/iwf-python-sdk",children:"Python SDK"}),". Long has been busy writing articles to share iWF tips and tricks as well as some general ideas about workflows and processes. Links to Long's articles can be found below:"]}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsxs)(n.li,{children:["\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.a,{href:"https://medium.com/@qlong/iwf-deep-dive-workflowstate-durable-timer-1-0bb89e6d6fd4",children:"iWF Deep Dive: workflowState+Durable Timer#1"})}),"\n"]}),"\n",(0,a.jsxs)(n.li,{children:["\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.a,{href:"https://medium.com/@qlong/gotchas-about-signalwithstart-in-cadence-temporal-c3783fe1cc2e",children:"Gotchas About SignalWithStart in Cadence/Temporal"})}),"\n"]}),"\n",(0,a.jsxs)(n.li,{children:["\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.a,{href:"https://medium.com/@qlong/workflow-could-be-process-in-workflowascode-frameworks-63dcb632c248",children:'"Workflow" could be "Process" in WorkflowAsCode frameworks'})}),"\n"]}),"\n"]}),"\n",(0,a.jsx)(n.h2,{id:"new-go-samples-for-cadence",children:"New Go Samples for Cadence"}),"\n",(0,a.jsx)(n.p,{children:"The Cadence core team is deprecating the old samples for Go and replacing them with new version 2 (V2) samples. They have received a lot of feedback from the community that people are having trouble with old samples, so are in the process of publishing a completely new set of samples for Go."}),"\n",(0,a.jsx)(n.p,{children:"Here are some major changes to the new samples:"}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsx)(n.li,{children:"Easy to use the read - the new samples will be completely based on CLIs instead of running a binary. (This is consistent with current Cadence use experience)"}),"\n",(0,a.jsx)(n.li,{children:"Simple and transparent worker configuration - the old samples did not provide user a clear demonstration about the relationship between the worker and workflow themselves"}),"\n",(0,a.jsx)(n.li,{children:"The new samples will help you bootstrap your Cadence workflow faster and easier."}),"\n",(0,a.jsx)(n.li,{children:'More vivid and self-explanatory - instead of the traditional "HelloWorld" type of samples, we want to make it more interesting and engaging. (Each sample will try to simulate a real-life use case to make them more understandable and fun to learn!)'}),"\n"]}),"\n",(0,a.jsxs)(n.p,{children:["We hope the community will enjoy these changes. If you have any questions or have new an idea for a new sample then please reach out to ",(0,a.jsx)(n.a,{href:"https://www.linkedin.com/in/chrisqin0610",children:"Chris Qin"}),"."]}),"\n",(0,a.jsx)(n.p,{children:"The new Go samples can be found at:"}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsxs)(n.li,{children:[(0,a.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence-samples/tree/master/new_samples",children:"https://github.com/cadence-workflow/cadence-samples/tree/master/new_samples"}),"."]}),"\n"]}),"\n",(0,a.jsx)(n.p,{children:"Note that the old samples will be removed once the new samples are fully refreshed."}),"\n",(0,a.jsx)(n.h2,{id:"cadence-retrospective",children:"Cadence Retrospective"}),"\n",(0,a.jsx)(n.p,{children:"We are nearly at the end of another year and yes it has gone so fast! Over this year Cadence and the community have evolved and grown. This is a good time to reflect about all the things that have happened in the project over the year and think about a possible roadmap for the future."}),"\n",(0,a.jsxs)(n.p,{children:["If you have any feedback, or comments about the project or ideas about what features you'd like to see in the roadmap then please feel free to begin a discussion in the #community ",(0,a.jsx)(n.a,{href:"http://t.uber.com/cadence-slack",children:"Slack"})," channel."]}),"\n",(0,a.jsx)(n.h2,{id:"cadence-in-the-news",children:"Cadence in the News!"}),"\n",(0,a.jsx)(n.p,{children:"Below are a selection of Cadence related articles, blogs and whitepapers.\nPlease take a look and feel free to share via your own social media channels."}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsxs)(n.li,{children:["\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.a,{href:"https://www.instaclustr.com/blog/how-to-throttle-cadence/",children:"How to Throttle Cadence"})}),"\n"]}),"\n",(0,a.jsxs)(n.li,{children:["\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.a,{href:"https://medium.com/@qlong/iwf-deep-dive-workflowstate-durable-timer-1-0bb89e6d6fd4",children:"iWF Deep Dive: workflowState+Durable Timer#1"})}),"\n"]}),"\n",(0,a.jsxs)(n.li,{children:["\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.a,{href:"https://medium.com/@qlong/gotchas-about-signalwithstart-in-cadence-temporal-c3783fe1cc2e",children:"Gotchas About SignalWithStart in Cadence/Temporal"})}),"\n"]}),"\n",(0,a.jsxs)(n.li,{children:["\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.a,{href:"https://medium.com/@qlong/workflow-could-be-process-in-workflowascode-frameworks-63dcb632c248",children:'"Workflow" could be "Process" in WorkflowAsCode frameworks'})}),"\n"]}),"\n"]}),"\n",(0,a.jsx)(n.h2,{id:"upcoming-events",children:"Upcoming Events"}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsx)(n.li,{children:(0,a.jsxs)(n.a,{href:"https://netapp.zoom.us/webinar/register/WN_jT5fxSldRhuzV0NSllBd7g#/registration",children:["On Demand Webinar: Building With Cadence",":Quantifiable"," Efficiency"]})}),"\n"]}),"\n",(0,a.jsxs)(n.p,{children:["If you have any news or topics you'd like us to include in our next update then please join our ",(0,a.jsx)(n.a,{href:"http://t.uber.com/cadence-slack",children:"Slack"})," #community channel."]}),"\n",(0,a.jsxs)(n.p,{children:["Please remember that this update is for you - so if you have any comments or feedback that could help us improve it then please share it with us in the #community ",(0,a.jsx)(n.a,{href:"http://t.uber.com/cadence-slack",children:"Slack"})," channel."]})]})}function d(e={}){const{wrapper:n}={...(0,i.R)(),...e.components};return n?(0,a.jsx)(n,{...e,children:(0,a.jsx)(h,{...e})}):h(e)}},8453:(e,n,t)=>{t.d(n,{R:()=>s,x:()=>r});var o=t(6540);const a={},i=o.createContext(a);function s(e){const n=o.useContext(i);return o.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function r(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:s(e.components),o.createElement(i.Provider,{value:n},e.children)}},586:e=>{e.exports=JSON.parse('{"permalink":"/blog/2023/11/30/community-spotlight-update-november-2023","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2023-11-30-community-spotlight-update-november-2023.md","source":"@site/blog/2023-11-30-community-spotlight-update-november-2023.md","title":"Cadence Community Spotlight Update - November 2023","description":"Welcome to the latest of our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!","date":"2023-11-30T00:00:00.000Z","tags":[{"inline":false,"label":"Community Spotlight","permalink":"/blog/tags/community-spotlights","description":"Community Spotlight tag description"},{"inline":false,"label":"Announcement","permalink":"/blog/tags/announcements","description":"Announcement tag description"}],"readingTime":3.46,"hasTruncateMarker":true,"authors":[{"name":"Sharan Foga","title":"Director of Operations & Customer Success @ Encube Technologies","url":"https://www.linkedin.com/in/sfoga/","page":{"permalink":"/blog/authors/sharanf"},"socials":{"linkedin":"https://www.linkedin.com/in/sfoga/","github":"https://github.com/sharanf"},"imageURL":"https://github.com/sharanf.png","key":"sharanf"}],"frontMatter":{"title":"Cadence Community Spotlight Update - November 2023","date":"2023-11-30T00:00:00.000Z","authors":"sharanf","tags":["community-spotlight","announcement"]},"unlisted":false,"prevItem":{"title":"Cadence non-derministic errors common question Q&A (part 1)","permalink":"/blog/2024/02/15/cadence-non-deterministic-common-qa"},"nextItem":{"title":"Cadence Community Spotlight Update - August 2023","permalink":"/blog/2023/08/31/community-spotlight-august-2023"}}')}}]); \ No newline at end of file +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[7770],{3800:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>l,contentTitle:()=>r,default:()=>d,frontMatter:()=>s,metadata:()=>o,toc:()=>c});var o=t(586),a=t(4848),i=t(8453);const s={title:"Cadence Community Spotlight Update - November 2023",date:new Date("2023-11-30T00:00:00.000Z"),authors:"sharanf",tags:["community-spotlight","announcement"]},r=void 0,l={authorsImageUrls:[void 0]},c=[{value:"Proposal for Cadence Native Authentication",id:"proposal-for-cadence-native-authentication",level:2},{value:"iWF Deep Dive and More!",id:"iwf-deep-dive-and-more",level:2},{value:"New Go Samples for Cadence",id:"new-go-samples-for-cadence",level:2},{value:"Cadence Retrospective",id:"cadence-retrospective",level:2},{value:"Cadence in the News!",id:"cadence-in-the-news",level:2},{value:"Upcoming Events",id:"upcoming-events",level:2}];function h(e){const n={a:"a",h2:"h2",li:"li",p:"p",ul:"ul",...(0,i.R)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(n.p,{children:"Welcome to the latest of our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!"}),"\n",(0,a.jsx)(n.p,{children:"It's been a couple of months since our last update so we have a lot of updates to share with you."}),"\n",(0,a.jsx)(n.p,{children:"Please see below for a roundup of the highlights:"}),"\n",(0,a.jsx)(n.h2,{id:"proposal-for-cadence-native-authentication",children:"Proposal for Cadence Native Authentication"}),"\n",(0,a.jsxs)(n.p,{children:["Community member ",(0,a.jsx)(n.a,{href:"https://lt.linkedin.com/in/mantassidlauskas",children:"Mantas Sidlauskas"})," has drafted a proposal around Cadence native authentication and is asking for community feedback. If you are interested in reviewing the current proposal and providing comments or feedback then please find the proposal details at the link below:"]}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsx)(n.li,{children:(0,a.jsx)(n.a,{href:"https://docs.google.com/document/d/13GxRBZfQkLyhDCrpFaZmRcw7DJJG-zdy0_mPXy3CcWw/edit#heading=h.c8u99ansg7ma",children:"Cadence Native Authentication Proposal"})}),"\n"]}),"\n",(0,a.jsx)(n.p,{children:"This is a great example of how we can focus on collaborating together to find a collective solution. A big thank you to Mantas for initiating this work and we hope to see the results of the community input soon!"}),"\n",(0,a.jsx)(n.h2,{id:"iwf-deep-dive-and-more",children:"iWF Deep Dive and More!"}),"\n",(0,a.jsxs)(n.p,{children:["During the last few months community member ",(0,a.jsx)(n.a,{href:"https://www.linkedin.com/in/prclqz/",children:"Quanzheng Long"})," has continued to share his thoughts about ",(0,a.jsx)(n.a,{href:"https://github.com/indeedeng/iwf",children:"iWF"}),", a layer implemented on top of Cadence. Since our last update iWF now has a",(0,a.jsx)(n.a,{href:"https://github.com/indeedeng/iwf-python-sdk",children:"Python SDK"}),". Long has been busy writing articles to share iWF tips and tricks as well as some general ideas about workflows and processes. Links to Long's articles can be found below:"]}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsxs)(n.li,{children:["\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.a,{href:"https://medium.com/@qlong/iwf-deep-dive-workflowstate-durable-timer-1-0bb89e6d6fd4",children:"iWF Deep Dive: workflowState+Durable Timer#1"})}),"\n"]}),"\n",(0,a.jsxs)(n.li,{children:["\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.a,{href:"https://medium.com/@qlong/gotchas-about-signalwithstart-in-cadence-temporal-c3783fe1cc2e",children:"Gotchas About SignalWithStart in Cadence/Temporal"})}),"\n"]}),"\n",(0,a.jsxs)(n.li,{children:["\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.a,{href:"https://medium.com/@qlong/workflow-could-be-process-in-workflowascode-frameworks-63dcb632c248",children:'"Workflow" could be "Process" in WorkflowAsCode frameworks'})}),"\n"]}),"\n"]}),"\n",(0,a.jsx)(n.h2,{id:"new-go-samples-for-cadence",children:"New Go Samples for Cadence"}),"\n",(0,a.jsx)(n.p,{children:"The Cadence core team is deprecating the old samples for Go and replacing them with new version 2 (V2) samples. They have received a lot of feedback from the community that people are having trouble with old samples, so are in the process of publishing a completely new set of samples for Go."}),"\n",(0,a.jsx)(n.p,{children:"Here are some major changes to the new samples:"}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsx)(n.li,{children:"Easy to use the read - the new samples will be completely based on CLIs instead of running a binary. (This is consistent with current Cadence use experience)"}),"\n",(0,a.jsx)(n.li,{children:"Simple and transparent worker configuration - the old samples did not provide user a clear demonstration about the relationship between the worker and workflow themselves"}),"\n",(0,a.jsx)(n.li,{children:"The new samples will help you bootstrap your Cadence workflow faster and easier."}),"\n",(0,a.jsx)(n.li,{children:'More vivid and self-explanatory - instead of the traditional "HelloWorld" type of samples, we want to make it more interesting and engaging. (Each sample will try to simulate a real-life use case to make them more understandable and fun to learn!)'}),"\n"]}),"\n",(0,a.jsxs)(n.p,{children:["We hope the community will enjoy these changes. If you have any questions or have new an idea for a new sample then please reach out to ",(0,a.jsx)(n.a,{href:"https://www.linkedin.com/in/chrisqin0610",children:"Chris Qin"}),"."]}),"\n",(0,a.jsx)(n.p,{children:"The new Go samples can be found at:"}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsxs)(n.li,{children:[(0,a.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence-samples/tree/master/new_samples",children:"https://github.com/cadence-workflow/cadence-samples/tree/master/new_samples"}),"."]}),"\n"]}),"\n",(0,a.jsx)(n.p,{children:"Note that the old samples will be removed once the new samples are fully refreshed."}),"\n",(0,a.jsx)(n.h2,{id:"cadence-retrospective",children:"Cadence Retrospective"}),"\n",(0,a.jsx)(n.p,{children:"We are nearly at the end of another year and yes it has gone so fast! Over this year Cadence and the community have evolved and grown. This is a good time to reflect about all the things that have happened in the project over the year and think about a possible roadmap for the future."}),"\n",(0,a.jsxs)(n.p,{children:["If you have any feedback, or comments about the project or ideas about what features you'd like to see in the roadmap then please feel free to begin a discussion in the #community ",(0,a.jsx)(n.a,{href:"http://t.uber.com/cadence-slack",children:"Slack"})," channel."]}),"\n",(0,a.jsx)(n.h2,{id:"cadence-in-the-news",children:"Cadence in the News!"}),"\n",(0,a.jsx)(n.p,{children:"Below are a selection of Cadence related articles, blogs and whitepapers.\nPlease take a look and feel free to share via your own social media channels."}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsxs)(n.li,{children:["\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.a,{href:"https://www.instaclustr.com/blog/how-to-throttle-cadence/",children:"How to Throttle Cadence"})}),"\n"]}),"\n",(0,a.jsxs)(n.li,{children:["\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.a,{href:"https://medium.com/@qlong/iwf-deep-dive-workflowstate-durable-timer-1-0bb89e6d6fd4",children:"iWF Deep Dive: workflowState+Durable Timer#1"})}),"\n"]}),"\n",(0,a.jsxs)(n.li,{children:["\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.a,{href:"https://medium.com/@qlong/gotchas-about-signalwithstart-in-cadence-temporal-c3783fe1cc2e",children:"Gotchas About SignalWithStart in Cadence/Temporal"})}),"\n"]}),"\n",(0,a.jsxs)(n.li,{children:["\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.a,{href:"https://medium.com/@qlong/workflow-could-be-process-in-workflowascode-frameworks-63dcb632c248",children:'"Workflow" could be "Process" in WorkflowAsCode frameworks'})}),"\n"]}),"\n"]}),"\n",(0,a.jsx)(n.h2,{id:"upcoming-events",children:"Upcoming Events"}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsx)(n.li,{children:(0,a.jsxs)(n.a,{href:"https://netapp.zoom.us/webinar/register/WN_jT5fxSldRhuzV0NSllBd7g#/registration",children:["On Demand Webinar: Building With Cadence",":Quantifiable"," Efficiency"]})}),"\n"]}),"\n",(0,a.jsxs)(n.p,{children:["If you have any news or topics you'd like us to include in our next update then please join our ",(0,a.jsx)(n.a,{href:"http://t.uber.com/cadence-slack",children:"Slack"})," #community channel."]}),"\n",(0,a.jsxs)(n.p,{children:["Please remember that this update is for you - so if you have any comments or feedback that could help us improve it then please share it with us in the #community ",(0,a.jsx)(n.a,{href:"http://t.uber.com/cadence-slack",children:"Slack"})," channel."]})]})}function d(e={}){const{wrapper:n}={...(0,i.R)(),...e.components};return n?(0,a.jsx)(n,{...e,children:(0,a.jsx)(h,{...e})}):h(e)}},8453:(e,n,t)=>{t.d(n,{R:()=>s,x:()=>r});var o=t(6540);const a={},i=o.createContext(a);function s(e){const n=o.useContext(i);return o.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function r(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:s(e.components),o.createElement(i.Provider,{value:n},e.children)}},586:e=>{e.exports=JSON.parse('{"permalink":"/Cadence-Docs/blog/2023/11/30/community-spotlight-update-november-2023","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2023-11-30-community-spotlight-update-november-2023.md","source":"@site/blog/2023-11-30-community-spotlight-update-november-2023.md","title":"Cadence Community Spotlight Update - November 2023","description":"Welcome to the latest of our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!","date":"2023-11-30T00:00:00.000Z","tags":[{"inline":false,"label":"Community Spotlight","permalink":"/Cadence-Docs/blog/tags/community-spotlights","description":"Community Spotlight tag description"},{"inline":false,"label":"Announcement","permalink":"/Cadence-Docs/blog/tags/announcements","description":"Announcement tag description"}],"readingTime":3.46,"hasTruncateMarker":true,"authors":[{"name":"Sharan Foga","title":"Director of Operations & Customer Success @ Encube Technologies","url":"https://www.linkedin.com/in/sfoga/","page":{"permalink":"/Cadence-Docs/blog/authors/sharanf"},"socials":{"linkedin":"https://www.linkedin.com/in/sfoga/","github":"https://github.com/sharanf"},"imageURL":"https://github.com/sharanf.png","key":"sharanf"}],"frontMatter":{"title":"Cadence Community Spotlight Update - November 2023","date":"2023-11-30T00:00:00.000Z","authors":"sharanf","tags":["community-spotlight","announcement"]},"unlisted":false,"prevItem":{"title":"Cadence non-derministic errors common question Q&A (part 1)","permalink":"/Cadence-Docs/blog/2024/02/15/cadence-non-deterministic-common-qa"},"nextItem":{"title":"Cadence Community Spotlight Update - August 2023","permalink":"/Cadence-Docs/blog/2023/08/31/community-spotlight-august-2023"}}')}}]); \ No newline at end of file diff --git a/assets/js/5ab0d6d5.63711599.js b/assets/js/5ab0d6d5.63711599.js deleted file mode 100644 index 8723ecfe8..000000000 --- a/assets/js/5ab0d6d5.63711599.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[8848],{2266:e=>{e.exports=JSON.parse('{"tag":{"label":"Deep Dives","permalink":"/blog/tags/deep-dives","description":"Deep Dives tag description","allTagsPath":"/blog/tags","count":10,"unlisted":false},"listMetadata":{"permalink":"/blog/tags/deep-dives","page":1,"postsPerPage":10,"totalPages":1,"totalCount":10,"blogDescription":"The latest news and updates from the Cadence team","blogTitle":"Cadence Blog"}}')}}]); \ No newline at end of file diff --git a/assets/js/5b895f91.2cb025b2.js b/assets/js/5b895f91.2cb025b2.js deleted file mode 100644 index 9bc172ee6..000000000 --- a/assets/js/5b895f91.2cb025b2.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[7180],{3112:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>a,contentTitle:()=>c,default:()=>p,frontMatter:()=>s,metadata:()=>i,toc:()=>l});var i=n(3315),o=n(4848),r=n(8453);const s={title:"Non-deterministic errors, replayers and shadowers",date:new Date("2023-08-27T00:00:00.000Z"),authors:"chopincode",tags:["deep-dive","testing"]},c=void 0,a={authorsImageUrls:[void 0]},l=[];function d(e){const t={code:"code",p:"p",pre:"pre",...(0,r.R)(),...e.components};return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsx)(t.p,{children:"It is conceivable that developers constantly update their Cadence workflow code based upon new business use cases and needs. However,\nthe definition of a Cadence workflow must be deterministic because behind the scenes cadence uses event sourcing to construct\nthe workflow state by replaying the historical events stored for this specific workflow. Introducing components that are not compatible\nwith an existing running workflow will yield to non-deterministic errors and sometimes developers find it tricky to debug. Consider the\nfollowing workflow that executes two activities."}),"\n",(0,o.jsx)(t.pre,{children:(0,o.jsx)(t.code,{className:"language-go",children:'func SampleWorkflow(ctx workflow.Context, data string) (string, error) {\n ao := workflow.ActivityOptions{\n ScheduleToStartTimeout: time.Minute,\n StartToCloseTimeout: time.Minute,\n }\n ctx = workflow.WithActivityOptions(ctx, ao)\n var result1 string\n err := workflow.ExecuteActivity(ctx, ActivityA, data).Get(ctx, &result1)\n if err != nil {\n return "", err\n }\n var result2 string\n err = workflow.ExecuteActivity(ctx, ActivityB, result1).Get(ctx, &result2)\n return result2, err\n}\n\n'})})]})}function p(e={}){const{wrapper:t}={...(0,r.R)(),...e.components};return t?(0,o.jsx)(t,{...e,children:(0,o.jsx)(d,{...e})}):d(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>s,x:()=>c});var i=n(6540);const o={},r=i.createContext(o);function s(e){const t=i.useContext(r);return i.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function c(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:s(e.components),i.createElement(r.Provider,{value:t},e.children)}},3315:e=>{e.exports=JSON.parse('{"permalink":"/blog/2023/08/28/nondeterministic-errors-replayers-shadowers","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2023-08-28-nondeterministic-errors-replayers-shadowers.md","source":"@site/blog/2023-08-28-nondeterministic-errors-replayers-shadowers.md","title":"Non-deterministic errors, replayers and shadowers","description":"It is conceivable that developers constantly update their Cadence workflow code based upon new business use cases and needs. However,","date":"2023-08-27T00:00:00.000Z","tags":[{"inline":false,"label":"Deep Dives","permalink":"/blog/tags/deep-dives","description":"Deep Dives tag description"},{"inline":false,"label":"Testing","permalink":"/blog/tags/testing","description":"Testing tag description"}],"readingTime":2.305,"hasTruncateMarker":true,"authors":[{"name":"Chris Qin","title":"Applications Developer @ Uber","url":"https://www.linkedin.com/in/chrisqin0610/","page":{"permalink":"/blog/authors/chopincode"},"socials":{"linkedin":"https://www.linkedin.com/in/chrisqin0610/","github":"https://github.com/chopincode"},"imageURL":"https://github.com/chopincode.png","key":"chopincode"}],"frontMatter":{"title":"Non-deterministic errors, replayers and shadowers","date":"2023-08-27T00:00:00.000Z","authors":"chopincode","tags":["deep-dive","testing"]},"unlisted":false,"prevItem":{"title":"Cadence Community Spotlight Update - August 2023","permalink":"/blog/2023/08/31/community-spotlight-august-2023"},"nextItem":{"title":"Cadence Community Spotlight Update - July 2023","permalink":"/blog/2023/07/31/community-spotlight-july-2023"}}')}}]); \ No newline at end of file diff --git a/assets/js/5b895f91.d7024f31.js b/assets/js/5b895f91.d7024f31.js new file mode 100644 index 000000000..a5b9c9c15 --- /dev/null +++ b/assets/js/5b895f91.d7024f31.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[7180],{3112:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>a,contentTitle:()=>c,default:()=>p,frontMatter:()=>s,metadata:()=>o,toc:()=>l});var o=n(3315),i=n(4848),r=n(8453);const s={title:"Non-deterministic errors, replayers and shadowers",date:new Date("2023-08-27T00:00:00.000Z"),authors:"chopincode",tags:["deep-dive","testing"]},c=void 0,a={authorsImageUrls:[void 0]},l=[];function d(e){const t={code:"code",p:"p",pre:"pre",...(0,r.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(t.p,{children:"It is conceivable that developers constantly update their Cadence workflow code based upon new business use cases and needs. However,\nthe definition of a Cadence workflow must be deterministic because behind the scenes cadence uses event sourcing to construct\nthe workflow state by replaying the historical events stored for this specific workflow. Introducing components that are not compatible\nwith an existing running workflow will yield to non-deterministic errors and sometimes developers find it tricky to debug. Consider the\nfollowing workflow that executes two activities."}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{className:"language-go",children:'func SampleWorkflow(ctx workflow.Context, data string) (string, error) {\n ao := workflow.ActivityOptions{\n ScheduleToStartTimeout: time.Minute,\n StartToCloseTimeout: time.Minute,\n }\n ctx = workflow.WithActivityOptions(ctx, ao)\n var result1 string\n err := workflow.ExecuteActivity(ctx, ActivityA, data).Get(ctx, &result1)\n if err != nil {\n return "", err\n }\n var result2 string\n err = workflow.ExecuteActivity(ctx, ActivityB, result1).Get(ctx, &result2)\n return result2, err\n}\n\n'})})]})}function p(e={}){const{wrapper:t}={...(0,r.R)(),...e.components};return t?(0,i.jsx)(t,{...e,children:(0,i.jsx)(d,{...e})}):d(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>s,x:()=>c});var o=n(6540);const i={},r=o.createContext(i);function s(e){const t=o.useContext(r);return o.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function c(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:s(e.components),o.createElement(r.Provider,{value:t},e.children)}},3315:e=>{e.exports=JSON.parse('{"permalink":"/Cadence-Docs/blog/2023/08/28/nondeterministic-errors-replayers-shadowers","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2023-08-28-nondeterministic-errors-replayers-shadowers.md","source":"@site/blog/2023-08-28-nondeterministic-errors-replayers-shadowers.md","title":"Non-deterministic errors, replayers and shadowers","description":"It is conceivable that developers constantly update their Cadence workflow code based upon new business use cases and needs. However,","date":"2023-08-27T00:00:00.000Z","tags":[{"inline":false,"label":"Deep Dives","permalink":"/Cadence-Docs/blog/tags/deep-dives","description":"Deep Dives tag description"},{"inline":false,"label":"Testing","permalink":"/Cadence-Docs/blog/tags/testing","description":"Testing tag description"}],"readingTime":2.305,"hasTruncateMarker":true,"authors":[{"name":"Chris Qin","title":"Applications Developer @ Uber","url":"https://www.linkedin.com/in/chrisqin0610/","page":{"permalink":"/Cadence-Docs/blog/authors/chopincode"},"socials":{"linkedin":"https://www.linkedin.com/in/chrisqin0610/","github":"https://github.com/chopincode"},"imageURL":"https://github.com/chopincode.png","key":"chopincode"}],"frontMatter":{"title":"Non-deterministic errors, replayers and shadowers","date":"2023-08-27T00:00:00.000Z","authors":"chopincode","tags":["deep-dive","testing"]},"unlisted":false,"prevItem":{"title":"Cadence Community Spotlight Update - August 2023","permalink":"/Cadence-Docs/blog/2023/08/31/community-spotlight-august-2023"},"nextItem":{"title":"Cadence Community Spotlight Update - July 2023","permalink":"/Cadence-Docs/blog/2023/07/31/community-spotlight-july-2023"}}')}}]); \ No newline at end of file diff --git a/assets/js/5cd48241.2597ea98.js b/assets/js/5cd48241.2597ea98.js new file mode 100644 index 000000000..e695ab84f --- /dev/null +++ b/assets/js/5cd48241.2597ea98.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[3732],{5835:(e,n,o)=>{o.r(n),o.d(n,{assets:()=>c,contentTitle:()=>a,default:()=>d,frontMatter:()=>r,metadata:()=>s,toc:()=>u});const s=JSON.parse('{"id":"use-cases/provisioning","title":"Infrastructure provisioning","description":"Provisioning a new datacenter or a pool of machines in a public cloud is a potentially long running operation with","source":"@site/docs/02-use-cases/07-provisioning.md","sourceDirName":"02-use-cases","slug":"/use-cases/provisioning","permalink":"/Cadence-Docs/docs/use-cases/provisioning","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/02-use-cases/07-provisioning.md","tags":[],"version":"current","sidebarPosition":7,"frontMatter":{"layout":"default","title":"Infrastructure provisioning","permalink":"/docs/use-cases/provisioning"},"sidebar":"docsSidebar","previous":{"title":"Batch job","permalink":"/Cadence-Docs/docs/use-cases/batch-job"},"next":{"title":"Deployment","permalink":"/Cadence-Docs/docs/use-cases/deployment"}}');var i=o(4848),t=o(8453);const r={layout:"default",title:"Infrastructure provisioning",permalink:"/docs/use-cases/provisioning"},a="Infrastructure provisioning",c={},u=[];function l(e){const n={a:"a",h1:"h1",header:"header",li:"li",p:"p",ul:"ul",...(0,t.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.header,{children:(0,i.jsx)(n.h1,{id:"infrastructure-provisioning",children:"Infrastructure provisioning"})}),"\n",(0,i.jsx)(n.p,{children:"Provisioning a new datacenter or a pool of machines in a public cloud is a potentially long running operation with\na lot of possibilities for intermittent failures. The scale is also a concern when tens or even hundreds of thousands of resources should be provisioned and configured. One useful feature for provisioning scenarios is Cadence support for routing activity execution to a specific process or host."}),"\n",(0,i.jsx)(n.p,{children:"A lot of operations require some sort of locking to ensure that no more than one mutation is executed on a resource at a time.\nCadence provides strong guarantees of uniqueness by business ID. This can be used to implement such locking behavior in a fault tolerant and scalable manner."}),"\n",(0,i.jsx)(n.p,{children:"Some real-world use cases:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"https://banzaicloud.com/blog/introduction-to-cadence/",children:"Using Cadence workflows to spin up Kubernetes, by Banzai Cloud"})}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"https://www.youtube.com/watch?v=kDlrM6sgk2k&feature=youtu.be&t=1188",children:"Using Cadence to orchestrate cluster life cycle in HashiCorp Consul, by HashiCorp"})}),"\n"]})]})}function d(e={}){const{wrapper:n}={...(0,t.R)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(l,{...e})}):l(e)}},8453:(e,n,o)=>{o.d(n,{R:()=>r,x:()=>a});var s=o(6540);const i={},t=s.createContext(i);function r(e){const n=s.useContext(t);return s.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function a(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:r(e.components),s.createElement(t.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/5cd48241.fe1e1a66.js b/assets/js/5cd48241.fe1e1a66.js deleted file mode 100644 index 4d04f349f..000000000 --- a/assets/js/5cd48241.fe1e1a66.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[3732],{5835:(e,n,o)=>{o.r(n),o.d(n,{assets:()=>c,contentTitle:()=>a,default:()=>d,frontMatter:()=>r,metadata:()=>s,toc:()=>u});const s=JSON.parse('{"id":"use-cases/provisioning","title":"Infrastructure provisioning","description":"Provisioning a new datacenter or a pool of machines in a public cloud is a potentially long running operation with","source":"@site/docs/02-use-cases/07-provisioning.md","sourceDirName":"02-use-cases","slug":"/use-cases/provisioning","permalink":"/docs/use-cases/provisioning","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/02-use-cases/07-provisioning.md","tags":[],"version":"current","sidebarPosition":7,"frontMatter":{"layout":"default","title":"Infrastructure provisioning","permalink":"/docs/use-cases/provisioning"},"sidebar":"docsSidebar","previous":{"title":"Batch job","permalink":"/docs/use-cases/batch-job"},"next":{"title":"Deployment","permalink":"/docs/use-cases/deployment"}}');var i=o(4848),t=o(8453);const r={layout:"default",title:"Infrastructure provisioning",permalink:"/docs/use-cases/provisioning"},a="Infrastructure provisioning",c={},u=[];function l(e){const n={a:"a",h1:"h1",header:"header",li:"li",p:"p",ul:"ul",...(0,t.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.header,{children:(0,i.jsx)(n.h1,{id:"infrastructure-provisioning",children:"Infrastructure provisioning"})}),"\n",(0,i.jsx)(n.p,{children:"Provisioning a new datacenter or a pool of machines in a public cloud is a potentially long running operation with\na lot of possibilities for intermittent failures. The scale is also a concern when tens or even hundreds of thousands of resources should be provisioned and configured. One useful feature for provisioning scenarios is Cadence support for routing activity execution to a specific process or host."}),"\n",(0,i.jsx)(n.p,{children:"A lot of operations require some sort of locking to ensure that no more than one mutation is executed on a resource at a time.\nCadence provides strong guarantees of uniqueness by business ID. This can be used to implement such locking behavior in a fault tolerant and scalable manner."}),"\n",(0,i.jsx)(n.p,{children:"Some real-world use cases:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"https://banzaicloud.com/blog/introduction-to-cadence/",children:"Using Cadence workflows to spin up Kubernetes, by Banzai Cloud"})}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"https://www.youtube.com/watch?v=kDlrM6sgk2k&feature=youtu.be&t=1188",children:"Using Cadence to orchestrate cluster life cycle in HashiCorp Consul, by HashiCorp"})}),"\n"]})]})}function d(e={}){const{wrapper:n}={...(0,t.R)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(l,{...e})}):l(e)}},8453:(e,n,o)=>{o.d(n,{R:()=>r,x:()=>a});var s=o(6540);const i={},t=s.createContext(i);function r(e){const n=s.useContext(t);return s.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function a(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:r(e.components),s.createElement(t.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/5cfaf3a2.c31bbd79.js b/assets/js/5cfaf3a2.fdd156a0.js similarity index 89% rename from assets/js/5cfaf3a2.c31bbd79.js rename to assets/js/5cfaf3a2.fdd156a0.js index 66c3c1f49..5d6010ffc 100644 --- a/assets/js/5cfaf3a2.c31bbd79.js +++ b/assets/js/5cfaf3a2.fdd156a0.js @@ -1 +1 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[4344],{5101:(e,n,o)=>{o.r(n),o.d(n,{assets:()=>l,contentTitle:()=>r,default:()=>h,frontMatter:()=>s,metadata:()=>t,toc:()=>d});var t=o(9390),i=o(4848),a=o(8453);const s={title:"Zonal Isolation for Cadence Workflows",subtitle:"test",date:new Date("2024-10-14T00:00:00.000Z"),authors:"shaddoll",tags:["deep-dive","cadence-operations"]},r=void 0,l={authorsImageUrls:[void 0]},d=[{value:"What is Zonal Isolation for Cadence Workflows?",id:"what-is-zonal-isolation-for-cadence-workflows",level:2},{value:"How Zonal Isolation Works in Cadence?",id:"how-zonal-isolation-works-in-cadence",level:2},{value:"Architecture",id:"architecture",level:3},{value:"Implementation",id:"implementation",level:3},{value:"Determine the zone of a workflow and workers",id:"determine-the-zone-of-a-workflow-and-workers",level:4},{value:"How to dispatch tasks to workers from the same zone?",id:"how-to-dispatch-tasks-to-workers-from-the-same-zone",level:4},{value:"How to handle workflows from a drained zone?",id:"how-to-handle-workflows-from-a-drained-zone",level:4},{value:"How to drain a zone explicitly?",id:"how-to-drain-a-zone-explicitly",level:5},{value:"How to enable Zonal Isolation?",id:"how-to-enable-zonal-isolation",level:2},{value:"Server Update",id:"server-update",level:3},{value:"SDK Update",id:"sdk-update",level:3},{value:"How to drain a zone explicitly?",id:"how-to-drain-a-zone-explicitly-1",level:2},{value:"Monitoring",id:"monitoring",level:2},{value:"Status at Uber",id:"status-at-uber",level:2},{value:"Next Step",id:"next-step",level:2}];function c(e){const n={a:"a",code:"code",em:"em",h2:"h2",h3:"h3",h4:"h4",h5:"h5",img:"img",li:"li",ol:"ol",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,a.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.p,{children:"At Uber, we want to achieve regional resilience such that losing a zone within a region can be tolerated without requiring a cross-region failover. We also want to make sure that losing a zone only affects a subset of workload, at most, rather than everything. However, in Cadence-based systems, the workload in a region is distributed randomly across all workers in the region at a \u201ctask-level granularity\u201d, which means a workflow may be worked on by any worker in the region where the domain is active. To achieve this goal, we introduced Zonal Isolation for Cadence Workflows - a feature designed to pin workflows to the zone they are started in, so that zonal isolation can be achieved at a workflow-level."}),"\n",(0,i.jsx)(n.h2,{id:"what-is-zonal-isolation-for-cadence-workflows",children:"What is Zonal Isolation for Cadence Workflows?"}),"\n",(0,i.jsx)(n.p,{children:"At high-level, Zonal Isolation for Cadence Workflows can be thought in 2 levels:"}),"\n",(0,i.jsxs)(n.ol,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Task-level isolation:"})," All decision tasks and activity tasks of a workflow are only processed by workers from the zone where the workflow was started"]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Infrastructure-level isolation:"})," Within a regional Cadence cluster, workflows are handled by server instances in the same zone where they were started, and the corresponding data is stored in that zone as well."]}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Infrastructure-level isolation is quite challenging to implement as it requires significant changes to the core design of the Cadence server. Due to the complexity involved, support for this feature is not planned for the foreseeable future."}),"\n",(0,i.jsx)(n.p,{children:"As a result, the focus remains on achieving task-level zonal isolation outside the Cadence server, which offers a more practical and immediate way to improve system resilience. It provides the capability of ensuring that an unhealthy zone (i.e. bad deployment of workers) only affect a subset of workflows (started from a certain zone) rather than every workflow in a Cadence domain."}),"\n",(0,i.jsx)(n.h2,{id:"how-zonal-isolation-works-in-cadence",children:"How Zonal Isolation Works in Cadence?"}),"\n",(0,i.jsx)(n.h3,{id:"architecture",children:"Architecture"}),"\n",(0,i.jsxs)(n.p,{children:["Here is what the architecture of a zonally isolated Cadence-based system looks like:\n",(0,i.jsx)(n.img,{alt:"zonal isolation overview",src:o(3905).A+"",width:"1600",height:"896"}),"\n",(0,i.jsx)(n.em,{children:(0,i.jsx)("p",{children:"Fig: Workflows started in one zone are only dispatched to workers from the same zone. Colors to emphasize pinning."})})]}),"\n",(0,i.jsx)(n.h3,{id:"implementation",children:"Implementation"}),"\n",(0,i.jsx)(n.h4,{id:"determine-the-zone-of-a-workflow-and-workers",children:"Determine the zone of a workflow and workers"}),"\n",(0,i.jsx)(n.p,{children:"To ensure that tasks are dispatched to workers in the same zone as the workflows, we must identify the origin zone of both. The zone of a workflow is determined by the origin zone of the StartWorkflowExecution request, while the zone of workers is determined by the origin zone of the PollForDecisionTask and PollForActivityTask requests. There are three possible ways to determine the origin zone for these requests:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Uber's Approach:"})," Let Cadence SDK set the origin zone in the headers of the requests before sending the request to Cadence."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Preferred Approach:"})," Get the origin zone of the requests from headers set by network infrastructure."]}),"\n",(0,i.jsx)(n.li,{children:"Determine the origin zone of the requests from the zone of the cadence-frontend instance receiving the request, if the network layer has already achieved zonal isolation."}),"\n"]}),"\n",(0,i.jsxs)(n.p,{children:["The 2nd approach is the ideal one, but Uber's network infrastructure doesn't provide such headers and the network layer is not ready for zonal isolation. As a result, we adopt the 1st approach. At Uber, we have internal libraries in Go and Java acting as wrappers around Cadence SDK injecting necessary configurations. These libraries have been updated to include the origin zone in the request headers using a header called ",(0,i.jsx)(n.code,{children:"cadence-client-isolation-group"}),"."]}),"\n",(0,i.jsx)(n.h4,{id:"how-to-dispatch-tasks-to-workers-from-the-same-zone",children:"How to dispatch tasks to workers from the same zone?"}),"\n",(0,i.jsxs)(n.p,{children:["To implement task-level isolation, we introduce a new dimension to the tasklist \u2014 ",(0,i.jsx)(n.strong,{children:"isolation group"}),". When a workflow is initiated, the origin zone of the workflow is stored in the database. Each time a decision or activity task is dispatched to cadence-matching, the workflow's origin zone is used as the isolation group for that task."]}),"\n",(0,i.jsxs)(n.p,{children:["When a worker sends a ",(0,i.jsx)(n.code,{children:"PollForDecisionTask"})," or ",(0,i.jsx)(n.code,{children:"PollForActivityTask"})," request to cadence-matching, the request is labeled with the worker's isolation group (i.e., the worker's zone). Tasks are then dispatched only to poller requests that have the same isolation group, ensuring that tasks are processed by workers in the same zone as the workflow's origin."]}),"\n",(0,i.jsx)(n.h4,{id:"how-to-handle-workflows-from-a-drained-zone",children:"How to handle workflows from a drained zone?"}),"\n",(0,i.jsx)(n.p,{children:"In the event of an outage, such as a bad deployment, customers may want to drain workers from a specific zone to mitigate the impact. There are two types of drains that can occur:"}),"\n",(0,i.jsxs)(n.ol,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Implicit drain:"})," Workers from a zone completely stop operating, either due to failures or manual shutdowns."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Explicit drain:"})," Customers explicitly mark workers from a zone as drained."]}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Within cadence-matching, a list of pollers is maintained for each tasklist, tracking the zone from which the pollers originate. An implicit drain can be detected by checking whether there are any active pollers from a particular zone. If a zone is drained (either explicitly or implicitly), workflows that were started in that zone will be reassigned and spread to workers in the remaining healthy zones."}),"\n",(0,i.jsx)(n.h5,{id:"how-to-drain-a-zone-explicitly",children:"How to drain a zone explicitly?"}),"\n",(0,i.jsx)(n.p,{children:"Explicitly draining a zone can be done at two levels:"}),"\n",(0,i.jsxs)(n.ol,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Domain-level drain:"})," This applies to a specific domain, allowing the zone to be drained only for workflows within that domain."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Cluster-level drain:"})," This applies to the entire Cadence cluster, draining the zone for all domains and workflows within the cluster."]}),"\n"]}),"\n",(0,i.jsxs)(n.p,{children:["For domain-level drain, the draining status is stored in ",(0,i.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence/blob/v1.2.13/schema/cassandra/cadence/schema.cql#L412",children:(0,i.jsx)(n.code,{children:"domains"})})," table. For cluster-level drain, the status is stored in ",(0,i.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence/blob/v1.2.13/schema/cassandra/cadence/schema.cql#L498",children:(0,i.jsx)(n.code,{children:"cluster_config"})})," table."]}),"\n",(0,i.jsx)(n.h2,{id:"how-to-enable-zonal-isolation",children:"How to enable Zonal Isolation?"}),"\n",(0,i.jsx)(n.h3,{id:"server-update",children:"Server Update"}),"\n",(0,i.jsxs)(n.p,{children:["In order to enable this feature, please upgrade Cadence server to ",(0,i.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence/releases/tag/v1.2.1",children:"v1.2.1"})," or later."]}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"NOTE:"})," If you're not using the provided main binary located in ",(0,i.jsx)(n.code,{children:"cmd/server"}),", you must adopt this ",(0,i.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence/blob/v1.2.1/common/rpc/middleware.go#L188",children:"middleware"}),". Depends on the appoach to ",(0,i.jsx)(n.a,{href:"#determine-the-zone-of-a-workflow-and-workers",children:"determine the origin zone of requests"}),", you can adopt this ",(0,i.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence/blob/v1.2.1/common/rpc/middleware.go#L229",children:"middleware"})," or build your own middleware using ",(0,i.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence/blob/v1.2.1/common/partition/context.go#L42",children:(0,i.jsx)(n.code,{children:"partition.ContextWithConfig"})})," function to inject origin zone into the context."]}),"\n",(0,i.jsx)(n.p,{children:"This feature is controlled by 2 dynamic config properties."}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"system.allIsolationGroups"}),": This property provides the list of available zones within a region."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"system.enableTasklistIsolation"}),": This property enables Zonal Isolation at domain level.\nIt\u2019s important to note that any update to the ",(0,i.jsx)(n.code,{children:"system.allIsolationGroups"})," property requires a restart of the cadence-matching service for the changes to take effect. This ensures that the new zone configuration is properly loaded and applied. However, the ",(0,i.jsx)(n.code,{children:"system.enableTasklistIsolation"})," property can be updated dynamically without requiring a restart, making it more flexible for enabling or disabling Zonal Isolation on a per-domain basis."]}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"An example configuration using the file based dynamic configuration could look like this:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-yaml",children:'system.allIsolationGroups:\n- value: []\n constraints: {}\n- value: ["dca1", "dca2", "dca3"]\n constraints:\n clusterName: prod-dca\n- value: ["phx1", "phx2", "phx3"]\n constraints:\n clusterName: prod-phx\nsystem.enableTasklistIsolation:\n- value: false\n constraints: {}\n- value: true\n constraints:\n domainName: samples-domain\n'})}),"\n",(0,i.jsxs)(n.p,{children:["In this example, the Cadence cluster spans two regions, each containing three zones: ",(0,i.jsx)(n.code,{children:"dca1"}),", ",(0,i.jsx)(n.code,{children:"dca2"}),", ",(0,i.jsx)(n.code,{children:"dca3"})," in the ",(0,i.jsx)(n.code,{children:"dca"})," region and ",(0,i.jsx)(n.code,{children:"phx1"}),", ",(0,i.jsx)(n.code,{children:"phx2"}),", ",(0,i.jsx)(n.code,{children:"phx3"})," in the ",(0,i.jsx)(n.code,{children:"phx"})," region. Zonal isolation is enabled only for the ",(0,i.jsx)(n.code,{children:"samples-domain"}),", while it remains disabled for other domains."]}),"\n",(0,i.jsx)(n.h3,{id:"sdk-update",children:"SDK Update"}),"\n",(0,i.jsxs)(n.p,{children:["NOTE: This update is only necessary if you're using the 1st approach to ",(0,i.jsx)(n.a,{href:"#determine-the-zone-of-a-workflow-and-workers",children:"determine the origin zone of requests"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"To support Zonal Isolation, please upgrade your SDK versions:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Go SDK:"})," Upgrade to ",(0,i.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence-go-client/releases/tag/v1.0.2",children:"v1.0.2"})," or later."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Java SDK:"})," Upgrade to ",(0,i.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence-java-client/releases/tag/v3.9.0",children:"v3.9.0"})," or later."]}),"\n"]}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"For Java SDK users"}),", set the ",(0,i.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence-java-client/blob/v3.9.0/src/main/java/com/uber/cadence/serviceclient/ClientOptions.java#L83",children:(0,i.jsx)(n.code,{children:"isolationGroup"})})," field to the zone of the instance when creating ",(0,i.jsx)(n.code,{children:"serviceClient"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"For Go SDK users"}),", set the ",(0,i.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence-go-client/blob/v1.0.2/internal/worker.go#L132",children:(0,i.jsx)(n.code,{children:"isolationGroup"})})," field to the zone of the instance when creating ",(0,i.jsx)(n.code,{children:"Worker"}),". Additionally, you need to use ",(0,i.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence-go-client/blob/v1.0.2/isolationgroup/wrapper.go#L29C39-L29C70",children:"this method"})," to wrap ",(0,i.jsx)(n.code,{children:"workflowserviceclient.Interface"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"how-to-drain-a-zone-explicitly-1",children:"How to drain a zone explicitly?"}),"\n",(0,i.jsxs)(n.p,{children:["Drains can be done via the ",(0,i.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence-idl/blob/50a4ee241e50c6baab8e5d47540b176c5ee022a4/proto/cadence-workflow/cadence/admin/v1/service.proto#L125",children:"Admin APIs"})," of cadence-frontend or CLI."]}),"\n",(0,i.jsx)(n.p,{children:"You can check the help message for the CLI by running:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"cadence admin isolation-groups -h\n"})}),"\n",(0,i.jsx)(n.h2,{id:"monitoring",children:"Monitoring"}),"\n",(0,i.jsx)(n.p,{children:"A new metric is introduced to help detect the leakage of tasks and skewness of traffic."}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.code,{children:"isolation_task_matches_per_tl"}),": This is a counter that counts the number of tasks polled by workers. The metric is tagged with the domain, tasklist name, tasklist type, the origin zone of the workflow and the origin zone of the worker polling the task."]}),"\n",(0,i.jsx)(n.p,{children:"This metric can be used in the following ways:"}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"Detecting task leakage:"})," By grouping tasks based on the origin zones of both the workflows and workers, you can identify tasks that have leaked, i.e., tasks assigned to workers in zones different from the workflow's origin zone."]}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"Identifying traffic skewness:"})," By grouping tasks based solely on the origin zones of workflows, you can determine if traffic is disproportionately distributed among the zones, helping to detect any uneven load or traffic imbalance across zones."]}),"\n",(0,i.jsx)(n.h2,{id:"status-at-uber",children:"Status at Uber"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"We launched this feature at Uber in July 2023. More than 100 domains have Zonal Isolation enabled."}),"\n",(0,i.jsxs)(n.li,{children:["However, as of 2024, the rollout of Zonal Isolation is paused due to a traffic skewness issue:","\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"Some customers have highly skewed traffic that some zones have more workflows than other zones, but the number of workers are evenly distributed in all zones. Enabling Zonal Isolation for the customers will decrease the utilization of their workers and may cause high latency for the customers."}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.h2,{id:"next-step",children:"Next Step"}),"\n",(0,i.jsxs)(n.p,{children:["Currently, Zonal Isolation is implemented as ",(0,i.jsx)(n.strong,{children:"hard isolation"}),", where tasks are strictly limited to the same zone as the originating workflow. To address the traffic skewness issue, we are working on iterating this feature to introduce ",(0,i.jsx)(n.strong,{children:"soft isolation"}),". This relaxed version will allow for some task leakage between zones if traffic skewness is detected, ensuring better worker utilization and reducing latency."]}),"\n",(0,i.jsx)(n.p,{children:"This enhancement is one of our major ongoing projects, and we plan to share more details in a future blog post once it is launched."})]})}function h(e={}){const{wrapper:n}={...(0,a.R)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(c,{...e})}):c(e)}},3905:(e,n,o)=>{o.d(n,{A:()=>t});const t=o.p+"assets/images/zone-isolation-3dab642dc554611aa31e398f4f020d63.png"},8453:(e,n,o)=>{o.d(n,{R:()=>s,x:()=>r});var t=o(6540);const i={},a=t.createContext(i);function s(e){const n=t.useContext(a);return t.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function r(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:s(e.components),t.createElement(a.Provider,{value:n},e.children)}},9390:e=>{e.exports=JSON.parse('{"permalink":"/blog/zonal-isolation-v1/zonal-isolation-v1","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/zonal-isolation-v1/zonal-isolation-v1.md","source":"@site/blog/zonal-isolation-v1/zonal-isolation-v1.md","title":"Zonal Isolation for Cadence Workflows","description":"At Uber, we want to achieve regional resilience such that losing a zone within a region can be tolerated without requiring a cross-region failover. We also want to make sure that losing a zone only affects a subset of workload, at most, rather than everything. However, in Cadence-based systems, the workload in a region is distributed randomly across all workers in the region at a \u201ctask-level granularity\u201d, which means a workflow may be worked on by any worker in the region where the domain is active. To achieve this goal, we introduced Zonal Isolation for Cadence Workflows - a feature designed to pin workflows to the zone they are started in, so that zonal isolation can be achieved at a workflow-level.","date":"2024-10-14T00:00:00.000Z","tags":[{"inline":false,"label":"Deep Dives","permalink":"/blog/tags/deep-dives","description":"Deep Dives tag description"},{"inline":false,"label":"Cadence Operations","permalink":"/blog/tags/cadence-operations","description":"Cadence Operations tag description"}],"readingTime":7.985,"hasTruncateMarker":true,"authors":[{"name":"Zijian Chen","title":"Software Engineer @ Uber","url":"https://www.linkedin.com/in/zijian-chen-5868938b/","page":{"permalink":"/blog/authors/shaddoll"},"socials":{"linkedin":"https://www.linkedin.com/in/zijian-chen-5868938b/","github":"https://github.com/Shaddoll"},"imageURL":"https://github.com/Shaddoll.png","key":"shaddoll"}],"frontMatter":{"title":"Zonal Isolation for Cadence Workflows","subtitle":"test","date":"2024-10-14T00:00:00.000Z","authors":"shaddoll","tags":["deep-dive","cadence-operations"]},"unlisted":false,"prevItem":{"title":"Cadence Repositories Have Moved!","permalink":"/blog/2024/11/18/cadence-workflows-github-organization"},"nextItem":{"title":"Announcement: Cadence Helm Charts v0 Release","permalink":"/blog/2024/10/01/announcing-cadence-helm-charts-v0"}}')}}]); \ No newline at end of file +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[4344],{5101:(e,n,o)=>{o.r(n),o.d(n,{assets:()=>l,contentTitle:()=>r,default:()=>h,frontMatter:()=>s,metadata:()=>t,toc:()=>d});var t=o(9390),i=o(4848),a=o(8453);const s={title:"Zonal Isolation for Cadence Workflows",subtitle:"test",date:new Date("2024-10-14T00:00:00.000Z"),authors:"shaddoll",tags:["deep-dive","cadence-operations"]},r=void 0,l={authorsImageUrls:[void 0]},d=[{value:"What is Zonal Isolation for Cadence Workflows?",id:"what-is-zonal-isolation-for-cadence-workflows",level:2},{value:"How Zonal Isolation Works in Cadence?",id:"how-zonal-isolation-works-in-cadence",level:2},{value:"Architecture",id:"architecture",level:3},{value:"Implementation",id:"implementation",level:3},{value:"Determine the zone of a workflow and workers",id:"determine-the-zone-of-a-workflow-and-workers",level:4},{value:"How to dispatch tasks to workers from the same zone?",id:"how-to-dispatch-tasks-to-workers-from-the-same-zone",level:4},{value:"How to handle workflows from a drained zone?",id:"how-to-handle-workflows-from-a-drained-zone",level:4},{value:"How to drain a zone explicitly?",id:"how-to-drain-a-zone-explicitly",level:5},{value:"How to enable Zonal Isolation?",id:"how-to-enable-zonal-isolation",level:2},{value:"Server Update",id:"server-update",level:3},{value:"SDK Update",id:"sdk-update",level:3},{value:"How to drain a zone explicitly?",id:"how-to-drain-a-zone-explicitly-1",level:2},{value:"Monitoring",id:"monitoring",level:2},{value:"Status at Uber",id:"status-at-uber",level:2},{value:"Next Step",id:"next-step",level:2}];function c(e){const n={a:"a",code:"code",em:"em",h2:"h2",h3:"h3",h4:"h4",h5:"h5",img:"img",li:"li",ol:"ol",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,a.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.p,{children:"At Uber, we want to achieve regional resilience such that losing a zone within a region can be tolerated without requiring a cross-region failover. We also want to make sure that losing a zone only affects a subset of workload, at most, rather than everything. However, in Cadence-based systems, the workload in a region is distributed randomly across all workers in the region at a \u201ctask-level granularity\u201d, which means a workflow may be worked on by any worker in the region where the domain is active. To achieve this goal, we introduced Zonal Isolation for Cadence Workflows - a feature designed to pin workflows to the zone they are started in, so that zonal isolation can be achieved at a workflow-level."}),"\n",(0,i.jsx)(n.h2,{id:"what-is-zonal-isolation-for-cadence-workflows",children:"What is Zonal Isolation for Cadence Workflows?"}),"\n",(0,i.jsx)(n.p,{children:"At high-level, Zonal Isolation for Cadence Workflows can be thought in 2 levels:"}),"\n",(0,i.jsxs)(n.ol,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Task-level isolation:"})," All decision tasks and activity tasks of a workflow are only processed by workers from the zone where the workflow was started"]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Infrastructure-level isolation:"})," Within a regional Cadence cluster, workflows are handled by server instances in the same zone where they were started, and the corresponding data is stored in that zone as well."]}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Infrastructure-level isolation is quite challenging to implement as it requires significant changes to the core design of the Cadence server. Due to the complexity involved, support for this feature is not planned for the foreseeable future."}),"\n",(0,i.jsx)(n.p,{children:"As a result, the focus remains on achieving task-level zonal isolation outside the Cadence server, which offers a more practical and immediate way to improve system resilience. It provides the capability of ensuring that an unhealthy zone (i.e. bad deployment of workers) only affect a subset of workflows (started from a certain zone) rather than every workflow in a Cadence domain."}),"\n",(0,i.jsx)(n.h2,{id:"how-zonal-isolation-works-in-cadence",children:"How Zonal Isolation Works in Cadence?"}),"\n",(0,i.jsx)(n.h3,{id:"architecture",children:"Architecture"}),"\n",(0,i.jsxs)(n.p,{children:["Here is what the architecture of a zonally isolated Cadence-based system looks like:\n",(0,i.jsx)(n.img,{alt:"zonal isolation overview",src:o(3905).A+"",width:"1600",height:"896"}),"\n",(0,i.jsx)(n.em,{children:(0,i.jsx)("p",{children:"Fig: Workflows started in one zone are only dispatched to workers from the same zone. Colors to emphasize pinning."})})]}),"\n",(0,i.jsx)(n.h3,{id:"implementation",children:"Implementation"}),"\n",(0,i.jsx)(n.h4,{id:"determine-the-zone-of-a-workflow-and-workers",children:"Determine the zone of a workflow and workers"}),"\n",(0,i.jsx)(n.p,{children:"To ensure that tasks are dispatched to workers in the same zone as the workflows, we must identify the origin zone of both. The zone of a workflow is determined by the origin zone of the StartWorkflowExecution request, while the zone of workers is determined by the origin zone of the PollForDecisionTask and PollForActivityTask requests. There are three possible ways to determine the origin zone for these requests:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Uber's Approach:"})," Let Cadence SDK set the origin zone in the headers of the requests before sending the request to Cadence."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Preferred Approach:"})," Get the origin zone of the requests from headers set by network infrastructure."]}),"\n",(0,i.jsx)(n.li,{children:"Determine the origin zone of the requests from the zone of the cadence-frontend instance receiving the request, if the network layer has already achieved zonal isolation."}),"\n"]}),"\n",(0,i.jsxs)(n.p,{children:["The 2nd approach is the ideal one, but Uber's network infrastructure doesn't provide such headers and the network layer is not ready for zonal isolation. As a result, we adopt the 1st approach. At Uber, we have internal libraries in Go and Java acting as wrappers around Cadence SDK injecting necessary configurations. These libraries have been updated to include the origin zone in the request headers using a header called ",(0,i.jsx)(n.code,{children:"cadence-client-isolation-group"}),"."]}),"\n",(0,i.jsx)(n.h4,{id:"how-to-dispatch-tasks-to-workers-from-the-same-zone",children:"How to dispatch tasks to workers from the same zone?"}),"\n",(0,i.jsxs)(n.p,{children:["To implement task-level isolation, we introduce a new dimension to the tasklist \u2014 ",(0,i.jsx)(n.strong,{children:"isolation group"}),". When a workflow is initiated, the origin zone of the workflow is stored in the database. Each time a decision or activity task is dispatched to cadence-matching, the workflow's origin zone is used as the isolation group for that task."]}),"\n",(0,i.jsxs)(n.p,{children:["When a worker sends a ",(0,i.jsx)(n.code,{children:"PollForDecisionTask"})," or ",(0,i.jsx)(n.code,{children:"PollForActivityTask"})," request to cadence-matching, the request is labeled with the worker's isolation group (i.e., the worker's zone). Tasks are then dispatched only to poller requests that have the same isolation group, ensuring that tasks are processed by workers in the same zone as the workflow's origin."]}),"\n",(0,i.jsx)(n.h4,{id:"how-to-handle-workflows-from-a-drained-zone",children:"How to handle workflows from a drained zone?"}),"\n",(0,i.jsx)(n.p,{children:"In the event of an outage, such as a bad deployment, customers may want to drain workers from a specific zone to mitigate the impact. There are two types of drains that can occur:"}),"\n",(0,i.jsxs)(n.ol,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Implicit drain:"})," Workers from a zone completely stop operating, either due to failures or manual shutdowns."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Explicit drain:"})," Customers explicitly mark workers from a zone as drained."]}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Within cadence-matching, a list of pollers is maintained for each tasklist, tracking the zone from which the pollers originate. An implicit drain can be detected by checking whether there are any active pollers from a particular zone. If a zone is drained (either explicitly or implicitly), workflows that were started in that zone will be reassigned and spread to workers in the remaining healthy zones."}),"\n",(0,i.jsx)(n.h5,{id:"how-to-drain-a-zone-explicitly",children:"How to drain a zone explicitly?"}),"\n",(0,i.jsx)(n.p,{children:"Explicitly draining a zone can be done at two levels:"}),"\n",(0,i.jsxs)(n.ol,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Domain-level drain:"})," This applies to a specific domain, allowing the zone to be drained only for workflows within that domain."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Cluster-level drain:"})," This applies to the entire Cadence cluster, draining the zone for all domains and workflows within the cluster."]}),"\n"]}),"\n",(0,i.jsxs)(n.p,{children:["For domain-level drain, the draining status is stored in ",(0,i.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence/blob/v1.2.13/schema/cassandra/cadence/schema.cql#L412",children:(0,i.jsx)(n.code,{children:"domains"})})," table. For cluster-level drain, the status is stored in ",(0,i.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence/blob/v1.2.13/schema/cassandra/cadence/schema.cql#L498",children:(0,i.jsx)(n.code,{children:"cluster_config"})})," table."]}),"\n",(0,i.jsx)(n.h2,{id:"how-to-enable-zonal-isolation",children:"How to enable Zonal Isolation?"}),"\n",(0,i.jsx)(n.h3,{id:"server-update",children:"Server Update"}),"\n",(0,i.jsxs)(n.p,{children:["In order to enable this feature, please upgrade Cadence server to ",(0,i.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence/releases/tag/v1.2.1",children:"v1.2.1"})," or later."]}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"NOTE:"})," If you're not using the provided main binary located in ",(0,i.jsx)(n.code,{children:"cmd/server"}),", you must adopt this ",(0,i.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence/blob/v1.2.1/common/rpc/middleware.go#L188",children:"middleware"}),". Depends on the appoach to ",(0,i.jsx)(n.a,{href:"#determine-the-zone-of-a-workflow-and-workers",children:"determine the origin zone of requests"}),", you can adopt this ",(0,i.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence/blob/v1.2.1/common/rpc/middleware.go#L229",children:"middleware"})," or build your own middleware using ",(0,i.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence/blob/v1.2.1/common/partition/context.go#L42",children:(0,i.jsx)(n.code,{children:"partition.ContextWithConfig"})})," function to inject origin zone into the context."]}),"\n",(0,i.jsx)(n.p,{children:"This feature is controlled by 2 dynamic config properties."}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"system.allIsolationGroups"}),": This property provides the list of available zones within a region."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"system.enableTasklistIsolation"}),": This property enables Zonal Isolation at domain level.\nIt\u2019s important to note that any update to the ",(0,i.jsx)(n.code,{children:"system.allIsolationGroups"})," property requires a restart of the cadence-matching service for the changes to take effect. This ensures that the new zone configuration is properly loaded and applied. However, the ",(0,i.jsx)(n.code,{children:"system.enableTasklistIsolation"})," property can be updated dynamically without requiring a restart, making it more flexible for enabling or disabling Zonal Isolation on a per-domain basis."]}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"An example configuration using the file based dynamic configuration could look like this:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-yaml",children:'system.allIsolationGroups:\n- value: []\n constraints: {}\n- value: ["dca1", "dca2", "dca3"]\n constraints:\n clusterName: prod-dca\n- value: ["phx1", "phx2", "phx3"]\n constraints:\n clusterName: prod-phx\nsystem.enableTasklistIsolation:\n- value: false\n constraints: {}\n- value: true\n constraints:\n domainName: samples-domain\n'})}),"\n",(0,i.jsxs)(n.p,{children:["In this example, the Cadence cluster spans two regions, each containing three zones: ",(0,i.jsx)(n.code,{children:"dca1"}),", ",(0,i.jsx)(n.code,{children:"dca2"}),", ",(0,i.jsx)(n.code,{children:"dca3"})," in the ",(0,i.jsx)(n.code,{children:"dca"})," region and ",(0,i.jsx)(n.code,{children:"phx1"}),", ",(0,i.jsx)(n.code,{children:"phx2"}),", ",(0,i.jsx)(n.code,{children:"phx3"})," in the ",(0,i.jsx)(n.code,{children:"phx"})," region. Zonal isolation is enabled only for the ",(0,i.jsx)(n.code,{children:"samples-domain"}),", while it remains disabled for other domains."]}),"\n",(0,i.jsx)(n.h3,{id:"sdk-update",children:"SDK Update"}),"\n",(0,i.jsxs)(n.p,{children:["NOTE: This update is only necessary if you're using the 1st approach to ",(0,i.jsx)(n.a,{href:"#determine-the-zone-of-a-workflow-and-workers",children:"determine the origin zone of requests"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"To support Zonal Isolation, please upgrade your SDK versions:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Go SDK:"})," Upgrade to ",(0,i.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence-go-client/releases/tag/v1.0.2",children:"v1.0.2"})," or later."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Java SDK:"})," Upgrade to ",(0,i.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence-java-client/releases/tag/v3.9.0",children:"v3.9.0"})," or later."]}),"\n"]}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"For Java SDK users"}),", set the ",(0,i.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence-java-client/blob/v3.9.0/src/main/java/com/uber/cadence/serviceclient/ClientOptions.java#L83",children:(0,i.jsx)(n.code,{children:"isolationGroup"})})," field to the zone of the instance when creating ",(0,i.jsx)(n.code,{children:"serviceClient"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"For Go SDK users"}),", set the ",(0,i.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence-go-client/blob/v1.0.2/internal/worker.go#L132",children:(0,i.jsx)(n.code,{children:"isolationGroup"})})," field to the zone of the instance when creating ",(0,i.jsx)(n.code,{children:"Worker"}),". Additionally, you need to use ",(0,i.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence-go-client/blob/v1.0.2/isolationgroup/wrapper.go#L29C39-L29C70",children:"this method"})," to wrap ",(0,i.jsx)(n.code,{children:"workflowserviceclient.Interface"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"how-to-drain-a-zone-explicitly-1",children:"How to drain a zone explicitly?"}),"\n",(0,i.jsxs)(n.p,{children:["Drains can be done via the ",(0,i.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence-idl/blob/50a4ee241e50c6baab8e5d47540b176c5ee022a4/proto/cadence-workflow/cadence/admin/v1/service.proto#L125",children:"Admin APIs"})," of cadence-frontend or CLI."]}),"\n",(0,i.jsx)(n.p,{children:"You can check the help message for the CLI by running:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"cadence admin isolation-groups -h\n"})}),"\n",(0,i.jsx)(n.h2,{id:"monitoring",children:"Monitoring"}),"\n",(0,i.jsx)(n.p,{children:"A new metric is introduced to help detect the leakage of tasks and skewness of traffic."}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.code,{children:"isolation_task_matches_per_tl"}),": This is a counter that counts the number of tasks polled by workers. The metric is tagged with the domain, tasklist name, tasklist type, the origin zone of the workflow and the origin zone of the worker polling the task."]}),"\n",(0,i.jsx)(n.p,{children:"This metric can be used in the following ways:"}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"Detecting task leakage:"})," By grouping tasks based on the origin zones of both the workflows and workers, you can identify tasks that have leaked, i.e., tasks assigned to workers in zones different from the workflow's origin zone."]}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"Identifying traffic skewness:"})," By grouping tasks based solely on the origin zones of workflows, you can determine if traffic is disproportionately distributed among the zones, helping to detect any uneven load or traffic imbalance across zones."]}),"\n",(0,i.jsx)(n.h2,{id:"status-at-uber",children:"Status at Uber"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"We launched this feature at Uber in July 2023. More than 100 domains have Zonal Isolation enabled."}),"\n",(0,i.jsxs)(n.li,{children:["However, as of 2024, the rollout of Zonal Isolation is paused due to a traffic skewness issue:","\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"Some customers have highly skewed traffic that some zones have more workflows than other zones, but the number of workers are evenly distributed in all zones. Enabling Zonal Isolation for the customers will decrease the utilization of their workers and may cause high latency for the customers."}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.h2,{id:"next-step",children:"Next Step"}),"\n",(0,i.jsxs)(n.p,{children:["Currently, Zonal Isolation is implemented as ",(0,i.jsx)(n.strong,{children:"hard isolation"}),", where tasks are strictly limited to the same zone as the originating workflow. To address the traffic skewness issue, we are working on iterating this feature to introduce ",(0,i.jsx)(n.strong,{children:"soft isolation"}),". This relaxed version will allow for some task leakage between zones if traffic skewness is detected, ensuring better worker utilization and reducing latency."]}),"\n",(0,i.jsx)(n.p,{children:"This enhancement is one of our major ongoing projects, and we plan to share more details in a future blog post once it is launched."})]})}function h(e={}){const{wrapper:n}={...(0,a.R)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(c,{...e})}):c(e)}},3905:(e,n,o)=>{o.d(n,{A:()=>t});const t=o.p+"assets/images/zone-isolation-3dab642dc554611aa31e398f4f020d63.png"},8453:(e,n,o)=>{o.d(n,{R:()=>s,x:()=>r});var t=o(6540);const i={},a=t.createContext(i);function s(e){const n=t.useContext(a);return t.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function r(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:s(e.components),t.createElement(a.Provider,{value:n},e.children)}},9390:e=>{e.exports=JSON.parse('{"permalink":"/Cadence-Docs/blog/zonal-isolation-v1/zonal-isolation-v1","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/zonal-isolation-v1/zonal-isolation-v1.md","source":"@site/blog/zonal-isolation-v1/zonal-isolation-v1.md","title":"Zonal Isolation for Cadence Workflows","description":"At Uber, we want to achieve regional resilience such that losing a zone within a region can be tolerated without requiring a cross-region failover. We also want to make sure that losing a zone only affects a subset of workload, at most, rather than everything. However, in Cadence-based systems, the workload in a region is distributed randomly across all workers in the region at a \u201ctask-level granularity\u201d, which means a workflow may be worked on by any worker in the region where the domain is active. To achieve this goal, we introduced Zonal Isolation for Cadence Workflows - a feature designed to pin workflows to the zone they are started in, so that zonal isolation can be achieved at a workflow-level.","date":"2024-10-14T00:00:00.000Z","tags":[{"inline":false,"label":"Deep Dives","permalink":"/Cadence-Docs/blog/tags/deep-dives","description":"Deep Dives tag description"},{"inline":false,"label":"Cadence Operations","permalink":"/Cadence-Docs/blog/tags/cadence-operations","description":"Cadence Operations tag description"}],"readingTime":7.985,"hasTruncateMarker":true,"authors":[{"name":"Zijian Chen","title":"Software Engineer @ Uber","url":"https://www.linkedin.com/in/zijian-chen-5868938b/","page":{"permalink":"/Cadence-Docs/blog/authors/shaddoll"},"socials":{"linkedin":"https://www.linkedin.com/in/zijian-chen-5868938b/","github":"https://github.com/Shaddoll"},"imageURL":"https://github.com/Shaddoll.png","key":"shaddoll"}],"frontMatter":{"title":"Zonal Isolation for Cadence Workflows","subtitle":"test","date":"2024-10-14T00:00:00.000Z","authors":"shaddoll","tags":["deep-dive","cadence-operations"]},"unlisted":false,"prevItem":{"title":"Cadence Repositories Have Moved!","permalink":"/Cadence-Docs/blog/2024/11/18/cadence-workflows-github-organization"},"nextItem":{"title":"Announcement: Cadence Helm Charts v0 Release","permalink":"/Cadence-Docs/blog/2024/10/01/announcing-cadence-helm-charts-v0"}}')}}]); \ No newline at end of file diff --git a/assets/js/5d1ead22.3ddcd12b.js b/assets/js/5d1ead22.3ddcd12b.js new file mode 100644 index 000000000..1487483ae --- /dev/null +++ b/assets/js/5d1ead22.3ddcd12b.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[4713],{6462:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>s,contentTitle:()=>a,default:()=>f,frontMatter:()=>c,metadata:()=>i,toc:()=>d});const i=JSON.parse('{"id":"java-client/side-effect","title":"Side Effect","description":"Side Effect allow workflow executes the provided function once, records its result into the workflow history.","source":"@site/docs/04-java-client/16-side-effect.md","sourceDirName":"04-java-client","slug":"/java-client/side-effect","permalink":"/Cadence-Docs/docs/java-client/side-effect","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/04-java-client/16-side-effect.md","tags":[],"version":"current","sidebarPosition":16,"frontMatter":{"layout":"default","title":"Side Effect","permalink":"/docs/java-client/side-effect"},"sidebar":"docsSidebar","previous":{"title":"Continue As New","permalink":"/Cadence-Docs/docs/java-client/continue-as-new"},"next":{"title":"Testing","permalink":"/Cadence-Docs/docs/java-client/testing"}}');var o=t(4848),r=t(8453);const c={layout:"default",title:"Side Effect",permalink:"/docs/java-client/side-effect"},a="Side Effect",s={},d=[{value:"Mutable Side Effect",id:"mutable-side-effect",level:2}];function l(e){const n={code:"code",h1:"h1",h2:"h2",header:"header",p:"p",pre:"pre",...(0,r.R)(),...e.components};return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsx)(n.header,{children:(0,o.jsx)(n.h1,{id:"side-effect",children:"Side Effect"})}),"\n",(0,o.jsx)(n.p,{children:"Side Effect allow workflow executes the provided function once, records its result into the workflow history.\nThe recorded result on history will be returned without executing the provided function during replay. This\nguarantees the deterministic requirement for workflow as the exact same result will be returned\nin replay. Common use case is to run some short non-deterministic code in workflow, like\ngetting random number. The only way to fail SideEffect is to panic which causes decision task\nfailure. The decision task after timeout is rescheduled and re-executed giving SideEffect\nanother chance to succeed."}),"\n",(0,o.jsx)(n.p,{children:"!!Caution: do not use sideEffect function to modify any workflow state. Only use the\nSideEffect's return value. For example this code is BROKEN:"}),"\n",(0,o.jsx)(n.p,{children:"Bad example:"}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-java",children:" AtomicInteger random = new AtomicInteger();\n Workflow.sideEffect(() -> {\n random.set(random.nextInt(100));\n return null;\n });\n // random will always be 0 in replay, thus this code is non-deterministic\n if random.get() < 50 {\n ....\n } else {\n ....\n }\n"})}),"\n",(0,o.jsx)(n.p,{children:"On replay the provided function is not executed, the random will always be 0, and the workflow\ncould takes a different path breaking the determinism."}),"\n",(0,o.jsx)(n.p,{children:"Here is the correct way to use sideEffect:"}),"\n",(0,o.jsx)(n.p,{children:"Good example:"}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-java",children:" int random = Workflow.sideEffect(Integer.class, () -> random.nextInt(100));\n if random < 50 {\n ....\n } else {\n ....\n }\n"})}),"\n",(0,o.jsx)(n.p,{children:"If function throws any exception it is not delivered to the workflow code. It is wrapped in\nan Error causing failure of the current decision."}),"\n",(0,o.jsx)(n.h2,{id:"mutable-side-effect",children:"Mutable Side Effect"}),"\n",(0,o.jsx)(n.p,{children:"MutableSideEffect is similar to sideEffect, in allowing\ncalls of non-deterministic functions from workflow code.\nThe difference is that every sideEffect call in non-replay mode results in a new\nmarker event recorded into the history. However, mutableSideEffect only records a new\nmarker if a value has changed. During the replay, mutableSideEffect will not execute\nthe function again, but it will return the exact same value as it was returning during the\nnon-replay run."}),"\n",(0,o.jsx)(n.p,{children:"One good use case of mutableSideEffect is to access a dynamically changing config\nwithout breaking determinism. Even if called very frequently the config value is recorded only\nwhen it changes not causing any performance degradation due to a large history size."}),"\n",(0,o.jsx)(n.p,{children:"!!Caution: do not use mutableSideEffect function to modify any workflow sate. Only use\nthe mutableSideEffect's return value."}),"\n",(0,o.jsx)(n.p,{children:"If function throws any exception it is not delivered to the workflow code. It is wrapped in\nan Error causing failure of the current decision."})]})}function f(e={}){const{wrapper:n}={...(0,r.R)(),...e.components};return n?(0,o.jsx)(n,{...e,children:(0,o.jsx)(l,{...e})}):l(e)}},8453:(e,n,t)=>{t.d(n,{R:()=>c,x:()=>a});var i=t(6540);const o={},r=i.createContext(o);function c(e){const n=i.useContext(r);return i.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function a(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:c(e.components),i.createElement(r.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/5d1ead22.d4f49fa9.js b/assets/js/5d1ead22.d4f49fa9.js deleted file mode 100644 index 6a67e572e..000000000 --- a/assets/js/5d1ead22.d4f49fa9.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[4713],{6462:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>s,contentTitle:()=>a,default:()=>f,frontMatter:()=>c,metadata:()=>i,toc:()=>d});const i=JSON.parse('{"id":"java-client/side-effect","title":"Side Effect","description":"Side Effect allow workflow executes the provided function once, records its result into the workflow history.","source":"@site/docs/04-java-client/16-side-effect.md","sourceDirName":"04-java-client","slug":"/java-client/side-effect","permalink":"/docs/java-client/side-effect","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/04-java-client/16-side-effect.md","tags":[],"version":"current","sidebarPosition":16,"frontMatter":{"layout":"default","title":"Side Effect","permalink":"/docs/java-client/side-effect"},"sidebar":"docsSidebar","previous":{"title":"Continue As New","permalink":"/docs/java-client/continue-as-new"},"next":{"title":"Testing","permalink":"/docs/java-client/testing"}}');var o=t(4848),r=t(8453);const c={layout:"default",title:"Side Effect",permalink:"/docs/java-client/side-effect"},a="Side Effect",s={},d=[{value:"Mutable Side Effect",id:"mutable-side-effect",level:2}];function l(e){const n={code:"code",h1:"h1",h2:"h2",header:"header",p:"p",pre:"pre",...(0,r.R)(),...e.components};return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsx)(n.header,{children:(0,o.jsx)(n.h1,{id:"side-effect",children:"Side Effect"})}),"\n",(0,o.jsx)(n.p,{children:"Side Effect allow workflow executes the provided function once, records its result into the workflow history.\nThe recorded result on history will be returned without executing the provided function during replay. This\nguarantees the deterministic requirement for workflow as the exact same result will be returned\nin replay. Common use case is to run some short non-deterministic code in workflow, like\ngetting random number. The only way to fail SideEffect is to panic which causes decision task\nfailure. The decision task after timeout is rescheduled and re-executed giving SideEffect\nanother chance to succeed."}),"\n",(0,o.jsx)(n.p,{children:"!!Caution: do not use sideEffect function to modify any workflow state. Only use the\nSideEffect's return value. For example this code is BROKEN:"}),"\n",(0,o.jsx)(n.p,{children:"Bad example:"}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-java",children:" AtomicInteger random = new AtomicInteger();\n Workflow.sideEffect(() -> {\n random.set(random.nextInt(100));\n return null;\n });\n // random will always be 0 in replay, thus this code is non-deterministic\n if random.get() < 50 {\n ....\n } else {\n ....\n }\n"})}),"\n",(0,o.jsx)(n.p,{children:"On replay the provided function is not executed, the random will always be 0, and the workflow\ncould takes a different path breaking the determinism."}),"\n",(0,o.jsx)(n.p,{children:"Here is the correct way to use sideEffect:"}),"\n",(0,o.jsx)(n.p,{children:"Good example:"}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-java",children:" int random = Workflow.sideEffect(Integer.class, () -> random.nextInt(100));\n if random < 50 {\n ....\n } else {\n ....\n }\n"})}),"\n",(0,o.jsx)(n.p,{children:"If function throws any exception it is not delivered to the workflow code. It is wrapped in\nan Error causing failure of the current decision."}),"\n",(0,o.jsx)(n.h2,{id:"mutable-side-effect",children:"Mutable Side Effect"}),"\n",(0,o.jsx)(n.p,{children:"MutableSideEffect is similar to sideEffect, in allowing\ncalls of non-deterministic functions from workflow code.\nThe difference is that every sideEffect call in non-replay mode results in a new\nmarker event recorded into the history. However, mutableSideEffect only records a new\nmarker if a value has changed. During the replay, mutableSideEffect will not execute\nthe function again, but it will return the exact same value as it was returning during the\nnon-replay run."}),"\n",(0,o.jsx)(n.p,{children:"One good use case of mutableSideEffect is to access a dynamically changing config\nwithout breaking determinism. Even if called very frequently the config value is recorded only\nwhen it changes not causing any performance degradation due to a large history size."}),"\n",(0,o.jsx)(n.p,{children:"!!Caution: do not use mutableSideEffect function to modify any workflow sate. Only use\nthe mutableSideEffect's return value."}),"\n",(0,o.jsx)(n.p,{children:"If function throws any exception it is not delivered to the workflow code. It is wrapped in\nan Error causing failure of the current decision."})]})}function f(e={}){const{wrapper:n}={...(0,r.R)(),...e.components};return n?(0,o.jsx)(n,{...e,children:(0,o.jsx)(l,{...e})}):l(e)}},8453:(e,n,t)=>{t.d(n,{R:()=>c,x:()=>a});var i=t(6540);const o={},r=i.createContext(o);function c(e){const n=i.useContext(r);return i.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function a(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:c(e.components),i.createElement(r.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/5f63c9de.e66461de.js b/assets/js/5f63c9de.9c513c71.js similarity index 66% rename from assets/js/5f63c9de.e66461de.js rename to assets/js/5f63c9de.9c513c71.js index c8dd3cbf5..5ec58c1ff 100644 --- a/assets/js/5f63c9de.e66461de.js +++ b/assets/js/5f63c9de.9c513c71.js @@ -1 +1 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[8770],{9344:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>c,contentTitle:()=>r,default:()=>u,frontMatter:()=>o,metadata:()=>i,toc:()=>d});var i=n(1230),s=n(4848),a=n(8453);const o={title:"Bad practices and Anti-patterns with Cadence (Part 1)",date:new Date("2023-07-10T00:00:00.000Z"),authors:"chopincode",tags:["introduction-to-cadence","deep-dive"]},r=void 0,c={authorsImageUrls:[void 0]},d=[];function l(e){const t={code:"code",li:"li",p:"p",ul:"ul",...(0,a.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(t.p,{children:"In the upcoming blog series, we will delve into a discussion about common bad practices and anti-patterns related to Cadence. As diverse teams often encounter distinct business use cases, it becomes imperative to address the most frequently reported issues in Cadence workflows. To provide valuable insights and guidance, the Cadence team has meticulously compiled these common challenges based on customer feedback."}),"\n",(0,s.jsxs)(t.ul,{children:["\n",(0,s.jsx)(t.li,{children:"Reusing the same workflow ID for very active/continuous running workflows"}),"\n"]}),"\n",(0,s.jsxs)(t.p,{children:["Cadence organizes workflows based on their unique IDs, using a process called ",(0,s.jsx)("b",{children:"partitioning"}),". If a workflow receives a large number of updates in a short period of time or frequently starts new runs using the ",(0,s.jsx)(t.code,{children:"continueAsNew"}),' function, all these updates will be directed to the same shard. Unfortunately, the Cadence backend is not equipped to handle this concentrated workload efficiently. As a result, a situation known as a "hot shard" arises, overloading the Cadence backend and worsening the problem.']}),"\n",(0,s.jsx)(t.p,{children:"Solution:\nWell, the best way to avoid this is simply just design your workflow in the way such that each workflow owns a uniformly distributed workflow ID across your Cadence domain. This will make sure that Cadence backend is able to evenly distribute the traffic with proper partition on your workflowIDs."}),"\n",(0,s.jsxs)(t.ul,{children:["\n",(0,s.jsx)(t.li,{children:"Excessive batch jobs or an enormous number of timers triggered at the same time"}),"\n"]}),"\n",(0,s.jsx)(t.p,{children:"Cadence has the capability to handle a large number of concurrent tasks initiated simultaneously, but tampering with this feature can lead to issues within the Cadence system. Consider a scenario where millions of jobs are scheduled to start at the same time and are expected to finish within a specific time interval. Cadence faces the challenge of understanding the desired behavior of customers in such cases. It is uncertain whether the intention is to complete all jobs simultaneously, provide progressive updates in parallel, or finish all jobs before a given deadline. This ambiguity arises due to the independent nature of each job and the difficulty in predicting their outcomes."}),"\n",(0,s.jsxs)(t.p,{children:["Moreover, Cadence workers utilize a sticky cache by default to optimize the runtime of workflows. However, when an overwhelming number of parallel workflows cannot fit into the cache, it can result in ",(0,s.jsx)("b",{children:"cache thrashing"}),". This, in turn, leads to a quadratic increase in runtime complexity, specifically O(n^2), exacerbating the overall performance of the system."]}),"\n",(0,s.jsx)(t.p,{children:"Solution:\nThere are multiple ways to address this issue. Customers can either run jobs in a smaller batch or use start workflow jitter to randomly distribute timers within certain timeframe."})]})}function u(e={}){const{wrapper:t}={...(0,a.R)(),...e.components};return t?(0,s.jsx)(t,{...e,children:(0,s.jsx)(l,{...e})}):l(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>o,x:()=>r});var i=n(6540);const s={},a=i.createContext(s);function o(e){const t=i.useContext(a);return i.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function r(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:o(e.components),i.createElement(a.Provider,{value:t},e.children)}},1230:e=>{e.exports=JSON.parse('{"permalink":"/blog/2023/07/10/cadence-bad-practices-part-1","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2023-07-10-cadence-bad-practices-part-1.md","source":"@site/blog/2023-07-10-cadence-bad-practices-part-1.md","title":"Bad practices and Anti-patterns with Cadence (Part 1)","description":"In the upcoming blog series, we will delve into a discussion about common bad practices and anti-patterns related to Cadence. As diverse teams often encounter distinct business use cases, it becomes imperative to address the most frequently reported issues in Cadence workflows. To provide valuable insights and guidance, the Cadence team has meticulously compiled these common challenges based on customer feedback.","date":"2023-07-10T00:00:00.000Z","tags":[{"inline":false,"label":"Introduction to Cadence","permalink":"/blog/tags/introduction-to-cadence","description":"Introduction to Cadence tag description"},{"inline":false,"label":"Deep Dives","permalink":"/blog/tags/deep-dives","description":"Deep Dives tag description"}],"readingTime":2.065,"hasTruncateMarker":true,"authors":[{"name":"Chris Qin","title":"Applications Developer @ Uber","url":"https://www.linkedin.com/in/chrisqin0610/","page":{"permalink":"/blog/authors/chopincode"},"socials":{"linkedin":"https://www.linkedin.com/in/chrisqin0610/","github":"https://github.com/chopincode"},"imageURL":"https://github.com/chopincode.png","key":"chopincode"}],"frontMatter":{"title":"Bad practices and Anti-patterns with Cadence (Part 1)","date":"2023-07-10T00:00:00.000Z","authors":"chopincode","tags":["introduction-to-cadence","deep-dive"]},"unlisted":false,"prevItem":{"title":"Write your first workflow with Cadence","permalink":"/blog/2023/07/16/2023-07-16-write-your-first-workflow-with-cadence/write-your-first-workflow-with-cadence"},"nextItem":{"title":"Implement a Cadence worker service from scratch","permalink":"/blog/2023/07/05/implement-cadence-worker-from-scratch"}}')}}]); \ No newline at end of file +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[8770],{9344:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>c,contentTitle:()=>r,default:()=>u,frontMatter:()=>o,metadata:()=>i,toc:()=>d});var i=n(1230),s=n(4848),a=n(8453);const o={title:"Bad practices and Anti-patterns with Cadence (Part 1)",date:new Date("2023-07-10T00:00:00.000Z"),authors:"chopincode",tags:["introduction-to-cadence","deep-dive"]},r=void 0,c={authorsImageUrls:[void 0]},d=[];function l(e){const t={code:"code",li:"li",p:"p",ul:"ul",...(0,a.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(t.p,{children:"In the upcoming blog series, we will delve into a discussion about common bad practices and anti-patterns related to Cadence. As diverse teams often encounter distinct business use cases, it becomes imperative to address the most frequently reported issues in Cadence workflows. To provide valuable insights and guidance, the Cadence team has meticulously compiled these common challenges based on customer feedback."}),"\n",(0,s.jsxs)(t.ul,{children:["\n",(0,s.jsx)(t.li,{children:"Reusing the same workflow ID for very active/continuous running workflows"}),"\n"]}),"\n",(0,s.jsxs)(t.p,{children:["Cadence organizes workflows based on their unique IDs, using a process called ",(0,s.jsx)("b",{children:"partitioning"}),". If a workflow receives a large number of updates in a short period of time or frequently starts new runs using the ",(0,s.jsx)(t.code,{children:"continueAsNew"}),' function, all these updates will be directed to the same shard. Unfortunately, the Cadence backend is not equipped to handle this concentrated workload efficiently. As a result, a situation known as a "hot shard" arises, overloading the Cadence backend and worsening the problem.']}),"\n",(0,s.jsx)(t.p,{children:"Solution:\nWell, the best way to avoid this is simply just design your workflow in the way such that each workflow owns a uniformly distributed workflow ID across your Cadence domain. This will make sure that Cadence backend is able to evenly distribute the traffic with proper partition on your workflowIDs."}),"\n",(0,s.jsxs)(t.ul,{children:["\n",(0,s.jsx)(t.li,{children:"Excessive batch jobs or an enormous number of timers triggered at the same time"}),"\n"]}),"\n",(0,s.jsx)(t.p,{children:"Cadence has the capability to handle a large number of concurrent tasks initiated simultaneously, but tampering with this feature can lead to issues within the Cadence system. Consider a scenario where millions of jobs are scheduled to start at the same time and are expected to finish within a specific time interval. Cadence faces the challenge of understanding the desired behavior of customers in such cases. It is uncertain whether the intention is to complete all jobs simultaneously, provide progressive updates in parallel, or finish all jobs before a given deadline. This ambiguity arises due to the independent nature of each job and the difficulty in predicting their outcomes."}),"\n",(0,s.jsxs)(t.p,{children:["Moreover, Cadence workers utilize a sticky cache by default to optimize the runtime of workflows. However, when an overwhelming number of parallel workflows cannot fit into the cache, it can result in ",(0,s.jsx)("b",{children:"cache thrashing"}),". This, in turn, leads to a quadratic increase in runtime complexity, specifically O(n^2), exacerbating the overall performance of the system."]}),"\n",(0,s.jsx)(t.p,{children:"Solution:\nThere are multiple ways to address this issue. Customers can either run jobs in a smaller batch or use start workflow jitter to randomly distribute timers within certain timeframe."})]})}function u(e={}){const{wrapper:t}={...(0,a.R)(),...e.components};return t?(0,s.jsx)(t,{...e,children:(0,s.jsx)(l,{...e})}):l(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>o,x:()=>r});var i=n(6540);const s={},a=i.createContext(s);function o(e){const t=i.useContext(a);return i.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function r(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:o(e.components),i.createElement(a.Provider,{value:t},e.children)}},1230:e=>{e.exports=JSON.parse('{"permalink":"/Cadence-Docs/blog/2023/07/10/cadence-bad-practices-part-1","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2023-07-10-cadence-bad-practices-part-1.md","source":"@site/blog/2023-07-10-cadence-bad-practices-part-1.md","title":"Bad practices and Anti-patterns with Cadence (Part 1)","description":"In the upcoming blog series, we will delve into a discussion about common bad practices and anti-patterns related to Cadence. As diverse teams often encounter distinct business use cases, it becomes imperative to address the most frequently reported issues in Cadence workflows. To provide valuable insights and guidance, the Cadence team has meticulously compiled these common challenges based on customer feedback.","date":"2023-07-10T00:00:00.000Z","tags":[{"inline":false,"label":"Introduction to Cadence","permalink":"/Cadence-Docs/blog/tags/introduction-to-cadence","description":"Introduction to Cadence tag description"},{"inline":false,"label":"Deep Dives","permalink":"/Cadence-Docs/blog/tags/deep-dives","description":"Deep Dives tag description"}],"readingTime":2.065,"hasTruncateMarker":true,"authors":[{"name":"Chris Qin","title":"Applications Developer @ Uber","url":"https://www.linkedin.com/in/chrisqin0610/","page":{"permalink":"/Cadence-Docs/blog/authors/chopincode"},"socials":{"linkedin":"https://www.linkedin.com/in/chrisqin0610/","github":"https://github.com/chopincode"},"imageURL":"https://github.com/chopincode.png","key":"chopincode"}],"frontMatter":{"title":"Bad practices and Anti-patterns with Cadence (Part 1)","date":"2023-07-10T00:00:00.000Z","authors":"chopincode","tags":["introduction-to-cadence","deep-dive"]},"unlisted":false,"prevItem":{"title":"Write your first workflow with Cadence","permalink":"/Cadence-Docs/blog/2023/07/16/2023-07-16-write-your-first-workflow-with-cadence/write-your-first-workflow-with-cadence"},"nextItem":{"title":"Implement a Cadence worker service from scratch","permalink":"/Cadence-Docs/blog/2023/07/05/implement-cadence-worker-from-scratch"}}')}}]); \ No newline at end of file diff --git a/assets/js/6081a96a.7b56cf7e.js b/assets/js/6081a96a.7b56cf7e.js new file mode 100644 index 000000000..67664c3e5 --- /dev/null +++ b/assets/js/6081a96a.7b56cf7e.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[8729],{2428:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>c,contentTitle:()=>i,default:()=>d,frontMatter:()=>r,metadata:()=>o,toc:()=>l});var o=t(7799),a=t(4848),s=t(8453);const r={title:"Cadence Community Spotlight Update - September 2022",date:new Date("2022-10-11T00:00:00.000Z"),authors:"sharanf",tags:["community-spotlight"]},i="Cadence at Developer Week",c={authorsImageUrls:[void 0]},l=[{value:"Cadence in the News!",id:"cadence-in-the-news",level:2},{value:"Upcoming Events",id:"upcoming-events",level:2}];function h(e){const n={a:"a",h1:"h1",h2:"h2",li:"li",p:"p",ul:"ul",...(0,s.R)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(n.p,{children:"Here\u2019s the latest in our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!"}),"\n",(0,a.jsx)(n.p,{children:"Please see below for a roundup of the highlights:"}),"\n",(0,a.jsxs)(n.p,{children:["A Cadence talk by ",(0,a.jsx)(n.a,{href:"https://www.linkedin.com/in/enderdemirkaya/",children:"Ender Demirkaya"})," and ",(0,a.jsx)(n.a,{href:"https://www.linkedin.com/in/ben-slater-2720562/",children:"Ben Slater"})," has been accepted for ",(0,a.jsx)(n.a,{href:"https://www.developerweek.com/global/conference/enterprise/",children:"Developer Week Enterprise"}),"."]}),"\n",(0,a.jsx)(n.p,{children:"The talk is scheduled to for 16th November so please make a note in your calendars."}),"\n",(0,a.jsx)(n.h1,{id:"sharing-knowledge",children:"Sharing Knowledge"}),"\n",(0,a.jsxs)(n.p,{children:["Over the last few months we have had a continual stream of Cadence questions in our ",(0,a.jsx)(n.a,{href:"http://t.uber.com/cadence-slack",children:"Slack"})," #support channel or on ",(0,a.jsx)(n.a,{href:"https://stackoverflow.com/questions/tagged/cadence-workflow",children:"StackOverflow"}),". As a result of the increased interest some members from the Cadence core team have decided to spend some time each day responding to your questions."]}),"\n",(0,a.jsx)(n.p,{children:"Remember that if you have received a response that has solved your problem especially on StackOverflow then please don't forget to accept answer!"}),"\n",(0,a.jsx)(n.h2,{id:"cadence-in-the-news",children:"Cadence in the News!"}),"\n",(0,a.jsx)(n.p,{children:"Below are a selection of Cadence related articles, blogs and whitepapers. Please take a look and feel free to share via your own social media channels."}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsxs)(n.li,{children:["\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.a,{href:"https://www.youtube.com/watch?v=uNwbdQyLpns",children:"Technical Showcase Event: DoorDash's Financial Products and Platforms\n"})}),"\n"]}),"\n",(0,a.jsxs)(n.li,{children:["\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.a,{href:"https://www.instaclustr.com/blog/airflow-vs-cadence-a-side-to-side-comparison/",children:"Airflow vs Cadence: A Side by Side Comparison"})}),"\n"]}),"\n",(0,a.jsxs)(n.li,{children:["\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.a,{href:"https://www.instaclustr.com/blog/new-instaclustr-offering-for-cadence-developers/",children:"New Offering for Cadence Developers"})}),"\n"]}),"\n",(0,a.jsxs)(n.li,{children:["\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.a,{href:"https://devm.io/open-source/open-source-cadence",children:"Open Source Cadence Is Built for the Developer Experience \u2013 Here\u2019s How to Take Advantage"})}),"\n"]}),"\n"]}),"\n",(0,a.jsx)(n.h2,{id:"upcoming-events",children:"Upcoming Events"}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsxs)(n.li,{children:["\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.a,{href:"https://info.instaclustr.com/webinar-fitting-cadence-in-corporate-architecture.html",children:"Fitting Cadence in Your Corporate Architecture - 18th October 2022 @ 10am PT"})}),"\n"]}),"\n",(0,a.jsxs)(n.li,{children:["\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.a,{href:"https://info.instaclustr.com/webinar-fitting-cadence-in-corporate-architecture.html",children:"Migrating Your Workflow Solution from Temporal to Cadence - 25th October 2022 @ 10am PT"})}),"\n"]}),"\n",(0,a.jsxs)(n.li,{children:["\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.a,{href:"https://calendar.google.com/calendar/u/0/embed?src=e6r40gp3c2r01054id7e99dlac@group.calendar.google.com&ctz=America/Los_Angeles",children:"Cadence Technical Office Hours - 31st October 2022 @ 9am PT"})}),"\n"]}),"\n"]}),"\n",(0,a.jsxs)(n.p,{children:["If you have any news or topics you'd like us to include in our next update then please join our ",(0,a.jsx)(n.a,{href:"http://t.uber.com/cadence-slack",children:"Slack"}),"#community channel."]}),"\n",(0,a.jsxs)(n.p,{children:["Please remember that this update is for you - so if you have any comments or feedback that could help us improve it then please share it with us in the #community ",(0,a.jsx)(n.a,{href:"http://t.uber.com/cadence-slack",children:"Slack"})," channel."]})]})}function d(e={}){const{wrapper:n}={...(0,s.R)(),...e.components};return n?(0,a.jsx)(n,{...e,children:(0,a.jsx)(h,{...e})}):h(e)}},8453:(e,n,t)=>{t.d(n,{R:()=>r,x:()=>i});var o=t(6540);const a={},s=o.createContext(a);function r(e){const n=o.useContext(s);return o.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function i(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:r(e.components),o.createElement(s.Provider,{value:n},e.children)}},7799:e=>{e.exports=JSON.parse('{"permalink":"/Cadence-Docs/blog/2022/09/30/community-spotlight-september-2022","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2022-09-30-community-spotlight-september-2022.md","source":"@site/blog/2022-09-30-community-spotlight-september-2022.md","title":"Cadence Community Spotlight Update - September 2022","description":"Here\u2019s the latest in our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!","date":"2022-10-11T00:00:00.000Z","tags":[{"inline":false,"label":"Community Spotlight","permalink":"/Cadence-Docs/blog/tags/community-spotlights","description":"Community Spotlight tag description"}],"readingTime":1.585,"hasTruncateMarker":true,"authors":[{"name":"Sharan Foga","title":"Director of Operations & Customer Success @ Encube Technologies","url":"https://www.linkedin.com/in/sfoga/","page":{"permalink":"/Cadence-Docs/blog/authors/sharanf"},"socials":{"linkedin":"https://www.linkedin.com/in/sfoga/","github":"https://github.com/sharanf"},"imageURL":"https://github.com/sharanf.png","key":"sharanf"}],"frontMatter":{"title":"Cadence Community Spotlight Update - September 2022","date":"2022-10-11T00:00:00.000Z","authors":"sharanf","tags":["community-spotlight"]},"unlisted":false,"prevItem":{"title":"Cadence Community Spotlight Update - October 2022","permalink":"/Cadence-Docs/blog/2022/10/31/community-spotlight-october-2022"},"nextItem":{"title":"Cadence Community Spotlight Update - August 2022","permalink":"/Cadence-Docs/blog/2022/08/31/community-spotlight-august-2022"}}')}}]); \ No newline at end of file diff --git a/assets/js/6081a96a.fa1eb8e0.js b/assets/js/6081a96a.fa1eb8e0.js deleted file mode 100644 index a38c7989b..000000000 --- a/assets/js/6081a96a.fa1eb8e0.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[8729],{2428:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>c,contentTitle:()=>i,default:()=>d,frontMatter:()=>s,metadata:()=>o,toc:()=>l});var o=t(7799),r=t(4848),a=t(8453);const s={title:"Cadence Community Spotlight Update - September 2022",date:new Date("2022-10-11T00:00:00.000Z"),authors:"sharanf",tags:["community-spotlight"]},i="Cadence at Developer Week",c={authorsImageUrls:[void 0]},l=[{value:"Cadence in the News!",id:"cadence-in-the-news",level:2},{value:"Upcoming Events",id:"upcoming-events",level:2}];function h(e){const n={a:"a",h1:"h1",h2:"h2",li:"li",p:"p",ul:"ul",...(0,a.R)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(n.p,{children:"Here\u2019s the latest in our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!"}),"\n",(0,r.jsx)(n.p,{children:"Please see below for a roundup of the highlights:"}),"\n",(0,r.jsxs)(n.p,{children:["A Cadence talk by ",(0,r.jsx)(n.a,{href:"https://www.linkedin.com/in/enderdemirkaya/",children:"Ender Demirkaya"})," and ",(0,r.jsx)(n.a,{href:"https://www.linkedin.com/in/ben-slater-2720562/",children:"Ben Slater"})," has been accepted for ",(0,r.jsx)(n.a,{href:"https://www.developerweek.com/global/conference/enterprise/",children:"Developer Week Enterprise"}),"."]}),"\n",(0,r.jsx)(n.p,{children:"The talk is scheduled to for 16th November so please make a note in your calendars."}),"\n",(0,r.jsx)(n.h1,{id:"sharing-knowledge",children:"Sharing Knowledge"}),"\n",(0,r.jsxs)(n.p,{children:["Over the last few months we have had a continual stream of Cadence questions in our ",(0,r.jsx)(n.a,{href:"http://t.uber.com/cadence-slack",children:"Slack"})," #support channel or on ",(0,r.jsx)(n.a,{href:"https://stackoverflow.com/questions/tagged/cadence-workflow",children:"StackOverflow"}),". As a result of the increased interest some members from the Cadence core team have decided to spend some time each day responding to your questions."]}),"\n",(0,r.jsx)(n.p,{children:"Remember that if you have received a response that has solved your problem especially on StackOverflow then please don't forget to accept answer!"}),"\n",(0,r.jsx)(n.h2,{id:"cadence-in-the-news",children:"Cadence in the News!"}),"\n",(0,r.jsx)(n.p,{children:"Below are a selection of Cadence related articles, blogs and whitepapers. Please take a look and feel free to share via your own social media channels."}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.a,{href:"https://www.youtube.com/watch?v=uNwbdQyLpns",children:"Technical Showcase Event: DoorDash's Financial Products and Platforms\n"})}),"\n"]}),"\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.a,{href:"https://www.instaclustr.com/blog/airflow-vs-cadence-a-side-to-side-comparison/",children:"Airflow vs Cadence: A Side by Side Comparison"})}),"\n"]}),"\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.a,{href:"https://www.instaclustr.com/blog/new-instaclustr-offering-for-cadence-developers/",children:"New Offering for Cadence Developers"})}),"\n"]}),"\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.a,{href:"https://devm.io/open-source/open-source-cadence",children:"Open Source Cadence Is Built for the Developer Experience \u2013 Here\u2019s How to Take Advantage"})}),"\n"]}),"\n"]}),"\n",(0,r.jsx)(n.h2,{id:"upcoming-events",children:"Upcoming Events"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.a,{href:"https://info.instaclustr.com/webinar-fitting-cadence-in-corporate-architecture.html",children:"Fitting Cadence in Your Corporate Architecture - 18th October 2022 @ 10am PT"})}),"\n"]}),"\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.a,{href:"https://info.instaclustr.com/webinar-fitting-cadence-in-corporate-architecture.html",children:"Migrating Your Workflow Solution from Temporal to Cadence - 25th October 2022 @ 10am PT"})}),"\n"]}),"\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.a,{href:"https://calendar.google.com/calendar/u/0/embed?src=e6r40gp3c2r01054id7e99dlac@group.calendar.google.com&ctz=America/Los_Angeles",children:"Cadence Technical Office Hours - 31st October 2022 @ 9am PT"})}),"\n"]}),"\n"]}),"\n",(0,r.jsxs)(n.p,{children:["If you have any news or topics you'd like us to include in our next update then please join our ",(0,r.jsx)(n.a,{href:"http://t.uber.com/cadence-slack",children:"Slack"}),"#community channel."]}),"\n",(0,r.jsxs)(n.p,{children:["Please remember that this update is for you - so if you have any comments or feedback that could help us improve it then please share it with us in the #community ",(0,r.jsx)(n.a,{href:"http://t.uber.com/cadence-slack",children:"Slack"})," channel."]})]})}function d(e={}){const{wrapper:n}={...(0,a.R)(),...e.components};return n?(0,r.jsx)(n,{...e,children:(0,r.jsx)(h,{...e})}):h(e)}},8453:(e,n,t)=>{t.d(n,{R:()=>s,x:()=>i});var o=t(6540);const r={},a=o.createContext(r);function s(e){const n=o.useContext(a);return o.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function i(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:s(e.components),o.createElement(a.Provider,{value:n},e.children)}},7799:e=>{e.exports=JSON.parse('{"permalink":"/blog/2022/09/30/community-spotlight-september-2022","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2022-09-30-community-spotlight-september-2022.md","source":"@site/blog/2022-09-30-community-spotlight-september-2022.md","title":"Cadence Community Spotlight Update - September 2022","description":"Here\u2019s the latest in our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!","date":"2022-10-11T00:00:00.000Z","tags":[{"inline":false,"label":"Community Spotlight","permalink":"/blog/tags/community-spotlights","description":"Community Spotlight tag description"}],"readingTime":1.585,"hasTruncateMarker":true,"authors":[{"name":"Sharan Foga","title":"Director of Operations & Customer Success @ Encube Technologies","url":"https://www.linkedin.com/in/sfoga/","page":{"permalink":"/blog/authors/sharanf"},"socials":{"linkedin":"https://www.linkedin.com/in/sfoga/","github":"https://github.com/sharanf"},"imageURL":"https://github.com/sharanf.png","key":"sharanf"}],"frontMatter":{"title":"Cadence Community Spotlight Update - September 2022","date":"2022-10-11T00:00:00.000Z","authors":"sharanf","tags":["community-spotlight"]},"unlisted":false,"prevItem":{"title":"Cadence Community Spotlight Update - October 2022","permalink":"/blog/2022/10/31/community-spotlight-october-2022"},"nextItem":{"title":"Cadence Community Spotlight Update - August 2022","permalink":"/blog/2022/08/31/community-spotlight-august-2022"}}')}}]); \ No newline at end of file diff --git a/assets/js/61aeb84e.3ad98202.js b/assets/js/61aeb84e.3ad98202.js deleted file mode 100644 index 4c7f5530f..000000000 --- a/assets/js/61aeb84e.3ad98202.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[2641],{754:(e,n,c)=>{c.r(n),c.d(n,{assets:()=>s,contentTitle:()=>l,default:()=>u,frontMatter:()=>r,metadata:()=>a,toc:()=>o});const a=JSON.parse('{"id":"java-client/index","title":"Introduction","description":"The following are important links for the Cadence Java client:","source":"@site/docs/04-java-client/index.md","sourceDirName":"04-java-client","slug":"/java-client/","permalink":"/docs/java-client/","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/04-java-client/index.md","tags":[],"version":"current","frontMatter":{"layout":"default","title":"Introduction","permalink":"/docs/java-client"},"sidebar":"docsSidebar","previous":{"title":"HTTP API","permalink":"/docs/concepts/http-api"},"next":{"title":"Client SDK Overview","permalink":"/docs/java-client/client-overview"}}');var t=c(4848),i=c(8453);const r={layout:"default",title:"Introduction",permalink:"/docs/java-client"},l="Java client Java Client Release",s={},o=[];function d(e){const n={a:"a",code:"code",em:"em",h1:"h1",header:"header",img:"img",li:"li",p:"p",pre:"pre",ul:"ul",...(0,i.R)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.header,{children:(0,t.jsxs)(n.h1,{id:"java-client-java-client-release",children:["Java client ",(0,t.jsx)(n.img,{src:"https://img.shields.io/github/v/release/cadence-workflow/cadence-java-client?sort=semver&display_name=tag&label=Latest%20Release&link=https%3A%2F%2Fgithub.com%2Fuber%2Fcadence-java-client%2Freleases%2Flatest",alt:"Java Client Release"})]})}),"\n",(0,t.jsx)(n.p,{children:"The following are important links for the Cadence Java client:"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:["GitHub project: ",(0,t.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence-java-client",children:"https://github.com/cadence-workflow/cadence-java-client"})]}),"\n",(0,t.jsxs)(n.li,{children:["Samples: ",(0,t.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence-java-samples",children:"https://github.com/cadence-workflow/cadence-java-samples"})]}),"\n",(0,t.jsxs)(n.li,{children:["JavaDoc documentation: ",(0,t.jsx)(n.a,{href:"https://www.javadoc.io/doc/com.uber.cadence/cadence-client",children:"https://www.javadoc.io/doc/com.uber.cadence/cadence-client"})]}),"\n"]}),"\n",(0,t.jsxs)(n.p,{children:["Add ",(0,t.jsx)(n.em,{children:"cadence-client"})," as a dependency to your ",(0,t.jsx)(n.em,{children:"pom.xml"}),":"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-xml",children:" \n com.uber.cadence\n cadence-client\n LATEST.RELEASE.VERSION\n \n"})}),"\n",(0,t.jsxs)(n.p,{children:["or to ",(0,t.jsx)(n.em,{children:"build.gradle"}),":"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-gradle",children:" dependencies {\n implementation group: 'com.uber.cadence', name: 'cadence-client', version: 'LATEST.RELEASE.VERSION'\n }\n"})}),"\n",(0,t.jsxs)(n.p,{children:["If you are using ",(0,t.jsx)(n.a,{href:"https://docs.gradle.org/current/userguide/upgrading_version_6.html#sec:configuration_removal",children:"gradle 6.9 or older"}),", you can use ",(0,t.jsx)(n.code,{children:"compile group"})]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-gradle",children:" dependencies {\n compile group: 'com.uber.cadence', name: 'cadence-client', version: 'LATEST.RELEASE.VERSION'\n }\n"})}),"\n",(0,t.jsxs)(n.p,{children:["Release versions are available in the ",(0,t.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence-java-client/releases",children:"release page"})]})]})}function u(e={}){const{wrapper:n}={...(0,i.R)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(d,{...e})}):d(e)}},8453:(e,n,c)=>{c.d(n,{R:()=>r,x:()=>l});var a=c(6540);const t={},i=a.createContext(t);function r(e){const n=a.useContext(i);return a.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function l(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(t):e.components||t:r(e.components),a.createElement(i.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/61aeb84e.b051285d.js b/assets/js/61aeb84e.b051285d.js new file mode 100644 index 000000000..637f056f8 --- /dev/null +++ b/assets/js/61aeb84e.b051285d.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[2641],{754:(e,n,c)=>{c.r(n),c.d(n,{assets:()=>s,contentTitle:()=>l,default:()=>u,frontMatter:()=>r,metadata:()=>a,toc:()=>o});const a=JSON.parse('{"id":"java-client/index","title":"Introduction","description":"The following are important links for the Cadence Java client:","source":"@site/docs/04-java-client/index.md","sourceDirName":"04-java-client","slug":"/java-client/","permalink":"/Cadence-Docs/docs/java-client/","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/04-java-client/index.md","tags":[],"version":"current","frontMatter":{"layout":"default","title":"Introduction","permalink":"/docs/java-client"},"sidebar":"docsSidebar","previous":{"title":"HTTP API","permalink":"/Cadence-Docs/docs/concepts/http-api"},"next":{"title":"Client SDK Overview","permalink":"/Cadence-Docs/docs/java-client/client-overview"}}');var t=c(4848),i=c(8453);const r={layout:"default",title:"Introduction",permalink:"/docs/java-client"},l="Java client Java Client Release",s={},o=[];function d(e){const n={a:"a",code:"code",em:"em",h1:"h1",header:"header",img:"img",li:"li",p:"p",pre:"pre",ul:"ul",...(0,i.R)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.header,{children:(0,t.jsxs)(n.h1,{id:"java-client-java-client-release",children:["Java client ",(0,t.jsx)(n.img,{src:"https://img.shields.io/github/v/release/cadence-workflow/cadence-java-client?sort=semver&display_name=tag&label=Latest%20Release&link=https%3A%2F%2Fgithub.com%2Fuber%2Fcadence-java-client%2Freleases%2Flatest",alt:"Java Client Release"})]})}),"\n",(0,t.jsx)(n.p,{children:"The following are important links for the Cadence Java client:"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:["GitHub project: ",(0,t.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence-java-client",children:"https://github.com/cadence-workflow/cadence-java-client"})]}),"\n",(0,t.jsxs)(n.li,{children:["Samples: ",(0,t.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence-java-samples",children:"https://github.com/cadence-workflow/cadence-java-samples"})]}),"\n",(0,t.jsxs)(n.li,{children:["JavaDoc documentation: ",(0,t.jsx)(n.a,{href:"https://www.javadoc.io/doc/com.uber.cadence/cadence-client",children:"https://www.javadoc.io/doc/com.uber.cadence/cadence-client"})]}),"\n"]}),"\n",(0,t.jsxs)(n.p,{children:["Add ",(0,t.jsx)(n.em,{children:"cadence-client"})," as a dependency to your ",(0,t.jsx)(n.em,{children:"pom.xml"}),":"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-xml",children:" \n com.uber.cadence\n cadence-client\n LATEST.RELEASE.VERSION\n \n"})}),"\n",(0,t.jsxs)(n.p,{children:["or to ",(0,t.jsx)(n.em,{children:"build.gradle"}),":"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-gradle",children:" dependencies {\n implementation group: 'com.uber.cadence', name: 'cadence-client', version: 'LATEST.RELEASE.VERSION'\n }\n"})}),"\n",(0,t.jsxs)(n.p,{children:["If you are using ",(0,t.jsx)(n.a,{href:"https://docs.gradle.org/current/userguide/upgrading_version_6.html#sec:configuration_removal",children:"gradle 6.9 or older"}),", you can use ",(0,t.jsx)(n.code,{children:"compile group"})]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-gradle",children:" dependencies {\n compile group: 'com.uber.cadence', name: 'cadence-client', version: 'LATEST.RELEASE.VERSION'\n }\n"})}),"\n",(0,t.jsxs)(n.p,{children:["Release versions are available in the ",(0,t.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence-java-client/releases",children:"release page"})]})]})}function u(e={}){const{wrapper:n}={...(0,i.R)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(d,{...e})}):d(e)}},8453:(e,n,c)=>{c.d(n,{R:()=>r,x:()=>l});var a=c(6540);const t={},i=a.createContext(t);function r(e){const n=a.useContext(i);return a.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function l(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(t):e.components||t:r(e.components),a.createElement(i.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/643bf5c6.15ecbcc3.js b/assets/js/643bf5c6.15ecbcc3.js deleted file mode 100644 index 64f6475f2..000000000 --- a/assets/js/643bf5c6.15ecbcc3.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[4950],{5770:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>l,contentTitle:()=>a,default:()=>h,frontMatter:()=>s,metadata:()=>r,toc:()=>c});const r=JSON.parse('{"id":"go-client/create-workflows","title":"Creating workflows","description":"The is the implementation of the coordination logic. The Cadence programming framework","source":"@site/docs/05-go-client/02-create-workflows.md","sourceDirName":"05-go-client","slug":"/go-client/create-workflows","permalink":"/docs/go-client/create-workflows","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/05-go-client/02-create-workflows.md","tags":[],"version":"current","sidebarPosition":2,"frontMatter":{"layout":"default","title":"Creating workflows","permalink":"/docs/go-client/create-workflows"},"sidebar":"docsSidebar","previous":{"title":"Worker service","permalink":"/docs/go-client/workers"},"next":{"title":"Starting workflows","permalink":"/docs/go-client/02.5-starting-workflows"}}');var o=t(4848),i=t(8453);const s={layout:"default",title:"Creating workflows",permalink:"/docs/go-client/create-workflows"},a="Creating workflows",l={},c=[{value:"Overview",id:"overview",level:2},{value:"Declaration",id:"declaration",level:2},{value:"Implementation",id:"implementation",level:2},{value:"Special Cadence client library functions and types",id:"special-cadence-client-library-functions-and-types",level:3},{value:"Failing a workflow",id:"failing-a-workflow",level:3},{value:"Registration",id:"registration",level:2}];function d(e){const n={code:"code",h1:"h1",h2:"h2",h3:"h3",header:"header",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,i.R)(),...e.components};return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsx)(n.header,{children:(0,o.jsx)(n.h1,{id:"creating-workflows",children:"Creating workflows"})}),"\n",(0,o.jsx)(n.p,{children:"The workflow is the implementation of the coordination logic. The Cadence programming framework\n(aka client library) allows you to write the workflow coordination logic as simple procedural code\nthat uses standard Go data modeling. The client library takes care of the communication between\nthe worker service and the Cadence service, and ensures state persistence between events even in\ncase of worker failures. Furthermore, any particular execution is not tied to a particular worker\nmachine. Different steps of the coordination logic can end up executing on different worker\ninstances, with the framework ensuring that the necessary state is recreated on the worker executing\nthe step."}),"\n",(0,o.jsxs)(n.p,{children:["However, in order to facilitate this operational model, both the Cadence programming framework and\nthe managed service impose some requirements and restrictions on the implementation of the\ncoordination logic. The details of these requirements and restrictions are described in the\n",(0,o.jsx)(n.strong,{children:"Implementation"})," section below."]}),"\n",(0,o.jsx)(n.h2,{id:"overview",children:"Overview"}),"\n",(0,o.jsx)(n.p,{children:"The sample code below shows a simple implementation of a workflow that executes one activity. The\nworkflow also passes the sole parameter it receives as part of its initialization as a parameter\nto the activity."}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-go",children:'package sample\n\nimport (\n "time"\n\n "go.uber.org/cadence/workflow"\n)\n\nfunc init() {\n workflow.Register(SimpleWorkflow)\n}\n\nfunc SimpleWorkflow(ctx workflow.Context, value string) error {\n ao := workflow.ActivityOptions{\n TaskList: "sampleTaskList",\n ScheduleToCloseTimeout: time.Second * 60,\n ScheduleToStartTimeout: time.Second * 60,\n StartToCloseTimeout: time.Second * 60,\n HeartbeatTimeout: time.Second * 10,\n WaitForCancellation: false,\n }\n ctx = workflow.WithActivityOptions(ctx, ao)\n\n future := workflow.ExecuteActivity(ctx, SimpleActivity, value)\n var result string\n if err := future.Get(ctx, &result); err != nil {\n return err\n }\n workflow.GetLogger(ctx).Info("Done", zap.String("result", result))\n return nil\n}\n'})}),"\n",(0,o.jsx)(n.h2,{id:"declaration",children:"Declaration"}),"\n",(0,o.jsx)(n.p,{children:"In the Cadence programing model, a workflow is implemented with a function. The function declaration\nspecifies the parameters the workflow accepts as well as any values it might return."}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-go",children:"func SimpleWorkflow(ctx workflow.Context, value string) error\n"})}),"\n",(0,o.jsx)(n.p,{children:"Let\u2019s deconstruct the declaration above:"}),"\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsxs)(n.li,{children:["The first parameter to the function is ",(0,o.jsx)(n.strong,{children:"ctx workflow.Context"}),". This is a required parameter for\nall workflow functions and is used by the Cadence client library to pass execution context.\nVirtually all the client library functions that are callable from the workflow functions require\nthis ",(0,o.jsx)(n.strong,{children:"ctx"})," parameter. This ",(0,o.jsx)(n.strong,{children:"context"})," parameter is the same concept as the standard\n",(0,o.jsx)(n.strong,{children:"context.Context"})," provided by Go. The only difference between ",(0,o.jsx)(n.strong,{children:"workflow.Context"})," and\n",(0,o.jsx)(n.strong,{children:"context.Context"})," is that the ",(0,o.jsx)(n.strong,{children:"Done()"})," function in ",(0,o.jsx)(n.strong,{children:"workflow.Context"})," returns\n",(0,o.jsx)(n.strong,{children:"workflow.Channel"})," instead the standard go ",(0,o.jsx)(n.strong,{children:"chan"}),"."]}),"\n",(0,o.jsxs)(n.li,{children:["The second parameter, ",(0,o.jsx)(n.strong,{children:"string"}),", is a custom workflow parameter that can be used to pass data\ninto the workflow on start. A workflow can have one or more such parameters. All parameters to a\nworkflow function must be serializable, which essentially means that params can\u2019t be channels,\nfunctions, variadic, or unsafe pointers."]}),"\n",(0,o.jsxs)(n.li,{children:["Since it only declares error as the return value, this means that the workflow does not return a\nvalue. The ",(0,o.jsx)(n.strong,{children:"error"})," return value is used to indicate an error was encountered during execution\nand the workflow should be terminated."]}),"\n"]}),"\n",(0,o.jsx)(n.h2,{id:"implementation",children:"Implementation"}),"\n",(0,o.jsx)(n.p,{children:"In order to support the synchronous and sequential programming model for the workflow\nimplementation, there are certain restrictions and requirements on how the workflow implementation\nmust behave in order to guarantee correctness. The requirements are that:"}),"\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsx)(n.li,{children:"Execution must be deterministic"}),"\n",(0,o.jsx)(n.li,{children:"Execution must be idempotent"}),"\n"]}),"\n",(0,o.jsx)(n.p,{children:"A straightforward way to think about these requirements is that the workflow code is as follows:"}),"\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsx)(n.li,{children:"Workflow code can only read and manipulate local state or state received as return values from\nCadence client library functions."}),"\n",(0,o.jsx)(n.li,{children:"Workflow code should not affect changes in external systems other than through invocation\nof activities."}),"\n",(0,o.jsxs)(n.li,{children:["Workflow code should interact with ",(0,o.jsx)(n.strong,{children:"time"})," only through the functions provided by the Cadence\nclient library (i.e. ",(0,o.jsx)(n.strong,{children:"workflow.Now()"}),", ",(0,o.jsx)(n.strong,{children:"workflow.Sleep()"}),")."]}),"\n",(0,o.jsxs)(n.li,{children:["Workflow code should not create and interact with goroutines directly, it should instead use the\nfunctions provided by the Cadence client library (i.e., ",(0,o.jsx)(n.strong,{children:"workflow.Go()"})," instead of ",(0,o.jsx)(n.strong,{children:"go"}),",\n",(0,o.jsx)(n.strong,{children:"workflow.Channel"})," instead of ",(0,o.jsx)(n.strong,{children:"chan"}),", ",(0,o.jsx)(n.strong,{children:"workflow.Selector"})," instead of ",(0,o.jsx)(n.strong,{children:"select"}),")."]}),"\n",(0,o.jsxs)(n.li,{children:["Workflow code should do all logging via the logger provided by the Cadence client library\n(i.e., ",(0,o.jsx)(n.strong,{children:"workflow.GetLogger()"}),")."]}),"\n",(0,o.jsx)(n.li,{children:"Workflow code should not iterate over maps using range because the order of map iteration is randomized."}),"\n"]}),"\n",(0,o.jsx)(n.p,{children:"Now that we have laid the ground rules, we can take a look at some of the special functions and types\nused for writing Cadence workflows and how to implement some common patterns."}),"\n",(0,o.jsx)(n.h3,{id:"special-cadence-client-library-functions-and-types",children:"Special Cadence client library functions and types"}),"\n",(0,o.jsx)(n.p,{children:"The Cadence client library provides a number of functions and types as alternatives to some native\nGo functions and types. Usage of these replacement functions/types is necessary in order to ensure\nthat the workflow code execution is deterministic and repeatable within an execution context."}),"\n",(0,o.jsx)(n.p,{children:"Coroutine related constructs:"}),"\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsxs)(n.li,{children:[(0,o.jsx)(n.strong,{children:"workflow.Go"})," : This is a replacement for the the ",(0,o.jsx)(n.strong,{children:"go"})," statement."]}),"\n",(0,o.jsxs)(n.li,{children:[(0,o.jsx)(n.strong,{children:"workflow.Channel"})," : This is a replacement for the native ",(0,o.jsx)(n.strong,{children:"chan"})," type. Cadence provides\nsupport for both buffered and unbuffered channels."]}),"\n",(0,o.jsxs)(n.li,{children:[(0,o.jsx)(n.strong,{children:"workflow.Selector"})," : This is a replacement for the ",(0,o.jsx)(n.strong,{children:"select"})," statement."]}),"\n"]}),"\n",(0,o.jsx)(n.p,{children:"Time related functions:"}),"\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsxs)(n.li,{children:[(0,o.jsx)(n.strong,{children:"workflow.Now()"})," : This is a replacement for ",(0,o.jsx)(n.strong,{children:"time.Now()"}),"."]}),"\n",(0,o.jsxs)(n.li,{children:[(0,o.jsx)(n.strong,{children:"workflow.Sleep()"})," : This is a replacement for ",(0,o.jsx)(n.strong,{children:"time.Sleep()"}),"."]}),"\n"]}),"\n",(0,o.jsx)(n.h3,{id:"failing-a-workflow",children:"Failing a workflow"}),"\n",(0,o.jsxs)(n.p,{children:["To mark a workflow as failed, all that needs to happen is for the workflow function to return an\nerror via the ",(0,o.jsx)(n.strong,{children:"err"})," return value."]}),"\n",(0,o.jsx)(n.h2,{id:"registration",children:"Registration"}),"\n",(0,o.jsx)(n.p,{children:"For some client code to be able to invoke a workflow type, the worker process needs to be aware of\nall the implementations it has access to. A workflow is registered with the following call:"}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-go",children:"workflow.Register(SimpleWorkflow)\n"})}),"\n",(0,o.jsxs)(n.p,{children:["This call essentially creates an in-memory mapping inside the worker process between the fully\nqualified function name and the implementation. It is safe to call this registration method from\nan ",(0,o.jsx)(n.strong,{children:"init()"})," function. If the worker receives tasks for a workflow type it does not know, it will\nfail that task. However, the failure of the task will not cause the entire workflow to fail."]})]})}function h(e={}){const{wrapper:n}={...(0,i.R)(),...e.components};return n?(0,o.jsx)(n,{...e,children:(0,o.jsx)(d,{...e})}):d(e)}},8453:(e,n,t)=>{t.d(n,{R:()=>s,x:()=>a});var r=t(6540);const o={},i=r.createContext(o);function s(e){const n=r.useContext(i);return r.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function a(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:s(e.components),r.createElement(i.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/643bf5c6.88245425.js b/assets/js/643bf5c6.88245425.js new file mode 100644 index 000000000..20c0b2ce8 --- /dev/null +++ b/assets/js/643bf5c6.88245425.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[4950],{5770:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>l,contentTitle:()=>a,default:()=>h,frontMatter:()=>s,metadata:()=>r,toc:()=>c});const r=JSON.parse('{"id":"go-client/create-workflows","title":"Creating workflows","description":"The is the implementation of the coordination logic. The Cadence programming framework","source":"@site/docs/05-go-client/02-create-workflows.md","sourceDirName":"05-go-client","slug":"/go-client/create-workflows","permalink":"/Cadence-Docs/docs/go-client/create-workflows","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/05-go-client/02-create-workflows.md","tags":[],"version":"current","sidebarPosition":2,"frontMatter":{"layout":"default","title":"Creating workflows","permalink":"/docs/go-client/create-workflows"},"sidebar":"docsSidebar","previous":{"title":"Worker service","permalink":"/Cadence-Docs/docs/go-client/workers"},"next":{"title":"Starting workflows","permalink":"/Cadence-Docs/docs/go-client/02.5-starting-workflows"}}');var o=t(4848),i=t(8453);const s={layout:"default",title:"Creating workflows",permalink:"/docs/go-client/create-workflows"},a="Creating workflows",l={},c=[{value:"Overview",id:"overview",level:2},{value:"Declaration",id:"declaration",level:2},{value:"Implementation",id:"implementation",level:2},{value:"Special Cadence client library functions and types",id:"special-cadence-client-library-functions-and-types",level:3},{value:"Failing a workflow",id:"failing-a-workflow",level:3},{value:"Registration",id:"registration",level:2}];function d(e){const n={code:"code",h1:"h1",h2:"h2",h3:"h3",header:"header",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,i.R)(),...e.components};return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsx)(n.header,{children:(0,o.jsx)(n.h1,{id:"creating-workflows",children:"Creating workflows"})}),"\n",(0,o.jsx)(n.p,{children:"The workflow is the implementation of the coordination logic. The Cadence programming framework\n(aka client library) allows you to write the workflow coordination logic as simple procedural code\nthat uses standard Go data modeling. The client library takes care of the communication between\nthe worker service and the Cadence service, and ensures state persistence between events even in\ncase of worker failures. Furthermore, any particular execution is not tied to a particular worker\nmachine. Different steps of the coordination logic can end up executing on different worker\ninstances, with the framework ensuring that the necessary state is recreated on the worker executing\nthe step."}),"\n",(0,o.jsxs)(n.p,{children:["However, in order to facilitate this operational model, both the Cadence programming framework and\nthe managed service impose some requirements and restrictions on the implementation of the\ncoordination logic. The details of these requirements and restrictions are described in the\n",(0,o.jsx)(n.strong,{children:"Implementation"})," section below."]}),"\n",(0,o.jsx)(n.h2,{id:"overview",children:"Overview"}),"\n",(0,o.jsx)(n.p,{children:"The sample code below shows a simple implementation of a workflow that executes one activity. The\nworkflow also passes the sole parameter it receives as part of its initialization as a parameter\nto the activity."}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-go",children:'package sample\n\nimport (\n "time"\n\n "go.uber.org/cadence/workflow"\n)\n\nfunc init() {\n workflow.Register(SimpleWorkflow)\n}\n\nfunc SimpleWorkflow(ctx workflow.Context, value string) error {\n ao := workflow.ActivityOptions{\n TaskList: "sampleTaskList",\n ScheduleToCloseTimeout: time.Second * 60,\n ScheduleToStartTimeout: time.Second * 60,\n StartToCloseTimeout: time.Second * 60,\n HeartbeatTimeout: time.Second * 10,\n WaitForCancellation: false,\n }\n ctx = workflow.WithActivityOptions(ctx, ao)\n\n future := workflow.ExecuteActivity(ctx, SimpleActivity, value)\n var result string\n if err := future.Get(ctx, &result); err != nil {\n return err\n }\n workflow.GetLogger(ctx).Info("Done", zap.String("result", result))\n return nil\n}\n'})}),"\n",(0,o.jsx)(n.h2,{id:"declaration",children:"Declaration"}),"\n",(0,o.jsx)(n.p,{children:"In the Cadence programing model, a workflow is implemented with a function. The function declaration\nspecifies the parameters the workflow accepts as well as any values it might return."}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-go",children:"func SimpleWorkflow(ctx workflow.Context, value string) error\n"})}),"\n",(0,o.jsx)(n.p,{children:"Let\u2019s deconstruct the declaration above:"}),"\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsxs)(n.li,{children:["The first parameter to the function is ",(0,o.jsx)(n.strong,{children:"ctx workflow.Context"}),". This is a required parameter for\nall workflow functions and is used by the Cadence client library to pass execution context.\nVirtually all the client library functions that are callable from the workflow functions require\nthis ",(0,o.jsx)(n.strong,{children:"ctx"})," parameter. This ",(0,o.jsx)(n.strong,{children:"context"})," parameter is the same concept as the standard\n",(0,o.jsx)(n.strong,{children:"context.Context"})," provided by Go. The only difference between ",(0,o.jsx)(n.strong,{children:"workflow.Context"})," and\n",(0,o.jsx)(n.strong,{children:"context.Context"})," is that the ",(0,o.jsx)(n.strong,{children:"Done()"})," function in ",(0,o.jsx)(n.strong,{children:"workflow.Context"})," returns\n",(0,o.jsx)(n.strong,{children:"workflow.Channel"})," instead the standard go ",(0,o.jsx)(n.strong,{children:"chan"}),"."]}),"\n",(0,o.jsxs)(n.li,{children:["The second parameter, ",(0,o.jsx)(n.strong,{children:"string"}),", is a custom workflow parameter that can be used to pass data\ninto the workflow on start. A workflow can have one or more such parameters. All parameters to a\nworkflow function must be serializable, which essentially means that params can\u2019t be channels,\nfunctions, variadic, or unsafe pointers."]}),"\n",(0,o.jsxs)(n.li,{children:["Since it only declares error as the return value, this means that the workflow does not return a\nvalue. The ",(0,o.jsx)(n.strong,{children:"error"})," return value is used to indicate an error was encountered during execution\nand the workflow should be terminated."]}),"\n"]}),"\n",(0,o.jsx)(n.h2,{id:"implementation",children:"Implementation"}),"\n",(0,o.jsx)(n.p,{children:"In order to support the synchronous and sequential programming model for the workflow\nimplementation, there are certain restrictions and requirements on how the workflow implementation\nmust behave in order to guarantee correctness. The requirements are that:"}),"\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsx)(n.li,{children:"Execution must be deterministic"}),"\n",(0,o.jsx)(n.li,{children:"Execution must be idempotent"}),"\n"]}),"\n",(0,o.jsx)(n.p,{children:"A straightforward way to think about these requirements is that the workflow code is as follows:"}),"\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsx)(n.li,{children:"Workflow code can only read and manipulate local state or state received as return values from\nCadence client library functions."}),"\n",(0,o.jsx)(n.li,{children:"Workflow code should not affect changes in external systems other than through invocation\nof activities."}),"\n",(0,o.jsxs)(n.li,{children:["Workflow code should interact with ",(0,o.jsx)(n.strong,{children:"time"})," only through the functions provided by the Cadence\nclient library (i.e. ",(0,o.jsx)(n.strong,{children:"workflow.Now()"}),", ",(0,o.jsx)(n.strong,{children:"workflow.Sleep()"}),")."]}),"\n",(0,o.jsxs)(n.li,{children:["Workflow code should not create and interact with goroutines directly, it should instead use the\nfunctions provided by the Cadence client library (i.e., ",(0,o.jsx)(n.strong,{children:"workflow.Go()"})," instead of ",(0,o.jsx)(n.strong,{children:"go"}),",\n",(0,o.jsx)(n.strong,{children:"workflow.Channel"})," instead of ",(0,o.jsx)(n.strong,{children:"chan"}),", ",(0,o.jsx)(n.strong,{children:"workflow.Selector"})," instead of ",(0,o.jsx)(n.strong,{children:"select"}),")."]}),"\n",(0,o.jsxs)(n.li,{children:["Workflow code should do all logging via the logger provided by the Cadence client library\n(i.e., ",(0,o.jsx)(n.strong,{children:"workflow.GetLogger()"}),")."]}),"\n",(0,o.jsx)(n.li,{children:"Workflow code should not iterate over maps using range because the order of map iteration is randomized."}),"\n"]}),"\n",(0,o.jsx)(n.p,{children:"Now that we have laid the ground rules, we can take a look at some of the special functions and types\nused for writing Cadence workflows and how to implement some common patterns."}),"\n",(0,o.jsx)(n.h3,{id:"special-cadence-client-library-functions-and-types",children:"Special Cadence client library functions and types"}),"\n",(0,o.jsx)(n.p,{children:"The Cadence client library provides a number of functions and types as alternatives to some native\nGo functions and types. Usage of these replacement functions/types is necessary in order to ensure\nthat the workflow code execution is deterministic and repeatable within an execution context."}),"\n",(0,o.jsx)(n.p,{children:"Coroutine related constructs:"}),"\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsxs)(n.li,{children:[(0,o.jsx)(n.strong,{children:"workflow.Go"})," : This is a replacement for the the ",(0,o.jsx)(n.strong,{children:"go"})," statement."]}),"\n",(0,o.jsxs)(n.li,{children:[(0,o.jsx)(n.strong,{children:"workflow.Channel"})," : This is a replacement for the native ",(0,o.jsx)(n.strong,{children:"chan"})," type. Cadence provides\nsupport for both buffered and unbuffered channels."]}),"\n",(0,o.jsxs)(n.li,{children:[(0,o.jsx)(n.strong,{children:"workflow.Selector"})," : This is a replacement for the ",(0,o.jsx)(n.strong,{children:"select"})," statement."]}),"\n"]}),"\n",(0,o.jsx)(n.p,{children:"Time related functions:"}),"\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsxs)(n.li,{children:[(0,o.jsx)(n.strong,{children:"workflow.Now()"})," : This is a replacement for ",(0,o.jsx)(n.strong,{children:"time.Now()"}),"."]}),"\n",(0,o.jsxs)(n.li,{children:[(0,o.jsx)(n.strong,{children:"workflow.Sleep()"})," : This is a replacement for ",(0,o.jsx)(n.strong,{children:"time.Sleep()"}),"."]}),"\n"]}),"\n",(0,o.jsx)(n.h3,{id:"failing-a-workflow",children:"Failing a workflow"}),"\n",(0,o.jsxs)(n.p,{children:["To mark a workflow as failed, all that needs to happen is for the workflow function to return an\nerror via the ",(0,o.jsx)(n.strong,{children:"err"})," return value."]}),"\n",(0,o.jsx)(n.h2,{id:"registration",children:"Registration"}),"\n",(0,o.jsx)(n.p,{children:"For some client code to be able to invoke a workflow type, the worker process needs to be aware of\nall the implementations it has access to. A workflow is registered with the following call:"}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-go",children:"workflow.Register(SimpleWorkflow)\n"})}),"\n",(0,o.jsxs)(n.p,{children:["This call essentially creates an in-memory mapping inside the worker process between the fully\nqualified function name and the implementation. It is safe to call this registration method from\nan ",(0,o.jsx)(n.strong,{children:"init()"})," function. If the worker receives tasks for a workflow type it does not know, it will\nfail that task. However, the failure of the task will not cause the entire workflow to fail."]})]})}function h(e={}){const{wrapper:n}={...(0,i.R)(),...e.components};return n?(0,o.jsx)(n,{...e,children:(0,o.jsx)(d,{...e})}):d(e)}},8453:(e,n,t)=>{t.d(n,{R:()=>s,x:()=>a});var r=t(6540);const o={},i=r.createContext(o);function s(e){const n=r.useContext(i);return r.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function a(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:s(e.components),r.createElement(i.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/647edc7e.53f565b0.js b/assets/js/647edc7e.7faa1898.js similarity index 66% rename from assets/js/647edc7e.53f565b0.js rename to assets/js/647edc7e.7faa1898.js index f49cac9e3..9ce963b3c 100644 --- a/assets/js/647edc7e.53f565b0.js +++ b/assets/js/647edc7e.7faa1898.js @@ -1 +1 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[7478],{3108:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>l,contentTitle:()=>r,default:()=>d,frontMatter:()=>s,metadata:()=>a,toc:()=>c});var a=n(3468),o=n(4848),i=n(8453);const s={title:"Cadence Community Spotlight Update - July 2023",date:new Date("2023-07-31T00:00:00.000Z"),authors:"sharanf",tags:["release","announcement","community-spotlight"]},r=void 0,l={authorsImageUrls:[void 0]},c=[{value:"Getting Started with Cadence",id:"getting-started-with-cadence",level:2},{value:"Cadence Go Client v1.0 Released",id:"cadence-go-client-v10-released",level:2},{value:"Cadence Release Strategy",id:"cadence-release-strategy",level:2},{value:"Cadence Helm Charts",id:"cadence-helm-charts",level:2},{value:"Upcoming Events",id:"upcoming-events",level:2}];function h(e){const t={a:"a",h2:"h2",li:"li",p:"p",ul:"ul",...(0,i.R)(),...e.components};return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsx)(t.p,{children:"Welcome to the latest of our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!"}),"\n",(0,o.jsx)(t.p,{children:"Please see below for a roundup of the highlights:"}),"\n",(0,o.jsx)(t.h2,{id:"getting-started-with-cadence",children:"Getting Started with Cadence"}),"\n",(0,o.jsx)(t.p,{children:"Are you new to Cadence and want to understand the basic concepts and architecture? Well we have some great information for you!"}),"\n",(0,o.jsxs)(t.p,{children:["Community member ",(0,o.jsx)(t.a,{href:"https://www.linkedin.com/in/chrisqin0610/",children:"Chris Qin"})," has written a ",(0,o.jsx)(t.a,{href:"https://cadenceworkflow.io/blog/2023/07/01/components-of-cadence-application-setup/",children:"short blog post"})," that takes you through the the three main components that make up a Cadence application. Please take a look and feel free to give us your comments and feedback."]}),"\n",(0,o.jsx)(t.p,{children:"Thanks Chris for sharing your knowledge and helping others to get started."}),"\n",(0,o.jsx)(t.h2,{id:"cadence-go-client-v10-released",children:"Cadence Go Client v1.0 Released"}),"\n",(0,o.jsxs)(t.p,{children:["This month saw the release of ",(0,o.jsx)(t.a,{href:"https://github.com/cadence-workflow/cadence-go-client/releases/tag/v1.0.0",children:"v1.0 of the Cadence Go Client"}),". Note that the work done on this release was as a result of community feedback asking for it - so we are listening and responding to community needs."]}),"\n",(0,o.jsx)(t.p,{children:"Thanks very much to everyone who worked hard to get this release out!"}),"\n",(0,o.jsx)(t.h2,{id:"cadence-release-strategy",children:"Cadence Release Strategy"}),"\n",(0,o.jsxs)(t.p,{children:["A recent discussion on the Cadence Release strategy was posted in ",(0,o.jsx)(t.a,{href:"https://github.com/cadence-workflow/cadence/discussions/5362",children:"Cadence Github Discussions"})," (and also our #general channel on our ",(0,o.jsx)(t.a,{href:"http://t.uber.com/cadence-slack",children:"Slack"})," about the approach we'd like to take for future releases. As a community we want to ensure code stability and to not burden people with having to upgrade frequently."]}),"\n",(0,o.jsx)(t.p,{children:"Based on feedback from the community we will be introducing quarterly release cycles but also give people the ability to make use of patches and minor releases. We will be communicating the intention to make a release at least a month beforehand so that the community has time to finalise any features they want to be included in the upcoming release."}),"\n",(0,o.jsx)(t.p,{children:"For those of you wanting to keep up to date or try out new features in between releases, the core team at Uber will continue to make patch and minor version updates available to the community."}),"\n",(0,o.jsx)(t.p,{children:"As always we welcome your feedback so please feel free to add your thoughts and comments to the discussion."}),"\n",(0,o.jsx)(t.h2,{id:"cadence-helm-charts",children:"Cadence Helm Charts"}),"\n",(0,o.jsxs)(t.p,{children:["Community member ",(0,o.jsx)(t.a,{href:"https://www.linkedin.com/in/sagikazarmark/",children:"Mark Sagi-Kazar"})," has been maintaining the Banzai Cloud Cadence Helm Charts for the community. As the Helm Charts are a key tool for the community we are planning to take over the maintenance of them."]}),"\n",(0,o.jsx)(t.p,{children:"Our plan is to move the charts into the Cadence repository and to maintain an official and supported Kubernetes solution with Cadence."}),"\n",(0,o.jsx)(t.p,{children:"Huge thanks to Mark for all the work you have done and it's great to see the task being handed over and made into a community effort."}),"\n",(0,o.jsx)(t.h2,{id:"upcoming-events",children:"Upcoming Events"}),"\n",(0,o.jsxs)(t.ul,{children:["\n",(0,o.jsx)(t.li,{children:"None"}),"\n"]}),"\n",(0,o.jsxs)(t.p,{children:["If you have any news or topics you'd like us to include in our next update then please join our ",(0,o.jsx)(t.a,{href:"http://t.uber.com/cadence-slack",children:"Slack"})," #community channel."]}),"\n",(0,o.jsxs)(t.p,{children:["Please remember that this update is for you - so if you have any comments or feedback that could help us improve it then please share it with us in the #community ",(0,o.jsx)(t.a,{href:"http://t.uber.com/cadence-slack",children:"Slack"})," channel."]})]})}function d(e={}){const{wrapper:t}={...(0,i.R)(),...e.components};return t?(0,o.jsx)(t,{...e,children:(0,o.jsx)(h,{...e})}):h(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>s,x:()=>r});var a=n(6540);const o={},i=a.createContext(o);function s(e){const t=a.useContext(i);return a.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function r(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:s(e.components),a.createElement(i.Provider,{value:t},e.children)}},3468:e=>{e.exports=JSON.parse('{"permalink":"/blog/2023/07/31/community-spotlight-july-2023","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2023-07-31-community-spotlight-july-2023.md","source":"@site/blog/2023-07-31-community-spotlight-july-2023.md","title":"Cadence Community Spotlight Update - July 2023","description":"Welcome to the latest of our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!","date":"2023-07-31T00:00:00.000Z","tags":[{"inline":false,"label":"Releases","permalink":"/blog/tags/releases","description":"Releases tag description"},{"inline":false,"label":"Announcement","permalink":"/blog/tags/announcements","description":"Announcement tag description"},{"inline":false,"label":"Community Spotlight","permalink":"/blog/tags/community-spotlights","description":"Community Spotlight tag description"}],"readingTime":2.49,"hasTruncateMarker":true,"authors":[{"name":"Sharan Foga","title":"Director of Operations & Customer Success @ Encube Technologies","url":"https://www.linkedin.com/in/sfoga/","page":{"permalink":"/blog/authors/sharanf"},"socials":{"linkedin":"https://www.linkedin.com/in/sfoga/","github":"https://github.com/sharanf"},"imageURL":"https://github.com/sharanf.png","key":"sharanf"}],"frontMatter":{"title":"Cadence Community Spotlight Update - July 2023","date":"2023-07-31T00:00:00.000Z","authors":"sharanf","tags":["release","announcement","community-spotlight"]},"unlisted":false,"prevItem":{"title":"Non-deterministic errors, replayers and shadowers","permalink":"/blog/2023/08/28/nondeterministic-errors-replayers-shadowers"},"nextItem":{"title":"Write your first workflow with Cadence","permalink":"/blog/2023/07/16/2023-07-16-write-your-first-workflow-with-cadence/write-your-first-workflow-with-cadence"}}')}}]); \ No newline at end of file +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[7478],{3108:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>c,contentTitle:()=>r,default:()=>d,frontMatter:()=>i,metadata:()=>a,toc:()=>l});var a=n(3468),o=n(4848),s=n(8453);const i={title:"Cadence Community Spotlight Update - July 2023",date:new Date("2023-07-31T00:00:00.000Z"),authors:"sharanf",tags:["release","announcement","community-spotlight"]},r=void 0,c={authorsImageUrls:[void 0]},l=[{value:"Getting Started with Cadence",id:"getting-started-with-cadence",level:2},{value:"Cadence Go Client v1.0 Released",id:"cadence-go-client-v10-released",level:2},{value:"Cadence Release Strategy",id:"cadence-release-strategy",level:2},{value:"Cadence Helm Charts",id:"cadence-helm-charts",level:2},{value:"Upcoming Events",id:"upcoming-events",level:2}];function h(e){const t={a:"a",h2:"h2",li:"li",p:"p",ul:"ul",...(0,s.R)(),...e.components};return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsx)(t.p,{children:"Welcome to the latest of our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!"}),"\n",(0,o.jsx)(t.p,{children:"Please see below for a roundup of the highlights:"}),"\n",(0,o.jsx)(t.h2,{id:"getting-started-with-cadence",children:"Getting Started with Cadence"}),"\n",(0,o.jsx)(t.p,{children:"Are you new to Cadence and want to understand the basic concepts and architecture? Well we have some great information for you!"}),"\n",(0,o.jsxs)(t.p,{children:["Community member ",(0,o.jsx)(t.a,{href:"https://www.linkedin.com/in/chrisqin0610/",children:"Chris Qin"})," has written a ",(0,o.jsx)(t.a,{href:"https://cadenceworkflow.io/blog/2023/07/01/components-of-cadence-application-setup/",children:"short blog post"})," that takes you through the the three main components that make up a Cadence application. Please take a look and feel free to give us your comments and feedback."]}),"\n",(0,o.jsx)(t.p,{children:"Thanks Chris for sharing your knowledge and helping others to get started."}),"\n",(0,o.jsx)(t.h2,{id:"cadence-go-client-v10-released",children:"Cadence Go Client v1.0 Released"}),"\n",(0,o.jsxs)(t.p,{children:["This month saw the release of ",(0,o.jsx)(t.a,{href:"https://github.com/cadence-workflow/cadence-go-client/releases/tag/v1.0.0",children:"v1.0 of the Cadence Go Client"}),". Note that the work done on this release was as a result of community feedback asking for it - so we are listening and responding to community needs."]}),"\n",(0,o.jsx)(t.p,{children:"Thanks very much to everyone who worked hard to get this release out!"}),"\n",(0,o.jsx)(t.h2,{id:"cadence-release-strategy",children:"Cadence Release Strategy"}),"\n",(0,o.jsxs)(t.p,{children:["A recent discussion on the Cadence Release strategy was posted in ",(0,o.jsx)(t.a,{href:"https://github.com/cadence-workflow/cadence/discussions/5362",children:"Cadence Github Discussions"})," (and also our #general channel on our ",(0,o.jsx)(t.a,{href:"http://t.uber.com/cadence-slack",children:"Slack"})," about the approach we'd like to take for future releases. As a community we want to ensure code stability and to not burden people with having to upgrade frequently."]}),"\n",(0,o.jsx)(t.p,{children:"Based on feedback from the community we will be introducing quarterly release cycles but also give people the ability to make use of patches and minor releases. We will be communicating the intention to make a release at least a month beforehand so that the community has time to finalise any features they want to be included in the upcoming release."}),"\n",(0,o.jsx)(t.p,{children:"For those of you wanting to keep up to date or try out new features in between releases, the core team at Uber will continue to make patch and minor version updates available to the community."}),"\n",(0,o.jsx)(t.p,{children:"As always we welcome your feedback so please feel free to add your thoughts and comments to the discussion."}),"\n",(0,o.jsx)(t.h2,{id:"cadence-helm-charts",children:"Cadence Helm Charts"}),"\n",(0,o.jsxs)(t.p,{children:["Community member ",(0,o.jsx)(t.a,{href:"https://www.linkedin.com/in/sagikazarmark/",children:"Mark Sagi-Kazar"})," has been maintaining the Banzai Cloud Cadence Helm Charts for the community. As the Helm Charts are a key tool for the community we are planning to take over the maintenance of them."]}),"\n",(0,o.jsx)(t.p,{children:"Our plan is to move the charts into the Cadence repository and to maintain an official and supported Kubernetes solution with Cadence."}),"\n",(0,o.jsx)(t.p,{children:"Huge thanks to Mark for all the work you have done and it's great to see the task being handed over and made into a community effort."}),"\n",(0,o.jsx)(t.h2,{id:"upcoming-events",children:"Upcoming Events"}),"\n",(0,o.jsxs)(t.ul,{children:["\n",(0,o.jsx)(t.li,{children:"None"}),"\n"]}),"\n",(0,o.jsxs)(t.p,{children:["If you have any news or topics you'd like us to include in our next update then please join our ",(0,o.jsx)(t.a,{href:"http://t.uber.com/cadence-slack",children:"Slack"})," #community channel."]}),"\n",(0,o.jsxs)(t.p,{children:["Please remember that this update is for you - so if you have any comments or feedback that could help us improve it then please share it with us in the #community ",(0,o.jsx)(t.a,{href:"http://t.uber.com/cadence-slack",children:"Slack"})," channel."]})]})}function d(e={}){const{wrapper:t}={...(0,s.R)(),...e.components};return t?(0,o.jsx)(t,{...e,children:(0,o.jsx)(h,{...e})}):h(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>i,x:()=>r});var a=n(6540);const o={},s=a.createContext(o);function i(e){const t=a.useContext(s);return a.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function r(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:i(e.components),a.createElement(s.Provider,{value:t},e.children)}},3468:e=>{e.exports=JSON.parse('{"permalink":"/Cadence-Docs/blog/2023/07/31/community-spotlight-july-2023","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2023-07-31-community-spotlight-july-2023.md","source":"@site/blog/2023-07-31-community-spotlight-july-2023.md","title":"Cadence Community Spotlight Update - July 2023","description":"Welcome to the latest of our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!","date":"2023-07-31T00:00:00.000Z","tags":[{"inline":false,"label":"Releases","permalink":"/Cadence-Docs/blog/tags/releases","description":"Releases tag description"},{"inline":false,"label":"Announcement","permalink":"/Cadence-Docs/blog/tags/announcements","description":"Announcement tag description"},{"inline":false,"label":"Community Spotlight","permalink":"/Cadence-Docs/blog/tags/community-spotlights","description":"Community Spotlight tag description"}],"readingTime":2.49,"hasTruncateMarker":true,"authors":[{"name":"Sharan Foga","title":"Director of Operations & Customer Success @ Encube Technologies","url":"https://www.linkedin.com/in/sfoga/","page":{"permalink":"/Cadence-Docs/blog/authors/sharanf"},"socials":{"linkedin":"https://www.linkedin.com/in/sfoga/","github":"https://github.com/sharanf"},"imageURL":"https://github.com/sharanf.png","key":"sharanf"}],"frontMatter":{"title":"Cadence Community Spotlight Update - July 2023","date":"2023-07-31T00:00:00.000Z","authors":"sharanf","tags":["release","announcement","community-spotlight"]},"unlisted":false,"prevItem":{"title":"Non-deterministic errors, replayers and shadowers","permalink":"/Cadence-Docs/blog/2023/08/28/nondeterministic-errors-replayers-shadowers"},"nextItem":{"title":"Write your first workflow with Cadence","permalink":"/Cadence-Docs/blog/2023/07/16/2023-07-16-write-your-first-workflow-with-cadence/write-your-first-workflow-with-cadence"}}')}}]); \ No newline at end of file diff --git a/assets/js/6601f8a9.9ea154cd.js b/assets/js/6601f8a9.9ea154cd.js new file mode 100644 index 000000000..581f973a7 --- /dev/null +++ b/assets/js/6601f8a9.9ea154cd.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[7998],{3276:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>s,contentTitle:()=>c,default:()=>h,frontMatter:()=>r,metadata:()=>o,toc:()=>a});const o=JSON.parse('{"id":"java-client/child-workflows","title":"Child workflows","description":"Besidesactivitiesworkflowworkflow.","source":"@site/docs/04-java-client/13-child-workflows.md","sourceDirName":"04-java-client","slug":"/java-client/child-workflows","permalink":"/Cadence-Docs/docs/java-client/child-workflows","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/04-java-client/13-child-workflows.md","tags":[],"version":"current","sidebarPosition":13,"frontMatter":{"layout":"default","title":"Child workflows","permalink":"/docs/java-client/child-workflows"},"sidebar":"docsSidebar","previous":{"title":"Retries","permalink":"/Cadence-Docs/docs/java-client/retries"},"next":{"title":"Exception Handling","permalink":"/Cadence-Docs/docs/java-client/exception-handling"}}');var i=t(4848),l=t(8453);const r={layout:"default",title:"Child workflows",permalink:"/docs/java-client/child-workflows"},c="Child workflows",s={},a=[];function d(e){const n={code:"code",h1:"h1",header:"header",p:"p",pre:"pre",...(0,l.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.header,{children:(0,i.jsx)(n.h1,{id:"child-workflows",children:"Child workflows"})}),"\n",(0,i.jsx)(n.p,{children:"Besides activities, a workflow can also orchestrate other workflows."}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.code,{children:"workflow.ExecuteChildWorkflow"})," enables the scheduling of other workflows from within a workflow's\nimplementation. The parent workflow has the ability to monitor and impact the lifecycle of the child\nworkflow, similar to the way it does for an activity that it invoked."]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",children:'public static class GreetingWorkflowImpl implements GreetingWorkflow {\n\n @Override\n public String getGreeting(String name) {\n // Workflows are stateful. So a new stub must be created for each new child.\n GreetingChild child = Workflow.newChildWorkflowStub(GreetingChild.class);\n\n // This is a non blocking call that returns immediately.\n // Use child.composeGreeting("Hello", name) to call synchronously.\n Promise greeting = Async.function(child::composeGreeting, "Hello", name);\n // Do something else here.\n return greeting.get(); // blocks waiting for the child to complete.\n }\n\n // This example shows how parent workflow return right after starting a child workflow,\n // and let the child run itself.\n private String demoAsyncChildRun(String name) {\n GreetingChild child = Workflow.newChildWorkflowStub(GreetingChild.class);\n // non blocking call that initiated child workflow\n Async.function(child::composeGreeting, "Hello", name);\n // instead of using greeting.get() to block till child complete,\n // sometimes we just want to return parent immediately and keep child running\n Promise childPromise = Workflow.getWorkflowExecution(child);\n childPromise.get(); // block until child started,\n // otherwise child may not start because parent complete first.\n return "let child run, parent just return";\n }\n}\n'})}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.code,{children:"Workflow.newChildWorkflowStub"})," returns a client-side stub that implements a child workflow interface.\nIt takes a child workflow type and optional child workflow options as arguments. Workflow options may be needed to override\nthe timeouts and task_list if they differ from the ones defined in the ",(0,i.jsx)(n.code,{children:"@WorkflowMethod"})," annotation or parent workflow."]}),"\n",(0,i.jsxs)(n.p,{children:["The first call to the child workflow stub must always be to a method annotated with ",(0,i.jsx)(n.code,{children:"@WorkflowMethod"}),". Similar to activities, a call\ncan be made synchronous or asynchronous by using ",(0,i.jsx)(n.code,{children:"Async#function"})," or ",(0,i.jsx)(n.code,{children:"Async#procedure"}),". The synchronous call blocks until a child workflow completes. The asynchronous call\nreturns a ",(0,i.jsx)(n.code,{children:"Promise"})," that can be used to wait for the completion. After an async call returns the stub, it can be used to send signals to the child\nby calling methods annotated with ",(0,i.jsx)(n.code,{children:"@SignalMethod"}),". Querying a child workflow by calling methods annotated with ",(0,i.jsx)(n.code,{children:"@QueryMethod"}),"\nfrom within workflow code is not supported. However, queries can be done from activities\nusing the provided ",(0,i.jsx)(n.code,{children:"WorkflowClient"})," stub."]}),"\n",(0,i.jsx)(n.p,{children:"Running two children in parallel:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",children:'public static class GreetingWorkflowImpl implements GreetingWorkflow {\n\n @Override\n public String getGreeting(String name) {\n\n // Workflows are stateful, so a new stub must be created for each new child.\n GreetingChild child1 = Workflow.newChildWorkflowStub(GreetingChild.class);\n Promise greeting1 = Async.function(child1::composeGreeting, "Hello", name);\n\n // Both children will run concurrently.\n GreetingChild child2 = Workflow.newChildWorkflowStub(GreetingChild.class);\n Promise greeting2 = Async.function(child2::composeGreeting, "Bye", name);\n\n // Do something else here.\n ...\n return "First: " + greeting1.get() + ", second: " + greeting2.get();\n }\n}\n'})}),"\n",(0,i.jsxs)(n.p,{children:["To send a signal to a child, call a method annotated with ",(0,i.jsx)(n.code,{children:"@SignalMethod"}),":"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",children:'public interface GreetingChild {\n @WorkflowMethod\n String composeGreeting(String greeting, String name);\n\n @SignalMethod\n void updateName(String name);\n}\n\npublic static class GreetingWorkflowImpl implements GreetingWorkflow {\n\n @Override\n public String getGreeting(String name) {\n GreetingChild child = Workflow.newChildWorkflowStub(GreetingChild.class);\n Promise greeting = Async.function(child::composeGreeting, "Hello", name);\n child.updateName("Cadence");\n return greeting.get();\n }\n}\n'})}),"\n",(0,i.jsxs)(n.p,{children:["Calling methods annotated with ",(0,i.jsx)(n.code,{children:"@QueryMethod"})," is not allowed from within workflow code."]})]})}function h(e={}){const{wrapper:n}={...(0,l.R)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(d,{...e})}):d(e)}},8453:(e,n,t)=>{t.d(n,{R:()=>r,x:()=>c});var o=t(6540);const i={},l=o.createContext(i);function r(e){const n=o.useContext(l);return o.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function c(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:r(e.components),o.createElement(l.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/6601f8a9.cf53fd6a.js b/assets/js/6601f8a9.cf53fd6a.js deleted file mode 100644 index d07a43981..000000000 --- a/assets/js/6601f8a9.cf53fd6a.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[7998],{3276:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>c,contentTitle:()=>s,default:()=>h,frontMatter:()=>r,metadata:()=>o,toc:()=>a});const o=JSON.parse('{"id":"java-client/child-workflows","title":"Child workflows","description":"Besidesactivitiesworkflowworkflow.","source":"@site/docs/04-java-client/13-child-workflows.md","sourceDirName":"04-java-client","slug":"/java-client/child-workflows","permalink":"/docs/java-client/child-workflows","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/04-java-client/13-child-workflows.md","tags":[],"version":"current","sidebarPosition":13,"frontMatter":{"layout":"default","title":"Child workflows","permalink":"/docs/java-client/child-workflows"},"sidebar":"docsSidebar","previous":{"title":"Retries","permalink":"/docs/java-client/retries"},"next":{"title":"Exception Handling","permalink":"/docs/java-client/exception-handling"}}');var i=t(4848),l=t(8453);const r={layout:"default",title:"Child workflows",permalink:"/docs/java-client/child-workflows"},s="Child workflows",c={},a=[];function d(e){const n={code:"code",h1:"h1",header:"header",p:"p",pre:"pre",...(0,l.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.header,{children:(0,i.jsx)(n.h1,{id:"child-workflows",children:"Child workflows"})}),"\n",(0,i.jsx)(n.p,{children:"Besides activities, a workflow can also orchestrate other workflows."}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.code,{children:"workflow.ExecuteChildWorkflow"})," enables the scheduling of other workflows from within a workflow's\nimplementation. The parent workflow has the ability to monitor and impact the lifecycle of the child\nworkflow, similar to the way it does for an activity that it invoked."]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",children:'public static class GreetingWorkflowImpl implements GreetingWorkflow {\n\n @Override\n public String getGreeting(String name) {\n // Workflows are stateful. So a new stub must be created for each new child.\n GreetingChild child = Workflow.newChildWorkflowStub(GreetingChild.class);\n\n // This is a non blocking call that returns immediately.\n // Use child.composeGreeting("Hello", name) to call synchronously.\n Promise greeting = Async.function(child::composeGreeting, "Hello", name);\n // Do something else here.\n return greeting.get(); // blocks waiting for the child to complete.\n }\n\n // This example shows how parent workflow return right after starting a child workflow,\n // and let the child run itself.\n private String demoAsyncChildRun(String name) {\n GreetingChild child = Workflow.newChildWorkflowStub(GreetingChild.class);\n // non blocking call that initiated child workflow\n Async.function(child::composeGreeting, "Hello", name);\n // instead of using greeting.get() to block till child complete,\n // sometimes we just want to return parent immediately and keep child running\n Promise childPromise = Workflow.getWorkflowExecution(child);\n childPromise.get(); // block until child started,\n // otherwise child may not start because parent complete first.\n return "let child run, parent just return";\n }\n}\n'})}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.code,{children:"Workflow.newChildWorkflowStub"})," returns a client-side stub that implements a child workflow interface.\nIt takes a child workflow type and optional child workflow options as arguments. Workflow options may be needed to override\nthe timeouts and task_list if they differ from the ones defined in the ",(0,i.jsx)(n.code,{children:"@WorkflowMethod"})," annotation or parent workflow."]}),"\n",(0,i.jsxs)(n.p,{children:["The first call to the child workflow stub must always be to a method annotated with ",(0,i.jsx)(n.code,{children:"@WorkflowMethod"}),". Similar to activities, a call\ncan be made synchronous or asynchronous by using ",(0,i.jsx)(n.code,{children:"Async#function"})," or ",(0,i.jsx)(n.code,{children:"Async#procedure"}),". The synchronous call blocks until a child workflow completes. The asynchronous call\nreturns a ",(0,i.jsx)(n.code,{children:"Promise"})," that can be used to wait for the completion. After an async call returns the stub, it can be used to send signals to the child\nby calling methods annotated with ",(0,i.jsx)(n.code,{children:"@SignalMethod"}),". Querying a child workflow by calling methods annotated with ",(0,i.jsx)(n.code,{children:"@QueryMethod"}),"\nfrom within workflow code is not supported. However, queries can be done from activities\nusing the provided ",(0,i.jsx)(n.code,{children:"WorkflowClient"})," stub."]}),"\n",(0,i.jsx)(n.p,{children:"Running two children in parallel:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",children:'public static class GreetingWorkflowImpl implements GreetingWorkflow {\n\n @Override\n public String getGreeting(String name) {\n\n // Workflows are stateful, so a new stub must be created for each new child.\n GreetingChild child1 = Workflow.newChildWorkflowStub(GreetingChild.class);\n Promise greeting1 = Async.function(child1::composeGreeting, "Hello", name);\n\n // Both children will run concurrently.\n GreetingChild child2 = Workflow.newChildWorkflowStub(GreetingChild.class);\n Promise greeting2 = Async.function(child2::composeGreeting, "Bye", name);\n\n // Do something else here.\n ...\n return "First: " + greeting1.get() + ", second: " + greeting2.get();\n }\n}\n'})}),"\n",(0,i.jsxs)(n.p,{children:["To send a signal to a child, call a method annotated with ",(0,i.jsx)(n.code,{children:"@SignalMethod"}),":"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",children:'public interface GreetingChild {\n @WorkflowMethod\n String composeGreeting(String greeting, String name);\n\n @SignalMethod\n void updateName(String name);\n}\n\npublic static class GreetingWorkflowImpl implements GreetingWorkflow {\n\n @Override\n public String getGreeting(String name) {\n GreetingChild child = Workflow.newChildWorkflowStub(GreetingChild.class);\n Promise greeting = Async.function(child::composeGreeting, "Hello", name);\n child.updateName("Cadence");\n return greeting.get();\n }\n}\n'})}),"\n",(0,i.jsxs)(n.p,{children:["Calling methods annotated with ",(0,i.jsx)(n.code,{children:"@QueryMethod"})," is not allowed from within workflow code."]})]})}function h(e={}){const{wrapper:n}={...(0,l.R)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(d,{...e})}):d(e)}},8453:(e,n,t)=>{t.d(n,{R:()=>r,x:()=>s});var o=t(6540);const i={},l=o.createContext(i);function r(e){const n=o.useContext(l);return o.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function s(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:r(e.components),o.createElement(l.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/667be76f.d1cad4dd.js b/assets/js/667be76f.d1cad4dd.js deleted file mode 100644 index c6fad1c4e..000000000 --- a/assets/js/667be76f.d1cad4dd.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[4120],{1515:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>s,contentTitle:()=>r,default:()=>p,frontMatter:()=>c,metadata:()=>o,toc:()=>l});var o=t(9871),i=t(4848),a=t(8453);const c={title:"Understanding components of Cadence application",date:new Date("2023-07-01T00:00:00.000Z"),authors:"chopincode",tags:["deep-dive","introduction-to-cadence"]},r=void 0,s={authorsImageUrls:[void 0]},l=[];function d(e){const n={li:"li",ol:"ol",p:"p",...(0,a.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.p,{children:"Cadence is a powerful, scalable, and fault-tolerant workflow orchestration framework that helps developers implement and manage complex workflow tasks. In most cases, developers contribute activities and workflows directly to their codebases, and they may not have a full understanding of the components behind a running Cadence application. We receive numerous inquiries about setting up Cadence in a local environment from scratch for testing. Therefore, in this article, we will explore the components that power a Cadence cluster."}),"\n",(0,i.jsx)(n.p,{children:"There are three critical components that are essential for any Cadence application:"}),"\n",(0,i.jsxs)(n.ol,{children:["\n",(0,i.jsx)(n.li,{children:"A running Cadence backend server."}),"\n",(0,i.jsx)(n.li,{children:"A registered Cadence domain."}),"\n",(0,i.jsx)(n.li,{children:"A running Cadence worker that registers all workflows and activities."}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Let's go over these components in more details."})]})}function p(e={}){const{wrapper:n}={...(0,a.R)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(d,{...e})}):d(e)}},8453:(e,n,t)=>{t.d(n,{R:()=>c,x:()=>r});var o=t(6540);const i={},a=o.createContext(i);function c(e){const n=o.useContext(a);return o.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function r(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:c(e.components),o.createElement(a.Provider,{value:n},e.children)}},9871:e=>{e.exports=JSON.parse('{"permalink":"/blog/2023/06/28/components-of-cadence-application-setup","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2023-06-28-components-of-cadence-application-setup.md","source":"@site/blog/2023-06-28-components-of-cadence-application-setup.md","title":"Understanding components of Cadence application","description":"Cadence is a powerful, scalable, and fault-tolerant workflow orchestration framework that helps developers implement and manage complex workflow tasks. In most cases, developers contribute activities and workflows directly to their codebases, and they may not have a full understanding of the components behind a running Cadence application. We receive numerous inquiries about setting up Cadence in a local environment from scratch for testing. Therefore, in this article, we will explore the components that power a Cadence cluster.","date":"2023-07-01T00:00:00.000Z","tags":[{"inline":false,"label":"Deep Dives","permalink":"/blog/tags/deep-dives","description":"Deep Dives tag description"},{"inline":false,"label":"Introduction to Cadence","permalink":"/blog/tags/introduction-to-cadence","description":"Introduction to Cadence tag description"}],"readingTime":1.615,"hasTruncateMarker":true,"authors":[{"name":"Chris Qin","title":"Applications Developer @ Uber","url":"https://www.linkedin.com/in/chrisqin0610/","page":{"permalink":"/blog/authors/chopincode"},"socials":{"linkedin":"https://www.linkedin.com/in/chrisqin0610/","github":"https://github.com/chopincode"},"imageURL":"https://github.com/chopincode.png","key":"chopincode"}],"frontMatter":{"title":"Understanding components of Cadence application","date":"2023-07-01T00:00:00.000Z","authors":"chopincode","tags":["deep-dive","introduction-to-cadence"]},"unlisted":false,"prevItem":{"title":"Implement a Cadence worker service from scratch","permalink":"/blog/2023/07/05/implement-cadence-worker-from-scratch"},"nextItem":{"title":"Cadence Community Spotlight Update - June 2023","permalink":"/blog/2023/06/30/community-spotlight-june-2023"}}')}}]); \ No newline at end of file diff --git a/assets/js/667be76f.d8e51ae2.js b/assets/js/667be76f.d8e51ae2.js new file mode 100644 index 000000000..dc5e03d76 --- /dev/null +++ b/assets/js/667be76f.d8e51ae2.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[4120],{1515:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>s,contentTitle:()=>r,default:()=>p,frontMatter:()=>c,metadata:()=>o,toc:()=>l});var o=t(9871),a=t(4848),i=t(8453);const c={title:"Understanding components of Cadence application",date:new Date("2023-07-01T00:00:00.000Z"),authors:"chopincode",tags:["deep-dive","introduction-to-cadence"]},r=void 0,s={authorsImageUrls:[void 0]},l=[];function d(e){const n={li:"li",ol:"ol",p:"p",...(0,i.R)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(n.p,{children:"Cadence is a powerful, scalable, and fault-tolerant workflow orchestration framework that helps developers implement and manage complex workflow tasks. In most cases, developers contribute activities and workflows directly to their codebases, and they may not have a full understanding of the components behind a running Cadence application. We receive numerous inquiries about setting up Cadence in a local environment from scratch for testing. Therefore, in this article, we will explore the components that power a Cadence cluster."}),"\n",(0,a.jsx)(n.p,{children:"There are three critical components that are essential for any Cadence application:"}),"\n",(0,a.jsxs)(n.ol,{children:["\n",(0,a.jsx)(n.li,{children:"A running Cadence backend server."}),"\n",(0,a.jsx)(n.li,{children:"A registered Cadence domain."}),"\n",(0,a.jsx)(n.li,{children:"A running Cadence worker that registers all workflows and activities."}),"\n"]}),"\n",(0,a.jsx)(n.p,{children:"Let's go over these components in more details."})]})}function p(e={}){const{wrapper:n}={...(0,i.R)(),...e.components};return n?(0,a.jsx)(n,{...e,children:(0,a.jsx)(d,{...e})}):d(e)}},8453:(e,n,t)=>{t.d(n,{R:()=>c,x:()=>r});var o=t(6540);const a={},i=o.createContext(a);function c(e){const n=o.useContext(i);return o.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function r(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:c(e.components),o.createElement(i.Provider,{value:n},e.children)}},9871:e=>{e.exports=JSON.parse('{"permalink":"/Cadence-Docs/blog/2023/06/28/components-of-cadence-application-setup","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2023-06-28-components-of-cadence-application-setup.md","source":"@site/blog/2023-06-28-components-of-cadence-application-setup.md","title":"Understanding components of Cadence application","description":"Cadence is a powerful, scalable, and fault-tolerant workflow orchestration framework that helps developers implement and manage complex workflow tasks. In most cases, developers contribute activities and workflows directly to their codebases, and they may not have a full understanding of the components behind a running Cadence application. We receive numerous inquiries about setting up Cadence in a local environment from scratch for testing. Therefore, in this article, we will explore the components that power a Cadence cluster.","date":"2023-07-01T00:00:00.000Z","tags":[{"inline":false,"label":"Deep Dives","permalink":"/Cadence-Docs/blog/tags/deep-dives","description":"Deep Dives tag description"},{"inline":false,"label":"Introduction to Cadence","permalink":"/Cadence-Docs/blog/tags/introduction-to-cadence","description":"Introduction to Cadence tag description"}],"readingTime":1.615,"hasTruncateMarker":true,"authors":[{"name":"Chris Qin","title":"Applications Developer @ Uber","url":"https://www.linkedin.com/in/chrisqin0610/","page":{"permalink":"/Cadence-Docs/blog/authors/chopincode"},"socials":{"linkedin":"https://www.linkedin.com/in/chrisqin0610/","github":"https://github.com/chopincode"},"imageURL":"https://github.com/chopincode.png","key":"chopincode"}],"frontMatter":{"title":"Understanding components of Cadence application","date":"2023-07-01T00:00:00.000Z","authors":"chopincode","tags":["deep-dive","introduction-to-cadence"]},"unlisted":false,"prevItem":{"title":"Implement a Cadence worker service from scratch","permalink":"/Cadence-Docs/blog/2023/07/05/implement-cadence-worker-from-scratch"},"nextItem":{"title":"Cadence Community Spotlight Update - June 2023","permalink":"/Cadence-Docs/blog/2023/06/30/community-spotlight-june-2023"}}')}}]); \ No newline at end of file diff --git a/assets/js/67affde7.a4a51df2.js b/assets/js/67affde7.a4a51df2.js new file mode 100644 index 000000000..71307ce35 --- /dev/null +++ b/assets/js/67affde7.a4a51df2.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[9609],{5519:(e,t,i)=>{i.r(t),i.d(t,{assets:()=>a,contentTitle:()=>l,default:()=>h,frontMatter:()=>s,metadata:()=>n,toc:()=>c});const n=JSON.parse('{"id":"java-client/retries","title":"Retries","description":"Activitiesworkflow can fail due to various intermediate conditions. In those cases, we want","source":"@site/docs/04-java-client/12-retries.md","sourceDirName":"04-java-client","slug":"/java-client/retries","permalink":"/Cadence-Docs/docs/java-client/retries","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/04-java-client/12-retries.md","tags":[],"version":"current","sidebarPosition":12,"frontMatter":{"layout":"default","title":"Retries","permalink":"/docs/java-client/retries"},"sidebar":"docsSidebar","previous":{"title":"Queries","permalink":"/Cadence-Docs/docs/java-client/queries"},"next":{"title":"Child workflows","permalink":"/Cadence-Docs/docs/java-client/child-workflows"}}');var o=i(4848),r=i(8453);const s={layout:"default",title:"Retries",permalink:"/docs/java-client/retries"},l="Activity and workflow retries",a={},c=[{value:"RetryOptions",id:"retryoptions",level:2},{value:"InitialInterval",id:"initialinterval",level:3},{value:"BackoffCoefficient",id:"backoffcoefficient",level:3},{value:"MaximumInterval",id:"maximuminterval",level:3},{value:"ExpirationInterval",id:"expirationinterval",level:3},{value:"MaximumAttempts",id:"maximumattempts",level:3},{value:"NonRetriableErrorReasons(via setDoNotRetry)",id:"nonretriableerrorreasonsvia-setdonotretry",level:3},{value:"Activity Timeout Usage",id:"activity-timeout-usage",level:2},{value:"Activity Timeout Internals",id:"activity-timeout-internals",level:2},{value:"Basics without Retry",id:"basics-without-retry",level:3},{value:"Heartbeat timeout",id:"heartbeat-timeout",level:3},{value:"RetryOptions and Activity with Retry",id:"retryoptions-and-activity-with-retry",level:3}];function d(e){const t={a:"a",blockquote:"blockquote",code:"code",h1:"h1",h2:"h2",h3:"h3",header:"header",li:"li",ol:"ol",p:"p",strong:"strong",ul:"ul",...(0,r.R)(),...e.components};return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsx)(t.header,{children:(0,o.jsx)(t.h1,{id:"activity-and-workflow-retries",children:"Activity and workflow retries"})}),"\n",(0,o.jsxs)(t.p,{children:["Activities and workflows can fail due to various intermediate conditions. In those cases, we want\nto retry the failed activity or child workflow or even the parent workflow. This can be achieved\nby supplying an optional ",(0,o.jsx)(t.a,{href:"https://www.javadoc.io/static/com.uber.cadence/cadence-client/2.7.9-alpha/com/cadence-workflow/cadence/common/RetryOptions.Builder.html#setInitialInterval-java.time.Duration-",children:"retry options"}),"."]}),"\n",(0,o.jsxs)(t.blockquote,{children:["\n",(0,o.jsx)(t.p,{children:"Note that sometimes it's also referred as RetryPolicy"}),"\n"]}),"\n",(0,o.jsx)(t.h2,{id:"retryoptions",children:"RetryOptions"}),"\n",(0,o.jsx)(t.p,{children:"A RetryOptions includes the following."}),"\n",(0,o.jsx)(t.h3,{id:"initialinterval",children:"InitialInterval"}),"\n",(0,o.jsx)(t.p,{children:"Backoff interval for the first retry. If coefficient is 1.0 then it is used for all retries.\nRequired, no default value."}),"\n",(0,o.jsx)(t.h3,{id:"backoffcoefficient",children:"BackoffCoefficient"}),"\n",(0,o.jsx)(t.p,{children:"Coefficient used to calculate the next retry backoff interval.\nThe next retry interval is previous interval multiplied by this coefficient.\nMust be 1 or larger. Default is 2.0."}),"\n",(0,o.jsx)(t.h3,{id:"maximuminterval",children:"MaximumInterval"}),"\n",(0,o.jsx)(t.p,{children:"Maximum backoff interval between retries. Exponential backoff leads to interval increase.\nThis value is the cap of the interval. Default is 100x of initial interval."}),"\n",(0,o.jsx)(t.h3,{id:"expirationinterval",children:"ExpirationInterval"}),"\n",(0,o.jsx)(t.p,{children:"Maximum time to retry. Either ExpirationInterval or MaximumAttempts is required.\nWhen exceeded the retries stop even if maximum retries is not reached yet.\nFirst (non-retry) attempt is unaffected by this field and is guaranteed to run\nfor the entirety of the workflow timeout duration (ExecutionStartToCloseTimeoutSeconds)."}),"\n",(0,o.jsx)(t.h3,{id:"maximumattempts",children:"MaximumAttempts"}),"\n",(0,o.jsx)(t.p,{children:"Maximum number of attempts. When exceeded the retries stop even if not expired yet.\nIf not set or set to 0, it means unlimited, and relies on ExpirationInterval to stop.\nEither MaximumAttempts or ExpirationInterval is required."}),"\n",(0,o.jsx)(t.h3,{id:"nonretriableerrorreasonsvia-setdonotretry",children:"NonRetriableErrorReasons(via setDoNotRetry)"}),"\n",(0,o.jsx)(t.p,{children:"Non-Retriable errors. This is optional. Cadence server will stop retry if error reason matches this list.\nWhen matching an exact match is used. So adding RuntimeException.class to this list is going to include only RuntimeException itself, not all of its subclasses. The reason for such behaviour is to be able to support server side retries without knowledge of Java exception hierarchy. When considering an exception type a cause of ActivityFailureException and ChildWorkflowFailureException is looked at.\nError and CancellationException are never retried and are not even passed to this filter."}),"\n",(0,o.jsx)(t.h2,{id:"activity-timeout-usage",children:"Activity Timeout Usage"}),"\n",(0,o.jsx)(t.p,{children:"It's probably too complicated to learn how to set those timeouts by reading the above. There is an easy way to deal with it."}),"\n",(0,o.jsxs)(t.p,{children:[(0,o.jsx)(t.strong,{children:"LocalActivity without retry"}),": Use ScheduleToClose for overall timeout"]}),"\n",(0,o.jsxs)(t.p,{children:[(0,o.jsx)(t.strong,{children:"Regular Activity without retry"}),":"]}),"\n",(0,o.jsxs)(t.ol,{children:["\n",(0,o.jsx)(t.li,{children:"Use ScheduleToClose for overall timeout"}),"\n",(0,o.jsx)(t.li,{children:"Leave ScheduleToStart and StartToClose empty"}),"\n",(0,o.jsx)(t.li,{children:"If ScheduleToClose is too large(like 10 mins), then set Heartbeat timeout to a smaller value like 10s. Call heartbeat API inside activity regularly."}),"\n"]}),"\n",(0,o.jsxs)(t.p,{children:[(0,o.jsx)(t.strong,{children:"LocalActivity with retry"}),":"]}),"\n",(0,o.jsxs)(t.ol,{children:["\n",(0,o.jsx)(t.li,{children:"Use ScheduleToClose as timeout of each attempt."}),"\n",(0,o.jsx)(t.li,{children:"Use retryOptions.InitialInterval, retryOptions.BackoffCoefficient, retryOptions.MaximumInterval to control backoff."}),"\n",(0,o.jsx)(t.li,{children:"Use retryOptions.ExperiationInterval as overall timeout of all attempts."}),"\n",(0,o.jsx)(t.li,{children:"Leave retryOptions.MaximumAttempts empty."}),"\n"]}),"\n",(0,o.jsxs)(t.p,{children:[(0,o.jsx)(t.strong,{children:"Regular Activity with retry"}),":"]}),"\n",(0,o.jsxs)(t.ol,{children:["\n",(0,o.jsx)(t.li,{children:"Use ScheduleToClose as timeout of each attempt"}),"\n",(0,o.jsx)(t.li,{children:"Leave ScheduleToStart and StartToClose empty"}),"\n",(0,o.jsx)(t.li,{children:"If ScheduleToClose is too large(like 10 mins), then set Heartbeat timeout to a smaller value like 10s. Call heartbeat API inside activity regularly."}),"\n",(0,o.jsx)(t.li,{children:"Use retryOptions.InitialInterval, retryOptions.BackoffCoefficient, retryOptions.MaximumInterval to control backoff."}),"\n",(0,o.jsx)(t.li,{children:"Use retryOptions.ExperiationInterval as overall timeout of all attempts."}),"\n",(0,o.jsx)(t.li,{children:"Leave retryOptions.MaximumAttempts empty."}),"\n"]}),"\n",(0,o.jsx)(t.h2,{id:"activity-timeout-internals",children:"Activity Timeout Internals"}),"\n",(0,o.jsx)(t.h3,{id:"basics-without-retry",children:"Basics without Retry"}),"\n",(0,o.jsx)(t.p,{children:"Things are easier to understand in the world without retry. Because Cadence started from it."}),"\n",(0,o.jsxs)(t.ul,{children:["\n",(0,o.jsxs)(t.li,{children:["\n",(0,o.jsx)(t.p,{children:"ScheduleToClose timeout is the overall end-to-end timeout from a workflow's perspective."}),"\n"]}),"\n",(0,o.jsxs)(t.li,{children:["\n",(0,o.jsx)(t.p,{children:"ScheduleToStart timeout is the time that activity worker needed to start an activity. Exceeding this timeout, activity will return an ScheduleToStart timeout error/exception to workflow"}),"\n"]}),"\n",(0,o.jsxs)(t.li,{children:["\n",(0,o.jsx)(t.p,{children:"StartToClose timeout is the time that an activity needed to run. Exceeding this will return\nStartToClose to workflow."}),"\n"]}),"\n",(0,o.jsxs)(t.li,{children:["\n",(0,o.jsx)(t.p,{children:(0,o.jsx)(t.strong,{children:"Requirement and defaults:"})}),"\n",(0,o.jsxs)(t.ul,{children:["\n",(0,o.jsx)(t.li,{children:"Either ScheduleToClose is provided or both of ScheduleToStart and StartToClose are provided."}),"\n",(0,o.jsx)(t.li,{children:"If only ScheduleToClose, then ScheduleToStart and StartToClose are default to it."}),"\n",(0,o.jsxs)(t.li,{children:["If only ScheduleToStart and StartToClose are provided, then ",(0,o.jsx)(t.code,{children:"ScheduleToClose = ScheduleToStart + StartToClose"}),"."]}),"\n",(0,o.jsxs)(t.li,{children:["All of them are capped by workflowTimeout. (e.g. if workflowTimeout is 1hour, set 2 hour for ScheduleToClose will still get 1 hour :",(0,o.jsx)(t.code,{children:"ScheduleToClose=Min(ScheduleToClose, workflowTimeout)"})," )"]}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,o.jsx)(t.p,{children:(0,o.jsx)(t.strong,{children:"So why are they?"})}),"\n",(0,o.jsxs)(t.p,{children:["You may notice that ScheduleToClose is only useful when\n",(0,o.jsx)(t.code,{children:"ScheduleToClose < ScheduleToStart + StartToClose"}),". Because if ",(0,o.jsx)(t.code,{children:"ScheduleToClose >= ScheduleToStart+StartToClose"})," the ScheduleToClose timeout is already enforced by the combination of the other two, and it become meaningless."]}),"\n",(0,o.jsxs)(t.p,{children:["So the main use case of ScheduleToClose being less than the sum of two is that people want to limit the overall timeout of the activity but give more timeout for scheduleToStart or startToClose. ",(0,o.jsx)(t.strong,{children:"This is extremely rare use case"}),"."]}),"\n",(0,o.jsxs)(t.p,{children:["Also the main use case that people want to distinguish ScheduleToStart and StartToClose is that the workflow may need to do some special handling for ScheduleToStart timeout error. ",(0,o.jsx)(t.strong,{children:"This is also very rare use case"}),"."]}),"\n",(0,o.jsxs)(t.p,{children:["Therefore, you can understand why in TL;DR that I recommend only using ",(0,o.jsx)(t.strong,{children:"ScheduleToClose"})," but leave the other two empty. Because only in some rare cases you may need it. If you can't think of the use case, then you do not need it."]}),"\n",(0,o.jsx)(t.p,{children:"LocalActivity doesn't have ScheduleToStart/StartToClose because it's started directly inside workflow worker without server scheduling involved."}),"\n",(0,o.jsx)(t.h3,{id:"heartbeat-timeout",children:"Heartbeat timeout"}),"\n",(0,o.jsxs)(t.p,{children:["Heartbeat is very important for long running activity, to prevent it from getting stuck. Not only bugs can cause activity getting stuck, regular deployment/host restart/failure could also cause it. Because without heartbeat, Cadence server couldn't know whether or not the activity is still being worked on. See more details about here ",(0,o.jsx)(t.a,{href:"https://stackoverflow.com/questions/65118584/solutions-to-stuck-timers-activities-in-cadence-swf-stepfunctions/65118585#65118585",children:"https://stackoverflow.com/questions/65118584/solutions-to-stuck-timers-activities-in-cadence-swf-stepfunctions/65118585#65118585"})]}),"\n",(0,o.jsx)(t.h3,{id:"retryoptions-and-activity-with-retry",children:"RetryOptions and Activity with Retry"}),"\n",(0,o.jsxs)(t.p,{children:["First of all, here RetryOptions is for ",(0,o.jsx)(t.code,{children:"server side"})," backoff retry -- meaning that the retry is managed automatically by Cadence without interacting with workflows. Because retry is managed by Cadence, the activity has to be specially handled in Cadence history that the started event can not written until the activity is closed. Here is some reference: ",(0,o.jsx)(t.a,{href:"https://stackoverflow.com/questions/65113363/why-an-activity-task-is-scheduled-but-not-started/65113365#65113365",children:"https://stackoverflow.com/questions/65113363/why-an-activity-task-is-scheduled-but-not-started/65113365#65113365"})]}),"\n",(0,o.jsxs)(t.p,{children:["In fact, workflow can do ",(0,o.jsx)(t.code,{children:"client side"})," retry on their own. This means workflow will be managing the retry logic. You can write your own retry function, or there is some helper function in SDK, like ",(0,o.jsx)(t.code,{children:"Workflow.retry"})," in Cadence-java-client. Client side retry will show all start events immediately, but there will be many events in the history when retrying for a single activity. It's not recommended because of performance issue."]}),"\n",(0,o.jsx)(t.p,{children:"So what do the options mean:"}),"\n",(0,o.jsxs)(t.ul,{children:["\n",(0,o.jsxs)(t.li,{children:["\n",(0,o.jsx)(t.p,{children:"ExpirationInterval:"}),"\n",(0,o.jsxs)(t.ul,{children:["\n",(0,o.jsx)(t.li,{children:"It replaces the ScheduleToClose timeout to become the actual overall timeout of the activity for all attempts."}),"\n",(0,o.jsxs)(t.li,{children:["It's also capped to workflow timeout like other three timeout options. ",(0,o.jsx)(t.code,{children:"ScheduleToClose = Min(ScheduleToClose, workflowTimeout)"})]}),"\n",(0,o.jsx)(t.li,{children:"The timeout of each attempt is StartToClose, but StartToClose defaults to ScheduleToClose like explanation above."}),"\n",(0,o.jsxs)(t.li,{children:["ScheduleToClose will be extended to ExpirationInterval:\n",(0,o.jsx)(t.code,{children:"ScheduleToClose = Max(ScheduleToClose, ExpirationInterval)"}),", and this happens before ScheduleToClose is copied to ScheduleToClose and StartToClose."]}),"\n"]}),"\n"]}),"\n",(0,o.jsxs)(t.li,{children:["\n",(0,o.jsx)(t.p,{children:"InitialInterval: the interval of first retry"}),"\n"]}),"\n",(0,o.jsxs)(t.li,{children:["\n",(0,o.jsx)(t.p,{children:"BackoffCoefficient: self explained"}),"\n"]}),"\n",(0,o.jsxs)(t.li,{children:["\n",(0,o.jsx)(t.p,{children:"MaximumInterval: maximum of the interval during retry"}),"\n"]}),"\n",(0,o.jsxs)(t.li,{children:["\n",(0,o.jsx)(t.p,{children:"MaximumAttempts: the maximum attempts. If existing with ExpirationInterval, then retry stops when either one of them is exceeded."}),"\n"]}),"\n",(0,o.jsxs)(t.li,{children:["\n",(0,o.jsxs)(t.p,{children:[(0,o.jsx)(t.strong,{children:"Requirements and defaults"}),":"]}),"\n"]}),"\n",(0,o.jsxs)(t.li,{children:["\n",(0,o.jsx)(t.p,{children:"Either MaximumAttempts or ExpirationInterval is required. ExpirationInterval is set to workflowTimeout if not provided."}),"\n"]}),"\n"]}),"\n",(0,o.jsx)(t.p,{children:"Since ExpirationInterval is always there, and in fact it's more useful. And I think it's quite confusing to use MaximumAttempts, so I would recommend just use ExpirationInterval. Unless you really need it."})]})}function h(e={}){const{wrapper:t}={...(0,r.R)(),...e.components};return t?(0,o.jsx)(t,{...e,children:(0,o.jsx)(d,{...e})}):d(e)}},8453:(e,t,i)=>{i.d(t,{R:()=>s,x:()=>l});var n=i(6540);const o={},r=n.createContext(o);function s(e){const t=n.useContext(r);return n.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function l(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:s(e.components),n.createElement(r.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/67affde7.ca974799.js b/assets/js/67affde7.ca974799.js deleted file mode 100644 index d00d19e28..000000000 --- a/assets/js/67affde7.ca974799.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[9609],{5519:(e,t,i)=>{i.r(t),i.d(t,{assets:()=>a,contentTitle:()=>l,default:()=>h,frontMatter:()=>s,metadata:()=>n,toc:()=>c});const n=JSON.parse('{"id":"java-client/retries","title":"Retries","description":"Activitiesworkflow can fail due to various intermediate conditions. In those cases, we want","source":"@site/docs/04-java-client/12-retries.md","sourceDirName":"04-java-client","slug":"/java-client/retries","permalink":"/docs/java-client/retries","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/04-java-client/12-retries.md","tags":[],"version":"current","sidebarPosition":12,"frontMatter":{"layout":"default","title":"Retries","permalink":"/docs/java-client/retries"},"sidebar":"docsSidebar","previous":{"title":"Queries","permalink":"/docs/java-client/queries"},"next":{"title":"Child workflows","permalink":"/docs/java-client/child-workflows"}}');var o=i(4848),r=i(8453);const s={layout:"default",title:"Retries",permalink:"/docs/java-client/retries"},l="Activity and workflow retries",a={},c=[{value:"RetryOptions",id:"retryoptions",level:2},{value:"InitialInterval",id:"initialinterval",level:3},{value:"BackoffCoefficient",id:"backoffcoefficient",level:3},{value:"MaximumInterval",id:"maximuminterval",level:3},{value:"ExpirationInterval",id:"expirationinterval",level:3},{value:"MaximumAttempts",id:"maximumattempts",level:3},{value:"NonRetriableErrorReasons(via setDoNotRetry)",id:"nonretriableerrorreasonsvia-setdonotretry",level:3},{value:"Activity Timeout Usage",id:"activity-timeout-usage",level:2},{value:"Activity Timeout Internals",id:"activity-timeout-internals",level:2},{value:"Basics without Retry",id:"basics-without-retry",level:3},{value:"Heartbeat timeout",id:"heartbeat-timeout",level:3},{value:"RetryOptions and Activity with Retry",id:"retryoptions-and-activity-with-retry",level:3}];function d(e){const t={a:"a",blockquote:"blockquote",code:"code",h1:"h1",h2:"h2",h3:"h3",header:"header",li:"li",ol:"ol",p:"p",strong:"strong",ul:"ul",...(0,r.R)(),...e.components};return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsx)(t.header,{children:(0,o.jsx)(t.h1,{id:"activity-and-workflow-retries",children:"Activity and workflow retries"})}),"\n",(0,o.jsxs)(t.p,{children:["Activities and workflows can fail due to various intermediate conditions. In those cases, we want\nto retry the failed activity or child workflow or even the parent workflow. This can be achieved\nby supplying an optional ",(0,o.jsx)(t.a,{href:"https://www.javadoc.io/static/com.uber.cadence/cadence-client/2.7.9-alpha/com/cadence-workflow/cadence/common/RetryOptions.Builder.html#setInitialInterval-java.time.Duration-",children:"retry options"}),"."]}),"\n",(0,o.jsxs)(t.blockquote,{children:["\n",(0,o.jsx)(t.p,{children:"Note that sometimes it's also referred as RetryPolicy"}),"\n"]}),"\n",(0,o.jsx)(t.h2,{id:"retryoptions",children:"RetryOptions"}),"\n",(0,o.jsx)(t.p,{children:"A RetryOptions includes the following."}),"\n",(0,o.jsx)(t.h3,{id:"initialinterval",children:"InitialInterval"}),"\n",(0,o.jsx)(t.p,{children:"Backoff interval for the first retry. If coefficient is 1.0 then it is used for all retries.\nRequired, no default value."}),"\n",(0,o.jsx)(t.h3,{id:"backoffcoefficient",children:"BackoffCoefficient"}),"\n",(0,o.jsx)(t.p,{children:"Coefficient used to calculate the next retry backoff interval.\nThe next retry interval is previous interval multiplied by this coefficient.\nMust be 1 or larger. Default is 2.0."}),"\n",(0,o.jsx)(t.h3,{id:"maximuminterval",children:"MaximumInterval"}),"\n",(0,o.jsx)(t.p,{children:"Maximum backoff interval between retries. Exponential backoff leads to interval increase.\nThis value is the cap of the interval. Default is 100x of initial interval."}),"\n",(0,o.jsx)(t.h3,{id:"expirationinterval",children:"ExpirationInterval"}),"\n",(0,o.jsx)(t.p,{children:"Maximum time to retry. Either ExpirationInterval or MaximumAttempts is required.\nWhen exceeded the retries stop even if maximum retries is not reached yet.\nFirst (non-retry) attempt is unaffected by this field and is guaranteed to run\nfor the entirety of the workflow timeout duration (ExecutionStartToCloseTimeoutSeconds)."}),"\n",(0,o.jsx)(t.h3,{id:"maximumattempts",children:"MaximumAttempts"}),"\n",(0,o.jsx)(t.p,{children:"Maximum number of attempts. When exceeded the retries stop even if not expired yet.\nIf not set or set to 0, it means unlimited, and relies on ExpirationInterval to stop.\nEither MaximumAttempts or ExpirationInterval is required."}),"\n",(0,o.jsx)(t.h3,{id:"nonretriableerrorreasonsvia-setdonotretry",children:"NonRetriableErrorReasons(via setDoNotRetry)"}),"\n",(0,o.jsx)(t.p,{children:"Non-Retriable errors. This is optional. Cadence server will stop retry if error reason matches this list.\nWhen matching an exact match is used. So adding RuntimeException.class to this list is going to include only RuntimeException itself, not all of its subclasses. The reason for such behaviour is to be able to support server side retries without knowledge of Java exception hierarchy. When considering an exception type a cause of ActivityFailureException and ChildWorkflowFailureException is looked at.\nError and CancellationException are never retried and are not even passed to this filter."}),"\n",(0,o.jsx)(t.h2,{id:"activity-timeout-usage",children:"Activity Timeout Usage"}),"\n",(0,o.jsx)(t.p,{children:"It's probably too complicated to learn how to set those timeouts by reading the above. There is an easy way to deal with it."}),"\n",(0,o.jsxs)(t.p,{children:[(0,o.jsx)(t.strong,{children:"LocalActivity without retry"}),": Use ScheduleToClose for overall timeout"]}),"\n",(0,o.jsxs)(t.p,{children:[(0,o.jsx)(t.strong,{children:"Regular Activity without retry"}),":"]}),"\n",(0,o.jsxs)(t.ol,{children:["\n",(0,o.jsx)(t.li,{children:"Use ScheduleToClose for overall timeout"}),"\n",(0,o.jsx)(t.li,{children:"Leave ScheduleToStart and StartToClose empty"}),"\n",(0,o.jsx)(t.li,{children:"If ScheduleToClose is too large(like 10 mins), then set Heartbeat timeout to a smaller value like 10s. Call heartbeat API inside activity regularly."}),"\n"]}),"\n",(0,o.jsxs)(t.p,{children:[(0,o.jsx)(t.strong,{children:"LocalActivity with retry"}),":"]}),"\n",(0,o.jsxs)(t.ol,{children:["\n",(0,o.jsx)(t.li,{children:"Use ScheduleToClose as timeout of each attempt."}),"\n",(0,o.jsx)(t.li,{children:"Use retryOptions.InitialInterval, retryOptions.BackoffCoefficient, retryOptions.MaximumInterval to control backoff."}),"\n",(0,o.jsx)(t.li,{children:"Use retryOptions.ExperiationInterval as overall timeout of all attempts."}),"\n",(0,o.jsx)(t.li,{children:"Leave retryOptions.MaximumAttempts empty."}),"\n"]}),"\n",(0,o.jsxs)(t.p,{children:[(0,o.jsx)(t.strong,{children:"Regular Activity with retry"}),":"]}),"\n",(0,o.jsxs)(t.ol,{children:["\n",(0,o.jsx)(t.li,{children:"Use ScheduleToClose as timeout of each attempt"}),"\n",(0,o.jsx)(t.li,{children:"Leave ScheduleToStart and StartToClose empty"}),"\n",(0,o.jsx)(t.li,{children:"If ScheduleToClose is too large(like 10 mins), then set Heartbeat timeout to a smaller value like 10s. Call heartbeat API inside activity regularly."}),"\n",(0,o.jsx)(t.li,{children:"Use retryOptions.InitialInterval, retryOptions.BackoffCoefficient, retryOptions.MaximumInterval to control backoff."}),"\n",(0,o.jsx)(t.li,{children:"Use retryOptions.ExperiationInterval as overall timeout of all attempts."}),"\n",(0,o.jsx)(t.li,{children:"Leave retryOptions.MaximumAttempts empty."}),"\n"]}),"\n",(0,o.jsx)(t.h2,{id:"activity-timeout-internals",children:"Activity Timeout Internals"}),"\n",(0,o.jsx)(t.h3,{id:"basics-without-retry",children:"Basics without Retry"}),"\n",(0,o.jsx)(t.p,{children:"Things are easier to understand in the world without retry. Because Cadence started from it."}),"\n",(0,o.jsxs)(t.ul,{children:["\n",(0,o.jsxs)(t.li,{children:["\n",(0,o.jsx)(t.p,{children:"ScheduleToClose timeout is the overall end-to-end timeout from a workflow's perspective."}),"\n"]}),"\n",(0,o.jsxs)(t.li,{children:["\n",(0,o.jsx)(t.p,{children:"ScheduleToStart timeout is the time that activity worker needed to start an activity. Exceeding this timeout, activity will return an ScheduleToStart timeout error/exception to workflow"}),"\n"]}),"\n",(0,o.jsxs)(t.li,{children:["\n",(0,o.jsx)(t.p,{children:"StartToClose timeout is the time that an activity needed to run. Exceeding this will return\nStartToClose to workflow."}),"\n"]}),"\n",(0,o.jsxs)(t.li,{children:["\n",(0,o.jsx)(t.p,{children:(0,o.jsx)(t.strong,{children:"Requirement and defaults:"})}),"\n",(0,o.jsxs)(t.ul,{children:["\n",(0,o.jsx)(t.li,{children:"Either ScheduleToClose is provided or both of ScheduleToStart and StartToClose are provided."}),"\n",(0,o.jsx)(t.li,{children:"If only ScheduleToClose, then ScheduleToStart and StartToClose are default to it."}),"\n",(0,o.jsxs)(t.li,{children:["If only ScheduleToStart and StartToClose are provided, then ",(0,o.jsx)(t.code,{children:"ScheduleToClose = ScheduleToStart + StartToClose"}),"."]}),"\n",(0,o.jsxs)(t.li,{children:["All of them are capped by workflowTimeout. (e.g. if workflowTimeout is 1hour, set 2 hour for ScheduleToClose will still get 1 hour :",(0,o.jsx)(t.code,{children:"ScheduleToClose=Min(ScheduleToClose, workflowTimeout)"})," )"]}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,o.jsx)(t.p,{children:(0,o.jsx)(t.strong,{children:"So why are they?"})}),"\n",(0,o.jsxs)(t.p,{children:["You may notice that ScheduleToClose is only useful when\n",(0,o.jsx)(t.code,{children:"ScheduleToClose < ScheduleToStart + StartToClose"}),". Because if ",(0,o.jsx)(t.code,{children:"ScheduleToClose >= ScheduleToStart+StartToClose"})," the ScheduleToClose timeout is already enforced by the combination of the other two, and it become meaningless."]}),"\n",(0,o.jsxs)(t.p,{children:["So the main use case of ScheduleToClose being less than the sum of two is that people want to limit the overall timeout of the activity but give more timeout for scheduleToStart or startToClose. ",(0,o.jsx)(t.strong,{children:"This is extremely rare use case"}),"."]}),"\n",(0,o.jsxs)(t.p,{children:["Also the main use case that people want to distinguish ScheduleToStart and StartToClose is that the workflow may need to do some special handling for ScheduleToStart timeout error. ",(0,o.jsx)(t.strong,{children:"This is also very rare use case"}),"."]}),"\n",(0,o.jsxs)(t.p,{children:["Therefore, you can understand why in TL;DR that I recommend only using ",(0,o.jsx)(t.strong,{children:"ScheduleToClose"})," but leave the other two empty. Because only in some rare cases you may need it. If you can't think of the use case, then you do not need it."]}),"\n",(0,o.jsx)(t.p,{children:"LocalActivity doesn't have ScheduleToStart/StartToClose because it's started directly inside workflow worker without server scheduling involved."}),"\n",(0,o.jsx)(t.h3,{id:"heartbeat-timeout",children:"Heartbeat timeout"}),"\n",(0,o.jsxs)(t.p,{children:["Heartbeat is very important for long running activity, to prevent it from getting stuck. Not only bugs can cause activity getting stuck, regular deployment/host restart/failure could also cause it. Because without heartbeat, Cadence server couldn't know whether or not the activity is still being worked on. See more details about here ",(0,o.jsx)(t.a,{href:"https://stackoverflow.com/questions/65118584/solutions-to-stuck-timers-activities-in-cadence-swf-stepfunctions/65118585#65118585",children:"https://stackoverflow.com/questions/65118584/solutions-to-stuck-timers-activities-in-cadence-swf-stepfunctions/65118585#65118585"})]}),"\n",(0,o.jsx)(t.h3,{id:"retryoptions-and-activity-with-retry",children:"RetryOptions and Activity with Retry"}),"\n",(0,o.jsxs)(t.p,{children:["First of all, here RetryOptions is for ",(0,o.jsx)(t.code,{children:"server side"})," backoff retry -- meaning that the retry is managed automatically by Cadence without interacting with workflows. Because retry is managed by Cadence, the activity has to be specially handled in Cadence history that the started event can not written until the activity is closed. Here is some reference: ",(0,o.jsx)(t.a,{href:"https://stackoverflow.com/questions/65113363/why-an-activity-task-is-scheduled-but-not-started/65113365#65113365",children:"https://stackoverflow.com/questions/65113363/why-an-activity-task-is-scheduled-but-not-started/65113365#65113365"})]}),"\n",(0,o.jsxs)(t.p,{children:["In fact, workflow can do ",(0,o.jsx)(t.code,{children:"client side"})," retry on their own. This means workflow will be managing the retry logic. You can write your own retry function, or there is some helper function in SDK, like ",(0,o.jsx)(t.code,{children:"Workflow.retry"})," in Cadence-java-client. Client side retry will show all start events immediately, but there will be many events in the history when retrying for a single activity. It's not recommended because of performance issue."]}),"\n",(0,o.jsx)(t.p,{children:"So what do the options mean:"}),"\n",(0,o.jsxs)(t.ul,{children:["\n",(0,o.jsxs)(t.li,{children:["\n",(0,o.jsx)(t.p,{children:"ExpirationInterval:"}),"\n",(0,o.jsxs)(t.ul,{children:["\n",(0,o.jsx)(t.li,{children:"It replaces the ScheduleToClose timeout to become the actual overall timeout of the activity for all attempts."}),"\n",(0,o.jsxs)(t.li,{children:["It's also capped to workflow timeout like other three timeout options. ",(0,o.jsx)(t.code,{children:"ScheduleToClose = Min(ScheduleToClose, workflowTimeout)"})]}),"\n",(0,o.jsx)(t.li,{children:"The timeout of each attempt is StartToClose, but StartToClose defaults to ScheduleToClose like explanation above."}),"\n",(0,o.jsxs)(t.li,{children:["ScheduleToClose will be extended to ExpirationInterval:\n",(0,o.jsx)(t.code,{children:"ScheduleToClose = Max(ScheduleToClose, ExpirationInterval)"}),", and this happens before ScheduleToClose is copied to ScheduleToClose and StartToClose."]}),"\n"]}),"\n"]}),"\n",(0,o.jsxs)(t.li,{children:["\n",(0,o.jsx)(t.p,{children:"InitialInterval: the interval of first retry"}),"\n"]}),"\n",(0,o.jsxs)(t.li,{children:["\n",(0,o.jsx)(t.p,{children:"BackoffCoefficient: self explained"}),"\n"]}),"\n",(0,o.jsxs)(t.li,{children:["\n",(0,o.jsx)(t.p,{children:"MaximumInterval: maximum of the interval during retry"}),"\n"]}),"\n",(0,o.jsxs)(t.li,{children:["\n",(0,o.jsx)(t.p,{children:"MaximumAttempts: the maximum attempts. If existing with ExpirationInterval, then retry stops when either one of them is exceeded."}),"\n"]}),"\n",(0,o.jsxs)(t.li,{children:["\n",(0,o.jsxs)(t.p,{children:[(0,o.jsx)(t.strong,{children:"Requirements and defaults"}),":"]}),"\n"]}),"\n",(0,o.jsxs)(t.li,{children:["\n",(0,o.jsx)(t.p,{children:"Either MaximumAttempts or ExpirationInterval is required. ExpirationInterval is set to workflowTimeout if not provided."}),"\n"]}),"\n"]}),"\n",(0,o.jsx)(t.p,{children:"Since ExpirationInterval is always there, and in fact it's more useful. And I think it's quite confusing to use MaximumAttempts, so I would recommend just use ExpirationInterval. Unless you really need it."})]})}function h(e={}){const{wrapper:t}={...(0,r.R)(),...e.components};return t?(0,o.jsx)(t,{...e,children:(0,o.jsx)(d,{...e})}):d(e)}},8453:(e,t,i)=>{i.d(t,{R:()=>s,x:()=>l});var n=i(6540);const o={},r=n.createContext(o);function s(e){const t=n.useContext(r);return n.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function l(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:s(e.components),n.createElement(r.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/67d45d0f.18a33aeb.js b/assets/js/67d45d0f.18a33aeb.js deleted file mode 100644 index 1b3c92824..000000000 --- a/assets/js/67d45d0f.18a33aeb.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[207],{5212:(e,t,r)=>{r.r(t),r.d(t,{assets:()=>l,contentTitle:()=>a,default:()=>h,frontMatter:()=>s,metadata:()=>i,toc:()=>c});const i=JSON.parse('{"id":"workflow-troubleshooting/retries","title":"Retries","description":"Cadence has a retry feature where a retry policy can be configured so that an activity or a workflow will be retried when it fails or times out.","source":"@site/docs/08-workflow-troubleshooting/03-retries.md","sourceDirName":"08-workflow-troubleshooting","slug":"/workflow-troubleshooting/retries","permalink":"/docs/workflow-troubleshooting/retries","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/08-workflow-troubleshooting/03-retries.md","tags":[],"version":"current","sidebarPosition":3,"frontMatter":{"layout":"default","title":"Retries","permalink":"/docs/workflow-troubleshooting/retries"},"sidebar":"docsSidebar","previous":{"title":"Activity Failures","permalink":"/docs/workflow-troubleshooting/activity-failures"},"next":{"title":"Contact us","permalink":"/docs/about/"}}');var o=r(4848),n=r(8453);const s={layout:"default",title:"Retries",permalink:"/docs/workflow-troubleshooting/retries"},a="Retries",l={},c=[{value:"Workflow execution history of retries",id:"workflow-execution-history-of-retries",level:2},{value:"Configuration of activity retries and workflow retries",id:"configuration-of-activity-retries-and-workflow-retries",level:2},{value:"MaximumAttempts set to 1",id:"maximumattempts-set-to-1",level:2},{value:"ExpirationIntervalInSeconds less than InitialIntervalInSeconds",id:"expirationintervalinseconds-less-than-initialintervalinseconds",level:2}];function d(e){const t={a:"a",code:"code",h1:"h1",h2:"h2",header:"header",p:"p",...(0,n.R)(),...e.components};return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsx)(t.header,{children:(0,o.jsx)(t.h1,{id:"retries",children:"Retries"})}),"\n",(0,o.jsx)(t.p,{children:"Cadence has a retry feature where a retry policy can be configured so that an activity or a workflow will be retried when it fails or times out."}),"\n",(0,o.jsxs)(t.p,{children:["Read more about ",(0,o.jsx)(t.a,{href:"https://cadenceworkflow.io/docs/concepts/activities/#retries",children:"activity retries"})," and ",(0,o.jsx)(t.a,{href:"https://cadenceworkflow.io/docs/concepts/workflows/#workflow-retries",children:"workflow retries"}),"."]}),"\n",(0,o.jsx)(t.h2,{id:"workflow-execution-history-of-retries",children:"Workflow execution history of retries"}),"\n",(0,o.jsx)(t.p,{children:"One thing to note is how activity retries and workflow retries are shown in the Cadence Web UI. Information about activity retries is not stored in Cadence. Only the last attempt is shown with the attempt number."}),"\n",(0,o.jsxs)(t.p,{children:["Moreover, attempt number starts from 0, so ",(0,o.jsx)(t.code,{children:"Attempt: 0"})," refers to the first and original attempt, ",(0,o.jsx)(t.code,{children:"Attempt: 1"})," refers to the second attempt or first retried attempt."]}),"\n",(0,o.jsx)(t.p,{children:"For workflow retries, when a workflow fails or times out and is retried, it completes the previous execution with a ContinuedAsNew event and a new execution is started with Attempt 1. The ContinuedAsNew event holds the details of the failure reason."}),"\n",(0,o.jsx)(t.h2,{id:"configuration-of-activity-retries-and-workflow-retries",children:"Configuration of activity retries and workflow retries"}),"\n",(0,o.jsx)(t.p,{children:"Some of the configurable values could be misconfigured and as a result will not have the intended behaviour. These are listed here."}),"\n",(0,o.jsx)(t.h2,{id:"maximumattempts-set-to-1",children:"MaximumAttempts set to 1"}),"\n",(0,o.jsx)(t.p,{children:"In both activity retries and workflow retries it is sufficient to mention a maximum number of attempts or an expiration interval. However, the maximum number of attempts counts the original attempt of the activity also. As a result, setting maximum number of attempts to 1 means the activity or workflow will not be retried."}),"\n",(0,o.jsx)(t.h2,{id:"expirationintervalinseconds-less-than-initialintervalinseconds",children:"ExpirationIntervalInSeconds less than InitialIntervalInSeconds"}),"\n",(0,o.jsx)(t.p,{children:"In both activity retries and workflow retries it is sufficient to specify a maximum number of attempts or an expiration interval. The first retry attempt waits for the InitialIntervalInSeconds before starting and when an expiration interval is set lower than the initial interval, the retry policy becomes invalid and the activity or workflow will not be retried."})]})}function h(e={}){const{wrapper:t}={...(0,n.R)(),...e.components};return t?(0,o.jsx)(t,{...e,children:(0,o.jsx)(d,{...e})}):d(e)}},8453:(e,t,r)=>{r.d(t,{R:()=>s,x:()=>a});var i=r(6540);const o={},n=i.createContext(o);function s(e){const t=i.useContext(n);return i.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function a(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:s(e.components),i.createElement(n.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/67d45d0f.691d25f4.js b/assets/js/67d45d0f.691d25f4.js new file mode 100644 index 000000000..555f94b5c --- /dev/null +++ b/assets/js/67d45d0f.691d25f4.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[207],{5212:(e,t,r)=>{r.r(t),r.d(t,{assets:()=>l,contentTitle:()=>a,default:()=>h,frontMatter:()=>s,metadata:()=>i,toc:()=>c});const i=JSON.parse('{"id":"workflow-troubleshooting/retries","title":"Retries","description":"Cadence has a retry feature where a retry policy can be configured so that an activity or a workflow will be retried when it fails or times out.","source":"@site/docs/08-workflow-troubleshooting/03-retries.md","sourceDirName":"08-workflow-troubleshooting","slug":"/workflow-troubleshooting/retries","permalink":"/Cadence-Docs/docs/workflow-troubleshooting/retries","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/08-workflow-troubleshooting/03-retries.md","tags":[],"version":"current","sidebarPosition":3,"frontMatter":{"layout":"default","title":"Retries","permalink":"/docs/workflow-troubleshooting/retries"},"sidebar":"docsSidebar","previous":{"title":"Activity Failures","permalink":"/Cadence-Docs/docs/workflow-troubleshooting/activity-failures"},"next":{"title":"Contact us","permalink":"/Cadence-Docs/docs/about/"}}');var o=r(4848),n=r(8453);const s={layout:"default",title:"Retries",permalink:"/docs/workflow-troubleshooting/retries"},a="Retries",l={},c=[{value:"Workflow execution history of retries",id:"workflow-execution-history-of-retries",level:2},{value:"Configuration of activity retries and workflow retries",id:"configuration-of-activity-retries-and-workflow-retries",level:2},{value:"MaximumAttempts set to 1",id:"maximumattempts-set-to-1",level:2},{value:"ExpirationIntervalInSeconds less than InitialIntervalInSeconds",id:"expirationintervalinseconds-less-than-initialintervalinseconds",level:2}];function d(e){const t={a:"a",code:"code",h1:"h1",h2:"h2",header:"header",p:"p",...(0,n.R)(),...e.components};return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsx)(t.header,{children:(0,o.jsx)(t.h1,{id:"retries",children:"Retries"})}),"\n",(0,o.jsx)(t.p,{children:"Cadence has a retry feature where a retry policy can be configured so that an activity or a workflow will be retried when it fails or times out."}),"\n",(0,o.jsxs)(t.p,{children:["Read more about ",(0,o.jsx)(t.a,{href:"https://cadenceworkflow.io/docs/concepts/activities/#retries",children:"activity retries"})," and ",(0,o.jsx)(t.a,{href:"https://cadenceworkflow.io/docs/concepts/workflows/#workflow-retries",children:"workflow retries"}),"."]}),"\n",(0,o.jsx)(t.h2,{id:"workflow-execution-history-of-retries",children:"Workflow execution history of retries"}),"\n",(0,o.jsx)(t.p,{children:"One thing to note is how activity retries and workflow retries are shown in the Cadence Web UI. Information about activity retries is not stored in Cadence. Only the last attempt is shown with the attempt number."}),"\n",(0,o.jsxs)(t.p,{children:["Moreover, attempt number starts from 0, so ",(0,o.jsx)(t.code,{children:"Attempt: 0"})," refers to the first and original attempt, ",(0,o.jsx)(t.code,{children:"Attempt: 1"})," refers to the second attempt or first retried attempt."]}),"\n",(0,o.jsx)(t.p,{children:"For workflow retries, when a workflow fails or times out and is retried, it completes the previous execution with a ContinuedAsNew event and a new execution is started with Attempt 1. The ContinuedAsNew event holds the details of the failure reason."}),"\n",(0,o.jsx)(t.h2,{id:"configuration-of-activity-retries-and-workflow-retries",children:"Configuration of activity retries and workflow retries"}),"\n",(0,o.jsx)(t.p,{children:"Some of the configurable values could be misconfigured and as a result will not have the intended behaviour. These are listed here."}),"\n",(0,o.jsx)(t.h2,{id:"maximumattempts-set-to-1",children:"MaximumAttempts set to 1"}),"\n",(0,o.jsx)(t.p,{children:"In both activity retries and workflow retries it is sufficient to mention a maximum number of attempts or an expiration interval. However, the maximum number of attempts counts the original attempt of the activity also. As a result, setting maximum number of attempts to 1 means the activity or workflow will not be retried."}),"\n",(0,o.jsx)(t.h2,{id:"expirationintervalinseconds-less-than-initialintervalinseconds",children:"ExpirationIntervalInSeconds less than InitialIntervalInSeconds"}),"\n",(0,o.jsx)(t.p,{children:"In both activity retries and workflow retries it is sufficient to specify a maximum number of attempts or an expiration interval. The first retry attempt waits for the InitialIntervalInSeconds before starting and when an expiration interval is set lower than the initial interval, the retry policy becomes invalid and the activity or workflow will not be retried."})]})}function h(e={}){const{wrapper:t}={...(0,n.R)(),...e.components};return t?(0,o.jsx)(t,{...e,children:(0,o.jsx)(d,{...e})}):d(e)}},8453:(e,t,r)=>{r.d(t,{R:()=>s,x:()=>a});var i=r(6540);const o={},n=i.createContext(o);function s(e){const t=i.useContext(n);return i.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function a(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:s(e.components),i.createElement(n.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/69a323c8.52cc3671.js b/assets/js/69a323c8.52cc3671.js new file mode 100644 index 000000000..28e0bc9b0 --- /dev/null +++ b/assets/js/69a323c8.52cc3671.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[6156],{887:(e,t,i)=>{i.r(t),i.d(t,{assets:()=>r,contentTitle:()=>s,default:()=>h,frontMatter:()=>a,metadata:()=>n,toc:()=>l});const n=JSON.parse('{"id":"go-client/execute-activity","title":"Executing activities","description":"The primary responsibility of a implementation is to scheduleactivities: for execution. The","source":"@site/docs/05-go-client/04-execute-activity.md","sourceDirName":"05-go-client","slug":"/go-client/execute-activity","permalink":"/Cadence-Docs/docs/go-client/execute-activity","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/05-go-client/04-execute-activity.md","tags":[],"version":"current","sidebarPosition":4,"frontMatter":{"layout":"default","title":"Executing activities","permalink":"/docs/go-client/execute-activity"},"sidebar":"docsSidebar","previous":{"title":"Activity overview","permalink":"/Cadence-Docs/docs/go-client/activities"},"next":{"title":"Child workflows","permalink":"/Cadence-Docs/docs/go-client/child-workflows"}}');var c=i(4848),o=i(8453);const a={layout:"default",title:"Executing activities",permalink:"/docs/go-client/execute-activity"},s="Executing activities",r={},l=[{value:"Activity options",id:"activity-options",level:2},{value:"Activity timeouts",id:"activity-timeouts",level:2},{value:"ExecuteActivity call",id:"executeactivity-call",level:2}];function d(e){const t={code:"code",em:"em",h1:"h1",h2:"h2",header:"header",p:"p",pre:"pre",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",...(0,o.R)(),...e.components};return(0,c.jsxs)(c.Fragment,{children:[(0,c.jsx)(t.header,{children:(0,c.jsx)(t.h1,{id:"executing-activities",children:"Executing activities"})}),"\n",(0,c.jsxs)(t.p,{children:["The primary responsibility of a workflow implementation is to schedule activities for execution. The\nmost straightforward way to do this is via the library method ",(0,c.jsx)(t.code,{children:"workflow.ExecuteActivity"}),". The following\nsample code demonstrates making this call:"]}),"\n",(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:"language-go",children:'ao := cadence.ActivityOptions{\n TaskList: "sampleTaskList",\n ScheduleToCloseTimeout: time.Second * 60,\n ScheduleToStartTimeout: time.Second * 60,\n StartToCloseTimeout: time.Second * 60,\n HeartbeatTimeout: time.Second * 10,\n WaitForCancellation: false,\n}\nctx = cadence.WithActivityOptions(ctx, ao)\n\nfuture := workflow.ExecuteActivity(ctx, SimpleActivity, value)\nvar result string\nif err := future.Get(ctx, &result); err != nil {\n return err\n}\n'})}),"\n",(0,c.jsx)(t.p,{children:"Let's take a look at each component of this call."}),"\n",(0,c.jsx)(t.h2,{id:"activity-options",children:"Activity options"}),"\n",(0,c.jsxs)(t.p,{children:["Before calling ",(0,c.jsx)(t.code,{children:"workflow.ExecuteActivity()"}),", you must configure ",(0,c.jsx)(t.code,{children:"ActivityOptions"})," for the\ninvocation. These options customize various execution timeouts, and are passed in by creating a child\ncontext from the initial context and overwriting the desired values. The child context is then passed\ninto the ",(0,c.jsx)(t.code,{children:"workflow.ExecuteActivity()"})," call. If multiple activities are sharing the same option\nvalues, then the same context instance can be used when calling ",(0,c.jsx)(t.code,{children:"workflow.ExecuteActivity()"}),"."]}),"\n",(0,c.jsx)(t.h2,{id:"activity-timeouts",children:"Activity timeouts"}),"\n",(0,c.jsxs)(t.p,{children:["There can be various kinds of timeouts associated with an activity. Cadence guarantees that activities\nare executed ",(0,c.jsx)(t.em,{children:"at most once"}),", so an activity either succeeds or fails with one of the following timeouts:"]}),"\n",(0,c.jsxs)(t.table,{children:[(0,c.jsx)(t.thead,{children:(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.th,{children:"Timeout"}),(0,c.jsx)(t.th,{children:"Description"})]})}),(0,c.jsxs)(t.tbody,{children:[(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:"StartToCloseTimeout"})}),(0,c.jsx)(t.td,{children:"Maximum time that a worker can take to process a task after it has received the task."})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:"ScheduleToStartTimeout"})}),(0,c.jsx)(t.td,{children:"Time a task can wait to be picked up by an activity_worker after a workflow schedules it. If there are no workers available to process this task for the specified duration, the task will time out."})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:"ScheduleToCloseTimeout"})}),(0,c.jsxs)(t.td,{children:["Time a task can take to complete after it is scheduled by a workflow. This is usually greater than the sum of ",(0,c.jsx)(t.code,{children:"StartToClose"})," and ",(0,c.jsx)(t.code,{children:"ScheduleToStart"})," timeouts."]})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:"HeartbeatTimeout"})}),(0,c.jsx)(t.td,{children:"If a task doesn't heartbeat to the Cadence service for this duration, it will be considered to have failed. This is useful for long-running tasks."})]})]})]}),"\n",(0,c.jsx)(t.h2,{id:"executeactivity-call",children:"ExecuteActivity call"}),"\n",(0,c.jsxs)(t.p,{children:["The first parameter in the call is the required ",(0,c.jsx)(t.code,{children:"cadence.Context"})," object. This type is a copy of\n",(0,c.jsx)(t.code,{children:"context.Context"})," with the ",(0,c.jsx)(t.code,{children:"Done()"})," method returning ",(0,c.jsx)(t.code,{children:"cadence.Channel"})," instead of the native Go ",(0,c.jsx)(t.code,{children:"chan"}),"."]}),"\n",(0,c.jsx)(t.p,{children:"The second parameter is the function that we registered as an activity function. This parameter can\nalso be a string representing the fully qualified name of the activity function. The benefit of passing\nin the actual function object is that the framework can validate activity parameters."}),"\n",(0,c.jsxs)(t.p,{children:["The remaining parameters are passed to the activity as part of the call. In our example, we have a\nsingle parameter: ",(0,c.jsx)(t.code,{children:"value"}),". This list of parameters must match the list of parameters declared by\nthe activity function. The Cadence client library will validate this."]}),"\n",(0,c.jsxs)(t.p,{children:["The method call returns immediately and returns a ",(0,c.jsx)(t.code,{children:"cadence.Future"}),". This allows you to execute more\ncode without having to wait for the scheduled activity to complete."]}),"\n",(0,c.jsxs)(t.p,{children:["When you are ready to process the results of the activity, call the ",(0,c.jsx)(t.code,{children:"Get()"})," method on the future\nobject returned. The parameters to this method are the ",(0,c.jsx)(t.code,{children:"ctx"})," object we passed to the\n",(0,c.jsx)(t.code,{children:"workflow.ExecuteActivity()"})," call and an output parameter that will receive the output of the\nactivity. The type of the output parameter must match the type of the return value declared by the\nactivity function. The ",(0,c.jsx)(t.code,{children:"Get()"})," method will block until the activity completes and results are\navailable."]}),"\n",(0,c.jsxs)(t.p,{children:["You can retrieve the result value returned by ",(0,c.jsx)(t.code,{children:"workflow.ExecuteActivity()"})," from the future and use\nit like any normal result from a synchronous function call. The following sample code demonstrates how\nyou can use the result if it is a string value:"]}),"\n",(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:"language-go",children:'var result string\nif err := future.Get(ctx1, &result); err != nil {\n return err\n}\n\nswitch result {\ncase "apple":\n // Do something.\ncase "banana":\n // Do something.\ndefault:\n return err\n}\n'})}),"\n",(0,c.jsxs)(t.p,{children:["In this example, we called the ",(0,c.jsx)(t.code,{children:"Get()"})," method on the returned future immediately after ",(0,c.jsx)(t.code,{children:"workflow.ExecuteActivity()"}),".\nHowever, this is not necessary. If you want to execute multiple activities in parallel, you can\nrepeatedly call ",(0,c.jsx)(t.code,{children:"workflow.ExecuteActivity()"}),", store the returned futures, and then wait for all\nactivities to complete by calling the ",(0,c.jsx)(t.code,{children:"Get()"})," methods of the future at a later time."]}),"\n",(0,c.jsxs)(t.p,{children:["To implement more complex wait conditions on returned future objects, use the ",(0,c.jsx)(t.code,{children:"cadence.Selector"})," class."]})]})}function h(e={}){const{wrapper:t}={...(0,o.R)(),...e.components};return t?(0,c.jsx)(t,{...e,children:(0,c.jsx)(d,{...e})}):d(e)}},8453:(e,t,i)=>{i.d(t,{R:()=>a,x:()=>s});var n=i(6540);const c={},o=n.createContext(c);function a(e){const t=n.useContext(o);return n.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function s(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(c):e.components||c:a(e.components),n.createElement(o.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/69a323c8.e094494d.js b/assets/js/69a323c8.e094494d.js deleted file mode 100644 index 48ff56249..000000000 --- a/assets/js/69a323c8.e094494d.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[6156],{887:(e,t,i)=>{i.r(t),i.d(t,{assets:()=>r,contentTitle:()=>s,default:()=>h,frontMatter:()=>a,metadata:()=>n,toc:()=>l});const n=JSON.parse('{"id":"go-client/execute-activity","title":"Executing activities","description":"The primary responsibility of a implementation is to scheduleactivities: for execution. The","source":"@site/docs/05-go-client/04-execute-activity.md","sourceDirName":"05-go-client","slug":"/go-client/execute-activity","permalink":"/docs/go-client/execute-activity","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/05-go-client/04-execute-activity.md","tags":[],"version":"current","sidebarPosition":4,"frontMatter":{"layout":"default","title":"Executing activities","permalink":"/docs/go-client/execute-activity"},"sidebar":"docsSidebar","previous":{"title":"Activity overview","permalink":"/docs/go-client/activities"},"next":{"title":"Child workflows","permalink":"/docs/go-client/child-workflows"}}');var c=i(4848),o=i(8453);const a={layout:"default",title:"Executing activities",permalink:"/docs/go-client/execute-activity"},s="Executing activities",r={},l=[{value:"Activity options",id:"activity-options",level:2},{value:"Activity timeouts",id:"activity-timeouts",level:2},{value:"ExecuteActivity call",id:"executeactivity-call",level:2}];function d(e){const t={code:"code",em:"em",h1:"h1",h2:"h2",header:"header",p:"p",pre:"pre",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",...(0,o.R)(),...e.components};return(0,c.jsxs)(c.Fragment,{children:[(0,c.jsx)(t.header,{children:(0,c.jsx)(t.h1,{id:"executing-activities",children:"Executing activities"})}),"\n",(0,c.jsxs)(t.p,{children:["The primary responsibility of a workflow implementation is to schedule activities for execution. The\nmost straightforward way to do this is via the library method ",(0,c.jsx)(t.code,{children:"workflow.ExecuteActivity"}),". The following\nsample code demonstrates making this call:"]}),"\n",(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:"language-go",children:'ao := cadence.ActivityOptions{\n TaskList: "sampleTaskList",\n ScheduleToCloseTimeout: time.Second * 60,\n ScheduleToStartTimeout: time.Second * 60,\n StartToCloseTimeout: time.Second * 60,\n HeartbeatTimeout: time.Second * 10,\n WaitForCancellation: false,\n}\nctx = cadence.WithActivityOptions(ctx, ao)\n\nfuture := workflow.ExecuteActivity(ctx, SimpleActivity, value)\nvar result string\nif err := future.Get(ctx, &result); err != nil {\n return err\n}\n'})}),"\n",(0,c.jsx)(t.p,{children:"Let's take a look at each component of this call."}),"\n",(0,c.jsx)(t.h2,{id:"activity-options",children:"Activity options"}),"\n",(0,c.jsxs)(t.p,{children:["Before calling ",(0,c.jsx)(t.code,{children:"workflow.ExecuteActivity()"}),", you must configure ",(0,c.jsx)(t.code,{children:"ActivityOptions"})," for the\ninvocation. These options customize various execution timeouts, and are passed in by creating a child\ncontext from the initial context and overwriting the desired values. The child context is then passed\ninto the ",(0,c.jsx)(t.code,{children:"workflow.ExecuteActivity()"})," call. If multiple activities are sharing the same option\nvalues, then the same context instance can be used when calling ",(0,c.jsx)(t.code,{children:"workflow.ExecuteActivity()"}),"."]}),"\n",(0,c.jsx)(t.h2,{id:"activity-timeouts",children:"Activity timeouts"}),"\n",(0,c.jsxs)(t.p,{children:["There can be various kinds of timeouts associated with an activity. Cadence guarantees that activities\nare executed ",(0,c.jsx)(t.em,{children:"at most once"}),", so an activity either succeeds or fails with one of the following timeouts:"]}),"\n",(0,c.jsxs)(t.table,{children:[(0,c.jsx)(t.thead,{children:(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.th,{children:"Timeout"}),(0,c.jsx)(t.th,{children:"Description"})]})}),(0,c.jsxs)(t.tbody,{children:[(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:"StartToCloseTimeout"})}),(0,c.jsx)(t.td,{children:"Maximum time that a worker can take to process a task after it has received the task."})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:"ScheduleToStartTimeout"})}),(0,c.jsx)(t.td,{children:"Time a task can wait to be picked up by an activity_worker after a workflow schedules it. If there are no workers available to process this task for the specified duration, the task will time out."})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:"ScheduleToCloseTimeout"})}),(0,c.jsxs)(t.td,{children:["Time a task can take to complete after it is scheduled by a workflow. This is usually greater than the sum of ",(0,c.jsx)(t.code,{children:"StartToClose"})," and ",(0,c.jsx)(t.code,{children:"ScheduleToStart"})," timeouts."]})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:"HeartbeatTimeout"})}),(0,c.jsx)(t.td,{children:"If a task doesn't heartbeat to the Cadence service for this duration, it will be considered to have failed. This is useful for long-running tasks."})]})]})]}),"\n",(0,c.jsx)(t.h2,{id:"executeactivity-call",children:"ExecuteActivity call"}),"\n",(0,c.jsxs)(t.p,{children:["The first parameter in the call is the required ",(0,c.jsx)(t.code,{children:"cadence.Context"})," object. This type is a copy of\n",(0,c.jsx)(t.code,{children:"context.Context"})," with the ",(0,c.jsx)(t.code,{children:"Done()"})," method returning ",(0,c.jsx)(t.code,{children:"cadence.Channel"})," instead of the native Go ",(0,c.jsx)(t.code,{children:"chan"}),"."]}),"\n",(0,c.jsx)(t.p,{children:"The second parameter is the function that we registered as an activity function. This parameter can\nalso be a string representing the fully qualified name of the activity function. The benefit of passing\nin the actual function object is that the framework can validate activity parameters."}),"\n",(0,c.jsxs)(t.p,{children:["The remaining parameters are passed to the activity as part of the call. In our example, we have a\nsingle parameter: ",(0,c.jsx)(t.code,{children:"value"}),". This list of parameters must match the list of parameters declared by\nthe activity function. The Cadence client library will validate this."]}),"\n",(0,c.jsxs)(t.p,{children:["The method call returns immediately and returns a ",(0,c.jsx)(t.code,{children:"cadence.Future"}),". This allows you to execute more\ncode without having to wait for the scheduled activity to complete."]}),"\n",(0,c.jsxs)(t.p,{children:["When you are ready to process the results of the activity, call the ",(0,c.jsx)(t.code,{children:"Get()"})," method on the future\nobject returned. The parameters to this method are the ",(0,c.jsx)(t.code,{children:"ctx"})," object we passed to the\n",(0,c.jsx)(t.code,{children:"workflow.ExecuteActivity()"})," call and an output parameter that will receive the output of the\nactivity. The type of the output parameter must match the type of the return value declared by the\nactivity function. The ",(0,c.jsx)(t.code,{children:"Get()"})," method will block until the activity completes and results are\navailable."]}),"\n",(0,c.jsxs)(t.p,{children:["You can retrieve the result value returned by ",(0,c.jsx)(t.code,{children:"workflow.ExecuteActivity()"})," from the future and use\nit like any normal result from a synchronous function call. The following sample code demonstrates how\nyou can use the result if it is a string value:"]}),"\n",(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:"language-go",children:'var result string\nif err := future.Get(ctx1, &result); err != nil {\n return err\n}\n\nswitch result {\ncase "apple":\n // Do something.\ncase "banana":\n // Do something.\ndefault:\n return err\n}\n'})}),"\n",(0,c.jsxs)(t.p,{children:["In this example, we called the ",(0,c.jsx)(t.code,{children:"Get()"})," method on the returned future immediately after ",(0,c.jsx)(t.code,{children:"workflow.ExecuteActivity()"}),".\nHowever, this is not necessary. If you want to execute multiple activities in parallel, you can\nrepeatedly call ",(0,c.jsx)(t.code,{children:"workflow.ExecuteActivity()"}),", store the returned futures, and then wait for all\nactivities to complete by calling the ",(0,c.jsx)(t.code,{children:"Get()"})," methods of the future at a later time."]}),"\n",(0,c.jsxs)(t.p,{children:["To implement more complex wait conditions on returned future objects, use the ",(0,c.jsx)(t.code,{children:"cadence.Selector"})," class."]})]})}function h(e={}){const{wrapper:t}={...(0,o.R)(),...e.components};return t?(0,c.jsx)(t,{...e,children:(0,c.jsx)(d,{...e})}):d(e)}},8453:(e,t,i)=>{i.d(t,{R:()=>a,x:()=>s});var n=i(6540);const c={},o=n.createContext(c);function a(e){const t=n.useContext(o);return n.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function s(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(c):e.components||c:a(e.components),n.createElement(o.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/6abab11b.dd0f9a59.js b/assets/js/6abab11b.dd0f9a59.js new file mode 100644 index 000000000..d88739f07 --- /dev/null +++ b/assets/js/6abab11b.dd0f9a59.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[2709],{3571:e=>{e.exports=JSON.parse('{"version":{"pluginId":"default","version":"current","label":"Next","banner":null,"badge":false,"noIndex":false,"className":"docs-version-current","isLast":true,"docsSidebars":{"docsSidebar":[{"label":"Get Started","type":"category","items":[{"type":"link","label":"Overview","href":"/Cadence-Docs/docs/get-started/","docId":"get-started/index","unlisted":false},{"type":"link","label":"Server Installation","href":"/Cadence-Docs/docs/get-started/server-installation","docId":"get-started/server-installation","unlisted":false},{"type":"link","label":"Java hello world","href":"/Cadence-Docs/docs/get-started/java-hello-world","docId":"get-started/java-hello-world","unlisted":false},{"type":"link","label":"Golang hello world","href":"/Cadence-Docs/docs/get-started/golang-hello-world","docId":"get-started/golang-hello-world","unlisted":false},{"type":"link","label":"Video Tutorials","href":"/Cadence-Docs/docs/get-started/video-tutorials","docId":"get-started/video-tutorials","unlisted":false}],"collapsed":true,"collapsible":true},{"label":"Use Cases","type":"category","items":[{"type":"link","label":"Introduction","href":"/Cadence-Docs/docs/use-cases/","docId":"use-cases/index","unlisted":false},{"type":"link","label":"Periodic execution","href":"/Cadence-Docs/docs/use-cases/periodic-execution","docId":"use-cases/periodic-execution","unlisted":false},{"type":"link","label":"Orchestration","href":"/Cadence-Docs/docs/use-cases/orchestration","docId":"use-cases/orchestration","unlisted":false},{"type":"link","label":"Polling","href":"/Cadence-Docs/docs/use-cases/polling","docId":"use-cases/polling","unlisted":false},{"type":"link","label":"Event driven application","href":"/Cadence-Docs/docs/use-cases/event-driven","docId":"use-cases/event-driven","unlisted":false},{"type":"link","label":"Storage scan","href":"/Cadence-Docs/docs/use-cases/partitioned-scan","docId":"use-cases/partitioned-scan","unlisted":false},{"type":"link","label":"Batch job","href":"/Cadence-Docs/docs/use-cases/batch-job","docId":"use-cases/batch-job","unlisted":false},{"type":"link","label":"Infrastructure provisioning","href":"/Cadence-Docs/docs/use-cases/provisioning","docId":"use-cases/provisioning","unlisted":false},{"type":"link","label":"Deployment","href":"/Cadence-Docs/docs/use-cases/deployment","docId":"use-cases/deployment","unlisted":false},{"type":"link","label":"Operational management","href":"/Cadence-Docs/docs/use-cases/operational-management","docId":"use-cases/operational-management","unlisted":false},{"type":"link","label":"Interactive application","href":"/Cadence-Docs/docs/use-cases/interactive","docId":"use-cases/interactive","unlisted":false},{"type":"link","label":"DSL workflows","href":"/Cadence-Docs/docs/use-cases/dsl","docId":"use-cases/dsl","unlisted":false},{"type":"link","label":"Big data and ML","href":"/Cadence-Docs/docs/use-cases/big-ml","docId":"use-cases/big-ml","unlisted":false}],"collapsed":true,"collapsible":true},{"label":"Concepts","type":"category","items":[{"type":"link","label":"Introduction","href":"/Cadence-Docs/docs/concepts/","docId":"concepts/index","unlisted":false},{"type":"link","label":"Activities","href":"/Cadence-Docs/docs/concepts/activities","docId":"concepts/activities","unlisted":false},{"type":"link","label":"Event handling","href":"/Cadence-Docs/docs/concepts/events","docId":"concepts/events","unlisted":false},{"type":"link","label":"Synchronous query","href":"/Cadence-Docs/docs/concepts/queries","docId":"concepts/queries","unlisted":false},{"type":"link","label":"Deployment topology","href":"/Cadence-Docs/docs/concepts/topology","docId":"concepts/topology","unlisted":false},{"type":"link","label":"Task lists","href":"/Cadence-Docs/docs/concepts/task-lists","docId":"concepts/task-lists","unlisted":false},{"type":"link","label":"Archival","href":"/Cadence-Docs/docs/concepts/archival","docId":"concepts/archival","unlisted":false},{"type":"link","label":"Cross DC replication","href":"/Cadence-Docs/docs/concepts/cross-dc-replication","docId":"concepts/cross-dc-replication","unlisted":false},{"type":"link","label":"Search workflows(Advanced visibility)","href":"/Cadence-Docs/docs/concepts/search-workflows","docId":"concepts/search-workflows","unlisted":false},{"type":"link","label":"HTTP API","href":"/Cadence-Docs/docs/concepts/http-api","docId":"concepts/http-api","unlisted":false}],"collapsed":true,"collapsible":true},{"label":"Java Client","type":"category","items":[{"type":"link","label":"Introduction","href":"/Cadence-Docs/docs/java-client/","docId":"java-client/index","unlisted":false},{"type":"link","label":"Client SDK Overview","href":"/Cadence-Docs/docs/java-client/client-overview","docId":"java-client/client-overview","unlisted":false},{"type":"link","label":"Workflow interface","href":"/Cadence-Docs/docs/java-client/workflow-interface","docId":"java-client/workflow-interface","unlisted":false},{"type":"link","label":"Implementing workflows","href":"/Cadence-Docs/docs/java-client/implementing-workflows","docId":"java-client/implementing-workflows","unlisted":false},{"type":"link","label":"Starting workflows","href":"/Cadence-Docs/docs/java-client/starting-workflow-executions","docId":"java-client/starting-workflow-executions","unlisted":false},{"type":"link","label":"Activity interface","href":"/Cadence-Docs/docs/java-client/activity-interface","docId":"java-client/activity-interface","unlisted":false},{"type":"link","label":"Versioning","href":"/Cadence-Docs/docs/java-client/versioning","docId":"java-client/versioning","unlisted":false},{"type":"link","label":"Distributed CRON","href":"/Cadence-Docs/docs/java-client/distributed-cron","docId":"java-client/distributed-cron","unlisted":false},{"type":"link","label":"Worker service","href":"/Cadence-Docs/docs/java-client/workers","docId":"java-client/workers","unlisted":false},{"type":"link","label":"Signals","href":"/Cadence-Docs/docs/java-client/signals","docId":"java-client/signals","unlisted":false},{"type":"link","label":"Queries","href":"/Cadence-Docs/docs/java-client/queries","docId":"java-client/queries","unlisted":false},{"type":"link","label":"Retries","href":"/Cadence-Docs/docs/java-client/retries","docId":"java-client/retries","unlisted":false},{"type":"link","label":"Child workflows","href":"/Cadence-Docs/docs/java-client/child-workflows","docId":"java-client/child-workflows","unlisted":false},{"type":"link","label":"Exception Handling","href":"/Cadence-Docs/docs/java-client/exception-handling","docId":"java-client/exception-handling","unlisted":false},{"type":"link","label":"Continue As New","href":"/Cadence-Docs/docs/java-client/continue-as-new","docId":"java-client/continue-as-new","unlisted":false},{"type":"link","label":"Side Effect","href":"/Cadence-Docs/docs/java-client/side-effect","docId":"java-client/side-effect","unlisted":false},{"type":"link","label":"Testing","href":"/Cadence-Docs/docs/java-client/testing","docId":"java-client/testing","unlisted":false},{"type":"link","label":"Workflow Replay and Shadowing","href":"/Cadence-Docs/docs/java-client/workflow-replay-shadowing","docId":"java-client/workflow-replay-shadowing","unlisted":false}],"collapsed":true,"collapsible":true},{"label":"Go Client","type":"category","items":[{"type":"link","label":"Introduction","href":"/Cadence-Docs/docs/go-client/","docId":"go-client/index","unlisted":false},{"type":"link","label":"Worker service","href":"/Cadence-Docs/docs/go-client/workers","docId":"go-client/workers","unlisted":false},{"type":"link","label":"Creating workflows","href":"/Cadence-Docs/docs/go-client/create-workflows","docId":"go-client/create-workflows","unlisted":false},{"type":"link","label":"Starting workflows","href":"/Cadence-Docs/docs/go-client/02.5-starting-workflows","docId":"go-client/02.5-starting-workflows","unlisted":false},{"type":"link","label":"Activity overview","href":"/Cadence-Docs/docs/go-client/activities","docId":"go-client/activities","unlisted":false},{"type":"link","label":"Executing activities","href":"/Cadence-Docs/docs/go-client/execute-activity","docId":"go-client/execute-activity","unlisted":false},{"type":"link","label":"Child workflows","href":"/Cadence-Docs/docs/go-client/child-workflows","docId":"go-client/child-workflows","unlisted":false},{"type":"link","label":"Activity and workflow retries","href":"/Cadence-Docs/docs/go-client/retries","docId":"go-client/retries","unlisted":false},{"type":"link","label":"Error handling","href":"/Cadence-Docs/docs/go-client/error-handling","docId":"go-client/error-handling","unlisted":false},{"type":"link","label":"Signals","href":"/Cadence-Docs/docs/go-client/signals","docId":"go-client/signals","unlisted":false},{"type":"link","label":"Continue as new","href":"/Cadence-Docs/docs/go-client/continue-as-new","docId":"go-client/continue-as-new","unlisted":false},{"type":"link","label":"Side effect","href":"/Cadence-Docs/docs/go-client/side-effect","docId":"go-client/side-effect","unlisted":false},{"type":"link","label":"Queries","href":"/Cadence-Docs/docs/go-client/queries","docId":"go-client/queries","unlisted":false},{"type":"link","label":"Async activity completion","href":"/Cadence-Docs/docs/go-client/activity-async-completion","docId":"go-client/activity-async-completion","unlisted":false},{"type":"link","label":"Testing","href":"/Cadence-Docs/docs/go-client/workflow-testing","docId":"go-client/workflow-testing","unlisted":false},{"type":"link","label":"Versioning","href":"/Cadence-Docs/docs/go-client/workflow-versioning","docId":"go-client/workflow-versioning","unlisted":false},{"type":"link","label":"Sessions","href":"/Cadence-Docs/docs/go-client/sessions","docId":"go-client/sessions","unlisted":false},{"type":"link","label":"Distributed CRON","href":"/Cadence-Docs/docs/go-client/distributed-cron","docId":"go-client/distributed-cron","unlisted":false},{"type":"link","label":"Tracing and context propagation","href":"/Cadence-Docs/docs/go-client/tracing","docId":"go-client/tracing","unlisted":false},{"type":"link","label":"Workflow Replay and Shadowing","href":"/Cadence-Docs/docs/go-client/workflow-replay-shadowing","docId":"go-client/workflow-replay-shadowing","unlisted":false}],"collapsed":true,"collapsible":true},{"label":"Command Line Interface","type":"category","items":[{"type":"link","label":"Introduction","href":"/Cadence-Docs/docs/cli/","docId":"cli/index","unlisted":false}],"collapsed":true,"collapsible":true},{"label":"Production Operation","type":"category","items":[{"type":"link","label":"Overview","href":"/Cadence-Docs/docs/operation-guide/","docId":"operation-guide/index","unlisted":false},{"type":"link","label":"Cluster Configuration","href":"/Cadence-Docs/docs/operation-guide/setup","docId":"operation-guide/setup","unlisted":false},{"type":"link","label":"Cluster Maintenance","href":"/Cadence-Docs/docs/operation-guide/maintain","docId":"operation-guide/maintain","unlisted":false},{"type":"link","label":"Cluster Monitoring","href":"/Cadence-Docs/docs/operation-guide/monitoring","docId":"operation-guide/monitoring","unlisted":false},{"type":"link","label":"Cluster Troubleshooting","href":"/Cadence-Docs/docs/operation-guide/troubleshooting","docId":"operation-guide/troubleshooting","unlisted":false},{"type":"link","label":"Cluster Migration","href":"/Cadence-Docs/docs/operation-guide/migration","docId":"operation-guide/migration","unlisted":false}],"collapsed":true,"collapsible":true},{"label":"Workflow Troubleshooting","type":"category","items":[{"type":"link","label":"Overview","href":"/Cadence-Docs/docs/workflow-troubleshooting/","docId":"workflow-troubleshooting/index","unlisted":false},{"type":"link","label":"Timeouts","href":"/Cadence-Docs/docs/workflow-troubleshooting/timeouts","docId":"workflow-troubleshooting/timeouts","unlisted":false},{"type":"link","label":"Activity Failures","href":"/Cadence-Docs/docs/workflow-troubleshooting/activity-failures","docId":"workflow-troubleshooting/activity-failures","unlisted":false},{"type":"link","label":"Retries","href":"/Cadence-Docs/docs/workflow-troubleshooting/retries","docId":"workflow-troubleshooting/retries","unlisted":false}],"collapsed":true,"collapsible":true},{"label":"About","type":"category","items":[{"type":"link","label":"Contact us","href":"/Cadence-Docs/docs/about/","docId":"about/index","unlisted":false},{"type":"link","label":"MIT License","href":"/Cadence-Docs/docs/about/license","docId":"about/license","unlisted":false}],"collapsed":true,"collapsible":true}]},"docs":{"about/index":{"id":"about/index","title":"Contact us","description":"If you have a question, check whether it is already answered at stackoverflow under cadence-workflow tag.","sidebar":"docsSidebar"},"about/license":{"id":"about/license","title":"MIT License","description":"","sidebar":"docsSidebar"},"cli/index":{"id":"cli/index","title":"Introduction","description":"The Cadence is a command-line tool you can use to perform varioustasks: on a Cadence server. It can perform","sidebar":"docsSidebar"},"concepts/activities":{"id":"concepts/activities","title":"Activities","description":"Fault-oblivious stateful code is the core abstraction of Cadence. But, due to deterministic execution requirements, they are not allowed to call any external API directly.","sidebar":"docsSidebar"},"concepts/archival":{"id":"concepts/archival","title":"Archival","description":"Archivalworkflow","sidebar":"docsSidebar"},"concepts/cross-dc-replication":{"id":"concepts/cross-dc-replication","title":"Cross DC replication","description":"The Cadence GlobalDomainworkflow_execution: from another","sidebar":"docsSidebar"},"concepts/events":{"id":"concepts/events","title":"Event handling","description":"Fault-oblivious statefulworkflowssignal about an external. A is always point to point destined to a specific instance.Signals: are always processed in the order in which they are received.","sidebar":"docsSidebar"},"concepts/http-api":{"id":"concepts/http-api","title":"HTTP API","description":"Introduction","sidebar":"docsSidebar"},"concepts/index":{"id":"concepts/index","title":"Introduction","description":"Cadence is a new developer friendly way to develop distributed applications.","sidebar":"docsSidebar"},"concepts/queries":{"id":"concepts/queries","title":"Synchronous query","description":"Workflowworkflow_executionqueryworkflowqueryworkflow: type exposing different information to different external systems.","sidebar":"docsSidebar"},"concepts/search-workflows":{"id":"concepts/search-workflows","title":"Search workflows(Advanced visibility)","description":"Introduction","sidebar":"docsSidebar"},"concepts/task-lists":{"id":"concepts/task-lists","title":"Task lists","description":"When a invokes an, it sends the `ScheduleActivityTask` to the","sidebar":"docsSidebar"},"concepts/topology":{"id":"concepts/topology","title":"Deployment topology","description":"Overview","sidebar":"docsSidebar"},"concepts/workflows":{"id":"concepts/workflows","title":"Workflows","description":"Overview"},"get-started/golang-hello-world":{"id":"get-started/golang-hello-world","title":"Golang hello world","description":"This section provides step-by-step instructions on how to write and run a HelloWorld workflow in Cadence with Golang. You will learn two critical building blocks of Cadence: activities and workflows. First, you will write an activity function that prints a \\"Hello World!\\" message in the log. Then, you will write a workflow function that executes this activity.","sidebar":"docsSidebar"},"get-started/index":{"id":"get-started/index","title":"Overview","description":"A large number of use cases span beyond a single request-reply, require tracking of a complex state, respond to asynchronous events, and communicate to external unreliable dependencies.","sidebar":"docsSidebar"},"get-started/java-hello-world":{"id":"get-started/java-hello-world","title":"Java hello world","description":"This section provides step by step instructions on how to write and run a HelloWorld with Java.","sidebar":"docsSidebar"},"get-started/server-installation":{"id":"get-started/server-installation","title":"Server Installation","description":"To get started with Cadence, you need to set up three components successfully.","sidebar":"docsSidebar"},"get-started/video-tutorials":{"id":"get-started/video-tutorials","title":"Video Tutorials","description":"An Introduction to the Cadence programming model and value proposition.","sidebar":"docsSidebar"},"glossary":{"id":"glossary","title":"Glossary","description":"--\x3e"},"go-client/02.5-starting-workflows":{"id":"go-client/02.5-starting-workflows","title":"Starting workflows","description":"Starting workflows can be done from any service that can send requests to","sidebar":"docsSidebar"},"go-client/activities":{"id":"go-client/activities","title":"Activity overview","description":"An is the implementation of a particular in the business logic.","sidebar":"docsSidebar"},"go-client/activity-async-completion":{"id":"go-client/activity-async-completion","title":"Async activity completion","description":"There are certain scenarios when completing an upon completion of its function is not possible","sidebar":"docsSidebar"},"go-client/child-workflows":{"id":"go-client/child-workflows","title":"Child workflows","description":"workflow.ExecuteChildWorkflow enables the scheduling of otherworkflowsworkflow\'s","sidebar":"docsSidebar"},"go-client/continue-as-new":{"id":"go-client/continue-as-new","title":"Continue as new","description":"Workflows: that need to rerun periodically could naively be implemented as a big for loop with","sidebar":"docsSidebar"},"go-client/create-workflows":{"id":"go-client/create-workflows","title":"Creating workflows","description":"The is the implementation of the coordination logic. The Cadence programming framework","sidebar":"docsSidebar"},"go-client/distributed-cron":{"id":"go-client/distributed-cron","title":"Distributed CRON","description":"It is relatively straightforward to turn any Cadence into a Cron. All you need","sidebar":"docsSidebar"},"go-client/error-handling":{"id":"go-client/error-handling","title":"Error handling","description":"An, or child, might fail and you could handle errors differently based on different","sidebar":"docsSidebar"},"go-client/execute-activity":{"id":"go-client/execute-activity","title":"Executing activities","description":"The primary responsibility of a implementation is to scheduleactivities: for execution. The","sidebar":"docsSidebar"},"go-client/index":{"id":"go-client/index","title":"Introduction","description":"Overview","sidebar":"docsSidebar"},"go-client/queries":{"id":"go-client/queries","title":"Queries","description":"If a has been stuck at a state for longer than an expected period of time, you","sidebar":"docsSidebar"},"go-client/retries":{"id":"go-client/retries","title":"Activity and workflow retries","description":"Activitiesworkflow can fail due to various intermediate conditions. In those cases, we want","sidebar":"docsSidebar"},"go-client/sessions":{"id":"go-client/sessions","title":"Sessions","description":"The session framework provides a straightforward interface for scheduling multipleactivitiesworkertask_list: name. It also includes features like concurrent session limitation and worker failure detection.","sidebar":"docsSidebar"},"go-client/side-effect":{"id":"go-client/side-effect","title":"Side effect","description":"workflow.SideEffect is useful for short, nondeterministic code snippets, such as getting a random","sidebar":"docsSidebar"},"go-client/signals":{"id":"go-client/signals","title":"Signals","description":"Signalsworkflow:. Previously, you had","sidebar":"docsSidebar"},"go-client/tracing":{"id":"go-client/tracing","title":"Tracing and context propagation","description":"Tracing","sidebar":"docsSidebar"},"go-client/workers":{"id":"go-client/workers","title":"Worker service","description":"A or service is a service that hosts the and implementations. The polls the Cadence service fortaskstask, and communicates execution results back to the Cadence service.Worker: services are developed, deployed, and operated by Cadence customers.","sidebar":"docsSidebar"},"go-client/workflow-non-deterministic-error":{"id":"go-client/workflow-non-deterministic-error","title":"Workflow Non-deterministic errors","description":"Root cause of non-deterministic errors"},"go-client/workflow-replay-shadowing":{"id":"go-client/workflow-replay-shadowing","title":"Workflow Replay and Shadowing","description":"In the Versioning section, we mentioned that incompatible changes to workflow definition code could cause non-deterministic issues when processing workflow tasks if versioning is not done correctly. However, it may be hard for you to tell if a particular change is incompatible or not and whether versioning logic is needed. To help you identify incompatible changes and catch them before production traffic is impacted, we implemented Workflow Replayer and Workflow Shadower.","sidebar":"docsSidebar"},"go-client/workflow-testing":{"id":"go-client/workflow-testing","title":"Testing","description":"The Cadence Go client library provides a test framework to facilitate testing implementations.","sidebar":"docsSidebar"},"go-client/workflow-versioning":{"id":"go-client/workflow-versioning","title":"Versioning","description":"The definition code of a Cadence must be deterministic because Cadence uses sourcing","sidebar":"docsSidebar"},"java-client/activity-interface":{"id":"java-client/activity-interface","title":"Activity interface","description":"An is a manifestation of a particular in the business logic.","sidebar":"docsSidebar"},"java-client/child-workflows":{"id":"java-client/child-workflows","title":"Child workflows","description":"Besidesactivitiesworkflowworkflow.","sidebar":"docsSidebar"},"java-client/client-overview":{"id":"java-client/client-overview","title":"Client SDK Overview","description":"- Samples//github.com/cadence-workflow/cadence-java-samples","sidebar":"docsSidebar"},"java-client/continue-as-new":{"id":"java-client/continue-as-new","title":"Continue As New","description":"Workflows: that need to rerun periodically could naively be implemented as a big for loop with","sidebar":"docsSidebar"},"java-client/distributed-cron":{"id":"java-client/distributed-cron","title":"Distributed CRON","description":"It is relatively straightforward to turn any Cadence into a Cron. All you need","sidebar":"docsSidebar"},"java-client/exception-handling":{"id":"java-client/exception-handling","title":"Exception Handling","description":"By default, Exceptions thrown by an activity are received by the workflow wrapped into an com.uber.cadence.workflow.ActivityFailureException,","sidebar":"docsSidebar"},"java-client/implementing-activities":{"id":"java-client/implementing-activities","title":"Implementing activities","description":"Activityactivityactivity implementation"},"java-client/implementing-workflows":{"id":"java-client/implementing-workflows","title":"Implementing workflows","description":"A implementation implements a interface. Each time a new is started,","sidebar":"docsSidebar"},"java-client/index":{"id":"java-client/index","title":"Introduction","description":"The following are important links for the Cadence Java client:","sidebar":"docsSidebar"},"java-client/queries":{"id":"java-client/queries","title":"Queries","description":"Query is to expose this internal state to the external world Cadence provides a synchronous feature. From the implementer point of view the is exposed as a synchronous callback that is invoked by external entities. Multiple such callbacks can be provided per type exposing different information to different external systems.","sidebar":"docsSidebar"},"java-client/retries":{"id":"java-client/retries","title":"Retries","description":"Activitiesworkflow can fail due to various intermediate conditions. In those cases, we want","sidebar":"docsSidebar"},"java-client/side-effect":{"id":"java-client/side-effect","title":"Side Effect","description":"Side Effect allow workflow executes the provided function once, records its result into the workflow history.","sidebar":"docsSidebar"},"java-client/signals":{"id":"java-client/signals","title":"Signals","description":"Signalsworkflow:. Previously, you had","sidebar":"docsSidebar"},"java-client/starting-workflow-executions":{"id":"java-client/starting-workflow-executions","title":"Starting workflows","description":"Creating a WorkflowClient","sidebar":"docsSidebar"},"java-client/testing":{"id":"java-client/testing","title":"Testing","description":"TestActivityEnvironment is the helper class for unit testing activity implementations. Supports calls to Activity methods from the tested activities. An example test:","sidebar":"docsSidebar"},"java-client/versioning":{"id":"java-client/versioning","title":"Versioning","description":"As outlined in the Workflow Implementation Constraints section, code has to be deterministic by taking the same","sidebar":"docsSidebar"},"java-client/workers":{"id":"java-client/workers","title":"Worker service","description":"A or service is a service that hosts the and implementations. The polls the Cadence service fortaskstask, and communicates execution results back to the Cadence service.Worker: services are developed, deployed, and operated by Cadence customers.","sidebar":"docsSidebar"},"java-client/workflow-interface":{"id":"java-client/workflow-interface","title":"Workflow interface","description":"Workflowactivity and childworkflows:.","sidebar":"docsSidebar"},"java-client/workflow-replay-shadowing":{"id":"java-client/workflow-replay-shadowing","title":"Workflow Replay and Shadowing","description":"In the Versioning section, we mentioned that incompatible changes to workflow definition code could cause non-deterministic issues when processing workflow tasks if versioning is not done correctly. However, it may be hard for you to tell if a particular change is incompatible or not and whether versioning logic is needed. To help you identify incompatible changes and catch them before production traffic is impacted, we implemented Workflow Replayer and Workflow Shadower.","sidebar":"docsSidebar"},"operation-guide/index":{"id":"operation-guide/index","title":"Overview","description":"This document will cover things that you need to know to run a Cadence cluster in production. Topics including: setup, monitoring, maintenance and troubleshooting.","sidebar":"docsSidebar"},"operation-guide/maintain":{"id":"operation-guide/maintain","title":"Cluster Maintenance","description":"This includes how to use and maintain a Cadence cluster for both clients and server clusters.","sidebar":"docsSidebar"},"operation-guide/migration":{"id":"operation-guide/migration","title":"Cluster Migration","description":"There could be some reasons that you need to migrate Cadence clusters:","sidebar":"docsSidebar"},"operation-guide/monitoring":{"id":"operation-guide/monitoring","title":"Cluster Monitoring","description":"Instructions","sidebar":"docsSidebar"},"operation-guide/setup":{"id":"operation-guide/setup","title":"Cluster Configuration","description":"This section will help to understand what you need for setting up a Cadence cluster.","sidebar":"docsSidebar"},"operation-guide/troubleshooting":{"id":"operation-guide/troubleshooting","title":"Cluster Troubleshooting","description":"This section is to cover some common operation issues as a RunBook. Feel free to add more, or raise issues in the to ask for more in cadence-docs project.Or talk to us in Slack support channel!","sidebar":"docsSidebar"},"use-cases/batch-job":{"id":"use-cases/batch-job","title":"Batch job","description":"A lot of batch jobs are not pure data manipulation programs. For those, the existing big data frameworks are the best fit.","sidebar":"docsSidebar"},"use-cases/big-ml":{"id":"use-cases/big-ml","title":"Big data and ML","description":"A lot of companies build custom ETL and ML training and deployment solutions. Cadence is a good fit for a control plane for such applications.","sidebar":"docsSidebar"},"use-cases/deployment":{"id":"use-cases/deployment","title":"Deployment","description":"Implementing CI/CD pipelines and deployment of applications to containers or virtual or physical machines is a non-trivial process.","sidebar":"docsSidebar"},"use-cases/dsl":{"id":"use-cases/dsl","title":"DSL workflows","description":"Cadence supports implementing business logic directly in programming languages like Java and Go. But there are cases when","sidebar":"docsSidebar"},"use-cases/event-driven":{"id":"use-cases/event-driven","title":"Event driven application","description":"Many applications listen to multiple sources, update the state of correspondent business entities,","sidebar":"docsSidebar"},"use-cases/index":{"id":"use-cases/index","title":"Introduction","description":"As Cadence developers, we face a difficult non-technical problem: How to position and describe the Cadence platform.","sidebar":"docsSidebar"},"use-cases/interactive":{"id":"use-cases/interactive","title":"Interactive application","description":"Cadence is performant and scalable enough to support interactive applications. It can be used to track UI session state and","sidebar":"docsSidebar"},"use-cases/operational-management":{"id":"use-cases/operational-management","title":"Operational management","description":"Imagine that you have to create a self operating database similar to Amazon RDS. Cadence is used in multiple projects","sidebar":"docsSidebar"},"use-cases/orchestration":{"id":"use-cases/orchestration","title":"Orchestration","description":"It is common that some business processes are implemented as multiple microservice calls.","sidebar":"docsSidebar"},"use-cases/partitioned-scan":{"id":"use-cases/partitioned-scan","title":"Storage scan","description":"It is common to have large data sets partitioned across a large number of hosts or databases, or having billions of files in an Amazon S3 bucket.","sidebar":"docsSidebar"},"use-cases/periodic-execution":{"id":"use-cases/periodic-execution","title":"Periodic execution","description":"Periodic execution, frequently referred to as distributed cron, is when you execute business logic periodically. The advantage of Cadence for these scenarios is that it guarantees execution, sophisticated error handling, retry policies, and visibility into execution history.","sidebar":"docsSidebar"},"use-cases/polling":{"id":"use-cases/polling","title":"Polling","description":"Polling is executing a periodic action checking for a state change. Examples are pinging a host, calling a REST API, or listing an Amazon S3 bucket for newly uploaded files.","sidebar":"docsSidebar"},"use-cases/provisioning":{"id":"use-cases/provisioning","title":"Infrastructure provisioning","description":"Provisioning a new datacenter or a pool of machines in a public cloud is a potentially long running operation with","sidebar":"docsSidebar"},"workflow-troubleshooting/activity-failures":{"id":"workflow-troubleshooting/activity-failures","title":"Activity Failures","description":"An activity fails when it encounters an error during its execution. This results in ActivityTaskFailed event in the workflow execution with some details of the error. The different kinds of errors that can be seen in activity failures are listed here.","sidebar":"docsSidebar"},"workflow-troubleshooting/index":{"id":"workflow-troubleshooting/index","title":"Overview","description":"This document will serve as a guide for troubleshooting a workflow for potential issues.","sidebar":"docsSidebar"},"workflow-troubleshooting/retries":{"id":"workflow-troubleshooting/retries","title":"Retries","description":"Cadence has a retry feature where a retry policy can be configured so that an activity or a workflow will be retried when it fails or times out.","sidebar":"docsSidebar"},"workflow-troubleshooting/timeouts":{"id":"workflow-troubleshooting/timeouts","title":"Timeouts","description":"A workflow could fail if an activity times out and will timeout when the entire workflow execution times out. Workflows or activities time out when their time to execute or time to start has been longer than their configured timeout. Some of the common causes for timeouts have been listed here.","sidebar":"docsSidebar"}}}}')}}]); \ No newline at end of file diff --git a/assets/js/6e9b4a66.7fe6da2b.js b/assets/js/6e9b4a66.7fe6da2b.js new file mode 100644 index 000000000..73ec66067 --- /dev/null +++ b/assets/js/6e9b4a66.7fe6da2b.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[3252],{5907:(e,n,i)=>{i.r(n),i.d(n,{assets:()=>c,contentTitle:()=>o,default:()=>h,frontMatter:()=>s,metadata:()=>a,toc:()=>l});const a=JSON.parse('{"id":"operation-guide/monitoring","title":"Cluster Monitoring","description":"Instructions","source":"@site/docs/07-operation-guide/03-monitoring.md","sourceDirName":"07-operation-guide","slug":"/operation-guide/monitoring","permalink":"/Cadence-Docs/docs/operation-guide/monitoring","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/07-operation-guide/03-monitoring.md","tags":[],"version":"current","sidebarPosition":3,"frontMatter":{"layout":"default","title":"Cluster Monitoring","permalink":"/docs/operation-guide/monitor"},"sidebar":"docsSidebar","previous":{"title":"Cluster Maintenance","permalink":"/Cadence-Docs/docs/operation-guide/maintain"},"next":{"title":"Cluster Troubleshooting","permalink":"/Cadence-Docs/docs/operation-guide/troubleshooting"}}');var r=i(4848),t=i(8453);const s={layout:"default",title:"Cluster Monitoring",permalink:"/docs/operation-guide/monitor"},o="Cluster Monitoring",c={},l=[{value:"Instructions",id:"instructions",level:2},{value:"DataDog dashboard templates",id:"datadog-dashboard-templates",level:2},{value:"Grafana+Prometheus dashboard templates",id:"grafanaprometheus-dashboard-templates",level:2},{value:"Periodic tests(Canary) for health check",id:"periodic-testscanary-for-health-check",level:2},{value:"Cadence Frontend Monitoring",id:"cadence-frontend-monitoring",level:2},{value:"Service Availability(server metrics)",id:"service-availabilityserver-metrics",level:3},{value:"StartWorkflow Per Second",id:"startworkflow-per-second",level:3},{value:"Activities Started Per Second",id:"activities-started-per-second",level:3},{value:"Decisions Started Per Second",id:"decisions-started-per-second",level:3},{value:"Periodical Test Suite Success(aka Canary)",id:"periodical-test-suite-successaka-canary",level:3},{value:"Frontend all API per second",id:"frontend-all-api-per-second",level:3},{value:"Frontend API per second (breakdown per operation)",id:"frontend-api-per-second-breakdown-per-operation",level:3},{value:"Frontend API errors per second(breakdown per operation)",id:"frontend-api-errors-per-secondbreakdown-per-operation",level:3},{value:"Frontend Regular API Latency",id:"frontend-regular-api-latency",level:3},{value:"Frontend ListWorkflow API Latency",id:"frontend-listworkflow-api-latency",level:3},{value:"Frontend Long Poll API Latency",id:"frontend-long-poll-api-latency",level:3},{value:"Frontend Get History/Query Workflow API Latency",id:"frontend-get-historyquery-workflow-api-latency",level:3},{value:"Frontend WorkflowClient API per seconds by domain",id:"frontend-workflowclient-api-per-seconds-by-domain",level:3},{value:"Cadence Application Monitoring",id:"cadence-application-monitoring",level:2},{value:"Workflow Start and Successful completion",id:"workflow-start-and-successful-completion",level:3},{value:"Workflow Failure",id:"workflow-failure",level:3},{value:"Decision Poll Counters",id:"decision-poll-counters",level:3},{value:"DecisionTasks Scheduled per second",id:"decisiontasks-scheduled-per-second",level:3},{value:"Decision Scheduled To Start Latency",id:"decision-scheduled-to-start-latency",level:3},{value:"Decision Execution Failure",id:"decision-execution-failure",level:3},{value:"Decision Execution Timeout",id:"decision-execution-timeout",level:3},{value:"Workflow End to End Latency",id:"workflow-end-to-end-latency",level:3},{value:"Workflow Panic and NonDeterministicError",id:"workflow-panic-and-nondeterministicerror",level:3},{value:"Workflow Sticky Cache Hit Rate and Miss Count",id:"workflow-sticky-cache-hit-rate-and-miss-count",level:3},{value:"Activity Task Operations",id:"activity-task-operations",level:3},{value:"Local Activity Task Operations",id:"local-activity-task-operations",level:3},{value:"Activity Execution Latency",id:"activity-execution-latency",level:3},{value:"Activity Poll Counters",id:"activity-poll-counters",level:3},{value:"ActivityTasks Scheduled per second",id:"activitytasks-scheduled-per-second",level:3},{value:"Activity Scheduled To Start Latency",id:"activity-scheduled-to-start-latency",level:3},{value:"Activity Failure",id:"activity-failure",level:3},{value:"Service API success rate",id:"service-api-success-rate",level:3},{value:"Service API Latency",id:"service-api-latency",level:3},{value:"Service API Breakdown",id:"service-api-breakdown",level:3},{value:"Service API Error Breakdown",id:"service-api-error-breakdown",level:3},{value:"Max Event Blob size",id:"max-event-blob-size",level:3},{value:"Max History Size",id:"max-history-size",level:3},{value:"Max History Length",id:"max-history-length",level:3},{value:"Cadence History Service Monitoring",id:"cadence-history-service-monitoring",level:2},{value:"History shard movements",id:"history-shard-movements",level:3},{value:"Transfer Tasks Per Second",id:"transfer-tasks-per-second",level:3},{value:"Timer Tasks Per Second",id:"timer-tasks-per-second",level:3},{value:"Transfer Tasks Per Domain",id:"transfer-tasks-per-domain",level:3},{value:"Timer Tasks Per Domain",id:"timer-tasks-per-domain",level:3},{value:"Transfer Latency by Type",id:"transfer-latency-by-type",level:3},{value:"Timer Task Latency by type",id:"timer-task-latency-by-type",level:3},{value:"NOTE: Task Queue Latency vs Executing Latency vs Processing Latency In Transfer & Timer Task Latency Metrics",id:"note-task-queue-latency-vs-executing-latency-vs-processing-latency-in-transfer--timer-task-latency-metrics",level:3},{value:"Transfer Task Latency Per Domain",id:"transfer-task-latency-per-domain",level:3},{value:"Timer Task Latency Per Domain",id:"timer-task-latency-per-domain",level:3},{value:"History API per Second",id:"history-api-per-second",level:3},{value:"History API Errors per Second",id:"history-api-errors-per-second",level:3},{value:"Max History Size",id:"max-history-size-1",level:3},{value:"Max History Length",id:"max-history-length-1",level:3},{value:"Max Event Blob Size",id:"max-event-blob-size-1",level:3},{value:"Cadence Matching Service Monitoring",id:"cadence-matching-service-monitoring",level:2},{value:"Matching APIs per Second",id:"matching-apis-per-second",level:3},{value:"Matching API Errors per Second",id:"matching-api-errors-per-second",level:3},{value:"Matching Regular API Latency",id:"matching-regular-api-latency",level:3},{value:"Sync Match Latency:",id:"sync-match-latency",level:3},{value:"Async match Latency",id:"async-match-latency",level:3},{value:"Cadence Default Persistence Monitoring",id:"cadence-default-persistence-monitoring",level:2},{value:"Persistence Availability",id:"persistence-availability",level:3},{value:"Persistence By Service TPS",id:"persistence-by-service-tps",level:3},{value:"Persistence By Operation TPS",id:"persistence-by-operation-tps",level:3},{value:"Persistence By Operation Latency",id:"persistence-by-operation-latency",level:3},{value:"Persistence Error By Operation Count",id:"persistence-error-by-operation-count",level:3},{value:"Cadence Advanced Visibility Persistence Monitoring(if applicable)",id:"cadence-advanced-visibility-persistence-monitoringif-applicable",level:2},{value:"Persistence Availability",id:"persistence-availability-1",level:3},{value:"Persistence By Service TPS",id:"persistence-by-service-tps-1",level:3},{value:"Persistence By Operation TPS(read: ES, write: Kafka)",id:"persistence-by-operation-tpsread-es-write-kafka",level:3},{value:"Persistence By Operation Latency(in seconds) (read: ES, write: Kafka)",id:"persistence-by-operation-latencyin-seconds-read-es-write-kafka",level:3},{value:"Persistence Error By Operation Count (read: ES, write: Kafka)",id:"persistence-error-by-operation-count-read-es-write-kafka",level:3},{value:"Kafka->ES processor counter",id:"kafka-es-processor-counter",level:3},{value:"Kafka->ES processor error",id:"kafka-es-processor-error",level:3},{value:"Kafka->ES processor latency",id:"kafka-es-processor-latency",level:3},{value:"Cadence Dependency Metrics Monitor suggestion",id:"cadence-dependency-metrics-monitor-suggestion",level:2},{value:"Computing platform metrics for Cadence deployment",id:"computing-platform-metrics-for-cadence-deployment",level:3},{value:"Database",id:"database",level:3},{value:"Kafka (if applicable)",id:"kafka-if-applicable",level:3},{value:"ElasticSearch (if applicable)",id:"elasticsearch-if-applicable",level:3},{value:"Cadence Service SLO Recommendation",id:"cadence-service-slo-recommendation",level:2}];function d(e){const n={a:"a",code:"code",h1:"h1",h2:"h2",h3:"h3",header:"header",li:"li",p:"p",pre:"pre",ul:"ul",...(0,t.R)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(n.header,{children:(0,r.jsx)(n.h1,{id:"cluster-monitoring",children:"Cluster Monitoring"})}),"\n",(0,r.jsx)(n.h2,{id:"instructions",children:"Instructions"}),"\n",(0,r.jsx)(n.p,{children:"Cadence emits metrics for both Server and client libraries:"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsxs)(n.p,{children:["Follow this example to emit ",(0,r.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence-samples/pull/36",children:"client side metrics for Golang client"})]}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:["You can use other metrics emitter like ",(0,r.jsx)(n.a,{href:"https://github.com/uber-go/tally/tree/master/m3",children:"M3"})]}),"\n",(0,r.jsxs)(n.li,{children:["Alternatively, you can implement the tally ",(0,r.jsx)(n.a,{href:"https://github.com/uber-go/tally/blob/master/reporter.go",children:"Reporter interface"})]}),"\n"]}),"\n"]}),"\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsxs)(n.p,{children:["Follow this example to emit ",(0,r.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence-java-samples/blob/master/src/main/java/com/uber/cadence/samples/hello/HelloMetric.java",children:"client side metrics for Java client"})," if using 3.x client, or ",(0,r.jsx)(n.a,{href:"https://github.com/longquanzheng/cadence-java-samples-1/pull/1",children:"this example"})," if using 2.x client."]}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:["You can use other metrics emitter like ",(0,r.jsx)(n.a,{href:"https://github.com/uber-java/tally/tree/master/m3",children:"M3"})]}),"\n",(0,r.jsxs)(n.li,{children:["Alternatively, you can implement the tally ",(0,r.jsx)(n.a,{href:"https://github.com/uber-java/tally/blob/master/core/src/main/java/com/uber/m3/tally/Scope.java",children:"Reporter interface"})]}),"\n"]}),"\n"]}),"\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsxs)(n.p,{children:["For running Cadence services in production, please follow this ",(0,r.jsx)(n.a,{href:"https://github.com/banzaicloud/banzai-charts/blob/master/cadence/templates/server-service-monitor.yaml",children:"example of hemlchart"})," to emit server side metrics. Or you can follow ",(0,r.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence/blob/master/config/development_prometheus.yaml#L40",children:"the example of local environment"})," to Prometheus. All services need to expose a HTTP port to provide metircs like below"]}),"\n"]}),"\n"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-yaml",children:'metrics:\n prometheus:\n timerType: "histogram"\n listenAddress: "0.0.0.0:8001"\n'})}),"\n",(0,r.jsx)(n.p,{children:"The rest of the instruction uses local environment as an example."}),"\n",(0,r.jsxs)(n.p,{children:["For testing local server emitting metrics to Promethues, the easiest way is to use ",(0,r.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence/blob/master/docker/",children:"docker-compose"})," to start a local Cadence instance."]}),"\n",(0,r.jsxs)(n.p,{children:["Make sure to update the ",(0,r.jsx)(n.code,{children:"prometheus_config.yml"}),' to add "host.docker.internal:9098" to the scrape list before starting the docker-compose:']}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-yaml",children:"global:\n scrape_interval: 5s\n external_labels:\n monitor: 'cadence-monitor'\nscrape_configs:\n - job_name: 'prometheus'\n static_configs:\n - targets: # addresses to scrape\n - 'cadence:9090'\n - 'cadence:8000'\n - 'cadence:8001'\n - 'cadence:8002'\n - 'cadence:8003'\n - 'host.docker.internal:9098'\n"})}),"\n",(0,r.jsxs)(n.p,{children:["Note: ",(0,r.jsx)(n.code,{children:"host.docker.internal"})," ",(0,r.jsx)(n.a,{href:"https://docs.docker.com/docker-for-mac/networking/#use-cases-and-workarounds",children:"may not work for some docker versions"})]}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsxs)(n.p,{children:["After updating the prometheus_config.yaml as above, run ",(0,r.jsx)(n.code,{children:"docker-compose up"})," to start the local Cadence instance"]}),"\n"]}),"\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsxs)(n.p,{children:["Go the the sample repo, build the helloworld sample ",(0,r.jsx)(n.code,{children:"make helloworld"})," and run the worker ",(0,r.jsx)(n.code,{children:"./bin/helloworld -m worker"}),", and then in another Shell start a workflow ",(0,r.jsx)(n.code,{children:"./bin/helloworld"})]}),"\n"]}),"\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsxs)(n.p,{children:["Go to your ",(0,r.jsx)(n.a,{href:"http://localhost:9090/",children:"local Prometheus dashboard"}),", you should be able to check the metrics emitted by handler from client/frontend/matching/history/sysWorker and confirm your services are healthy through ",(0,r.jsx)(n.a,{href:"http://localhost:9090/targets",children:"targets"})]}),"\n"]}),"\n"]}),"\n",(0,r.jsx)("img",{width:"1192",alt:"Screen Shot 2021-02-20 at 11 31 11 AM",src:"https://user-images.githubusercontent.com/4523955/108606555-8d0dfb80-736f-11eb-968d-7678df37455c.png"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:["Go to ",(0,r.jsx)(n.a,{href:"http://localhost:3000",children:"local Grafana"})," , login as ",(0,r.jsx)(n.code,{children:"admin/admin"}),"."]}),"\n",(0,r.jsxs)(n.li,{children:["Configure Prometheus as datasource: use ",(0,r.jsx)(n.code,{children:"http://host.docker.internal:9090"})," as URL of prometheus."]}),"\n",(0,r.jsxs)(n.li,{children:["Import the ",(0,r.jsx)(n.a,{href:"monitoring#grafanaprometheus-dashboard-templates",children:"Grafana dashboard tempalte"})," as JSON files."]}),"\n"]}),"\n",(0,r.jsx)(n.p,{children:"Client side dashboard looks like this:"}),"\n",(0,r.jsx)("img",{width:"1513",alt:"Screen Shot 2021-02-20 at 12 32 23 PM",src:"https://user-images.githubusercontent.com/4523955/108607838-b7fc4d80-7377-11eb-8fd9-edc0e58afaad.png"}),"\n",(0,r.jsx)(n.p,{children:"And server basic dashboard:"}),"\n",(0,r.jsx)("img",{width:"1514",alt:"Screen Shot 2021-02-20 at 12 31 54 PM",src:"https://user-images.githubusercontent.com/4523955/108607843-baf73e00-7377-11eb-9759-e67a1a00f442.png"}),"\n",(0,r.jsx)("img",{width:"1519",alt:"Screen Shot 2021-02-20 at 11 06 54 AM",src:"https://user-images.githubusercontent.com/4523955/108606577-b169d800-736f-11eb-8fcb-88801f23b656.png"}),"\n",(0,r.jsx)(n.h2,{id:"datadog-dashboard-templates",children:"DataDog dashboard templates"}),"\n",(0,r.jsxs)(n.p,{children:["This ",(0,r.jsx)(n.a,{href:"https://github.com/cadence-workflow/Cadence-Docs/tree/master/src/datadog",children:"package"})," contains examples of Cadence dashboards with DataDog."]}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"Cadence-Client"})," is the dashboard that includes all the metrics to help you understand Cadence client behavior. Most of these metrics are emitted by the client SDKs, with a few exceptions from server side (for example, workflow timeout)."]}),"\n"]}),"\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"Cadence-Server"})," is the the server dashboard that you can use to monitor and undertand the health and status of your Cadence cluster."]}),"\n"]}),"\n"]}),"\n",(0,r.jsxs)(n.p,{children:["To use DataDog with Cadence, follow ",(0,r.jsx)(n.a,{href:"https://docs.datadoghq.com/integrations/guide/prometheus-metrics/",children:"this instruction"})," to collect Prometheus metrics using DataDog agent."]}),"\n",(0,r.jsxs)(n.p,{children:["NOTE1: don't forget to adjust ",(0,r.jsx)(n.code,{children:"max_returned_metrics"})," to a higher number(e.g. 100000). Otherwise DataDog agent won't be able to ",(0,r.jsx)(n.a,{href:"https://docs.datadoghq.com/integrations/guide/prometheus-host-collection/",children:"collect all metrics(default is 2000)"}),"."]}),"\n",(0,r.jsxs)(n.p,{children:["NOTE2: the template contains templating variables ",(0,r.jsx)(n.code,{children:"$App"})," and ",(0,r.jsx)(n.code,{children:"$Availability_Zone"}),". Feel free to remove them if you don't have them in your setup."]}),"\n",(0,r.jsx)(n.h2,{id:"grafanaprometheus-dashboard-templates",children:"Grafana+Prometheus dashboard templates"}),"\n",(0,r.jsxs)(n.p,{children:["This ",(0,r.jsx)(n.a,{href:"https://github.com/cadence-workflow/Cadence-Docs/tree/master/src/grafana/prometheus",children:"package"})," contains examples of Cadence dashboards with Prometheus."]}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"Cadence-Client"})," is the dashboard of client metrics, and a few server side metrics that belong to client side but have to be emitted by server(for example, workflow timeout)."]}),"\n"]}),"\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"Cadence-Server-Basic"})," is the the basic server dashboard to monitor/navigate the health/status of a Cadence cluster."]}),"\n"]}),"\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsxs)(n.p,{children:["Apart from the basic server dashboard, it's recommended to set up dashboards on different components for Cadence server: Frontend, History, Matching, Worker, Persistence, Archival, etc. Any ",(0,r.jsx)(n.a,{href:"https://github.com/cadence-workflow/Cadence-Docs",children:"contribution"})," is always welcome to enrich the existing templates or new templates!"]}),"\n"]}),"\n"]}),"\n",(0,r.jsx)(n.h2,{id:"periodic-testscanary-for-health-check",children:"Periodic tests(Canary) for health check"}),"\n",(0,r.jsxs)(n.p,{children:["It's recommended that you run periodical test to get signals on the healthness of your cluster. Please following instructions in ",(0,r.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence/tree/master/canary",children:"our canary package"})," to set these tests up."]}),"\n",(0,r.jsx)(n.h2,{id:"cadence-frontend-monitoring",children:"Cadence Frontend Monitoring"}),"\n",(0,r.jsx)(n.p,{children:"This section describes recommended dashboards for monitoring Cadence services in your cluster. The structure mostly follows the DataDog dashboard template listed above."}),"\n",(0,r.jsx)(n.h3,{id:"service-availabilityserver-metrics",children:"Service Availability(server metrics)"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"Meaning: the availability of Cadence server using server metrics."}),"\n",(0,r.jsx)(n.li,{children:"Suggested monitor: below 95% > 5 min then alert, below 99% for > 5 min triggers a warning"}),"\n",(0,r.jsx)(n.li,{children:"Monitor action: When fired, check if there is any persistence errors. If so then check the healthness of the database(may need to restart or scale up). If not then check the error logs."}),"\n",(0,r.jsx)(n.li,{children:"Datadog query example"}),"\n"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-dql",children:"sum:cadence_frontend.cadence_errors{*}\nsum:cadence_frontend.cadence_requests{*}\n(1 - a / b) * 100\n"})}),"\n",(0,r.jsx)(n.h3,{id:"startworkflow-per-second",children:"StartWorkflow Per Second"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"Meaning: how many workflows are started per second. This helps determine if your server is overloaded."}),"\n",(0,r.jsx)(n.li,{children:"Suggested monitor: This is a business metrics. No monitoring required."}),"\n",(0,r.jsx)(n.li,{children:"Datadog query example"}),"\n"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-dql",children:"sum:cadence_frontend.cadence_requests{(operation IN (startworkflowexecution,signalwithstartworkflowexecution))} by {operation}.as_rate()\n"})}),"\n",(0,r.jsx)(n.h3,{id:"activities-started-per-second",children:"Activities Started Per Second"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"Meaning: How many activities are started per second. Helps determine if the server is overloaded."}),"\n",(0,r.jsx)(n.li,{children:"Suggested monitor: This is a business metrics. No monitoring required."}),"\n",(0,r.jsx)(n.li,{children:"Datadog query example"}),"\n"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-dql",children:"sum:cadence_frontend.cadence_requests{operation:pollforactivitytask} by {operation}.as_rate()\n"})}),"\n",(0,r.jsx)(n.h3,{id:"decisions-started-per-second",children:"Decisions Started Per Second"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"Meaning: How many workflow decisions are started per second. Helps determine if the server is overloaded."}),"\n",(0,r.jsx)(n.li,{children:"Suggested monitor: This is a business metrics. No monitoring required."}),"\n",(0,r.jsx)(n.li,{children:"Datadog query example"}),"\n"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-dql",children:"sum:cadence_frontend.cadence_requests{operation:pollfordecisiontask} by {operation}.as_rate()\n"})}),"\n",(0,r.jsx)(n.h3,{id:"periodical-test-suite-successaka-canary",children:"Periodical Test Suite Success(aka Canary)"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"Meaning: The success counter of canary test suite"}),"\n",(0,r.jsx)(n.li,{children:"Suggested monitor: Monitor needed. If fired, look at the failed canary test case and investigate the reason of failure."}),"\n",(0,r.jsx)(n.li,{children:"Datadog query example"}),"\n"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-dql",children:"sum:cadence_history.workflow_success{workflowtype:workflow_sanity} by {workflowtype}.as_count()\n"})}),"\n",(0,r.jsx)(n.h3,{id:"frontend-all-api-per-second",children:"Frontend all API per second"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"Meaning: all API on frontend per second. Information only."}),"\n",(0,r.jsx)(n.li,{children:"Suggested monitor: This is a business metrics. No monitoring required."}),"\n",(0,r.jsx)(n.li,{children:"Datadog query example"}),"\n"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-dql",children:"sum:cadence_frontend.cadence_requests{*}.as_rate()\n"})}),"\n",(0,r.jsx)(n.h3,{id:"frontend-api-per-second-breakdown-per-operation",children:"Frontend API per second (breakdown per operation)"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"Meaning: API on frontend per second. Information only."}),"\n",(0,r.jsx)(n.li,{children:"Suggested monitor: This is a business metrics. No monitoring required."}),"\n",(0,r.jsx)(n.li,{children:"Datadog query example"}),"\n"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-dql",children:"sum:cadence_frontend.cadence_requests{*} by {operation}.as_rate()\n"})}),"\n",(0,r.jsx)(n.h3,{id:"frontend-api-errors-per-secondbreakdown-per-operation",children:"Frontend API errors per second(breakdown per operation)"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"Meaning: API error on frontend per second. Information only."}),"\n",(0,r.jsx)(n.li,{children:"Suggested monitor: This is to facilitate investigation. No monitoring required."}),"\n",(0,r.jsx)(n.li,{children:"Datadog query example"}),"\n"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-dql",children:"sum:cadence_frontend.cadence_errors{*} by {operation}.as_rate()\nsum:cadence_frontend.cadence_errors_bad_request{*} by {operation}.as_rate()\nsum:cadence_frontend.cadence_errors_domain_not_active{*} by {operation}.as_rate()\nsum:cadence_frontend.cadence_errors_service_busy{*} by {operation}.as_rate()\nsum:cadence_frontend.cadence_errors_entity_not_exists{*} by {operation}.as_rate()\nsum:cadence_frontend.cadence_errors_workflow_execution_already_completed{*} by {operation}.as_rate()\nsum:cadence_frontend.cadence_errors_execution_already_started{*} by {operation}.as_rate()\nsum:cadence_frontend.cadence_errors_domain_already_exists{*} by {operation}.as_rate()\nsum:cadence_frontend.cadence_errors_cancellation_already_requested{*} by {operation}.as_rate()\nsum:cadence_frontend.cadence_errors_query_failed{*} by {operation}.as_rate()\nsum:cadence_frontend.cadence_errors_limit_exceeded{*} by {operation}.as_rate()\nsum:cadence_frontend.cadence_errors_context_timeout{*} by {operation}.as_rate()\nsum:cadence_frontend.cadence_errors_retry_task{*} by {operation}.as_rate()\nsum:cadence_frontend.cadence_errors_bad_binary{*} by {operation}.as_rate()\nsum:cadence_frontend.cadence_errors_client_version_not_supported{*} by {operation}.as_rate()\nsum:cadence_frontend.cadence_errors_incomplete_history{*} by {operation}.as_rate()\nsum:cadence_frontend.cadence_errors_nondeterministic{*} by {operation}.as_rate()\nsum:cadence_frontend.cadence_errors_unauthorized{*} by {operation}.as_rate()\nsum:cadence_frontend.cadence_errors_authorize_failed{*} by {operation}.as_rate()\nsum:cadence_frontend.cadence_errors_remote_syncmatch_failed{*} by {operation}.as_rate()\nsum:cadence_frontend.cadence_errors_domain_name_exceeded_warn_limit{*} by {operation}.as_rate()\nsum:cadence_frontend.cadence_errors_identity_exceeded_warn_limit{*} by {operation}.as_rate()\nsum:cadence_frontend.cadence_errors_workflow_id_exceeded_warn_limit{*} by {operation}.as_rate()\nsum:cadence_frontend.cadence_errors_signal_name_exceeded_warn_limit{*} by {operation}.as_rate()\nsum:cadence_frontend.cadence_errors_workflow_type_exceeded_warn_limit{*} by {operation}.as_rate()\nsum:cadence_frontend.cadence_errors_request_id_exceeded_warn_limit{*} by {operation}.as_rate()\nsum:cadence_frontend.cadence_errors_task_list_name_exceeded_warn_limit{*} by {operation}.as_rate()\nsum:cadence_frontend.cadence_errors_activity_id_exceeded_warn_limit{*} by {operation}.as_rate()\nsum:cadence_frontend.cadence_errors_activity_type_exceeded_warn_limit{*} by {operation}.as_rate()\nsum:cadence_frontend.cadence_errors_marker_name_exceeded_warn_limit{*} by {operation}.as_rate()\nsum:cadence_frontend.cadence_errors_timer_id_exceeded_warn_limit{*} by {operation}.as_rate()\n"})}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.code,{children:"cadence_errors"})," is internal service errors."]}),"\n",(0,r.jsxs)(n.li,{children:["any ",(0,r.jsx)(n.code,{children:"cadence_errors_*"})," is client side error"]}),"\n"]}),"\n",(0,r.jsx)(n.h3,{id:"frontend-regular-api-latency",children:"Frontend Regular API Latency"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"Meaning: The latency of regular core API -- excluding long-poll/queryWorkflow/getHistory/ListWorkflow/CountWorkflow API."}),"\n",(0,r.jsx)(n.li,{children:"Suggested monitor: 95% of all apis and of all operations that take over 1.5 seconds triggers a warning, over 2 seconds triggers an alert"}),"\n",(0,r.jsx)(n.li,{children:"Monitor action: If fired, investigate the database read/write latency. May need to throttle some spiky traffic from certain domains, or scale up the database"}),"\n",(0,r.jsx)(n.li,{children:"Datadog query example"}),"\n"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-dql",children:"avg:cadence_frontend.cadence_latency.quantile{(operation NOT IN (pollfordecisiontask,pollforactivitytask,getworkflowexecutionhistory,queryworkflow,listworkflowexecutions,listclosedworkflowexecutions,listopenworkflowexecutions)) AND $pXXLatency} by {operation}\n"})}),"\n",(0,r.jsx)(n.h3,{id:"frontend-listworkflow-api-latency",children:"Frontend ListWorkflow API Latency"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"Meaning: The latency of ListWorkflow API."}),"\n",(0,r.jsx)(n.li,{children:"Monitor: 95% of all apis and of all operations that take over 2 seconds triggers a warning, over 3 seconds triggers an alert"}),"\n",(0,r.jsx)(n.li,{children:"Monitor action: If fired, investigate the ElasticSearch read latency. May need to throttle some spiky traffic from certain domains, or scale up ElasticSearch cluster."}),"\n",(0,r.jsx)(n.li,{children:"Datadog query example"}),"\n"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-dql",children:"avg:cadence_frontend.cadence_latency.quantile{(operation IN (listclosedworkflowexecutions,listopenworkflowexecutions,listworkflowexecutions,countworkflowexecutions)) AND $pXXLatency} by {operation}\n"})}),"\n",(0,r.jsx)(n.h3,{id:"frontend-long-poll-api-latency",children:"Frontend Long Poll API Latency"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"Meaning: Long poll means that the worker is waiting for a task. The latency is an Indicator for how busy the worker is. Poll for activity task and poll for decision task are the types of long poll requests.The api call times out at 50 seconds if no task can be picked up.A very low latency could mean that more workers need to be added."}),"\n",(0,r.jsx)(n.li,{children:"Suggested monitor: No monitor needed as long latency is expected."}),"\n",(0,r.jsx)(n.li,{children:"Datadog query example"}),"\n"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-dql",children:"avg:cadence_frontend.cadence_latency.quantile{$pXXLatency,operation:pollforactivitytask} by {operation}\navg:cadence_frontend.cadence_latency.quantile{$pXXLatency,operation:pollfordecisiontask} by {operation}\n"})}),"\n",(0,r.jsx)(n.h3,{id:"frontend-get-historyquery-workflow-api-latency",children:"Frontend Get History/Query Workflow API Latency"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"Meaning: GetHistory API acts like a long poll api, but there\u2019s no explicit timeout. Long-poll of GetHistory is being used when WorkflowClient is waiting for the result of the workflow(essentially, WorkflowExecutionCompletedEvent).\nThis latency depends on the time it takes for the workflow to complete. QueryWorkflow API latency is also unpredictable as it depends on the availability and performance of workflow workers, which are owned by the application and workflow implementation(may require replaying history)."}),"\n",(0,r.jsx)(n.li,{children:"Suggested monitor: No monitor needed"}),"\n",(0,r.jsx)(n.li,{children:"Datadog query example"}),"\n"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-dql",children:"avg:cadence_frontend.cadence_latency.quantile{(operation IN (getworkflowexecutionhistory,queryworkflow)) AND $pXXLatency} by {operation}\n"})}),"\n",(0,r.jsx)(n.h3,{id:"frontend-workflowclient-api-per-seconds-by-domain",children:"Frontend WorkflowClient API per seconds by domain"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"Meaning: Shows which domains are making the most requests using WorkflowClient(excluding worker API like PollForDecisionTask and RespondDecisionTaskCompleted). Used for troubleshooting.\nIn the future it can be used to set some rate limiting per domain."}),"\n",(0,r.jsx)(n.li,{children:"Suggested monitor: No monitor needed."}),"\n",(0,r.jsx)(n.li,{children:"Datadog query example"}),"\n"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-dql",children:"sum:cadence_frontend.cadence_requests{(operation IN (signalwithstartworkflowexecution,signalworkflowexecution,startworkflowexecution,terminateworkflowexecution,resetworkflowexecution,requestcancelworkflowexecution,listworkflowexecutions))} by {domain,operation}.as_rate()\n"})}),"\n",(0,r.jsx)(n.h2,{id:"cadence-application-monitoring",children:"Cadence Application Monitoring"}),"\n",(0,r.jsxs)(n.p,{children:["This section describes the recommended dashboards for monitoring Cadence application using metrics emitted by SDK. See the ",(0,r.jsx)(n.code,{children:"setup"})," section about how to collect those metrics."]}),"\n",(0,r.jsx)(n.h3,{id:"workflow-start-and-successful-completion",children:"Workflow Start and Successful completion"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"Workflow successfully started/signalWithStart and completed/canceled/continuedAsNew"}),"\n",(0,r.jsx)(n.li,{children:"Monitor: not recommended"}),"\n",(0,r.jsx)(n.li,{children:"Datadog query example"}),"\n"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-dql",children:"sum:cadence_client.cadence_workflow_start{$Domain,$Tasklist,$WorkflowType} by {workflowtype,env,domain,tasklist}.as_rate()\nsum:cadence_client.cadence_workflow_completed{$Domain,$Tasklist,$WorkflowType} by {workflowtype,env,domain,tasklist}.as_rate()\nsum:cadence_client.cadence_workflow_canceled{$Domain,$Tasklist,$WorkflowType} by {workflowtype,domain,env,tasklist}.as_rate()\nsum:cadence_client.cadence_workflow_continue_as_new{$Domain,$Tasklist,$WorkflowType} by {workflowtype,domain,env,tasklist}.as_rate()\nsum:cadence_client.cadence_workflow_signal_with_start{$Domain,$Tasklist,$WorkflowType} by {workflowtype,domain,env,tasklist}.as_rate()\n"})}),"\n",(0,r.jsx)(n.h3,{id:"workflow-failure",children:"Workflow Failure"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"Metrics for all types of failures, including workflow failures(throw uncaught exceptions), workflow timeout and termination."}),"\n",(0,r.jsx)(n.li,{children:"For timeout and termination, workflow worker doesn\u2019t have a chance to emit metrics when it\u2019s terminate, so the metric comes from the history service"}),"\n",(0,r.jsx)(n.li,{children:"Monitor: application should set monitor on timeout and failure to make sure workflow are not failing. Cancel/terminate are usually triggered by human intentionally."}),"\n",(0,r.jsx)(n.li,{children:"When the metrics fire, go to Cadence UI to find the failed workflows and investigate the workflow history to understand the type of failure"}),"\n",(0,r.jsx)(n.li,{children:"Datadog query example"}),"\n"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-dql",children:"sum:cadence_client.cadence_workflow_failed{$Domain,$Tasklist,$WorkflowType} by {workflowtype,domain,env}.as_count()\nsum:cadence_history.workflow_failed{$Domain,$WorkflowType} by {domain,env,workflowtype}.as_count()\nsum:cadence_history.workflow_terminate{$Domain,$WorkflowType} by {domain,env,workflowtype}.as_count()\nsum:cadence_history.workflow_timeout{$Domain,$WorkflowType} by {domain,env,workflowtype}.as_count()\n"})}),"\n",(0,r.jsx)(n.h3,{id:"decision-poll-counters",children:"Decision Poll Counters"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"Indicates if the workflow worker is available and is polling tasks. If the worker is not available no counters will show.\nCan also check if the worker is using the right task list.\n\u201cNo task\u201d poll type means that the worker exists and is idle.\nThe timeout for this long poll api is 50 seconds. If no task is received within 50 seconds, then an empty response will be returned and another long poll request will be sent."}),"\n",(0,r.jsx)(n.li,{children:"Monitor: application can should monitor on it to make sure workers are available"}),"\n",(0,r.jsx)(n.li,{children:"When fires, investigate the worker deployment to see why they are not available, also check if they are using the right domain/tasklist"}),"\n",(0,r.jsx)(n.li,{children:"Datadog query example"}),"\n"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-dql",children:"sum:cadence_client.cadence_decision_poll_total{$Domain,$Tasklist}.as_count()\nsum:cadence_client.cadence_decision_poll_failed{$Domain,$Tasklist}.as_count()\nsum:cadence_client.cadence_decision_poll_no_task{$Domain,$Tasklist}.as_count()\nsum:cadence_client.cadence_decision_poll_succeed{$Domain,$Tasklist}.as_count()\n"})}),"\n",(0,r.jsx)(n.h3,{id:"decisiontasks-scheduled-per-second",children:"DecisionTasks Scheduled per second"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"Indicate how many decision tasks are scheduled"}),"\n",(0,r.jsx)(n.li,{children:"Monitor: not recommended -- Information only to know whether or not a tasklist is overloaded"}),"\n",(0,r.jsx)(n.li,{children:"Datadog query example"}),"\n"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-dql",children:"sum:cadence_matching.cadence_requests_per_tl{*,operation:adddecisiontask,$Tasklist,$Domain} by {tasklist,domain}.as_rate()\n"})}),"\n",(0,r.jsx)(n.h3,{id:"decision-scheduled-to-start-latency",children:"Decision Scheduled To Start Latency"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"If this latency is too high then either:\nThe worker is not available or too busy after the task has been scheduled.\nThe task list is overloaded(confirmed by DecisionTaskScheduled per second widget). By default a task list only has one partition and a partition can only be owned by one host and so the throughput of a task list is limited. More task lists can be added to scale or a scalable task list can be used to add more partitions."}),"\n",(0,r.jsx)(n.li,{children:"Monitor: application can set monitor on it to make sure latency is tolerable"}),"\n",(0,r.jsx)(n.li,{children:"When fired, check if worker capacity is enough, then check if tasklist is overloaded. If needed, contact the Cadence cluster Admin to enable scalable tasklist to add more partitions to the tasklist"}),"\n",(0,r.jsx)(n.li,{children:"Datadog query example"}),"\n"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-dql",children:"avg:cadence_client.cadence_decision_scheduled_to_start_latency.avg{$Domain,$Tasklist} by {env,domain,tasklist}\nmax:cadence_client.cadence_decision_scheduled_to_start_latency.max{$Domain,$Tasklist} by {env,domain,tasklist}\nmax:cadence_client.cadence_decision_scheduled_to_start_latency.95percentile{$Domain,$Tasklist} by {env,domain,tasklist}\n"})}),"\n",(0,r.jsx)(n.h3,{id:"decision-execution-failure",children:"Decision Execution Failure"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"This means some critical bugs in workflow code causing decision task execution failure"}),"\n",(0,r.jsx)(n.li,{children:"Monitor: application should set monitor on it to make sure no consistent failure"}),"\n",(0,r.jsx)(n.li,{children:"When fired, you may need to terminate the problematic workflows to mitigate the issue. After you identify the bugs, you can fix the code and then reset the workflow to recover"}),"\n",(0,r.jsx)(n.li,{children:"Datadog query example"}),"\n"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-dql",children:"sum:cadence_client.cadence_decision_execution_failed{$Domain,$Tasklist} by {tasklist,workflowtype}.as_count()\n"})}),"\n",(0,r.jsx)(n.h3,{id:"decision-execution-timeout",children:"Decision Execution Timeout"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"This means some critical bugs in workflow code causing decision task execution timeout"}),"\n",(0,r.jsx)(n.li,{children:"Monitor: application should set monitor on it to make sure no consistent timeout"}),"\n",(0,r.jsx)(n.li,{children:"When fired, you may need to terminate the problematic workflows to mitigate the issue. After you identify the bugs, you can fix the code and then reset the workflow to recover"}),"\n",(0,r.jsx)(n.li,{children:"Datadog query example"}),"\n"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-dql",children:"sum:cadence_history.start_to_close_timeout{operation:timeractivetaskdecision*,$Domain}.as_count()\n"})}),"\n",(0,r.jsx)(n.h3,{id:"workflow-end-to-end-latency",children:"Workflow End to End Latency"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"This is for the client application to track their SLOs\nFor example, if you expect a workflow to take duration d to complete, you can use this latency to set a monitor."}),"\n",(0,r.jsx)(n.li,{children:"Monitor: application can monitor this metrics if expecting workflow to complete within a certain duration."}),"\n",(0,r.jsx)(n.li,{children:"When fired, investigate the workflow history to see the workflow takes longer than expected to complete"}),"\n",(0,r.jsx)(n.li,{children:"Datadog query example"}),"\n"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-dql",children:"avg:cadence_client.cadence_workflow_endtoend_latency.median{$Domain,$Tasklist,$WorkflowType} by {env,domain,tasklist,workflowtype}\navg:cadence_client.cadence_workflow_endtoend_latency.95percentile{$Domain,$Tasklist,$WorkflowType} by {env,domain,tasklist,workflowtype}\n"})}),"\n",(0,r.jsx)(n.h3,{id:"workflow-panic-and-nondeterministicerror",children:"Workflow Panic and NonDeterministicError"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"These errors mean that there is a bug in the code and the deploy should be rolled back."}),"\n",(0,r.jsx)(n.li,{children:"A monitor should be set on this metric"}),"\n",(0,r.jsx)(n.li,{children:"When fired, you may rollback the deployment to mitigate your issue. Usually this caused by bad (non-backward compatible) code change. After rollback, look at your worker error logs to see where the bug is."}),"\n",(0,r.jsx)(n.li,{children:"Datadog query example"}),"\n"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-dql",children:"sum:cadence_client.cadence_worker_panic{$Domain} by {env,domain}.as_rate()\nsum:cadence_client.cadence_non_deterministic_error{$Domain} by {env,domain}.as_rate()\n"})}),"\n",(0,r.jsx)(n.h3,{id:"workflow-sticky-cache-hit-rate-and-miss-count",children:"Workflow Sticky Cache Hit Rate and Miss Count"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:["This metric can be used for performance optimization.\nThis can be improved by adding more worker instances, or adjust the workerOption(GoSDK) or WorkferFactoryOption(Java SDK).\nCacheHitRate too low means workers will have to replay history to rebuild the workflow stack when executing a decision task. Depending on the the history size","\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"If less than 1MB, then it\u2019s okay to be lower than 50%"}),"\n",(0,r.jsx)(n.li,{children:"If greater than 1MB, then it\u2019s okay to be greater than 50%"}),"\n",(0,r.jsx)(n.li,{children:"If greater than 5MB, , then it\u2019s okay to be greater than 60%"}),"\n",(0,r.jsx)(n.li,{children:"If greater than 10MB , then it\u2019s okay to be greater than 70%"}),"\n",(0,r.jsx)(n.li,{children:"If greater than 20MB , then it\u2019s okay to be greater than 80%"}),"\n",(0,r.jsx)(n.li,{children:"If greater than 30MB , then it\u2019s okay to be greater than 90%"}),"\n",(0,r.jsx)(n.li,{children:"Workflow history size should never be greater than 50MB."}),"\n"]}),"\n"]}),"\n",(0,r.jsx)(n.li,{children:"A monitor can be set on this metric, if performance is important."}),"\n",(0,r.jsx)(n.li,{children:"When fired, adjust the stickyCacheSize in the WorkerFactoryOption, or add more workers"}),"\n",(0,r.jsx)(n.li,{children:"Datadog query example"}),"\n"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-dql",children:"sum:cadence_client.cadence_sticky_cache_miss{$Domain} by {env,domain}.as_count()\nsum:cadence_client.cadence_sticky_cache_hit{$Domain} by {env,domain}.as_count()\n(b / (a+b)) * 100\n"})}),"\n",(0,r.jsx)(n.h3,{id:"activity-task-operations",children:"Activity Task Operations"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"Activity started/completed counters"}),"\n",(0,r.jsx)(n.li,{children:"Monitor: not recommended"}),"\n",(0,r.jsx)(n.li,{children:"Datadog query example"}),"\n"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-dql",children:"sum:cadence_client.cadence_activity_task_failed{$Domain,$Tasklist} by {activitytype}.as_rate()\nsum:cadence_client.cadence_activity_task_completed{$Domain,$Tasklist} by {activitytype}.as_rate()\nsum:cadence_client.cadence_activity_task_timeouted{$Domain,$Tasklist} by {activitytype}.as_rate()\n"})}),"\n",(0,r.jsx)(n.h3,{id:"local-activity-task-operations",children:"Local Activity Task Operations"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"Local Activity execution counters"}),"\n",(0,r.jsx)(n.li,{children:"Monitor: not recommended"}),"\n",(0,r.jsx)(n.li,{children:"Datadog query example"}),"\n"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-dql",children:"sum:cadence_client.cadence_local_activity_total{$Domain,$Tasklist} by {activitytype}.as_count()\n"})}),"\n",(0,r.jsx)(n.h3,{id:"activity-execution-latency",children:"Activity Execution Latency"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"If it\u2019s expected that an activity will take x amount of time to complete, a monitor on this metric could be helpful to enforce that expectation."}),"\n",(0,r.jsx)(n.li,{children:"Monitor: application can set monitor on it if expecting workflow start/complete activities with certain latency"}),"\n",(0,r.jsx)(n.li,{children:"When fired, investigate the activity code and its dependencies"}),"\n",(0,r.jsx)(n.li,{children:"Datadog query example"}),"\n"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-dql",children:"avg:cadence_client.cadence_activity_execution_latency.avg{$Domain,$Tasklist} by {env,domain,tasklist,activitytype}\nmax:cadence_client.cadence_activity_execution_latency.max{$Domain,$Tasklist} by {env,domain,tasklist,activitytype}\n"})}),"\n",(0,r.jsx)(n.h3,{id:"activity-poll-counters",children:"Activity Poll Counters"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"Indicates the activity worker is available and is polling tasks. If the worker is not available no counters will show.\nCan also check if the worker is using the right task list.\n\u201cNo task\u201d poll type means that the worker exists and is idle.\nThe timeout for this long poll api is 50 seconds. If within that 50 seconds, no task is received then an empty response will be returned and another long poll request will be sent."}),"\n",(0,r.jsx)(n.li,{children:"Monitor: application can set monitor on it to make sure activity workers are available"}),"\n",(0,r.jsx)(n.li,{children:"When fires, investigate the worker deployment to see why they are not available, also check if they are using the right domain/tasklist"}),"\n",(0,r.jsx)(n.li,{children:"Datadog query example"}),"\n"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-dql",children:"sum:cadence_client.cadence_activity_poll_total{$Domain,$Tasklist} by {activitytype}.as_count()\nsum:cadence_client.cadence_activity_poll_failed{$Domain,$Tasklist} by {activitytype}.as_count()\nsum:cadence_client.cadence_activity_poll_succeed{$Domain,$Tasklist} by {activitytype}.as_count()\nsum:cadence_client.cadence_activity_poll_no_task{$Domain,$Tasklist} by {activitytype}.as_count()\n"})}),"\n",(0,r.jsx)(n.h3,{id:"activitytasks-scheduled-per-second",children:"ActivityTasks Scheduled per second"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"Indicate how many activities tasks are scheduled"}),"\n",(0,r.jsx)(n.li,{children:"Monitor: not recommended -- Information only to know whether or not a tasklist is overloaded"}),"\n",(0,r.jsx)(n.li,{children:"Datadog query example"}),"\n"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-dql",children:"sum:cadence_matching.cadence_requests_per_tl{*,operation:addactivitytask,$Tasklist,$Domain} by {tasklist,domain}.as_rate()\n"})}),"\n",(0,r.jsx)(n.h3,{id:"activity-scheduled-to-start-latency",children:"Activity Scheduled To Start Latency"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"If the latency is too high either:\nThe worker is not available or too busy\nThere are too many activities scheduled into the same tasklist and the tasklist is not scalable. Same as Decision Scheduled To Start Latency"}),"\n",(0,r.jsx)(n.li,{children:"Monitor: application Should set monitor on it"}),"\n",(0,r.jsx)(n.li,{children:"When fired, check if workers are enough, then check if the tasklist is overloaded. If needed, contact the Cadence cluster Admin to enable scalable tasklist to add more partitions to the tasklist"}),"\n",(0,r.jsx)(n.li,{children:"Datadog query example"}),"\n"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-dql",children:"avg:cadence_client.cadence_activity_scheduled_to_start_latency.avg{$Domain,$Tasklist} by {env,domain,tasklist,activitytype}\nmax:cadence_client.cadence_activity_scheduled_to_start_latency.max{$Domain,$Tasklist} by {env,domain,tasklist,activitytype}\nmax:cadence_client.cadence_activity_scheduled_to_start_latency.95percentile{$Domain,$Tasklist} by {env,domain,tasklist,activitytype}\n"})}),"\n",(0,r.jsx)(n.h3,{id:"activity-failure",children:"Activity Failure"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"A monitor on this metric will alert the team that activities are failing\nThe activity timeout metrics are emitted by the history service, because a timeout causes a hard stop and the client doesn\u2019t have time to emit metrics."}),"\n",(0,r.jsx)(n.li,{children:"Monitor: application can set monitor on it"}),"\n",(0,r.jsx)(n.li,{children:"When fired, investigate the activity code and its dependencies"}),"\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.code,{children:"cadence_activity_execution_failed"})," vs ",(0,r.jsx)(n.code,{children:"cadence_activity_task_failed"}),":\nOnly have different when using RetryPolicy\ncadence_activity_task_failed counter increase per activity attempt\ncadence_activity_execution_failed counter increase when activity fails after all attempts"]}),"\n",(0,r.jsx)(n.li,{children:"should only monitor on cadence_activity_execution_failed"}),"\n",(0,r.jsx)(n.li,{children:"Datadog query example"}),"\n"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-dql",children:"sum:cadence_client.cadence_activity_execution_failed{$Domain} by {domain,env}.as_rate()\nsum:cadence_client.cadence_activity_task_panic{$Domain} by {domain,env}.as_count()\nsum:cadence_client.cadence_activity_task_failed{$Domain} by {domain,env}.as_rate()\nsum:cadence_client.cadence_activity_task_canceled{$Domain} by {domain,env}.as_count()\nsum:cadence_history.heartbeat_timeout{$Domain} by {domain,env}.as_count()\nsum:cadence_history.schedule_to_start_timeout{$Domain} by {domain,env}.as_rate()\nsum:cadence_history.start_to_close_timeout{$Domain} by {domain,env}.as_rate()\nsum:cadence_history.schedule_to_close_timeout{$Domain} by {domain,env}.as_count()\n"})}),"\n",(0,r.jsx)(n.h3,{id:"service-api-success-rate",children:"Service API success rate"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:["The client\u2019s experience of the service availability. It encompasses many apis. Things that could affect the service\u2019s API success rate are:","\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"Service availability"}),"\n",(0,r.jsx)(n.li,{children:"The network could have issues."}),"\n",(0,r.jsx)(n.li,{children:"A required api is not available."}),"\n",(0,r.jsx)(n.li,{children:"Client side errors like EntityNotExists, WorkflowAlreadyStarted etc. This means that application code has potential bugs of calling Cadence service."}),"\n"]}),"\n"]}),"\n",(0,r.jsx)(n.li,{children:"Monitor: application can set monitor on it"}),"\n",(0,r.jsx)(n.li,{children:"When fired, check application logs to see if the error is Cadence server error or client side error. Error like EntityNotExists/ExecutionAlreadyStarted/QueryWorkflowFailed/etc are client side error, meaning that the application is misusing the APIs. If most errors are server side errors(internalServiceError), you can contact Cadence admin."}),"\n",(0,r.jsx)(n.li,{children:"Datadog query example"}),"\n"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-dql",children:"sum:cadence_client.cadence_error{*} by {domain}.as_count()\nsum:cadence_client.cadence_request{*} by {domain}.as_count()\n(1 - a / b) * 100\n"})}),"\n",(0,r.jsx)(n.h3,{id:"service-api-latency",children:"Service API Latency"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"The latency of the API, excluding long poll APIs."}),"\n",(0,r.jsx)(n.li,{children:"Application can set monitor on certain APIs, if necessary."}),"\n",(0,r.jsx)(n.li,{children:"Datadog query example"}),"\n"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-dql",children:"avg:cadence_client.cadence_latency.95percentile{$Domain,!cadence_metric_scope:cadence-pollforactivitytask,!cadence_metric_scope:cadence-pollfordecisiontask} by {cadence_metric_scope}\n"})}),"\n",(0,r.jsx)(n.h3,{id:"service-api-breakdown",children:"Service API Breakdown"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"A counter breakdown by API to help investigate availability"}),"\n",(0,r.jsx)(n.li,{children:"No monitor needed"}),"\n",(0,r.jsx)(n.li,{children:"Datadog query example"}),"\n"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-dql",children:"sum:cadence_client.cadence_request{$Domain,!cadence_metric_scope:cadence-pollforactivitytask,!cadence_metric_scope:cadence-pollfordecisiontask} by {cadence_metric_scope}.as_count()\n"})}),"\n",(0,r.jsx)(n.h3,{id:"service-api-error-breakdown",children:"Service API Error Breakdown"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"A counter breakdown by API error to help investigate availability"}),"\n",(0,r.jsx)(n.li,{children:"No monitor needed"}),"\n",(0,r.jsx)(n.li,{children:"Datadog query example"}),"\n"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-dql",children:"sum:cadence_client.cadence_error{$Domain} by {cadence_metric_scope}.as_count()\n"})}),"\n",(0,r.jsx)(n.h3,{id:"max-event-blob-size",children:"Max Event Blob size"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"By default the max size is 2 MB. If the input is greater than the max size the server will reject the request.\nThe size of a single history event. This applies to any event input, like start workflow event, start activity event, or signal event.\nIt should never be greater than 2MB."}),"\n",(0,r.jsx)(n.li,{children:"A monitor should be set on this metric."}),"\n",(0,r.jsx)(n.li,{children:"When fired, please review the design/code ASAP to reduce the blob size. Reducing the input/output of workflow/activity/signal will help."}),"\n",(0,r.jsx)(n.li,{children:"Datadog query example"}),"\n"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-dql",children:"\u200b\u200bmax:cadence_history.event_blob_size.quantile{!domain:all,$Domain} by {domain}\n"})}),"\n",(0,r.jsx)(n.h3,{id:"max-history-size",children:"Max History Size"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"Workflow history cannot grow indefinitely. It will cause replay issues.\nIf the workflow exceeds the history\u2019s max size the workflow will be terminate automatically. The max size by default is 200 megabytes.\nAs a suggestion for workflow design, workflow history should never grow greater than 50MB. Use continueAsNew to break long workflows into multiple runs."}),"\n",(0,r.jsx)(n.li,{children:"A monitor should be set on this metric."}),"\n",(0,r.jsx)(n.li,{children:"When fired, please review the design/code ASAP to reduce the history size. Reducing the input/output of workflow/activity/signal will help. Also you may need to use ContinueAsNew to break a single execution into smaller pieces."}),"\n",(0,r.jsx)(n.li,{children:"Datadog query example"}),"\n"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-dql",children:"\u200b\u200bmax:cadence_history.history_size.quantile{!domain:all,$Domain} by {domain}\n"})}),"\n",(0,r.jsx)(n.h3,{id:"max-history-length",children:"Max History Length"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"The number of events of workflow history.\nIt should never be greater than 50K(workflow exceeding 200K events will be terminated by server). Use continueAsNew to break long workflows into multiple runs."}),"\n",(0,r.jsx)(n.li,{children:"A monitor should be set on this metric."}),"\n",(0,r.jsx)(n.li,{children:"When fired, please review the design/code ASAP to reduce the history length. You may need to use ContinueAsNew to break a single execution into smaller pieces."}),"\n",(0,r.jsx)(n.li,{children:"Datadog query example"}),"\n"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-dql",children:"\u200b\u200bmax:cadence_history.history_count.quantile{!domain:all,$Domain} by {domain}\n"})}),"\n",(0,r.jsx)(n.h2,{id:"cadence-history-service-monitoring",children:"Cadence History Service Monitoring"}),"\n",(0,r.jsx)(n.p,{children:"History is the most critical/core service for cadence which implements the workflow logic."}),"\n",(0,r.jsx)(n.h3,{id:"history-shard-movements",children:"History shard movements"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"Should only happen during deployment or when the node restarts.\nIf there\u2019s shard movement without deployments then that\u2019s unexpected and there\u2019s probably a performance issue. The shard ownership is assigned by a particular history host, so if the shard is moving it\u2019ll be hard for the frontend service to route a request to a particular history shard and to find it."}),"\n",(0,r.jsx)(n.li,{children:"A monitor can be set to be alerted on shard movements without deployment."}),"\n",(0,r.jsx)(n.li,{children:"Datadog query example"}),"\n"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-dql",children:"sum:cadence_history.membership_changed_count{operation:shardcontroller}\nsum:cadence_history.shard_closed_count{operation:shardcontroller}\nsum:cadence_history.sharditem_created_count{operation:shardcontroller}\nsum:cadence_history.sharditem_removed_count{operation:shardcontroller}\n"})}),"\n",(0,r.jsx)(n.h3,{id:"transfer-tasks-per-second",children:"Transfer Tasks Per Second"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"TransferTask is an internal background task that moves workflow state and transfers an action task from the history engine to another service(e.g. Matching service, ElasticSearch, etc)"}),"\n",(0,r.jsx)(n.li,{children:"No monitor needed"}),"\n",(0,r.jsx)(n.li,{children:"Datadog query example"}),"\n"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-dql",children:"sum:cadence_history.task_requests{operation:transferactivetask*} by {operation}.as_rate()\n"})}),"\n",(0,r.jsx)(n.h3,{id:"timer-tasks-per-second",children:"Timer Tasks Per Second"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"Timer tasks are tasks that are scheduled to be triggered at a given time in future. For example, workflow.sleep() will wait an x amount of time then the task will be pushed somewhere for a worker to pick up."}),"\n",(0,r.jsx)(n.li,{children:"Datadog query example"}),"\n"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-dql",children:"sum:cadence_history.task_requests{operation:timeractivetask*} by {operation}.as_rate()\n"})}),"\n",(0,r.jsx)(n.h3,{id:"transfer-tasks-per-domain",children:"Transfer Tasks Per Domain"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"Count breakdown by domain"}),"\n",(0,r.jsx)(n.li,{children:"Datadog query example"}),"\n"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-dql",children:"sum:cadence_history.task_requests_per_domain{operation:transferactive*} by {domain}.as_count()\n"})}),"\n",(0,r.jsx)(n.h3,{id:"timer-tasks-per-domain",children:"Timer Tasks Per Domain"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"Count breakdown by domain"}),"\n",(0,r.jsx)(n.li,{children:"Datadog query example"}),"\n"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-dql",children:"sum:cadence_history.task_requests_per_domain{operation:timeractive*} by {domain}.as_count()\n"})}),"\n",(0,r.jsx)(n.h3,{id:"transfer-latency-by-type",children:"Transfer Latency by Type"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"If latency is too high then it\u2019s an issue for a workflow. For example, if transfer task latency is 5 second, then it takes 5 second for activity/decision to actual receive the task."}),"\n",(0,r.jsxs)(n.li,{children:["Monitor should be set on diffeernt types of latency. Note that ",(0,r.jsx)(n.code,{children:"queue_latency"})," can go very high during deployment and it's expected. See below NOTE for explanation."]}),"\n",(0,r.jsx)(n.li,{children:"When fired, check if it\u2019s due to some persistence issue.\nIf so then investigate the database(may need to scale up)\nIf not then see if need to scale up Cadence deployment(K8s instance)"}),"\n",(0,r.jsx)(n.li,{children:"Datadog query example"}),"\n"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-dql",children:"avg:cadence_history.task_latency.quantile{$pXXLatency,operation:transfer*} by {operation}\navg:cadence_history.task_latency_processing.quantile{$pXXLatency,operation:transfer*} by {operation}\navg:cadence_history.task_latency_queue.quantile{$pXXLatency,operation:transfer*} by {operation}\n"})}),"\n",(0,r.jsx)(n.h3,{id:"timer-task-latency-by-type",children:"Timer Task Latency by type"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"If latency is too high then it\u2019s an issue for a workflow. For example, if you set the workflow.sleep() for 10 seconds and the timer latency is 5 secs then the workflow will sleep for 15 seconds."}),"\n",(0,r.jsx)(n.li,{children:"Monitor should be set on diffeernt types of latency."}),"\n",(0,r.jsx)(n.li,{children:"When fired, check if it\u2019s due to some persistence issue.\nIf so then investigate the database(may need to scale up) [Mostly]\nIf not then see if need to scale up Cadence deployment(K8s instance)"}),"\n",(0,r.jsx)(n.li,{children:"Datadog query example"}),"\n"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-dql",children:"avg:cadence_history.task_latency.quantile{$pXXLatency,operation:timer*} by {operation}\navg:cadence_history.task_latency_processing.quantile{$pXXLatency,operation:timer*} by {operation}\navg:cadence_history.task_latency_queue.quantile{$pXXLatency,operation:timer*} by {operation}\n"})}),"\n",(0,r.jsx)(n.h3,{id:"note-task-queue-latency-vs-executing-latency-vs-processing-latency-in-transfer--timer-task-latency-metrics",children:"NOTE: Task Queue Latency vs Executing Latency vs Processing Latency In Transfer & Timer Task Latency Metrics"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.code,{children:"task_latency_queue"}),": \u201cQueue Latency\u201d is \u201cend to end\u201d latency for users. The latency could go to several minutes during deployment because of metrics being re-emitted (but the actual latency is not that high)"]}),"\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.code,{children:"task_latency"}),": \u201cExecuting latency\u201d is the time from submission to executing pool to completion. It includes scheduling, retry and processing time of the task."]}),"\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.code,{children:"task_latency_processing"}),": \u201cProcessing latency\u201d is the processing time of the task of a single attempt(without retry)"]}),"\n"]}),"\n",(0,r.jsx)(n.h3,{id:"transfer-task-latency-per-domain",children:"Transfer Task Latency Per Domain"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"Latency breakdown by domain"}),"\n",(0,r.jsx)(n.li,{children:"No monitor needed."}),"\n",(0,r.jsx)(n.li,{children:"Datadog query example: modify above queries to use domain tag."}),"\n"]}),"\n",(0,r.jsx)(n.h3,{id:"timer-task-latency-per-domain",children:"Timer Task Latency Per Domain"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"Latency breakdown by domain"}),"\n",(0,r.jsx)(n.li,{children:"No monitor needed."}),"\n",(0,r.jsx)(n.li,{children:"Datadog query example: modify above queries to use domain tag."}),"\n"]}),"\n",(0,r.jsx)(n.h3,{id:"history-api-per-second",children:"History API per Second"}),"\n",(0,r.jsx)(n.p,{children:"Information about history API\nDatadog query example"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-dql",children:"sum:cadence_history.cadence_requests{*} by {operation}.as_rate()\n"})}),"\n",(0,r.jsx)(n.h3,{id:"history-api-errors-per-second",children:"History API Errors per Second"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"Information about history API"}),"\n",(0,r.jsx)(n.li,{children:"No monitor needed"}),"\n",(0,r.jsx)(n.li,{children:"Datadog query example"}),"\n"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-dql",children:"sum:cadence_history.cadence_errors{*} by {operation}.as_rate()\nsum:cadence_history.cadence_errors_bad_request{*} by {operation}.as_rate()\nsum:cadence_history.cadence_errors_domain_not_active{*} by {operation}.as_rate()\nsum:cadence_history.cadence_errors_service_busy{*} by {operation}.as_rate()\nsum:cadence_history.cadence_errors_entity_not_exists{*} by {operation}.as_rate()\nsum:cadence_history.cadence_errors_workflow_execution_already_completed{*} by {operation}.as_rate()\nsum:cadence_history.cadence_errors_execution_already_started{*} by {operation}.as_rate()\nsum:cadence_history.cadence_errors_domain_already_exists{*} by {operation}.as_rate()\nsum:cadence_history.cadence_errors_cancellation_already_requested{*} by {operation}.as_rate()\nsum:cadence_history.cadence_errors_query_failed{*} by {operation}.as_rate()\nsum:cadence_history.cadence_errors_limit_exceeded{*} by {operation}.as_rate()\nsum:cadence_history.cadence_errors_context_timeout{*} by {operation}.as_rate()\nsum:cadence_history.cadence_errors_retry_task{*} by {operation}.as_rate()\nsum:cadence_history.cadence_errors_bad_binary{*} by {operation}.as_rate()\nsum:cadence_history.cadence_errors_client_version_not_supported{*} by {operation}.as_rate()\nsum:cadence_history.cadence_errors_incomplete_history{*} by {operation}.as_rate()\nsum:cadence_history.cadence_errors_nondeterministic{*} by {operation}.as_rate()\nsum:cadence_history.cadence_errors_unauthorized{*} by {operation}.as_rate()\nsum:cadence_history.cadence_errors_authorize_failed{*} by {operation}.as_rate()\nsum:cadence_history.cadence_errors_remote_syncmatch_failed{*} by {operation}.as_rate()\nsum:cadence_history.cadence_errors_domain_name_exceeded_warn_limit{*} by {operation}.as_rate()\nsum:cadence_history.cadence_errors_identity_exceeded_warn_limit{*} by {operation}.as_rate()\nsum:cadence_history.cadence_errors_workflow_id_exceeded_warn_limit{*} by {operation}.as_rate()\nsum:cadence_history.cadence_errors_signal_name_exceeded_warn_limit{*} by {operation}.as_rate()\nsum:cadence_history.cadence_errors_workflow_type_exceeded_warn_limit{*} by {operation}.as_rate()\nsum:cadence_history.cadence_errors_request_id_exceeded_warn_limit{*} by {operation}.as_rate()\nsum:cadence_history.cadence_errors_task_list_name_exceeded_warn_limit{*} by {operation}.as_rate()\nsum:cadence_history.cadence_errors_activity_id_exceeded_warn_limit{*} by {operation}.as_rate()\nsum:cadence_history.cadence_errors_activity_type_exceeded_warn_limit{*} by {operation}.as_rate()\nsum:cadence_history.cadence_errors_marker_name_exceeded_warn_limit{*} by {operation}.as_rate()\nsum:cadence_history.cadence_errors_timer_id_exceeded_warn_limit{*} by {operation}.as_rate()\n"})}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.code,{children:"cadence_errors"})," is internal service errors."]}),"\n",(0,r.jsxs)(n.li,{children:["any ",(0,r.jsx)(n.code,{children:"cadence_errors_*"})," is client side error"]}),"\n"]}),"\n",(0,r.jsx)(n.h3,{id:"max-history-size-1",children:"Max History Size"}),"\n",(0,r.jsx)(n.p,{children:"The history size of the workflow cannot be too large otherwise it will cause performance issue during replay. The soft limit is 200MB. If exceeding workflow will be terminated by server."}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"No monitor needed"}),"\n",(0,r.jsx)(n.li,{children:"Datadog query is same as the client section"}),"\n"]}),"\n",(0,r.jsx)(n.h3,{id:"max-history-length-1",children:"Max History Length"}),"\n",(0,r.jsx)(n.p,{children:"Similarly, the history length of the workflow cannot be too large otherwise it will cause performance issues during replay. The soft limit is 200K events. If exceeding, workflow will be terminated by server."}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"No monitor needed"}),"\n",(0,r.jsx)(n.li,{children:"Datadog query is same as the client section"}),"\n"]}),"\n",(0,r.jsx)(n.h3,{id:"max-event-blob-size-1",children:"Max Event Blob Size"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"The size of each event(e.g. Decided by input/output of workflow/activity/signal/chidlWorkflow/etc) cannot be too large otherwise it will also cause performance issue. The soft limit is 2MB. If exceeding, the requests will be rejected by server, meaning that workflow won\u2019t be able to make any progress."}),"\n",(0,r.jsx)(n.li,{children:"No monitor needed"}),"\n",(0,r.jsx)(n.li,{children:"Datadog query is same as the client section"}),"\n"]}),"\n",(0,r.jsx)(n.h2,{id:"cadence-matching-service-monitoring",children:"Cadence Matching Service Monitoring"}),"\n",(0,r.jsx)(n.p,{children:"Matching service is to match/assign tasks from cadence service to workers. Matching got the tasks from history service. If workers are active the task will be matched immediately , It\u2019s called \u201csync match\u201d. If workers are not available, matching will persist into database and then reload the tasks when workers are back(called \u201casync match\u201d)"}),"\n",(0,r.jsx)(n.h3,{id:"matching-apis-per-second",children:"Matching APIs per Second"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"API processed by matching service per second"}),"\n",(0,r.jsx)(n.li,{children:"No monitor needed"}),"\n",(0,r.jsx)(n.li,{children:"Datadog query example"}),"\n"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-dql",children:"sum:cadence_matching.cadence_requests{*} by {operation}.as_rate()\n"})}),"\n",(0,r.jsx)(n.h3,{id:"matching-api-errors-per-second",children:"Matching API Errors per Second"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"API errors by matching service per second"}),"\n",(0,r.jsx)(n.li,{children:"No monitor needed"}),"\n",(0,r.jsx)(n.li,{children:"Datadog query example"}),"\n"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-dql",children:"sum:cadence_matching.cadence_errors_per_tl{*} by {operation,domain,tasklist}.as_rate()\nsum:cadence_matching.cadence_errors_bad_request_per_tl{*} by {operation,domain,tasklist}\nsum:cadence_matching.cadence_errors_bad_request{*} by {operation,domain,tasklist}\nsum:cadence_matching.cadence_errors_domain_not_active_per_tl{*} by {operation,domain,tasklist}\nsum:cadence_matching.cadence_errors_domain_not_active{*} by {operation,domain,tasklist}\nsum:cadence_matching.cadence_errors_service_busy_per_tl{*} by {operation,domain,tasklist}\nsum:cadence_matching.cadence_errors_service_busy{*} by {operation,domain,tasklist}\nsum:cadence_matching.cadence_errors_entity_not_exists_per_tl{*} by {operation,domain,tasklist}\nsum:cadence_matching.cadence_errors_entity_not_exists{*} by {operation,domain,tasklist}\nsum:cadence_matching.cadence_errors_execution_already_started_per_tl{*} by {operation,domain,tasklist}\nsum:cadence_matching.cadence_errors_execution_already_started{*} by {operation,domain,tasklist}\nsum:cadence_matching.cadence_errors_domain_already_exists_per_tl{*} by {operation,domain,tasklist}\nsum:cadence_matching.cadence_errors_domain_already_exists{*} by {operation,domain,tasklist}\nsum:cadence_matching.cadence_errors_cancellation_already_requested_per_tl{*} by {operation,domain,tasklist}\nsum:cadence_matching.cadence_errors_cancellation_already_requested{*} by {operation,domain,tasklist}\nsum:cadence_matching.cadence_errors_query_failed_per_tl{*} by {operation,domain,tasklist}\nsum:cadence_matching.cadence_errors_query_failed{*} by {operation,domain,tasklist}\nsum:cadence_matching.cadence_errors_limit_exceeded_per_tl{*} by {operation,domain,tasklist}\nsum:cadence_matching.cadence_errors_limit_exceeded{*} by {operation,domain,tasklist}\nsum:cadence_matching.cadence_errors_context_timeout_per_tl{*} by {operation,domain,tasklist}\nsum:cadence_matching.cadence_errors_context_timeout{*} by {operation,domain,tasklist}\nsum:cadence_matching.cadence_errors_retry_task_per_tl{*} by {operation,domain,tasklist}\nsum:cadence_matching.cadence_errors_retry_task{*} by {operation,domain,tasklist}\nsum:cadence_matching.cadence_errors_bad_binary_per_tl{*} by {operation,domain,tasklist}\nsum:cadence_matching.cadence_errors_bad_binary{*} by {operation,domain,tasklist}\nsum:cadence_matching.cadence_errors_client_version_not_supported_per_tl{*} by {operation,domain,tasklist}\nsum:cadence_matching.cadence_errors_client_version_not_supported{*} by {operation,domain,tasklist}\nsum:cadence_matching.cadence_errors_incomplete_history_per_tl{*} by {operation,domain,tasklist}\nsum:cadence_matching.cadence_errors_incomplete_history{*} by {operation,domain,tasklist}\nsum:cadence_matching.cadence_errors_nondeterministic_per_tl{*} by {operation,domain,tasklist}\nsum:cadence_matching.cadence_errors_nondeterministic{*} by {operation,domain,tasklist}\nsum:cadence_matching.cadence_errors_unauthorized_per_tl{*} by {operation,domain,tasklist}\nsum:cadence_matching.cadence_errors_unauthorized{*} by {operation,domain,tasklist}\nsum:cadence_matching.cadence_errors_authorize_failed_per_tl{*} by {operation,domain,tasklist}\nsum:cadence_matching.cadence_errors_authorize_failed{*} by {operation,domain,tasklist}\nsum:cadence_matching.cadence_errors_remote_syncmatch_failed_per_tl{*} by {operation,domain,tasklist}\nsum:cadence_matching.cadence_errors_remote_syncmatch_failed{*} by {operation,domain,tasklist}\nsum:cadence_matching.cadence_errors_shard_ownership_lost{*} by {operation,domain,tasklist}\nsum:cadence_matching.cadence_errors_event_already_started{*} by {operation,domain,tasklist}\n"})}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.code,{children:"cadence_errors"})," is internal service errors."]}),"\n",(0,r.jsxs)(n.li,{children:["any ",(0,r.jsx)(n.code,{children:"cadence_errors_*"})," is client side error"]}),"\n"]}),"\n",(0,r.jsx)(n.h3,{id:"matching-regular-api-latency",children:"Matching Regular API Latency"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"Regular APIs are the APIs excluding long polls"}),"\n",(0,r.jsx)(n.li,{children:"No monitor needed"}),"\n",(0,r.jsx)(n.li,{children:"Datadog query example"}),"\n"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-dql",children:"avg:cadence_matching.cadence_latency_per_tl.quantile{$pXXLatency,!operation:pollfor*,!operation:queryworkflow} by {operation,tasklist}\n"})}),"\n",(0,r.jsx)(n.h3,{id:"sync-match-latency",children:"Sync Match Latency:"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"If the latency is too high, probably the tasklist is overloaded. Consider using multiple tasklist, or enable scalable tasklist feature by adding more partition to the tasklist(default is one)\nTo confirm if there are too many tasks being added to the tasklist, use \u201cAddTasks per second - domain, tasklist breakdown\u201d"}),"\n",(0,r.jsx)(n.li,{children:"No monitor needed"}),"\n",(0,r.jsx)(n.li,{children:"Datadog query example"}),"\n"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-dql",children:"sum:cadence_matching.syncmatch_latency_per_tl.quantile{$pXXLatency} by {operation,tasklist,domain}\n"})}),"\n",(0,r.jsx)(n.h3,{id:"async-match-latency",children:"Async match Latency"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"If a match is done asynchronously it writes a match to the db to use later. Measures the time when the worker is not actively looking for tasks. If this is high, more workers are needed."}),"\n",(0,r.jsx)(n.li,{children:"No monitor needed"}),"\n",(0,r.jsx)(n.li,{children:"Datadog query example"}),"\n"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-dql",children:"sum:cadence_matching.asyncmatch_latency_per_tl.quantile{$pXXLatency} by {operation,tasklist,domain}\n"})}),"\n",(0,r.jsx)(n.h2,{id:"cadence-default-persistence-monitoring",children:"Cadence Default Persistence Monitoring"}),"\n",(0,r.jsx)(n.p,{children:"The following monotors should be set up for Cadence persistence."}),"\n",(0,r.jsx)(n.h3,{id:"persistence-availability",children:"Persistence Availability"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"The availability of the primary database for your Cadence server"}),"\n",(0,r.jsx)(n.li,{children:"Monitor required: Below 95% > 5min then alert, below 99% triggers a slack warning"}),"\n",(0,r.jsx)(n.li,{children:"When fired, check if it\u2019s due to some persistence issue.\nIf so then investigate the database(may need to scale up) [Mostly]\nIf not then see if need to scale up Cadence deployment(K8s instance)"}),"\n",(0,r.jsx)(n.li,{children:"Datadog query example"}),"\n"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-dql",children:"sum:cadence_frontend.persistence_errors{*} by {operation}.as_count()\nsum:cadence_frontend.persistence_requests{*} by {operation}.as_count()\nsum:cadence_matching.persistence_errors{*} by {operation}.as_count()\nsum:cadence_matching.persistence_requests{*} by {operation}.as_count()\nsum:cadence_history.persistence_errors{*} by {operation}.as_count()\nsum:cadence_history.persistence_requests{*} by {operation}.as_count()\nsum:cadence_worker.persistence_errors{*} by {operation}.as_count()\nsum:cadence_worker.persistence_requests{*} by {operation}.as_count()\n(1 - a / b) * 100\n(1 - c / d) * 100\n(1 - e / f) * 100\n(1 - g / h) * 100\n"})}),"\n",(0,r.jsx)(n.h3,{id:"persistence-by-service-tps",children:"Persistence By Service TPS"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"No monitor needed"}),"\n",(0,r.jsx)(n.li,{children:"Datadog query example"}),"\n"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-dql",children:"sum:cadence_frontend.persistence_requests{*}.as_rate()\nsum:cadence_history.persistence_requests{*}.as_rate()\nsum:cadence_worker.persistence_requests{*}.as_rate()\nsum:cadence_matching.persistence_requests{*}.as_rate()\n\n"})}),"\n",(0,r.jsx)(n.h3,{id:"persistence-by-operation-tps",children:"Persistence By Operation TPS"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"No monitor needed"}),"\n",(0,r.jsx)(n.li,{children:"Datadog query example"}),"\n"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-dql",children:"sum:cadence_frontend.persistence_requests{*} by {operation}.as_rate()\nsum:cadence_history.persistence_requests{*} by {operation}.as_rate()\nsum:cadence_worker.persistence_requests{*} by {operation}.as_rate()\nsum:cadence_matching.persistence_requests{*} by {operation}.as_rate()\n\n"})}),"\n",(0,r.jsx)(n.h3,{id:"persistence-by-operation-latency",children:"Persistence By Operation Latency"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"Monitor required, alert if 95% of all operation latency is greater than 1 second for 5mins, warning if greater than 0.5 seconds"}),"\n",(0,r.jsx)(n.li,{children:"When fired, investigate the database(may need to scale up) [Mostly]\nIf there\u2019s a high latency, then there could be errors or something wrong with the db"}),"\n",(0,r.jsx)(n.li,{children:"Datadog query example"}),"\n"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-dql",children:"avg:cadence_matching.persistence_latency.quantile{$pXXLatency} by {operation}\navg:cadence_worker.persistence_latency.quantile{$pXXLatency} by {operation}\navg:cadence_frontend.persistence_latency.quantile{$pXXLatency} by {operation}\navg:cadence_history.persistence_latency.quantile{$pXXLatency} by {operation}\n"})}),"\n",(0,r.jsx)(n.h3,{id:"persistence-error-by-operation-count",children:"Persistence Error By Operation Count"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"It's to help investigate availability issue"}),"\n",(0,r.jsx)(n.li,{children:"No monitor needed"}),"\n",(0,r.jsx)(n.li,{children:"Datadog query example"}),"\n"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-dql",children:"sum:cadence_frontend.persistence_errors{*} by {operation}.as_count()\nsum:cadence_history.persistence_errors{*} by {operation}.as_count()\nsum:cadence_worker.persistence_errors{*} by {operation}.as_count()\nsum:cadence_matching.persistence_errors{*} by {operation}.as_count()\n\nsum:cadence_frontend.persistence_errors_shard_exists{*} by {operation}.as_count()\nsum:cadence_frontend.persistence_errors_shard_ownership_lost{*} by {operation}.as_count()\nsum:cadence_frontend.persistence_errors_condition_failed{*} by {operation}.as_count()\nsum:cadence_frontend.persistence_errors_current_workflow_condition_failed{*} by {operation}.as_count()\nsum:cadence_frontend.persistence_errors_timeout{*} by {operation}.as_count()\nsum:cadence_frontend.persistence_errors_busy{*} by {operation}.as_count()\nsum:cadence_frontend.persistence_errors_entity_not_exists{*} by {operation}.as_count()\nsum:cadence_frontend.persistence_errors_execution_already_started{*} by {operation}.as_count()\nsum:cadence_frontend.persistence_errors_domain_already_exists{*} by {operation}.as_count()\nsum:cadence_frontend.persistence_errors_bad_request{*} by {operation}.as_count()\n\nsum:cadence_history.persistence_errors_shard_exists{*} by {operation}.as_count()\nsum:cadence_history.persistence_errors_shard_ownership_lost{*} by {operation}.as_count()\nsum:cadence_history.persistence_errors_condition_failed{*} by {operation}.as_count()\nsum:cadence_history.persistence_errors_current_workflow_condition_failed{*} by {operation}.as_count()\nsum:cadence_history.persistence_errors_timeout{*} by {operation}.as_count()\nsum:cadence_history.persistence_errors_busy{*} by {operation}.as_count()\nsum:cadence_history.persistence_errors_entity_not_exists{*} by {operation}.as_count()\nsum:cadence_history.persistence_errors_execution_already_started{*} by {operation}.as_count()\nsum:cadence_history.persistence_errors_domain_already_exists{*} by {operation}.as_count()\nsum:cadence_history.persistence_errors_bad_request{*} by {operation}.as_count()\n\nsum:cadence_matching.persistence_errors_shard_exists{*} by {operation}.as_count()\nsum:cadence_matching.persistence_errors_shard_ownership_lost{*} by {operation}.as_count()\nsum:cadence_matching.persistence_errors_condition_failed{*} by {operation}.as_count()\nsum:cadence_matching.persistence_errors_current_workflow_condition_failed{*} by {operation}.as_count()\nsum:cadence_matching.persistence_errors_timeout{*} by {operation}.as_count()\nsum:cadence_matching.persistence_errors_busy{*} by {operation}.as_count()\nsum:cadence_matching.persistence_errors_entity_not_exists{*} by {operation}.as_count()\nsum:cadence_matching.persistence_errors_execution_already_started{*} by {operation}.as_count()\nsum:cadence_matching.persistence_errors_domain_already_exists{*} by {operation}.as_count()\nsum:cadence_matching.persistence_errors_bad_request{*} by {operation}.as_count()\n\nsum:cadence_worker.persistence_errors_shard_exists{*} by {operation}.as_count()\nsum:cadence_worker.persistence_errors_shard_ownership_lost{*} by {operation}.as_count()\nsum:cadence_worker.persistence_errors_condition_failed{*} by {operation}.as_count()\nsum:cadence_worker.persistence_errors_current_workflow_condition_failed{*} by {operation}.as_count()\nsum:cadence_worker.persistence_errors_timeout{*} by {operation}.as_count()\nsum:cadence_worker.persistence_errors_busy{*} by {operation}.as_count()\nsum:cadence_worker.persistence_errors_entity_not_exists{*} by {operation}.as_count()\nsum:cadence_worker.persistence_errors_execution_already_started{*} by {operation}.as_count()\nsum:cadence_worker.persistence_errors_domain_already_exists{*} by {operation}.as_count()\nsum:cadence_worker.persistence_errors_bad_request{*} by {operation}.as_count()\n\n"})}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.code,{children:"cadence_errors"})," is internal service errors."]}),"\n",(0,r.jsxs)(n.li,{children:["any ",(0,r.jsx)(n.code,{children:"cadence_errors_*"})," is client side error"]}),"\n"]}),"\n",(0,r.jsx)(n.h2,{id:"cadence-advanced-visibility-persistence-monitoringif-applicable",children:"Cadence Advanced Visibility Persistence Monitoring(if applicable)"}),"\n",(0,r.jsx)(n.p,{children:"Kafka & ElasticSearch are only for visibility. Only applicable \u200b\u200bif using advanced visibility.\nFor writing visibility records, Cadence history service will write down the records into Kafka, and then Cadence worker service will read from Kafka and write into ElasticSearch(in batch, for performance optimization)\nFor reading visibility records, Frontend service will query ElasticSearch directly."}),"\n",(0,r.jsx)(n.h3,{id:"persistence-availability-1",children:"Persistence Availability"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"The availability of Cadence server using database"}),"\n",(0,r.jsx)(n.li,{children:"Monitor can be set"}),"\n",(0,r.jsx)(n.li,{children:"Datadog query example"}),"\n"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-dql",children:"sum:cadence_frontend.elasticsearch_errors{*} by {operation}.as_count()\nsum:cadence_frontend.elasticsearch_requests{*} by {operation}.as_count()\nsum:cadence_history.elasticsearch_errors{*} by {operation}.as_count()\nsum:cadence_history.elasticsearch_requests{*} by {operation}.as_count()\n(1 - a / b) * 100\n(1 - c / d) * 100\n"})}),"\n",(0,r.jsx)(n.h3,{id:"persistence-by-service-tps-1",children:"Persistence By Service TPS"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"The error of persistence API call by service"}),"\n",(0,r.jsx)(n.li,{children:"No monitor needed"}),"\n",(0,r.jsx)(n.li,{children:"Datadog query example"}),"\n"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-dql",children:"sum:cadence_frontend.elasticsearch_requests{*}.as_rate()\nsum:cadence_history.elasticsearch_requests{*}.as_rate()\n"})}),"\n",(0,r.jsx)(n.h3,{id:"persistence-by-operation-tpsread-es-write-kafka",children:"Persistence By Operation TPS(read: ES, write: Kafka)"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"The rate of persistence API call by API"}),"\n",(0,r.jsx)(n.li,{children:"No monitor needed"}),"\n",(0,r.jsx)(n.li,{children:"Datadog query example"}),"\n"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-dql",children:"sum:cadence_frontend.elasticsearch_requests{*} by {operation}.as_rate()\nsum:cadence_history.elasticsearch_requests{*} by {operation}.as_rate()\n"})}),"\n",(0,r.jsx)(n.h3,{id:"persistence-by-operation-latencyin-seconds-read-es-write-kafka",children:"Persistence By Operation Latency(in seconds) (read: ES, write: Kafka)"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"The latency of persistence API call"}),"\n",(0,r.jsx)(n.li,{children:"No monitor needed"}),"\n",(0,r.jsx)(n.li,{children:"Datadog query example"}),"\n"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-dql",children:"avg:cadence_frontend.elasticsearch_latency.quantile{$pXXLatency} by {operation}\navg:cadence_history.elasticsearch_latency.quantile{$pXXLatency} by {operation}\n"})}),"\n",(0,r.jsx)(n.h3,{id:"persistence-error-by-operation-count-read-es-write-kafka",children:"Persistence Error By Operation Count (read: ES, write: Kafka)"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"The error of persistence API call"}),"\n",(0,r.jsx)(n.li,{children:"No monitor needed"}),"\n",(0,r.jsx)(n.li,{children:"Datadog query example"}),"\n"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-dql",children:"sum:cadence_frontend.elasticsearch_errors{*} by {operation}.as_count()\nsum:cadence_history.elasticsearch_errors{*} by {operation}.as_count()\n"})}),"\n",(0,r.jsx)(n.h3,{id:"kafka-es-processor-counter",children:"Kafka->ES processor counter"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"This is the metrics of a background processing: consuming Kafka messages and then populate to ElasticSearch in batch"}),"\n",(0,r.jsx)(n.li,{children:"Monitor on the running of the background processing(counter metrics is > 0)"}),"\n",(0,r.jsx)(n.li,{children:"When fired, restart Cadence service first to mitigate. Then look at logs to see why the process is stopped(process panic/error/etc).\nMay consider add more pods (replicaCount) to sys-worker service for higher availability"}),"\n",(0,r.jsx)(n.li,{children:"Datadog query example"}),"\n"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-dql",children:"sum:cadence_worker.es_processor_requests{*} by {operation}.as_count()\nsum:cadence_worker.es_processor_retries{*} by {operation}.as_count()\n"})}),"\n",(0,r.jsx)(n.h3,{id:"kafka-es-processor-error",children:"Kafka->ES processor error"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"This is the error metrics of the above processing logic\nAlmost all errors are retryable errors so it\u2019s not a problem."}),"\n",(0,r.jsx)(n.li,{children:"Need to monitor error"}),"\n",(0,r.jsx)(n.li,{children:"When fired, Go to Kibana to find logs about the error details.\nThe most common error is missing the ElasticSearch index field -- an index field is added in dynamicconfig but not in ElasticSearch, or vice versa . If so, follow the runbook to add the field to ElasticSearch or dynamic config."}),"\n",(0,r.jsx)(n.li,{children:"Datadog query example"}),"\n"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-dql",children:"sum:cadence_worker.es_processor_error{*} by {operation}.as_count()\nsum:cadence_worker.es_processor_corrupted_data{*} by {operation}.as_count()\n"})}),"\n",(0,r.jsx)(n.h3,{id:"kafka-es-processor-latency",children:"Kafka->ES processor latency"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"The latency of the processing logic"}),"\n",(0,r.jsx)(n.li,{children:"No monitor needed"}),"\n",(0,r.jsx)(n.li,{children:"Datadog query example"}),"\n"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-dql",children:"sum:cadence_worker.es_processor_process_msg_latency.quantile{$pXXLatency} by {operation}.as_count()\n"})}),"\n",(0,r.jsx)(n.h2,{id:"cadence-dependency-metrics-monitor-suggestion",children:"Cadence Dependency Metrics Monitor suggestion"}),"\n",(0,r.jsx)(n.h3,{id:"computing-platform-metrics-for-cadence-deployment",children:"Computing platform metrics for Cadence deployment"}),"\n",(0,r.jsx)(n.p,{children:"Cadence server being deployed on any computing platform(e.g. Kubernetese) should be monitored on the blow metrics:"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"CPU"}),"\n",(0,r.jsx)(n.li,{children:"Memory"}),"\n"]}),"\n",(0,r.jsx)(n.h3,{id:"database",children:"Database"}),"\n",(0,r.jsx)(n.p,{children:"Depends on which database, you should at least monitor on the below metrics"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"Disk Usage"}),"\n",(0,r.jsx)(n.li,{children:"CPU"}),"\n",(0,r.jsx)(n.li,{children:"Memory"}),"\n",(0,r.jsx)(n.li,{children:"Read API latency"}),"\n",(0,r.jsx)(n.li,{children:"Write API Latency"}),"\n"]}),"\n",(0,r.jsx)(n.h3,{id:"kafka-if-applicable",children:"Kafka (if applicable)"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"Disk Usage"}),"\n",(0,r.jsx)(n.li,{children:"CPU"}),"\n",(0,r.jsx)(n.li,{children:"Memory"}),"\n"]}),"\n",(0,r.jsx)(n.h3,{id:"elasticsearch-if-applicable",children:"ElasticSearch (if applicable)"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"Disk Usage"}),"\n",(0,r.jsx)(n.li,{children:"CPU"}),"\n",(0,r.jsx)(n.li,{children:"Memory"}),"\n"]}),"\n",(0,r.jsx)(n.h2,{id:"cadence-service-slo-recommendation",children:"Cadence Service SLO Recommendation"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:["Core API availability: ",(0,r.jsx)(n.code,{children:"99.9%"})]}),"\n",(0,r.jsxs)(n.li,{children:["Core API latency: ",(0,r.jsx)(n.code,{children:"<1s"})]}),"\n",(0,r.jsxs)(n.li,{children:["Overall task dispatch latency: ",(0,r.jsx)(n.code,{children:"<2s"})," (queue_latency for transfer task and timer task)"]}),"\n"]})]})}function h(e={}){const{wrapper:n}={...(0,t.R)(),...e.components};return n?(0,r.jsx)(n,{...e,children:(0,r.jsx)(d,{...e})}):d(e)}},8453:(e,n,i)=>{i.d(n,{R:()=>s,x:()=>o});var a=i(6540);const r={},t=a.createContext(r);function s(e){const n=a.useContext(t);return a.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function o(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:s(e.components),a.createElement(t.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/6e9b4a66.f413300e.js b/assets/js/6e9b4a66.f413300e.js deleted file mode 100644 index 21fa1a6ac..000000000 --- a/assets/js/6e9b4a66.f413300e.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[3252],{5907:(e,n,i)=>{i.r(n),i.d(n,{assets:()=>c,contentTitle:()=>o,default:()=>h,frontMatter:()=>s,metadata:()=>r,toc:()=>l});const r=JSON.parse('{"id":"operation-guide/monitoring","title":"Cluster Monitoring","description":"Instructions","source":"@site/docs/07-operation-guide/03-monitoring.md","sourceDirName":"07-operation-guide","slug":"/operation-guide/monitoring","permalink":"/docs/operation-guide/monitoring","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/07-operation-guide/03-monitoring.md","tags":[],"version":"current","sidebarPosition":3,"frontMatter":{"layout":"default","title":"Cluster Monitoring","permalink":"/docs/operation-guide/monitor"},"sidebar":"docsSidebar","previous":{"title":"Cluster Maintenance","permalink":"/docs/operation-guide/maintain"},"next":{"title":"Cluster Troubleshooting","permalink":"/docs/operation-guide/troubleshooting"}}');var a=i(4848),t=i(8453);const s={layout:"default",title:"Cluster Monitoring",permalink:"/docs/operation-guide/monitor"},o="Cluster Monitoring",c={},l=[{value:"Instructions",id:"instructions",level:2},{value:"DataDog dashboard templates",id:"datadog-dashboard-templates",level:2},{value:"Grafana+Prometheus dashboard templates",id:"grafanaprometheus-dashboard-templates",level:2},{value:"Periodic tests(Canary) for health check",id:"periodic-testscanary-for-health-check",level:2},{value:"Cadence Frontend Monitoring",id:"cadence-frontend-monitoring",level:2},{value:"Service Availability(server metrics)",id:"service-availabilityserver-metrics",level:3},{value:"StartWorkflow Per Second",id:"startworkflow-per-second",level:3},{value:"Activities Started Per Second",id:"activities-started-per-second",level:3},{value:"Decisions Started Per Second",id:"decisions-started-per-second",level:3},{value:"Periodical Test Suite Success(aka Canary)",id:"periodical-test-suite-successaka-canary",level:3},{value:"Frontend all API per second",id:"frontend-all-api-per-second",level:3},{value:"Frontend API per second (breakdown per operation)",id:"frontend-api-per-second-breakdown-per-operation",level:3},{value:"Frontend API errors per second(breakdown per operation)",id:"frontend-api-errors-per-secondbreakdown-per-operation",level:3},{value:"Frontend Regular API Latency",id:"frontend-regular-api-latency",level:3},{value:"Frontend ListWorkflow API Latency",id:"frontend-listworkflow-api-latency",level:3},{value:"Frontend Long Poll API Latency",id:"frontend-long-poll-api-latency",level:3},{value:"Frontend Get History/Query Workflow API Latency",id:"frontend-get-historyquery-workflow-api-latency",level:3},{value:"Frontend WorkflowClient API per seconds by domain",id:"frontend-workflowclient-api-per-seconds-by-domain",level:3},{value:"Cadence Application Monitoring",id:"cadence-application-monitoring",level:2},{value:"Workflow Start and Successful completion",id:"workflow-start-and-successful-completion",level:3},{value:"Workflow Failure",id:"workflow-failure",level:3},{value:"Decision Poll Counters",id:"decision-poll-counters",level:3},{value:"DecisionTasks Scheduled per second",id:"decisiontasks-scheduled-per-second",level:3},{value:"Decision Scheduled To Start Latency",id:"decision-scheduled-to-start-latency",level:3},{value:"Decision Execution Failure",id:"decision-execution-failure",level:3},{value:"Decision Execution Timeout",id:"decision-execution-timeout",level:3},{value:"Workflow End to End Latency",id:"workflow-end-to-end-latency",level:3},{value:"Workflow Panic and NonDeterministicError",id:"workflow-panic-and-nondeterministicerror",level:3},{value:"Workflow Sticky Cache Hit Rate and Miss Count",id:"workflow-sticky-cache-hit-rate-and-miss-count",level:3},{value:"Activity Task Operations",id:"activity-task-operations",level:3},{value:"Local Activity Task Operations",id:"local-activity-task-operations",level:3},{value:"Activity Execution Latency",id:"activity-execution-latency",level:3},{value:"Activity Poll Counters",id:"activity-poll-counters",level:3},{value:"ActivityTasks Scheduled per second",id:"activitytasks-scheduled-per-second",level:3},{value:"Activity Scheduled To Start Latency",id:"activity-scheduled-to-start-latency",level:3},{value:"Activity Failure",id:"activity-failure",level:3},{value:"Service API success rate",id:"service-api-success-rate",level:3},{value:"Service API Latency",id:"service-api-latency",level:3},{value:"Service API Breakdown",id:"service-api-breakdown",level:3},{value:"Service API Error Breakdown",id:"service-api-error-breakdown",level:3},{value:"Max Event Blob size",id:"max-event-blob-size",level:3},{value:"Max History Size",id:"max-history-size",level:3},{value:"Max History Length",id:"max-history-length",level:3},{value:"Cadence History Service Monitoring",id:"cadence-history-service-monitoring",level:2},{value:"History shard movements",id:"history-shard-movements",level:3},{value:"Transfer Tasks Per Second",id:"transfer-tasks-per-second",level:3},{value:"Timer Tasks Per Second",id:"timer-tasks-per-second",level:3},{value:"Transfer Tasks Per Domain",id:"transfer-tasks-per-domain",level:3},{value:"Timer Tasks Per Domain",id:"timer-tasks-per-domain",level:3},{value:"Transfer Latency by Type",id:"transfer-latency-by-type",level:3},{value:"Timer Task Latency by type",id:"timer-task-latency-by-type",level:3},{value:"NOTE: Task Queue Latency vs Executing Latency vs Processing Latency In Transfer & Timer Task Latency Metrics",id:"note-task-queue-latency-vs-executing-latency-vs-processing-latency-in-transfer--timer-task-latency-metrics",level:3},{value:"Transfer Task Latency Per Domain",id:"transfer-task-latency-per-domain",level:3},{value:"Timer Task Latency Per Domain",id:"timer-task-latency-per-domain",level:3},{value:"History API per Second",id:"history-api-per-second",level:3},{value:"History API Errors per Second",id:"history-api-errors-per-second",level:3},{value:"Max History Size",id:"max-history-size-1",level:3},{value:"Max History Length",id:"max-history-length-1",level:3},{value:"Max Event Blob Size",id:"max-event-blob-size-1",level:3},{value:"Cadence Matching Service Monitoring",id:"cadence-matching-service-monitoring",level:2},{value:"Matching APIs per Second",id:"matching-apis-per-second",level:3},{value:"Matching API Errors per Second",id:"matching-api-errors-per-second",level:3},{value:"Matching Regular API Latency",id:"matching-regular-api-latency",level:3},{value:"Sync Match Latency:",id:"sync-match-latency",level:3},{value:"Async match Latency",id:"async-match-latency",level:3},{value:"Cadence Default Persistence Monitoring",id:"cadence-default-persistence-monitoring",level:2},{value:"Persistence Availability",id:"persistence-availability",level:3},{value:"Persistence By Service TPS",id:"persistence-by-service-tps",level:3},{value:"Persistence By Operation TPS",id:"persistence-by-operation-tps",level:3},{value:"Persistence By Operation Latency",id:"persistence-by-operation-latency",level:3},{value:"Persistence Error By Operation Count",id:"persistence-error-by-operation-count",level:3},{value:"Cadence Advanced Visibility Persistence Monitoring(if applicable)",id:"cadence-advanced-visibility-persistence-monitoringif-applicable",level:2},{value:"Persistence Availability",id:"persistence-availability-1",level:3},{value:"Persistence By Service TPS",id:"persistence-by-service-tps-1",level:3},{value:"Persistence By Operation TPS(read: ES, write: Kafka)",id:"persistence-by-operation-tpsread-es-write-kafka",level:3},{value:"Persistence By Operation Latency(in seconds) (read: ES, write: Kafka)",id:"persistence-by-operation-latencyin-seconds-read-es-write-kafka",level:3},{value:"Persistence Error By Operation Count (read: ES, write: Kafka)",id:"persistence-error-by-operation-count-read-es-write-kafka",level:3},{value:"Kafka->ES processor counter",id:"kafka-es-processor-counter",level:3},{value:"Kafka->ES processor error",id:"kafka-es-processor-error",level:3},{value:"Kafka->ES processor latency",id:"kafka-es-processor-latency",level:3},{value:"Cadence Dependency Metrics Monitor suggestion",id:"cadence-dependency-metrics-monitor-suggestion",level:2},{value:"Computing platform metrics for Cadence deployment",id:"computing-platform-metrics-for-cadence-deployment",level:3},{value:"Database",id:"database",level:3},{value:"Kafka (if applicable)",id:"kafka-if-applicable",level:3},{value:"ElasticSearch (if applicable)",id:"elasticsearch-if-applicable",level:3},{value:"Cadence Service SLO Recommendation",id:"cadence-service-slo-recommendation",level:2}];function d(e){const n={a:"a",code:"code",h1:"h1",h2:"h2",h3:"h3",header:"header",li:"li",p:"p",pre:"pre",ul:"ul",...(0,t.R)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(n.header,{children:(0,a.jsx)(n.h1,{id:"cluster-monitoring",children:"Cluster Monitoring"})}),"\n",(0,a.jsx)(n.h2,{id:"instructions",children:"Instructions"}),"\n",(0,a.jsx)(n.p,{children:"Cadence emits metrics for both Server and client libraries:"}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsxs)(n.li,{children:["\n",(0,a.jsxs)(n.p,{children:["Follow this example to emit ",(0,a.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence-samples/pull/36",children:"client side metrics for Golang client"})]}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsxs)(n.li,{children:["You can use other metrics emitter like ",(0,a.jsx)(n.a,{href:"https://github.com/uber-go/tally/tree/master/m3",children:"M3"})]}),"\n",(0,a.jsxs)(n.li,{children:["Alternatively, you can implement the tally ",(0,a.jsx)(n.a,{href:"https://github.com/uber-go/tally/blob/master/reporter.go",children:"Reporter interface"})]}),"\n"]}),"\n"]}),"\n",(0,a.jsxs)(n.li,{children:["\n",(0,a.jsxs)(n.p,{children:["Follow this example to emit ",(0,a.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence-java-samples/blob/master/src/main/java/com/uber/cadence/samples/hello/HelloMetric.java",children:"client side metrics for Java client"})," if using 3.x client, or ",(0,a.jsx)(n.a,{href:"https://github.com/longquanzheng/cadence-java-samples-1/pull/1",children:"this example"})," if using 2.x client."]}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsxs)(n.li,{children:["You can use other metrics emitter like ",(0,a.jsx)(n.a,{href:"https://github.com/uber-java/tally/tree/master/m3",children:"M3"})]}),"\n",(0,a.jsxs)(n.li,{children:["Alternatively, you can implement the tally ",(0,a.jsx)(n.a,{href:"https://github.com/uber-java/tally/blob/master/core/src/main/java/com/uber/m3/tally/Scope.java",children:"Reporter interface"})]}),"\n"]}),"\n"]}),"\n",(0,a.jsxs)(n.li,{children:["\n",(0,a.jsxs)(n.p,{children:["For running Cadence services in production, please follow this ",(0,a.jsx)(n.a,{href:"https://github.com/banzaicloud/banzai-charts/blob/master/cadence/templates/server-service-monitor.yaml",children:"example of hemlchart"})," to emit server side metrics. Or you can follow ",(0,a.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence/blob/master/config/development_prometheus.yaml#L40",children:"the example of local environment"})," to Prometheus. All services need to expose a HTTP port to provide metircs like below"]}),"\n"]}),"\n"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-yaml",children:'metrics:\n prometheus:\n timerType: "histogram"\n listenAddress: "0.0.0.0:8001"\n'})}),"\n",(0,a.jsx)(n.p,{children:"The rest of the instruction uses local environment as an example."}),"\n",(0,a.jsxs)(n.p,{children:["For testing local server emitting metrics to Promethues, the easiest way is to use ",(0,a.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence/blob/master/docker/",children:"docker-compose"})," to start a local Cadence instance."]}),"\n",(0,a.jsxs)(n.p,{children:["Make sure to update the ",(0,a.jsx)(n.code,{children:"prometheus_config.yml"}),' to add "host.docker.internal:9098" to the scrape list before starting the docker-compose:']}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-yaml",children:"global:\n scrape_interval: 5s\n external_labels:\n monitor: 'cadence-monitor'\nscrape_configs:\n - job_name: 'prometheus'\n static_configs:\n - targets: # addresses to scrape\n - 'cadence:9090'\n - 'cadence:8000'\n - 'cadence:8001'\n - 'cadence:8002'\n - 'cadence:8003'\n - 'host.docker.internal:9098'\n"})}),"\n",(0,a.jsxs)(n.p,{children:["Note: ",(0,a.jsx)(n.code,{children:"host.docker.internal"})," ",(0,a.jsx)(n.a,{href:"https://docs.docker.com/docker-for-mac/networking/#use-cases-and-workarounds",children:"may not work for some docker versions"})]}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsxs)(n.li,{children:["\n",(0,a.jsxs)(n.p,{children:["After updating the prometheus_config.yaml as above, run ",(0,a.jsx)(n.code,{children:"docker-compose up"})," to start the local Cadence instance"]}),"\n"]}),"\n",(0,a.jsxs)(n.li,{children:["\n",(0,a.jsxs)(n.p,{children:["Go the the sample repo, build the helloworld sample ",(0,a.jsx)(n.code,{children:"make helloworld"})," and run the worker ",(0,a.jsx)(n.code,{children:"./bin/helloworld -m worker"}),", and then in another Shell start a workflow ",(0,a.jsx)(n.code,{children:"./bin/helloworld"})]}),"\n"]}),"\n",(0,a.jsxs)(n.li,{children:["\n",(0,a.jsxs)(n.p,{children:["Go to your ",(0,a.jsx)(n.a,{href:"http://localhost:9090/",children:"local Prometheus dashboard"}),", you should be able to check the metrics emitted by handler from client/frontend/matching/history/sysWorker and confirm your services are healthy through ",(0,a.jsx)(n.a,{href:"http://localhost:9090/targets",children:"targets"})]}),"\n"]}),"\n"]}),"\n",(0,a.jsx)("img",{width:"1192",alt:"Screen Shot 2021-02-20 at 11 31 11 AM",src:"https://user-images.githubusercontent.com/4523955/108606555-8d0dfb80-736f-11eb-968d-7678df37455c.png"}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsxs)(n.li,{children:["Go to ",(0,a.jsx)(n.a,{href:"http://localhost:3000",children:"local Grafana"})," , login as ",(0,a.jsx)(n.code,{children:"admin/admin"}),"."]}),"\n",(0,a.jsxs)(n.li,{children:["Configure Prometheus as datasource: use ",(0,a.jsx)(n.code,{children:"http://host.docker.internal:9090"})," as URL of prometheus."]}),"\n",(0,a.jsxs)(n.li,{children:["Import the ",(0,a.jsx)(n.a,{href:"monitoring#grafanaprometheus-dashboard-templates",children:"Grafana dashboard tempalte"})," as JSON files."]}),"\n"]}),"\n",(0,a.jsx)(n.p,{children:"Client side dashboard looks like this:"}),"\n",(0,a.jsx)("img",{width:"1513",alt:"Screen Shot 2021-02-20 at 12 32 23 PM",src:"https://user-images.githubusercontent.com/4523955/108607838-b7fc4d80-7377-11eb-8fd9-edc0e58afaad.png"}),"\n",(0,a.jsx)(n.p,{children:"And server basic dashboard:"}),"\n",(0,a.jsx)("img",{width:"1514",alt:"Screen Shot 2021-02-20 at 12 31 54 PM",src:"https://user-images.githubusercontent.com/4523955/108607843-baf73e00-7377-11eb-9759-e67a1a00f442.png"}),"\n",(0,a.jsx)("img",{width:"1519",alt:"Screen Shot 2021-02-20 at 11 06 54 AM",src:"https://user-images.githubusercontent.com/4523955/108606577-b169d800-736f-11eb-8fcb-88801f23b656.png"}),"\n",(0,a.jsx)(n.h2,{id:"datadog-dashboard-templates",children:"DataDog dashboard templates"}),"\n",(0,a.jsxs)(n.p,{children:["This ",(0,a.jsx)(n.a,{href:"https://github.com/cadence-workflow/Cadence-Docs/tree/master/src/datadog",children:"package"})," contains examples of Cadence dashboards with DataDog."]}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsxs)(n.li,{children:["\n",(0,a.jsxs)(n.p,{children:[(0,a.jsx)(n.code,{children:"Cadence-Client"})," is the dashboard that includes all the metrics to help you understand Cadence client behavior. Most of these metrics are emitted by the client SDKs, with a few exceptions from server side (for example, workflow timeout)."]}),"\n"]}),"\n",(0,a.jsxs)(n.li,{children:["\n",(0,a.jsxs)(n.p,{children:[(0,a.jsx)(n.code,{children:"Cadence-Server"})," is the the server dashboard that you can use to monitor and undertand the health and status of your Cadence cluster."]}),"\n"]}),"\n"]}),"\n",(0,a.jsxs)(n.p,{children:["To use DataDog with Cadence, follow ",(0,a.jsx)(n.a,{href:"https://docs.datadoghq.com/integrations/guide/prometheus-metrics/",children:"this instruction"})," to collect Prometheus metrics using DataDog agent."]}),"\n",(0,a.jsxs)(n.p,{children:["NOTE1: don't forget to adjust ",(0,a.jsx)(n.code,{children:"max_returned_metrics"})," to a higher number(e.g. 100000). Otherwise DataDog agent won't be able to ",(0,a.jsx)(n.a,{href:"https://docs.datadoghq.com/integrations/guide/prometheus-host-collection/",children:"collect all metrics(default is 2000)"}),"."]}),"\n",(0,a.jsxs)(n.p,{children:["NOTE2: the template contains templating variables ",(0,a.jsx)(n.code,{children:"$App"})," and ",(0,a.jsx)(n.code,{children:"$Availability_Zone"}),". Feel free to remove them if you don't have them in your setup."]}),"\n",(0,a.jsx)(n.h2,{id:"grafanaprometheus-dashboard-templates",children:"Grafana+Prometheus dashboard templates"}),"\n",(0,a.jsxs)(n.p,{children:["This ",(0,a.jsx)(n.a,{href:"https://github.com/cadence-workflow/Cadence-Docs/tree/master/src/grafana/prometheus",children:"package"})," contains examples of Cadence dashboards with Prometheus."]}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsxs)(n.li,{children:["\n",(0,a.jsxs)(n.p,{children:[(0,a.jsx)(n.code,{children:"Cadence-Client"})," is the dashboard of client metrics, and a few server side metrics that belong to client side but have to be emitted by server(for example, workflow timeout)."]}),"\n"]}),"\n",(0,a.jsxs)(n.li,{children:["\n",(0,a.jsxs)(n.p,{children:[(0,a.jsx)(n.code,{children:"Cadence-Server-Basic"})," is the the basic server dashboard to monitor/navigate the health/status of a Cadence cluster."]}),"\n"]}),"\n",(0,a.jsxs)(n.li,{children:["\n",(0,a.jsxs)(n.p,{children:["Apart from the basic server dashboard, it's recommended to set up dashboards on different components for Cadence server: Frontend, History, Matching, Worker, Persistence, Archival, etc. Any ",(0,a.jsx)(n.a,{href:"https://github.com/cadence-workflow/Cadence-Docs",children:"contribution"})," is always welcome to enrich the existing templates or new templates!"]}),"\n"]}),"\n"]}),"\n",(0,a.jsx)(n.h2,{id:"periodic-testscanary-for-health-check",children:"Periodic tests(Canary) for health check"}),"\n",(0,a.jsxs)(n.p,{children:["It's recommended that you run periodical test to get signals on the healthness of your cluster. Please following instructions in ",(0,a.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence/tree/master/canary",children:"our canary package"})," to set these tests up."]}),"\n",(0,a.jsx)(n.h2,{id:"cadence-frontend-monitoring",children:"Cadence Frontend Monitoring"}),"\n",(0,a.jsx)(n.p,{children:"This section describes recommended dashboards for monitoring Cadence services in your cluster. The structure mostly follows the DataDog dashboard template listed above."}),"\n",(0,a.jsx)(n.h3,{id:"service-availabilityserver-metrics",children:"Service Availability(server metrics)"}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsx)(n.li,{children:"Meaning: the availability of Cadence server using server metrics."}),"\n",(0,a.jsx)(n.li,{children:"Suggested monitor: below 95% > 5 min then alert, below 99% for > 5 min triggers a warning"}),"\n",(0,a.jsx)(n.li,{children:"Monitor action: When fired, check if there is any persistence errors. If so then check the healthness of the database(may need to restart or scale up). If not then check the error logs."}),"\n",(0,a.jsx)(n.li,{children:"Datadog query example"}),"\n"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-dql",children:"sum:cadence_frontend.cadence_errors{*}\nsum:cadence_frontend.cadence_requests{*}\n(1 - a / b) * 100\n"})}),"\n",(0,a.jsx)(n.h3,{id:"startworkflow-per-second",children:"StartWorkflow Per Second"}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsx)(n.li,{children:"Meaning: how many workflows are started per second. This helps determine if your server is overloaded."}),"\n",(0,a.jsx)(n.li,{children:"Suggested monitor: This is a business metrics. No monitoring required."}),"\n",(0,a.jsx)(n.li,{children:"Datadog query example"}),"\n"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-dql",children:"sum:cadence_frontend.cadence_requests{(operation IN (startworkflowexecution,signalwithstartworkflowexecution))} by {operation}.as_rate()\n"})}),"\n",(0,a.jsx)(n.h3,{id:"activities-started-per-second",children:"Activities Started Per Second"}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsx)(n.li,{children:"Meaning: How many activities are started per second. Helps determine if the server is overloaded."}),"\n",(0,a.jsx)(n.li,{children:"Suggested monitor: This is a business metrics. No monitoring required."}),"\n",(0,a.jsx)(n.li,{children:"Datadog query example"}),"\n"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-dql",children:"sum:cadence_frontend.cadence_requests{operation:pollforactivitytask} by {operation}.as_rate()\n"})}),"\n",(0,a.jsx)(n.h3,{id:"decisions-started-per-second",children:"Decisions Started Per Second"}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsx)(n.li,{children:"Meaning: How many workflow decisions are started per second. Helps determine if the server is overloaded."}),"\n",(0,a.jsx)(n.li,{children:"Suggested monitor: This is a business metrics. No monitoring required."}),"\n",(0,a.jsx)(n.li,{children:"Datadog query example"}),"\n"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-dql",children:"sum:cadence_frontend.cadence_requests{operation:pollfordecisiontask} by {operation}.as_rate()\n"})}),"\n",(0,a.jsx)(n.h3,{id:"periodical-test-suite-successaka-canary",children:"Periodical Test Suite Success(aka Canary)"}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsx)(n.li,{children:"Meaning: The success counter of canary test suite"}),"\n",(0,a.jsx)(n.li,{children:"Suggested monitor: Monitor needed. If fired, look at the failed canary test case and investigate the reason of failure."}),"\n",(0,a.jsx)(n.li,{children:"Datadog query example"}),"\n"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-dql",children:"sum:cadence_history.workflow_success{workflowtype:workflow_sanity} by {workflowtype}.as_count()\n"})}),"\n",(0,a.jsx)(n.h3,{id:"frontend-all-api-per-second",children:"Frontend all API per second"}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsx)(n.li,{children:"Meaning: all API on frontend per second. Information only."}),"\n",(0,a.jsx)(n.li,{children:"Suggested monitor: This is a business metrics. No monitoring required."}),"\n",(0,a.jsx)(n.li,{children:"Datadog query example"}),"\n"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-dql",children:"sum:cadence_frontend.cadence_requests{*}.as_rate()\n"})}),"\n",(0,a.jsx)(n.h3,{id:"frontend-api-per-second-breakdown-per-operation",children:"Frontend API per second (breakdown per operation)"}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsx)(n.li,{children:"Meaning: API on frontend per second. Information only."}),"\n",(0,a.jsx)(n.li,{children:"Suggested monitor: This is a business metrics. No monitoring required."}),"\n",(0,a.jsx)(n.li,{children:"Datadog query example"}),"\n"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-dql",children:"sum:cadence_frontend.cadence_requests{*} by {operation}.as_rate()\n"})}),"\n",(0,a.jsx)(n.h3,{id:"frontend-api-errors-per-secondbreakdown-per-operation",children:"Frontend API errors per second(breakdown per operation)"}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsx)(n.li,{children:"Meaning: API error on frontend per second. Information only."}),"\n",(0,a.jsx)(n.li,{children:"Suggested monitor: This is to facilitate investigation. No monitoring required."}),"\n",(0,a.jsx)(n.li,{children:"Datadog query example"}),"\n"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-dql",children:"sum:cadence_frontend.cadence_errors{*} by {operation}.as_rate()\nsum:cadence_frontend.cadence_errors_bad_request{*} by {operation}.as_rate()\nsum:cadence_frontend.cadence_errors_domain_not_active{*} by {operation}.as_rate()\nsum:cadence_frontend.cadence_errors_service_busy{*} by {operation}.as_rate()\nsum:cadence_frontend.cadence_errors_entity_not_exists{*} by {operation}.as_rate()\nsum:cadence_frontend.cadence_errors_workflow_execution_already_completed{*} by {operation}.as_rate()\nsum:cadence_frontend.cadence_errors_execution_already_started{*} by {operation}.as_rate()\nsum:cadence_frontend.cadence_errors_domain_already_exists{*} by {operation}.as_rate()\nsum:cadence_frontend.cadence_errors_cancellation_already_requested{*} by {operation}.as_rate()\nsum:cadence_frontend.cadence_errors_query_failed{*} by {operation}.as_rate()\nsum:cadence_frontend.cadence_errors_limit_exceeded{*} by {operation}.as_rate()\nsum:cadence_frontend.cadence_errors_context_timeout{*} by {operation}.as_rate()\nsum:cadence_frontend.cadence_errors_retry_task{*} by {operation}.as_rate()\nsum:cadence_frontend.cadence_errors_bad_binary{*} by {operation}.as_rate()\nsum:cadence_frontend.cadence_errors_client_version_not_supported{*} by {operation}.as_rate()\nsum:cadence_frontend.cadence_errors_incomplete_history{*} by {operation}.as_rate()\nsum:cadence_frontend.cadence_errors_nondeterministic{*} by {operation}.as_rate()\nsum:cadence_frontend.cadence_errors_unauthorized{*} by {operation}.as_rate()\nsum:cadence_frontend.cadence_errors_authorize_failed{*} by {operation}.as_rate()\nsum:cadence_frontend.cadence_errors_remote_syncmatch_failed{*} by {operation}.as_rate()\nsum:cadence_frontend.cadence_errors_domain_name_exceeded_warn_limit{*} by {operation}.as_rate()\nsum:cadence_frontend.cadence_errors_identity_exceeded_warn_limit{*} by {operation}.as_rate()\nsum:cadence_frontend.cadence_errors_workflow_id_exceeded_warn_limit{*} by {operation}.as_rate()\nsum:cadence_frontend.cadence_errors_signal_name_exceeded_warn_limit{*} by {operation}.as_rate()\nsum:cadence_frontend.cadence_errors_workflow_type_exceeded_warn_limit{*} by {operation}.as_rate()\nsum:cadence_frontend.cadence_errors_request_id_exceeded_warn_limit{*} by {operation}.as_rate()\nsum:cadence_frontend.cadence_errors_task_list_name_exceeded_warn_limit{*} by {operation}.as_rate()\nsum:cadence_frontend.cadence_errors_activity_id_exceeded_warn_limit{*} by {operation}.as_rate()\nsum:cadence_frontend.cadence_errors_activity_type_exceeded_warn_limit{*} by {operation}.as_rate()\nsum:cadence_frontend.cadence_errors_marker_name_exceeded_warn_limit{*} by {operation}.as_rate()\nsum:cadence_frontend.cadence_errors_timer_id_exceeded_warn_limit{*} by {operation}.as_rate()\n"})}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsxs)(n.li,{children:[(0,a.jsx)(n.code,{children:"cadence_errors"})," is internal service errors."]}),"\n",(0,a.jsxs)(n.li,{children:["any ",(0,a.jsx)(n.code,{children:"cadence_errors_*"})," is client side error"]}),"\n"]}),"\n",(0,a.jsx)(n.h3,{id:"frontend-regular-api-latency",children:"Frontend Regular API Latency"}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsx)(n.li,{children:"Meaning: The latency of regular core API -- excluding long-poll/queryWorkflow/getHistory/ListWorkflow/CountWorkflow API."}),"\n",(0,a.jsx)(n.li,{children:"Suggested monitor: 95% of all apis and of all operations that take over 1.5 seconds triggers a warning, over 2 seconds triggers an alert"}),"\n",(0,a.jsx)(n.li,{children:"Monitor action: If fired, investigate the database read/write latency. May need to throttle some spiky traffic from certain domains, or scale up the database"}),"\n",(0,a.jsx)(n.li,{children:"Datadog query example"}),"\n"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-dql",children:"avg:cadence_frontend.cadence_latency.quantile{(operation NOT IN (pollfordecisiontask,pollforactivitytask,getworkflowexecutionhistory,queryworkflow,listworkflowexecutions,listclosedworkflowexecutions,listopenworkflowexecutions)) AND $pXXLatency} by {operation}\n"})}),"\n",(0,a.jsx)(n.h3,{id:"frontend-listworkflow-api-latency",children:"Frontend ListWorkflow API Latency"}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsx)(n.li,{children:"Meaning: The latency of ListWorkflow API."}),"\n",(0,a.jsx)(n.li,{children:"Monitor: 95% of all apis and of all operations that take over 2 seconds triggers a warning, over 3 seconds triggers an alert"}),"\n",(0,a.jsx)(n.li,{children:"Monitor action: If fired, investigate the ElasticSearch read latency. May need to throttle some spiky traffic from certain domains, or scale up ElasticSearch cluster."}),"\n",(0,a.jsx)(n.li,{children:"Datadog query example"}),"\n"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-dql",children:"avg:cadence_frontend.cadence_latency.quantile{(operation IN (listclosedworkflowexecutions,listopenworkflowexecutions,listworkflowexecutions,countworkflowexecutions)) AND $pXXLatency} by {operation}\n"})}),"\n",(0,a.jsx)(n.h3,{id:"frontend-long-poll-api-latency",children:"Frontend Long Poll API Latency"}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsx)(n.li,{children:"Meaning: Long poll means that the worker is waiting for a task. The latency is an Indicator for how busy the worker is. Poll for activity task and poll for decision task are the types of long poll requests.The api call times out at 50 seconds if no task can be picked up.A very low latency could mean that more workers need to be added."}),"\n",(0,a.jsx)(n.li,{children:"Suggested monitor: No monitor needed as long latency is expected."}),"\n",(0,a.jsx)(n.li,{children:"Datadog query example"}),"\n"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-dql",children:"avg:cadence_frontend.cadence_latency.quantile{$pXXLatency,operation:pollforactivitytask} by {operation}\navg:cadence_frontend.cadence_latency.quantile{$pXXLatency,operation:pollfordecisiontask} by {operation}\n"})}),"\n",(0,a.jsx)(n.h3,{id:"frontend-get-historyquery-workflow-api-latency",children:"Frontend Get History/Query Workflow API Latency"}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsx)(n.li,{children:"Meaning: GetHistory API acts like a long poll api, but there\u2019s no explicit timeout. Long-poll of GetHistory is being used when WorkflowClient is waiting for the result of the workflow(essentially, WorkflowExecutionCompletedEvent).\nThis latency depends on the time it takes for the workflow to complete. QueryWorkflow API latency is also unpredictable as it depends on the availability and performance of workflow workers, which are owned by the application and workflow implementation(may require replaying history)."}),"\n",(0,a.jsx)(n.li,{children:"Suggested monitor: No monitor needed"}),"\n",(0,a.jsx)(n.li,{children:"Datadog query example"}),"\n"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-dql",children:"avg:cadence_frontend.cadence_latency.quantile{(operation IN (getworkflowexecutionhistory,queryworkflow)) AND $pXXLatency} by {operation}\n"})}),"\n",(0,a.jsx)(n.h3,{id:"frontend-workflowclient-api-per-seconds-by-domain",children:"Frontend WorkflowClient API per seconds by domain"}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsx)(n.li,{children:"Meaning: Shows which domains are making the most requests using WorkflowClient(excluding worker API like PollForDecisionTask and RespondDecisionTaskCompleted). Used for troubleshooting.\nIn the future it can be used to set some rate limiting per domain."}),"\n",(0,a.jsx)(n.li,{children:"Suggested monitor: No monitor needed."}),"\n",(0,a.jsx)(n.li,{children:"Datadog query example"}),"\n"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-dql",children:"sum:cadence_frontend.cadence_requests{(operation IN (signalwithstartworkflowexecution,signalworkflowexecution,startworkflowexecution,terminateworkflowexecution,resetworkflowexecution,requestcancelworkflowexecution,listworkflowexecutions))} by {domain,operation}.as_rate()\n"})}),"\n",(0,a.jsx)(n.h2,{id:"cadence-application-monitoring",children:"Cadence Application Monitoring"}),"\n",(0,a.jsxs)(n.p,{children:["This section describes the recommended dashboards for monitoring Cadence application using metrics emitted by SDK. See the ",(0,a.jsx)(n.code,{children:"setup"})," section about how to collect those metrics."]}),"\n",(0,a.jsx)(n.h3,{id:"workflow-start-and-successful-completion",children:"Workflow Start and Successful completion"}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsx)(n.li,{children:"Workflow successfully started/signalWithStart and completed/canceled/continuedAsNew"}),"\n",(0,a.jsx)(n.li,{children:"Monitor: not recommended"}),"\n",(0,a.jsx)(n.li,{children:"Datadog query example"}),"\n"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-dql",children:"sum:cadence_client.cadence_workflow_start{$Domain,$Tasklist,$WorkflowType} by {workflowtype,env,domain,tasklist}.as_rate()\nsum:cadence_client.cadence_workflow_completed{$Domain,$Tasklist,$WorkflowType} by {workflowtype,env,domain,tasklist}.as_rate()\nsum:cadence_client.cadence_workflow_canceled{$Domain,$Tasklist,$WorkflowType} by {workflowtype,domain,env,tasklist}.as_rate()\nsum:cadence_client.cadence_workflow_continue_as_new{$Domain,$Tasklist,$WorkflowType} by {workflowtype,domain,env,tasklist}.as_rate()\nsum:cadence_client.cadence_workflow_signal_with_start{$Domain,$Tasklist,$WorkflowType} by {workflowtype,domain,env,tasklist}.as_rate()\n"})}),"\n",(0,a.jsx)(n.h3,{id:"workflow-failure",children:"Workflow Failure"}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsx)(n.li,{children:"Metrics for all types of failures, including workflow failures(throw uncaught exceptions), workflow timeout and termination."}),"\n",(0,a.jsx)(n.li,{children:"For timeout and termination, workflow worker doesn\u2019t have a chance to emit metrics when it\u2019s terminate, so the metric comes from the history service"}),"\n",(0,a.jsx)(n.li,{children:"Monitor: application should set monitor on timeout and failure to make sure workflow are not failing. Cancel/terminate are usually triggered by human intentionally."}),"\n",(0,a.jsx)(n.li,{children:"When the metrics fire, go to Cadence UI to find the failed workflows and investigate the workflow history to understand the type of failure"}),"\n",(0,a.jsx)(n.li,{children:"Datadog query example"}),"\n"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-dql",children:"sum:cadence_client.cadence_workflow_failed{$Domain,$Tasklist,$WorkflowType} by {workflowtype,domain,env}.as_count()\nsum:cadence_history.workflow_failed{$Domain,$WorkflowType} by {domain,env,workflowtype}.as_count()\nsum:cadence_history.workflow_terminate{$Domain,$WorkflowType} by {domain,env,workflowtype}.as_count()\nsum:cadence_history.workflow_timeout{$Domain,$WorkflowType} by {domain,env,workflowtype}.as_count()\n"})}),"\n",(0,a.jsx)(n.h3,{id:"decision-poll-counters",children:"Decision Poll Counters"}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsx)(n.li,{children:"Indicates if the workflow worker is available and is polling tasks. If the worker is not available no counters will show.\nCan also check if the worker is using the right task list.\n\u201cNo task\u201d poll type means that the worker exists and is idle.\nThe timeout for this long poll api is 50 seconds. If no task is received within 50 seconds, then an empty response will be returned and another long poll request will be sent."}),"\n",(0,a.jsx)(n.li,{children:"Monitor: application can should monitor on it to make sure workers are available"}),"\n",(0,a.jsx)(n.li,{children:"When fires, investigate the worker deployment to see why they are not available, also check if they are using the right domain/tasklist"}),"\n",(0,a.jsx)(n.li,{children:"Datadog query example"}),"\n"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-dql",children:"sum:cadence_client.cadence_decision_poll_total{$Domain,$Tasklist}.as_count()\nsum:cadence_client.cadence_decision_poll_failed{$Domain,$Tasklist}.as_count()\nsum:cadence_client.cadence_decision_poll_no_task{$Domain,$Tasklist}.as_count()\nsum:cadence_client.cadence_decision_poll_succeed{$Domain,$Tasklist}.as_count()\n"})}),"\n",(0,a.jsx)(n.h3,{id:"decisiontasks-scheduled-per-second",children:"DecisionTasks Scheduled per second"}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsx)(n.li,{children:"Indicate how many decision tasks are scheduled"}),"\n",(0,a.jsx)(n.li,{children:"Monitor: not recommended -- Information only to know whether or not a tasklist is overloaded"}),"\n",(0,a.jsx)(n.li,{children:"Datadog query example"}),"\n"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-dql",children:"sum:cadence_matching.cadence_requests_per_tl{*,operation:adddecisiontask,$Tasklist,$Domain} by {tasklist,domain}.as_rate()\n"})}),"\n",(0,a.jsx)(n.h3,{id:"decision-scheduled-to-start-latency",children:"Decision Scheduled To Start Latency"}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsx)(n.li,{children:"If this latency is too high then either:\nThe worker is not available or too busy after the task has been scheduled.\nThe task list is overloaded(confirmed by DecisionTaskScheduled per second widget). By default a task list only has one partition and a partition can only be owned by one host and so the throughput of a task list is limited. More task lists can be added to scale or a scalable task list can be used to add more partitions."}),"\n",(0,a.jsx)(n.li,{children:"Monitor: application can set monitor on it to make sure latency is tolerable"}),"\n",(0,a.jsx)(n.li,{children:"When fired, check if worker capacity is enough, then check if tasklist is overloaded. If needed, contact the Cadence cluster Admin to enable scalable tasklist to add more partitions to the tasklist"}),"\n",(0,a.jsx)(n.li,{children:"Datadog query example"}),"\n"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-dql",children:"avg:cadence_client.cadence_decision_scheduled_to_start_latency.avg{$Domain,$Tasklist} by {env,domain,tasklist}\nmax:cadence_client.cadence_decision_scheduled_to_start_latency.max{$Domain,$Tasklist} by {env,domain,tasklist}\nmax:cadence_client.cadence_decision_scheduled_to_start_latency.95percentile{$Domain,$Tasklist} by {env,domain,tasklist}\n"})}),"\n",(0,a.jsx)(n.h3,{id:"decision-execution-failure",children:"Decision Execution Failure"}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsx)(n.li,{children:"This means some critical bugs in workflow code causing decision task execution failure"}),"\n",(0,a.jsx)(n.li,{children:"Monitor: application should set monitor on it to make sure no consistent failure"}),"\n",(0,a.jsx)(n.li,{children:"When fired, you may need to terminate the problematic workflows to mitigate the issue. After you identify the bugs, you can fix the code and then reset the workflow to recover"}),"\n",(0,a.jsx)(n.li,{children:"Datadog query example"}),"\n"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-dql",children:"sum:cadence_client.cadence_decision_execution_failed{$Domain,$Tasklist} by {tasklist,workflowtype}.as_count()\n"})}),"\n",(0,a.jsx)(n.h3,{id:"decision-execution-timeout",children:"Decision Execution Timeout"}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsx)(n.li,{children:"This means some critical bugs in workflow code causing decision task execution timeout"}),"\n",(0,a.jsx)(n.li,{children:"Monitor: application should set monitor on it to make sure no consistent timeout"}),"\n",(0,a.jsx)(n.li,{children:"When fired, you may need to terminate the problematic workflows to mitigate the issue. After you identify the bugs, you can fix the code and then reset the workflow to recover"}),"\n",(0,a.jsx)(n.li,{children:"Datadog query example"}),"\n"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-dql",children:"sum:cadence_history.start_to_close_timeout{operation:timeractivetaskdecision*,$Domain}.as_count()\n"})}),"\n",(0,a.jsx)(n.h3,{id:"workflow-end-to-end-latency",children:"Workflow End to End Latency"}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsx)(n.li,{children:"This is for the client application to track their SLOs\nFor example, if you expect a workflow to take duration d to complete, you can use this latency to set a monitor."}),"\n",(0,a.jsx)(n.li,{children:"Monitor: application can monitor this metrics if expecting workflow to complete within a certain duration."}),"\n",(0,a.jsx)(n.li,{children:"When fired, investigate the workflow history to see the workflow takes longer than expected to complete"}),"\n",(0,a.jsx)(n.li,{children:"Datadog query example"}),"\n"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-dql",children:"avg:cadence_client.cadence_workflow_endtoend_latency.median{$Domain,$Tasklist,$WorkflowType} by {env,domain,tasklist,workflowtype}\navg:cadence_client.cadence_workflow_endtoend_latency.95percentile{$Domain,$Tasklist,$WorkflowType} by {env,domain,tasklist,workflowtype}\n"})}),"\n",(0,a.jsx)(n.h3,{id:"workflow-panic-and-nondeterministicerror",children:"Workflow Panic and NonDeterministicError"}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsx)(n.li,{children:"These errors mean that there is a bug in the code and the deploy should be rolled back."}),"\n",(0,a.jsx)(n.li,{children:"A monitor should be set on this metric"}),"\n",(0,a.jsx)(n.li,{children:"When fired, you may rollback the deployment to mitigate your issue. Usually this caused by bad (non-backward compatible) code change. After rollback, look at your worker error logs to see where the bug is."}),"\n",(0,a.jsx)(n.li,{children:"Datadog query example"}),"\n"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-dql",children:"sum:cadence_client.cadence_worker_panic{$Domain} by {env,domain}.as_rate()\nsum:cadence_client.cadence_non_deterministic_error{$Domain} by {env,domain}.as_rate()\n"})}),"\n",(0,a.jsx)(n.h3,{id:"workflow-sticky-cache-hit-rate-and-miss-count",children:"Workflow Sticky Cache Hit Rate and Miss Count"}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsxs)(n.li,{children:["This metric can be used for performance optimization.\nThis can be improved by adding more worker instances, or adjust the workerOption(GoSDK) or WorkferFactoryOption(Java SDK).\nCacheHitRate too low means workers will have to replay history to rebuild the workflow stack when executing a decision task. Depending on the the history size","\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsx)(n.li,{children:"If less than 1MB, then it\u2019s okay to be lower than 50%"}),"\n",(0,a.jsx)(n.li,{children:"If greater than 1MB, then it\u2019s okay to be greater than 50%"}),"\n",(0,a.jsx)(n.li,{children:"If greater than 5MB, , then it\u2019s okay to be greater than 60%"}),"\n",(0,a.jsx)(n.li,{children:"If greater than 10MB , then it\u2019s okay to be greater than 70%"}),"\n",(0,a.jsx)(n.li,{children:"If greater than 20MB , then it\u2019s okay to be greater than 80%"}),"\n",(0,a.jsx)(n.li,{children:"If greater than 30MB , then it\u2019s okay to be greater than 90%"}),"\n",(0,a.jsx)(n.li,{children:"Workflow history size should never be greater than 50MB."}),"\n"]}),"\n"]}),"\n",(0,a.jsx)(n.li,{children:"A monitor can be set on this metric, if performance is important."}),"\n",(0,a.jsx)(n.li,{children:"When fired, adjust the stickyCacheSize in the WorkerFactoryOption, or add more workers"}),"\n",(0,a.jsx)(n.li,{children:"Datadog query example"}),"\n"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-dql",children:"sum:cadence_client.cadence_sticky_cache_miss{$Domain} by {env,domain}.as_count()\nsum:cadence_client.cadence_sticky_cache_hit{$Domain} by {env,domain}.as_count()\n(b / (a+b)) * 100\n"})}),"\n",(0,a.jsx)(n.h3,{id:"activity-task-operations",children:"Activity Task Operations"}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsx)(n.li,{children:"Activity started/completed counters"}),"\n",(0,a.jsx)(n.li,{children:"Monitor: not recommended"}),"\n",(0,a.jsx)(n.li,{children:"Datadog query example"}),"\n"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-dql",children:"sum:cadence_client.cadence_activity_task_failed{$Domain,$Tasklist} by {activitytype}.as_rate()\nsum:cadence_client.cadence_activity_task_completed{$Domain,$Tasklist} by {activitytype}.as_rate()\nsum:cadence_client.cadence_activity_task_timeouted{$Domain,$Tasklist} by {activitytype}.as_rate()\n"})}),"\n",(0,a.jsx)(n.h3,{id:"local-activity-task-operations",children:"Local Activity Task Operations"}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsx)(n.li,{children:"Local Activity execution counters"}),"\n",(0,a.jsx)(n.li,{children:"Monitor: not recommended"}),"\n",(0,a.jsx)(n.li,{children:"Datadog query example"}),"\n"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-dql",children:"sum:cadence_client.cadence_local_activity_total{$Domain,$Tasklist} by {activitytype}.as_count()\n"})}),"\n",(0,a.jsx)(n.h3,{id:"activity-execution-latency",children:"Activity Execution Latency"}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsx)(n.li,{children:"If it\u2019s expected that an activity will take x amount of time to complete, a monitor on this metric could be helpful to enforce that expectation."}),"\n",(0,a.jsx)(n.li,{children:"Monitor: application can set monitor on it if expecting workflow start/complete activities with certain latency"}),"\n",(0,a.jsx)(n.li,{children:"When fired, investigate the activity code and its dependencies"}),"\n",(0,a.jsx)(n.li,{children:"Datadog query example"}),"\n"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-dql",children:"avg:cadence_client.cadence_activity_execution_latency.avg{$Domain,$Tasklist} by {env,domain,tasklist,activitytype}\nmax:cadence_client.cadence_activity_execution_latency.max{$Domain,$Tasklist} by {env,domain,tasklist,activitytype}\n"})}),"\n",(0,a.jsx)(n.h3,{id:"activity-poll-counters",children:"Activity Poll Counters"}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsx)(n.li,{children:"Indicates the activity worker is available and is polling tasks. If the worker is not available no counters will show.\nCan also check if the worker is using the right task list.\n\u201cNo task\u201d poll type means that the worker exists and is idle.\nThe timeout for this long poll api is 50 seconds. If within that 50 seconds, no task is received then an empty response will be returned and another long poll request will be sent."}),"\n",(0,a.jsx)(n.li,{children:"Monitor: application can set monitor on it to make sure activity workers are available"}),"\n",(0,a.jsx)(n.li,{children:"When fires, investigate the worker deployment to see why they are not available, also check if they are using the right domain/tasklist"}),"\n",(0,a.jsx)(n.li,{children:"Datadog query example"}),"\n"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-dql",children:"sum:cadence_client.cadence_activity_poll_total{$Domain,$Tasklist} by {activitytype}.as_count()\nsum:cadence_client.cadence_activity_poll_failed{$Domain,$Tasklist} by {activitytype}.as_count()\nsum:cadence_client.cadence_activity_poll_succeed{$Domain,$Tasklist} by {activitytype}.as_count()\nsum:cadence_client.cadence_activity_poll_no_task{$Domain,$Tasklist} by {activitytype}.as_count()\n"})}),"\n",(0,a.jsx)(n.h3,{id:"activitytasks-scheduled-per-second",children:"ActivityTasks Scheduled per second"}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsx)(n.li,{children:"Indicate how many activities tasks are scheduled"}),"\n",(0,a.jsx)(n.li,{children:"Monitor: not recommended -- Information only to know whether or not a tasklist is overloaded"}),"\n",(0,a.jsx)(n.li,{children:"Datadog query example"}),"\n"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-dql",children:"sum:cadence_matching.cadence_requests_per_tl{*,operation:addactivitytask,$Tasklist,$Domain} by {tasklist,domain}.as_rate()\n"})}),"\n",(0,a.jsx)(n.h3,{id:"activity-scheduled-to-start-latency",children:"Activity Scheduled To Start Latency"}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsx)(n.li,{children:"If the latency is too high either:\nThe worker is not available or too busy\nThere are too many activities scheduled into the same tasklist and the tasklist is not scalable. Same as Decision Scheduled To Start Latency"}),"\n",(0,a.jsx)(n.li,{children:"Monitor: application Should set monitor on it"}),"\n",(0,a.jsx)(n.li,{children:"When fired, check if workers are enough, then check if the tasklist is overloaded. If needed, contact the Cadence cluster Admin to enable scalable tasklist to add more partitions to the tasklist"}),"\n",(0,a.jsx)(n.li,{children:"Datadog query example"}),"\n"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-dql",children:"avg:cadence_client.cadence_activity_scheduled_to_start_latency.avg{$Domain,$Tasklist} by {env,domain,tasklist,activitytype}\nmax:cadence_client.cadence_activity_scheduled_to_start_latency.max{$Domain,$Tasklist} by {env,domain,tasklist,activitytype}\nmax:cadence_client.cadence_activity_scheduled_to_start_latency.95percentile{$Domain,$Tasklist} by {env,domain,tasklist,activitytype}\n"})}),"\n",(0,a.jsx)(n.h3,{id:"activity-failure",children:"Activity Failure"}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsx)(n.li,{children:"A monitor on this metric will alert the team that activities are failing\nThe activity timeout metrics are emitted by the history service, because a timeout causes a hard stop and the client doesn\u2019t have time to emit metrics."}),"\n",(0,a.jsx)(n.li,{children:"Monitor: application can set monitor on it"}),"\n",(0,a.jsx)(n.li,{children:"When fired, investigate the activity code and its dependencies"}),"\n",(0,a.jsxs)(n.li,{children:[(0,a.jsx)(n.code,{children:"cadence_activity_execution_failed"})," vs ",(0,a.jsx)(n.code,{children:"cadence_activity_task_failed"}),":\nOnly have different when using RetryPolicy\ncadence_activity_task_failed counter increase per activity attempt\ncadence_activity_execution_failed counter increase when activity fails after all attempts"]}),"\n",(0,a.jsx)(n.li,{children:"should only monitor on cadence_activity_execution_failed"}),"\n",(0,a.jsx)(n.li,{children:"Datadog query example"}),"\n"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-dql",children:"sum:cadence_client.cadence_activity_execution_failed{$Domain} by {domain,env}.as_rate()\nsum:cadence_client.cadence_activity_task_panic{$Domain} by {domain,env}.as_count()\nsum:cadence_client.cadence_activity_task_failed{$Domain} by {domain,env}.as_rate()\nsum:cadence_client.cadence_activity_task_canceled{$Domain} by {domain,env}.as_count()\nsum:cadence_history.heartbeat_timeout{$Domain} by {domain,env}.as_count()\nsum:cadence_history.schedule_to_start_timeout{$Domain} by {domain,env}.as_rate()\nsum:cadence_history.start_to_close_timeout{$Domain} by {domain,env}.as_rate()\nsum:cadence_history.schedule_to_close_timeout{$Domain} by {domain,env}.as_count()\n"})}),"\n",(0,a.jsx)(n.h3,{id:"service-api-success-rate",children:"Service API success rate"}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsxs)(n.li,{children:["The client\u2019s experience of the service availability. It encompasses many apis. Things that could affect the service\u2019s API success rate are:","\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsx)(n.li,{children:"Service availability"}),"\n",(0,a.jsx)(n.li,{children:"The network could have issues."}),"\n",(0,a.jsx)(n.li,{children:"A required api is not available."}),"\n",(0,a.jsx)(n.li,{children:"Client side errors like EntityNotExists, WorkflowAlreadyStarted etc. This means that application code has potential bugs of calling Cadence service."}),"\n"]}),"\n"]}),"\n",(0,a.jsx)(n.li,{children:"Monitor: application can set monitor on it"}),"\n",(0,a.jsx)(n.li,{children:"When fired, check application logs to see if the error is Cadence server error or client side error. Error like EntityNotExists/ExecutionAlreadyStarted/QueryWorkflowFailed/etc are client side error, meaning that the application is misusing the APIs. If most errors are server side errors(internalServiceError), you can contact Cadence admin."}),"\n",(0,a.jsx)(n.li,{children:"Datadog query example"}),"\n"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-dql",children:"sum:cadence_client.cadence_error{*} by {domain}.as_count()\nsum:cadence_client.cadence_request{*} by {domain}.as_count()\n(1 - a / b) * 100\n"})}),"\n",(0,a.jsx)(n.h3,{id:"service-api-latency",children:"Service API Latency"}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsx)(n.li,{children:"The latency of the API, excluding long poll APIs."}),"\n",(0,a.jsx)(n.li,{children:"Application can set monitor on certain APIs, if necessary."}),"\n",(0,a.jsx)(n.li,{children:"Datadog query example"}),"\n"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-dql",children:"avg:cadence_client.cadence_latency.95percentile{$Domain,!cadence_metric_scope:cadence-pollforactivitytask,!cadence_metric_scope:cadence-pollfordecisiontask} by {cadence_metric_scope}\n"})}),"\n",(0,a.jsx)(n.h3,{id:"service-api-breakdown",children:"Service API Breakdown"}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsx)(n.li,{children:"A counter breakdown by API to help investigate availability"}),"\n",(0,a.jsx)(n.li,{children:"No monitor needed"}),"\n",(0,a.jsx)(n.li,{children:"Datadog query example"}),"\n"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-dql",children:"sum:cadence_client.cadence_request{$Domain,!cadence_metric_scope:cadence-pollforactivitytask,!cadence_metric_scope:cadence-pollfordecisiontask} by {cadence_metric_scope}.as_count()\n"})}),"\n",(0,a.jsx)(n.h3,{id:"service-api-error-breakdown",children:"Service API Error Breakdown"}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsx)(n.li,{children:"A counter breakdown by API error to help investigate availability"}),"\n",(0,a.jsx)(n.li,{children:"No monitor needed"}),"\n",(0,a.jsx)(n.li,{children:"Datadog query example"}),"\n"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-dql",children:"sum:cadence_client.cadence_error{$Domain} by {cadence_metric_scope}.as_count()\n"})}),"\n",(0,a.jsx)(n.h3,{id:"max-event-blob-size",children:"Max Event Blob size"}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsx)(n.li,{children:"By default the max size is 2 MB. If the input is greater than the max size the server will reject the request.\nThe size of a single history event. This applies to any event input, like start workflow event, start activity event, or signal event.\nIt should never be greater than 2MB."}),"\n",(0,a.jsx)(n.li,{children:"A monitor should be set on this metric."}),"\n",(0,a.jsx)(n.li,{children:"When fired, please review the design/code ASAP to reduce the blob size. Reducing the input/output of workflow/activity/signal will help."}),"\n",(0,a.jsx)(n.li,{children:"Datadog query example"}),"\n"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-dql",children:"\u200b\u200bmax:cadence_history.event_blob_size.quantile{!domain:all,$Domain} by {domain}\n"})}),"\n",(0,a.jsx)(n.h3,{id:"max-history-size",children:"Max History Size"}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsx)(n.li,{children:"Workflow history cannot grow indefinitely. It will cause replay issues.\nIf the workflow exceeds the history\u2019s max size the workflow will be terminate automatically. The max size by default is 200 megabytes.\nAs a suggestion for workflow design, workflow history should never grow greater than 50MB. Use continueAsNew to break long workflows into multiple runs."}),"\n",(0,a.jsx)(n.li,{children:"A monitor should be set on this metric."}),"\n",(0,a.jsx)(n.li,{children:"When fired, please review the design/code ASAP to reduce the history size. Reducing the input/output of workflow/activity/signal will help. Also you may need to use ContinueAsNew to break a single execution into smaller pieces."}),"\n",(0,a.jsx)(n.li,{children:"Datadog query example"}),"\n"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-dql",children:"\u200b\u200bmax:cadence_history.history_size.quantile{!domain:all,$Domain} by {domain}\n"})}),"\n",(0,a.jsx)(n.h3,{id:"max-history-length",children:"Max History Length"}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsx)(n.li,{children:"The number of events of workflow history.\nIt should never be greater than 50K(workflow exceeding 200K events will be terminated by server). Use continueAsNew to break long workflows into multiple runs."}),"\n",(0,a.jsx)(n.li,{children:"A monitor should be set on this metric."}),"\n",(0,a.jsx)(n.li,{children:"When fired, please review the design/code ASAP to reduce the history length. You may need to use ContinueAsNew to break a single execution into smaller pieces."}),"\n",(0,a.jsx)(n.li,{children:"Datadog query example"}),"\n"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-dql",children:"\u200b\u200bmax:cadence_history.history_count.quantile{!domain:all,$Domain} by {domain}\n"})}),"\n",(0,a.jsx)(n.h2,{id:"cadence-history-service-monitoring",children:"Cadence History Service Monitoring"}),"\n",(0,a.jsx)(n.p,{children:"History is the most critical/core service for cadence which implements the workflow logic."}),"\n",(0,a.jsx)(n.h3,{id:"history-shard-movements",children:"History shard movements"}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsx)(n.li,{children:"Should only happen during deployment or when the node restarts.\nIf there\u2019s shard movement without deployments then that\u2019s unexpected and there\u2019s probably a performance issue. The shard ownership is assigned by a particular history host, so if the shard is moving it\u2019ll be hard for the frontend service to route a request to a particular history shard and to find it."}),"\n",(0,a.jsx)(n.li,{children:"A monitor can be set to be alerted on shard movements without deployment."}),"\n",(0,a.jsx)(n.li,{children:"Datadog query example"}),"\n"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-dql",children:"sum:cadence_history.membership_changed_count{operation:shardcontroller}\nsum:cadence_history.shard_closed_count{operation:shardcontroller}\nsum:cadence_history.sharditem_created_count{operation:shardcontroller}\nsum:cadence_history.sharditem_removed_count{operation:shardcontroller}\n"})}),"\n",(0,a.jsx)(n.h3,{id:"transfer-tasks-per-second",children:"Transfer Tasks Per Second"}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsx)(n.li,{children:"TransferTask is an internal background task that moves workflow state and transfers an action task from the history engine to another service(e.g. Matching service, ElasticSearch, etc)"}),"\n",(0,a.jsx)(n.li,{children:"No monitor needed"}),"\n",(0,a.jsx)(n.li,{children:"Datadog query example"}),"\n"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-dql",children:"sum:cadence_history.task_requests{operation:transferactivetask*} by {operation}.as_rate()\n"})}),"\n",(0,a.jsx)(n.h3,{id:"timer-tasks-per-second",children:"Timer Tasks Per Second"}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsx)(n.li,{children:"Timer tasks are tasks that are scheduled to be triggered at a given time in future. For example, workflow.sleep() will wait an x amount of time then the task will be pushed somewhere for a worker to pick up."}),"\n",(0,a.jsx)(n.li,{children:"Datadog query example"}),"\n"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-dql",children:"sum:cadence_history.task_requests{operation:timeractivetask*} by {operation}.as_rate()\n"})}),"\n",(0,a.jsx)(n.h3,{id:"transfer-tasks-per-domain",children:"Transfer Tasks Per Domain"}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsx)(n.li,{children:"Count breakdown by domain"}),"\n",(0,a.jsx)(n.li,{children:"Datadog query example"}),"\n"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-dql",children:"sum:cadence_history.task_requests_per_domain{operation:transferactive*} by {domain}.as_count()\n"})}),"\n",(0,a.jsx)(n.h3,{id:"timer-tasks-per-domain",children:"Timer Tasks Per Domain"}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsx)(n.li,{children:"Count breakdown by domain"}),"\n",(0,a.jsx)(n.li,{children:"Datadog query example"}),"\n"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-dql",children:"sum:cadence_history.task_requests_per_domain{operation:timeractive*} by {domain}.as_count()\n"})}),"\n",(0,a.jsx)(n.h3,{id:"transfer-latency-by-type",children:"Transfer Latency by Type"}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsx)(n.li,{children:"If latency is too high then it\u2019s an issue for a workflow. For example, if transfer task latency is 5 second, then it takes 5 second for activity/decision to actual receive the task."}),"\n",(0,a.jsxs)(n.li,{children:["Monitor should be set on diffeernt types of latency. Note that ",(0,a.jsx)(n.code,{children:"queue_latency"})," can go very high during deployment and it's expected. See below NOTE for explanation."]}),"\n",(0,a.jsx)(n.li,{children:"When fired, check if it\u2019s due to some persistence issue.\nIf so then investigate the database(may need to scale up)\nIf not then see if need to scale up Cadence deployment(K8s instance)"}),"\n",(0,a.jsx)(n.li,{children:"Datadog query example"}),"\n"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-dql",children:"avg:cadence_history.task_latency.quantile{$pXXLatency,operation:transfer*} by {operation}\navg:cadence_history.task_latency_processing.quantile{$pXXLatency,operation:transfer*} by {operation}\navg:cadence_history.task_latency_queue.quantile{$pXXLatency,operation:transfer*} by {operation}\n"})}),"\n",(0,a.jsx)(n.h3,{id:"timer-task-latency-by-type",children:"Timer Task Latency by type"}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsx)(n.li,{children:"If latency is too high then it\u2019s an issue for a workflow. For example, if you set the workflow.sleep() for 10 seconds and the timer latency is 5 secs then the workflow will sleep for 15 seconds."}),"\n",(0,a.jsx)(n.li,{children:"Monitor should be set on diffeernt types of latency."}),"\n",(0,a.jsx)(n.li,{children:"When fired, check if it\u2019s due to some persistence issue.\nIf so then investigate the database(may need to scale up) [Mostly]\nIf not then see if need to scale up Cadence deployment(K8s instance)"}),"\n",(0,a.jsx)(n.li,{children:"Datadog query example"}),"\n"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-dql",children:"avg:cadence_history.task_latency.quantile{$pXXLatency,operation:timer*} by {operation}\navg:cadence_history.task_latency_processing.quantile{$pXXLatency,operation:timer*} by {operation}\navg:cadence_history.task_latency_queue.quantile{$pXXLatency,operation:timer*} by {operation}\n"})}),"\n",(0,a.jsx)(n.h3,{id:"note-task-queue-latency-vs-executing-latency-vs-processing-latency-in-transfer--timer-task-latency-metrics",children:"NOTE: Task Queue Latency vs Executing Latency vs Processing Latency In Transfer & Timer Task Latency Metrics"}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsxs)(n.li,{children:[(0,a.jsx)(n.code,{children:"task_latency_queue"}),": \u201cQueue Latency\u201d is \u201cend to end\u201d latency for users. The latency could go to several minutes during deployment because of metrics being re-emitted (but the actual latency is not that high)"]}),"\n",(0,a.jsxs)(n.li,{children:[(0,a.jsx)(n.code,{children:"task_latency"}),": \u201cExecuting latency\u201d is the time from submission to executing pool to completion. It includes scheduling, retry and processing time of the task."]}),"\n",(0,a.jsxs)(n.li,{children:[(0,a.jsx)(n.code,{children:"task_latency_processing"}),": \u201cProcessing latency\u201d is the processing time of the task of a single attempt(without retry)"]}),"\n"]}),"\n",(0,a.jsx)(n.h3,{id:"transfer-task-latency-per-domain",children:"Transfer Task Latency Per Domain"}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsx)(n.li,{children:"Latency breakdown by domain"}),"\n",(0,a.jsx)(n.li,{children:"No monitor needed."}),"\n",(0,a.jsx)(n.li,{children:"Datadog query example: modify above queries to use domain tag."}),"\n"]}),"\n",(0,a.jsx)(n.h3,{id:"timer-task-latency-per-domain",children:"Timer Task Latency Per Domain"}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsx)(n.li,{children:"Latency breakdown by domain"}),"\n",(0,a.jsx)(n.li,{children:"No monitor needed."}),"\n",(0,a.jsx)(n.li,{children:"Datadog query example: modify above queries to use domain tag."}),"\n"]}),"\n",(0,a.jsx)(n.h3,{id:"history-api-per-second",children:"History API per Second"}),"\n",(0,a.jsx)(n.p,{children:"Information about history API\nDatadog query example"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-dql",children:"sum:cadence_history.cadence_requests{*} by {operation}.as_rate()\n"})}),"\n",(0,a.jsx)(n.h3,{id:"history-api-errors-per-second",children:"History API Errors per Second"}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsx)(n.li,{children:"Information about history API"}),"\n",(0,a.jsx)(n.li,{children:"No monitor needed"}),"\n",(0,a.jsx)(n.li,{children:"Datadog query example"}),"\n"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-dql",children:"sum:cadence_history.cadence_errors{*} by {operation}.as_rate()\nsum:cadence_history.cadence_errors_bad_request{*} by {operation}.as_rate()\nsum:cadence_history.cadence_errors_domain_not_active{*} by {operation}.as_rate()\nsum:cadence_history.cadence_errors_service_busy{*} by {operation}.as_rate()\nsum:cadence_history.cadence_errors_entity_not_exists{*} by {operation}.as_rate()\nsum:cadence_history.cadence_errors_workflow_execution_already_completed{*} by {operation}.as_rate()\nsum:cadence_history.cadence_errors_execution_already_started{*} by {operation}.as_rate()\nsum:cadence_history.cadence_errors_domain_already_exists{*} by {operation}.as_rate()\nsum:cadence_history.cadence_errors_cancellation_already_requested{*} by {operation}.as_rate()\nsum:cadence_history.cadence_errors_query_failed{*} by {operation}.as_rate()\nsum:cadence_history.cadence_errors_limit_exceeded{*} by {operation}.as_rate()\nsum:cadence_history.cadence_errors_context_timeout{*} by {operation}.as_rate()\nsum:cadence_history.cadence_errors_retry_task{*} by {operation}.as_rate()\nsum:cadence_history.cadence_errors_bad_binary{*} by {operation}.as_rate()\nsum:cadence_history.cadence_errors_client_version_not_supported{*} by {operation}.as_rate()\nsum:cadence_history.cadence_errors_incomplete_history{*} by {operation}.as_rate()\nsum:cadence_history.cadence_errors_nondeterministic{*} by {operation}.as_rate()\nsum:cadence_history.cadence_errors_unauthorized{*} by {operation}.as_rate()\nsum:cadence_history.cadence_errors_authorize_failed{*} by {operation}.as_rate()\nsum:cadence_history.cadence_errors_remote_syncmatch_failed{*} by {operation}.as_rate()\nsum:cadence_history.cadence_errors_domain_name_exceeded_warn_limit{*} by {operation}.as_rate()\nsum:cadence_history.cadence_errors_identity_exceeded_warn_limit{*} by {operation}.as_rate()\nsum:cadence_history.cadence_errors_workflow_id_exceeded_warn_limit{*} by {operation}.as_rate()\nsum:cadence_history.cadence_errors_signal_name_exceeded_warn_limit{*} by {operation}.as_rate()\nsum:cadence_history.cadence_errors_workflow_type_exceeded_warn_limit{*} by {operation}.as_rate()\nsum:cadence_history.cadence_errors_request_id_exceeded_warn_limit{*} by {operation}.as_rate()\nsum:cadence_history.cadence_errors_task_list_name_exceeded_warn_limit{*} by {operation}.as_rate()\nsum:cadence_history.cadence_errors_activity_id_exceeded_warn_limit{*} by {operation}.as_rate()\nsum:cadence_history.cadence_errors_activity_type_exceeded_warn_limit{*} by {operation}.as_rate()\nsum:cadence_history.cadence_errors_marker_name_exceeded_warn_limit{*} by {operation}.as_rate()\nsum:cadence_history.cadence_errors_timer_id_exceeded_warn_limit{*} by {operation}.as_rate()\n"})}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsxs)(n.li,{children:[(0,a.jsx)(n.code,{children:"cadence_errors"})," is internal service errors."]}),"\n",(0,a.jsxs)(n.li,{children:["any ",(0,a.jsx)(n.code,{children:"cadence_errors_*"})," is client side error"]}),"\n"]}),"\n",(0,a.jsx)(n.h3,{id:"max-history-size-1",children:"Max History Size"}),"\n",(0,a.jsx)(n.p,{children:"The history size of the workflow cannot be too large otherwise it will cause performance issue during replay. The soft limit is 200MB. If exceeding workflow will be terminated by server."}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsx)(n.li,{children:"No monitor needed"}),"\n",(0,a.jsx)(n.li,{children:"Datadog query is same as the client section"}),"\n"]}),"\n",(0,a.jsx)(n.h3,{id:"max-history-length-1",children:"Max History Length"}),"\n",(0,a.jsx)(n.p,{children:"Similarly, the history length of the workflow cannot be too large otherwise it will cause performance issues during replay. The soft limit is 200K events. If exceeding, workflow will be terminated by server."}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsx)(n.li,{children:"No monitor needed"}),"\n",(0,a.jsx)(n.li,{children:"Datadog query is same as the client section"}),"\n"]}),"\n",(0,a.jsx)(n.h3,{id:"max-event-blob-size-1",children:"Max Event Blob Size"}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsx)(n.li,{children:"The size of each event(e.g. Decided by input/output of workflow/activity/signal/chidlWorkflow/etc) cannot be too large otherwise it will also cause performance issue. The soft limit is 2MB. If exceeding, the requests will be rejected by server, meaning that workflow won\u2019t be able to make any progress."}),"\n",(0,a.jsx)(n.li,{children:"No monitor needed"}),"\n",(0,a.jsx)(n.li,{children:"Datadog query is same as the client section"}),"\n"]}),"\n",(0,a.jsx)(n.h2,{id:"cadence-matching-service-monitoring",children:"Cadence Matching Service Monitoring"}),"\n",(0,a.jsx)(n.p,{children:"Matching service is to match/assign tasks from cadence service to workers. Matching got the tasks from history service. If workers are active the task will be matched immediately , It\u2019s called \u201csync match\u201d. If workers are not available, matching will persist into database and then reload the tasks when workers are back(called \u201casync match\u201d)"}),"\n",(0,a.jsx)(n.h3,{id:"matching-apis-per-second",children:"Matching APIs per Second"}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsx)(n.li,{children:"API processed by matching service per second"}),"\n",(0,a.jsx)(n.li,{children:"No monitor needed"}),"\n",(0,a.jsx)(n.li,{children:"Datadog query example"}),"\n"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-dql",children:"sum:cadence_matching.cadence_requests{*} by {operation}.as_rate()\n"})}),"\n",(0,a.jsx)(n.h3,{id:"matching-api-errors-per-second",children:"Matching API Errors per Second"}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsx)(n.li,{children:"API errors by matching service per second"}),"\n",(0,a.jsx)(n.li,{children:"No monitor needed"}),"\n",(0,a.jsx)(n.li,{children:"Datadog query example"}),"\n"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-dql",children:"sum:cadence_matching.cadence_errors_per_tl{*} by {operation,domain,tasklist}.as_rate()\nsum:cadence_matching.cadence_errors_bad_request_per_tl{*} by {operation,domain,tasklist}\nsum:cadence_matching.cadence_errors_bad_request{*} by {operation,domain,tasklist}\nsum:cadence_matching.cadence_errors_domain_not_active_per_tl{*} by {operation,domain,tasklist}\nsum:cadence_matching.cadence_errors_domain_not_active{*} by {operation,domain,tasklist}\nsum:cadence_matching.cadence_errors_service_busy_per_tl{*} by {operation,domain,tasklist}\nsum:cadence_matching.cadence_errors_service_busy{*} by {operation,domain,tasklist}\nsum:cadence_matching.cadence_errors_entity_not_exists_per_tl{*} by {operation,domain,tasklist}\nsum:cadence_matching.cadence_errors_entity_not_exists{*} by {operation,domain,tasklist}\nsum:cadence_matching.cadence_errors_execution_already_started_per_tl{*} by {operation,domain,tasklist}\nsum:cadence_matching.cadence_errors_execution_already_started{*} by {operation,domain,tasklist}\nsum:cadence_matching.cadence_errors_domain_already_exists_per_tl{*} by {operation,domain,tasklist}\nsum:cadence_matching.cadence_errors_domain_already_exists{*} by {operation,domain,tasklist}\nsum:cadence_matching.cadence_errors_cancellation_already_requested_per_tl{*} by {operation,domain,tasklist}\nsum:cadence_matching.cadence_errors_cancellation_already_requested{*} by {operation,domain,tasklist}\nsum:cadence_matching.cadence_errors_query_failed_per_tl{*} by {operation,domain,tasklist}\nsum:cadence_matching.cadence_errors_query_failed{*} by {operation,domain,tasklist}\nsum:cadence_matching.cadence_errors_limit_exceeded_per_tl{*} by {operation,domain,tasklist}\nsum:cadence_matching.cadence_errors_limit_exceeded{*} by {operation,domain,tasklist}\nsum:cadence_matching.cadence_errors_context_timeout_per_tl{*} by {operation,domain,tasklist}\nsum:cadence_matching.cadence_errors_context_timeout{*} by {operation,domain,tasklist}\nsum:cadence_matching.cadence_errors_retry_task_per_tl{*} by {operation,domain,tasklist}\nsum:cadence_matching.cadence_errors_retry_task{*} by {operation,domain,tasklist}\nsum:cadence_matching.cadence_errors_bad_binary_per_tl{*} by {operation,domain,tasklist}\nsum:cadence_matching.cadence_errors_bad_binary{*} by {operation,domain,tasklist}\nsum:cadence_matching.cadence_errors_client_version_not_supported_per_tl{*} by {operation,domain,tasklist}\nsum:cadence_matching.cadence_errors_client_version_not_supported{*} by {operation,domain,tasklist}\nsum:cadence_matching.cadence_errors_incomplete_history_per_tl{*} by {operation,domain,tasklist}\nsum:cadence_matching.cadence_errors_incomplete_history{*} by {operation,domain,tasklist}\nsum:cadence_matching.cadence_errors_nondeterministic_per_tl{*} by {operation,domain,tasklist}\nsum:cadence_matching.cadence_errors_nondeterministic{*} by {operation,domain,tasklist}\nsum:cadence_matching.cadence_errors_unauthorized_per_tl{*} by {operation,domain,tasklist}\nsum:cadence_matching.cadence_errors_unauthorized{*} by {operation,domain,tasklist}\nsum:cadence_matching.cadence_errors_authorize_failed_per_tl{*} by {operation,domain,tasklist}\nsum:cadence_matching.cadence_errors_authorize_failed{*} by {operation,domain,tasklist}\nsum:cadence_matching.cadence_errors_remote_syncmatch_failed_per_tl{*} by {operation,domain,tasklist}\nsum:cadence_matching.cadence_errors_remote_syncmatch_failed{*} by {operation,domain,tasklist}\nsum:cadence_matching.cadence_errors_shard_ownership_lost{*} by {operation,domain,tasklist}\nsum:cadence_matching.cadence_errors_event_already_started{*} by {operation,domain,tasklist}\n"})}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsxs)(n.li,{children:[(0,a.jsx)(n.code,{children:"cadence_errors"})," is internal service errors."]}),"\n",(0,a.jsxs)(n.li,{children:["any ",(0,a.jsx)(n.code,{children:"cadence_errors_*"})," is client side error"]}),"\n"]}),"\n",(0,a.jsx)(n.h3,{id:"matching-regular-api-latency",children:"Matching Regular API Latency"}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsx)(n.li,{children:"Regular APIs are the APIs excluding long polls"}),"\n",(0,a.jsx)(n.li,{children:"No monitor needed"}),"\n",(0,a.jsx)(n.li,{children:"Datadog query example"}),"\n"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-dql",children:"avg:cadence_matching.cadence_latency_per_tl.quantile{$pXXLatency,!operation:pollfor*,!operation:queryworkflow} by {operation,tasklist}\n"})}),"\n",(0,a.jsx)(n.h3,{id:"sync-match-latency",children:"Sync Match Latency:"}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsx)(n.li,{children:"If the latency is too high, probably the tasklist is overloaded. Consider using multiple tasklist, or enable scalable tasklist feature by adding more partition to the tasklist(default is one)\nTo confirm if there are too many tasks being added to the tasklist, use \u201cAddTasks per second - domain, tasklist breakdown\u201d"}),"\n",(0,a.jsx)(n.li,{children:"No monitor needed"}),"\n",(0,a.jsx)(n.li,{children:"Datadog query example"}),"\n"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-dql",children:"sum:cadence_matching.syncmatch_latency_per_tl.quantile{$pXXLatency} by {operation,tasklist,domain}\n"})}),"\n",(0,a.jsx)(n.h3,{id:"async-match-latency",children:"Async match Latency"}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsx)(n.li,{children:"If a match is done asynchronously it writes a match to the db to use later. Measures the time when the worker is not actively looking for tasks. If this is high, more workers are needed."}),"\n",(0,a.jsx)(n.li,{children:"No monitor needed"}),"\n",(0,a.jsx)(n.li,{children:"Datadog query example"}),"\n"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-dql",children:"sum:cadence_matching.asyncmatch_latency_per_tl.quantile{$pXXLatency} by {operation,tasklist,domain}\n"})}),"\n",(0,a.jsx)(n.h2,{id:"cadence-default-persistence-monitoring",children:"Cadence Default Persistence Monitoring"}),"\n",(0,a.jsx)(n.p,{children:"The following monotors should be set up for Cadence persistence."}),"\n",(0,a.jsx)(n.h3,{id:"persistence-availability",children:"Persistence Availability"}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsx)(n.li,{children:"The availability of the primary database for your Cadence server"}),"\n",(0,a.jsx)(n.li,{children:"Monitor required: Below 95% > 5min then alert, below 99% triggers a slack warning"}),"\n",(0,a.jsx)(n.li,{children:"When fired, check if it\u2019s due to some persistence issue.\nIf so then investigate the database(may need to scale up) [Mostly]\nIf not then see if need to scale up Cadence deployment(K8s instance)"}),"\n",(0,a.jsx)(n.li,{children:"Datadog query example"}),"\n"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-dql",children:"sum:cadence_frontend.persistence_errors{*} by {operation}.as_count()\nsum:cadence_frontend.persistence_requests{*} by {operation}.as_count()\nsum:cadence_matching.persistence_errors{*} by {operation}.as_count()\nsum:cadence_matching.persistence_requests{*} by {operation}.as_count()\nsum:cadence_history.persistence_errors{*} by {operation}.as_count()\nsum:cadence_history.persistence_requests{*} by {operation}.as_count()\nsum:cadence_worker.persistence_errors{*} by {operation}.as_count()\nsum:cadence_worker.persistence_requests{*} by {operation}.as_count()\n(1 - a / b) * 100\n(1 - c / d) * 100\n(1 - e / f) * 100\n(1 - g / h) * 100\n"})}),"\n",(0,a.jsx)(n.h3,{id:"persistence-by-service-tps",children:"Persistence By Service TPS"}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsx)(n.li,{children:"No monitor needed"}),"\n",(0,a.jsx)(n.li,{children:"Datadog query example"}),"\n"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-dql",children:"sum:cadence_frontend.persistence_requests{*}.as_rate()\nsum:cadence_history.persistence_requests{*}.as_rate()\nsum:cadence_worker.persistence_requests{*}.as_rate()\nsum:cadence_matching.persistence_requests{*}.as_rate()\n\n"})}),"\n",(0,a.jsx)(n.h3,{id:"persistence-by-operation-tps",children:"Persistence By Operation TPS"}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsx)(n.li,{children:"No monitor needed"}),"\n",(0,a.jsx)(n.li,{children:"Datadog query example"}),"\n"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-dql",children:"sum:cadence_frontend.persistence_requests{*} by {operation}.as_rate()\nsum:cadence_history.persistence_requests{*} by {operation}.as_rate()\nsum:cadence_worker.persistence_requests{*} by {operation}.as_rate()\nsum:cadence_matching.persistence_requests{*} by {operation}.as_rate()\n\n"})}),"\n",(0,a.jsx)(n.h3,{id:"persistence-by-operation-latency",children:"Persistence By Operation Latency"}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsx)(n.li,{children:"Monitor required, alert if 95% of all operation latency is greater than 1 second for 5mins, warning if greater than 0.5 seconds"}),"\n",(0,a.jsx)(n.li,{children:"When fired, investigate the database(may need to scale up) [Mostly]\nIf there\u2019s a high latency, then there could be errors or something wrong with the db"}),"\n",(0,a.jsx)(n.li,{children:"Datadog query example"}),"\n"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-dql",children:"avg:cadence_matching.persistence_latency.quantile{$pXXLatency} by {operation}\navg:cadence_worker.persistence_latency.quantile{$pXXLatency} by {operation}\navg:cadence_frontend.persistence_latency.quantile{$pXXLatency} by {operation}\navg:cadence_history.persistence_latency.quantile{$pXXLatency} by {operation}\n"})}),"\n",(0,a.jsx)(n.h3,{id:"persistence-error-by-operation-count",children:"Persistence Error By Operation Count"}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsx)(n.li,{children:"It's to help investigate availability issue"}),"\n",(0,a.jsx)(n.li,{children:"No monitor needed"}),"\n",(0,a.jsx)(n.li,{children:"Datadog query example"}),"\n"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-dql",children:"sum:cadence_frontend.persistence_errors{*} by {operation}.as_count()\nsum:cadence_history.persistence_errors{*} by {operation}.as_count()\nsum:cadence_worker.persistence_errors{*} by {operation}.as_count()\nsum:cadence_matching.persistence_errors{*} by {operation}.as_count()\n\nsum:cadence_frontend.persistence_errors_shard_exists{*} by {operation}.as_count()\nsum:cadence_frontend.persistence_errors_shard_ownership_lost{*} by {operation}.as_count()\nsum:cadence_frontend.persistence_errors_condition_failed{*} by {operation}.as_count()\nsum:cadence_frontend.persistence_errors_current_workflow_condition_failed{*} by {operation}.as_count()\nsum:cadence_frontend.persistence_errors_timeout{*} by {operation}.as_count()\nsum:cadence_frontend.persistence_errors_busy{*} by {operation}.as_count()\nsum:cadence_frontend.persistence_errors_entity_not_exists{*} by {operation}.as_count()\nsum:cadence_frontend.persistence_errors_execution_already_started{*} by {operation}.as_count()\nsum:cadence_frontend.persistence_errors_domain_already_exists{*} by {operation}.as_count()\nsum:cadence_frontend.persistence_errors_bad_request{*} by {operation}.as_count()\n\nsum:cadence_history.persistence_errors_shard_exists{*} by {operation}.as_count()\nsum:cadence_history.persistence_errors_shard_ownership_lost{*} by {operation}.as_count()\nsum:cadence_history.persistence_errors_condition_failed{*} by {operation}.as_count()\nsum:cadence_history.persistence_errors_current_workflow_condition_failed{*} by {operation}.as_count()\nsum:cadence_history.persistence_errors_timeout{*} by {operation}.as_count()\nsum:cadence_history.persistence_errors_busy{*} by {operation}.as_count()\nsum:cadence_history.persistence_errors_entity_not_exists{*} by {operation}.as_count()\nsum:cadence_history.persistence_errors_execution_already_started{*} by {operation}.as_count()\nsum:cadence_history.persistence_errors_domain_already_exists{*} by {operation}.as_count()\nsum:cadence_history.persistence_errors_bad_request{*} by {operation}.as_count()\n\nsum:cadence_matching.persistence_errors_shard_exists{*} by {operation}.as_count()\nsum:cadence_matching.persistence_errors_shard_ownership_lost{*} by {operation}.as_count()\nsum:cadence_matching.persistence_errors_condition_failed{*} by {operation}.as_count()\nsum:cadence_matching.persistence_errors_current_workflow_condition_failed{*} by {operation}.as_count()\nsum:cadence_matching.persistence_errors_timeout{*} by {operation}.as_count()\nsum:cadence_matching.persistence_errors_busy{*} by {operation}.as_count()\nsum:cadence_matching.persistence_errors_entity_not_exists{*} by {operation}.as_count()\nsum:cadence_matching.persistence_errors_execution_already_started{*} by {operation}.as_count()\nsum:cadence_matching.persistence_errors_domain_already_exists{*} by {operation}.as_count()\nsum:cadence_matching.persistence_errors_bad_request{*} by {operation}.as_count()\n\nsum:cadence_worker.persistence_errors_shard_exists{*} by {operation}.as_count()\nsum:cadence_worker.persistence_errors_shard_ownership_lost{*} by {operation}.as_count()\nsum:cadence_worker.persistence_errors_condition_failed{*} by {operation}.as_count()\nsum:cadence_worker.persistence_errors_current_workflow_condition_failed{*} by {operation}.as_count()\nsum:cadence_worker.persistence_errors_timeout{*} by {operation}.as_count()\nsum:cadence_worker.persistence_errors_busy{*} by {operation}.as_count()\nsum:cadence_worker.persistence_errors_entity_not_exists{*} by {operation}.as_count()\nsum:cadence_worker.persistence_errors_execution_already_started{*} by {operation}.as_count()\nsum:cadence_worker.persistence_errors_domain_already_exists{*} by {operation}.as_count()\nsum:cadence_worker.persistence_errors_bad_request{*} by {operation}.as_count()\n\n"})}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsxs)(n.li,{children:[(0,a.jsx)(n.code,{children:"cadence_errors"})," is internal service errors."]}),"\n",(0,a.jsxs)(n.li,{children:["any ",(0,a.jsx)(n.code,{children:"cadence_errors_*"})," is client side error"]}),"\n"]}),"\n",(0,a.jsx)(n.h2,{id:"cadence-advanced-visibility-persistence-monitoringif-applicable",children:"Cadence Advanced Visibility Persistence Monitoring(if applicable)"}),"\n",(0,a.jsx)(n.p,{children:"Kafka & ElasticSearch are only for visibility. Only applicable \u200b\u200bif using advanced visibility.\nFor writing visibility records, Cadence history service will write down the records into Kafka, and then Cadence worker service will read from Kafka and write into ElasticSearch(in batch, for performance optimization)\nFor reading visibility records, Frontend service will query ElasticSearch directly."}),"\n",(0,a.jsx)(n.h3,{id:"persistence-availability-1",children:"Persistence Availability"}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsx)(n.li,{children:"The availability of Cadence server using database"}),"\n",(0,a.jsx)(n.li,{children:"Monitor can be set"}),"\n",(0,a.jsx)(n.li,{children:"Datadog query example"}),"\n"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-dql",children:"sum:cadence_frontend.elasticsearch_errors{*} by {operation}.as_count()\nsum:cadence_frontend.elasticsearch_requests{*} by {operation}.as_count()\nsum:cadence_history.elasticsearch_errors{*} by {operation}.as_count()\nsum:cadence_history.elasticsearch_requests{*} by {operation}.as_count()\n(1 - a / b) * 100\n(1 - c / d) * 100\n"})}),"\n",(0,a.jsx)(n.h3,{id:"persistence-by-service-tps-1",children:"Persistence By Service TPS"}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsx)(n.li,{children:"The error of persistence API call by service"}),"\n",(0,a.jsx)(n.li,{children:"No monitor needed"}),"\n",(0,a.jsx)(n.li,{children:"Datadog query example"}),"\n"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-dql",children:"sum:cadence_frontend.elasticsearch_requests{*}.as_rate()\nsum:cadence_history.elasticsearch_requests{*}.as_rate()\n"})}),"\n",(0,a.jsx)(n.h3,{id:"persistence-by-operation-tpsread-es-write-kafka",children:"Persistence By Operation TPS(read: ES, write: Kafka)"}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsx)(n.li,{children:"The rate of persistence API call by API"}),"\n",(0,a.jsx)(n.li,{children:"No monitor needed"}),"\n",(0,a.jsx)(n.li,{children:"Datadog query example"}),"\n"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-dql",children:"sum:cadence_frontend.elasticsearch_requests{*} by {operation}.as_rate()\nsum:cadence_history.elasticsearch_requests{*} by {operation}.as_rate()\n"})}),"\n",(0,a.jsx)(n.h3,{id:"persistence-by-operation-latencyin-seconds-read-es-write-kafka",children:"Persistence By Operation Latency(in seconds) (read: ES, write: Kafka)"}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsx)(n.li,{children:"The latency of persistence API call"}),"\n",(0,a.jsx)(n.li,{children:"No monitor needed"}),"\n",(0,a.jsx)(n.li,{children:"Datadog query example"}),"\n"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-dql",children:"avg:cadence_frontend.elasticsearch_latency.quantile{$pXXLatency} by {operation}\navg:cadence_history.elasticsearch_latency.quantile{$pXXLatency} by {operation}\n"})}),"\n",(0,a.jsx)(n.h3,{id:"persistence-error-by-operation-count-read-es-write-kafka",children:"Persistence Error By Operation Count (read: ES, write: Kafka)"}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsx)(n.li,{children:"The error of persistence API call"}),"\n",(0,a.jsx)(n.li,{children:"No monitor needed"}),"\n",(0,a.jsx)(n.li,{children:"Datadog query example"}),"\n"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-dql",children:"sum:cadence_frontend.elasticsearch_errors{*} by {operation}.as_count()\nsum:cadence_history.elasticsearch_errors{*} by {operation}.as_count()\n"})}),"\n",(0,a.jsx)(n.h3,{id:"kafka-es-processor-counter",children:"Kafka->ES processor counter"}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsx)(n.li,{children:"This is the metrics of a background processing: consuming Kafka messages and then populate to ElasticSearch in batch"}),"\n",(0,a.jsx)(n.li,{children:"Monitor on the running of the background processing(counter metrics is > 0)"}),"\n",(0,a.jsx)(n.li,{children:"When fired, restart Cadence service first to mitigate. Then look at logs to see why the process is stopped(process panic/error/etc).\nMay consider add more pods (replicaCount) to sys-worker service for higher availability"}),"\n",(0,a.jsx)(n.li,{children:"Datadog query example"}),"\n"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-dql",children:"sum:cadence_worker.es_processor_requests{*} by {operation}.as_count()\nsum:cadence_worker.es_processor_retries{*} by {operation}.as_count()\n"})}),"\n",(0,a.jsx)(n.h3,{id:"kafka-es-processor-error",children:"Kafka->ES processor error"}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsx)(n.li,{children:"This is the error metrics of the above processing logic\nAlmost all errors are retryable errors so it\u2019s not a problem."}),"\n",(0,a.jsx)(n.li,{children:"Need to monitor error"}),"\n",(0,a.jsx)(n.li,{children:"When fired, Go to Kibana to find logs about the error details.\nThe most common error is missing the ElasticSearch index field -- an index field is added in dynamicconfig but not in ElasticSearch, or vice versa . If so, follow the runbook to add the field to ElasticSearch or dynamic config."}),"\n",(0,a.jsx)(n.li,{children:"Datadog query example"}),"\n"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-dql",children:"sum:cadence_worker.es_processor_error{*} by {operation}.as_count()\nsum:cadence_worker.es_processor_corrupted_data{*} by {operation}.as_count()\n"})}),"\n",(0,a.jsx)(n.h3,{id:"kafka-es-processor-latency",children:"Kafka->ES processor latency"}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsx)(n.li,{children:"The latency of the processing logic"}),"\n",(0,a.jsx)(n.li,{children:"No monitor needed"}),"\n",(0,a.jsx)(n.li,{children:"Datadog query example"}),"\n"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-dql",children:"sum:cadence_worker.es_processor_process_msg_latency.quantile{$pXXLatency} by {operation}.as_count()\n"})}),"\n",(0,a.jsx)(n.h2,{id:"cadence-dependency-metrics-monitor-suggestion",children:"Cadence Dependency Metrics Monitor suggestion"}),"\n",(0,a.jsx)(n.h3,{id:"computing-platform-metrics-for-cadence-deployment",children:"Computing platform metrics for Cadence deployment"}),"\n",(0,a.jsx)(n.p,{children:"Cadence server being deployed on any computing platform(e.g. Kubernetese) should be monitored on the blow metrics:"}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsx)(n.li,{children:"CPU"}),"\n",(0,a.jsx)(n.li,{children:"Memory"}),"\n"]}),"\n",(0,a.jsx)(n.h3,{id:"database",children:"Database"}),"\n",(0,a.jsx)(n.p,{children:"Depends on which database, you should at least monitor on the below metrics"}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsx)(n.li,{children:"Disk Usage"}),"\n",(0,a.jsx)(n.li,{children:"CPU"}),"\n",(0,a.jsx)(n.li,{children:"Memory"}),"\n",(0,a.jsx)(n.li,{children:"Read API latency"}),"\n",(0,a.jsx)(n.li,{children:"Write API Latency"}),"\n"]}),"\n",(0,a.jsx)(n.h3,{id:"kafka-if-applicable",children:"Kafka (if applicable)"}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsx)(n.li,{children:"Disk Usage"}),"\n",(0,a.jsx)(n.li,{children:"CPU"}),"\n",(0,a.jsx)(n.li,{children:"Memory"}),"\n"]}),"\n",(0,a.jsx)(n.h3,{id:"elasticsearch-if-applicable",children:"ElasticSearch (if applicable)"}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsx)(n.li,{children:"Disk Usage"}),"\n",(0,a.jsx)(n.li,{children:"CPU"}),"\n",(0,a.jsx)(n.li,{children:"Memory"}),"\n"]}),"\n",(0,a.jsx)(n.h2,{id:"cadence-service-slo-recommendation",children:"Cadence Service SLO Recommendation"}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsxs)(n.li,{children:["Core API availability: ",(0,a.jsx)(n.code,{children:"99.9%"})]}),"\n",(0,a.jsxs)(n.li,{children:["Core API latency: ",(0,a.jsx)(n.code,{children:"<1s"})]}),"\n",(0,a.jsxs)(n.li,{children:["Overall task dispatch latency: ",(0,a.jsx)(n.code,{children:"<2s"})," (queue_latency for transfer task and timer task)"]}),"\n"]})]})}function h(e={}){const{wrapper:n}={...(0,t.R)(),...e.components};return n?(0,a.jsx)(n,{...e,children:(0,a.jsx)(d,{...e})}):d(e)}},8453:(e,n,i)=>{i.d(n,{R:()=>s,x:()=>o});var r=i(6540);const a={},t=r.createContext(a);function s(e){const n=r.useContext(t);return r.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function o(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:s(e.components),r.createElement(t.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/7373c0c0.08dfd38a.js b/assets/js/7373c0c0.08dfd38a.js deleted file mode 100644 index 6aeaed7c5..000000000 --- a/assets/js/7373c0c0.08dfd38a.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[2779],{2123:(e,n,o)=>{o.r(n),o.d(n,{assets:()=>i,contentTitle:()=>s,default:()=>d,frontMatter:()=>a,metadata:()=>t,toc:()=>l});const t=JSON.parse('{"id":"concepts/queries","title":"Synchronous query","description":"Workflowworkflow_executionqueryworkflowqueryworkflow: type exposing different information to different external systems.","source":"@site/docs/03-concepts/04-queries.md","sourceDirName":"03-concepts","slug":"/concepts/queries","permalink":"/docs/concepts/queries","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/03-concepts/04-queries.md","tags":[],"version":"current","sidebarPosition":4,"frontMatter":{"layout":"default","title":"Synchronous query","permalink":"/docs/concepts/queries"},"sidebar":"docsSidebar","previous":{"title":"Event handling","permalink":"/docs/concepts/events"},"next":{"title":"Deployment topology","permalink":"/docs/concepts/topology"}}');var r=o(4848),c=o(8453);const a={layout:"default",title:"Synchronous query",permalink:"/docs/concepts/queries"},s="Synchronous query",i={},l=[{value:"Stack Trace Query",id:"stack-trace-query",level:2}];function u(e){const n={code:"code",em:"em",h1:"h1",h2:"h2",header:"header",p:"p",pre:"pre",...(0,c.R)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(n.header,{children:(0,r.jsx)(n.h1,{id:"synchronous-query",children:"Synchronous query"})}),"\n",(0,r.jsx)(n.p,{children:"Workflow code is stateful with the Cadence framework preserving it over various software and hardware failures. The state is constantly mutated during workflow_execution. To expose this internal state to the external world Cadence provides a synchronous query feature. From the workflow implementer point of view the query is exposed as a synchronous callback that is invoked by external entities. Multiple such callbacks can be provided per workflow type exposing different information to different external systems."}),"\n",(0,r.jsxs)(n.p,{children:["To execute a query an external client calls a synchronous Cadence API providing ",(0,r.jsx)(n.em,{children:"domain, workflowID, query name"})," and optional ",(0,r.jsx)(n.em,{children:"query arguments"}),"."]}),"\n",(0,r.jsx)(n.p,{children:"Query callbacks must be read-only not mutating the workflow state in any way. The other limitation is that the query callback cannot contain any blocking code. Both above limitations rule out ability to invoke activities from the query handlers."}),"\n",(0,r.jsxs)(n.p,{children:["Cadence team is currently working on implementing ",(0,r.jsx)(n.em,{children:"update"})," feature that would be similar to query in the way it is invoked, but would support workflow state mutation and local_activity invocations. From user's point of view, ",(0,r.jsx)(n.em,{children:"update"})," is similar to signal + strong consistent query, but implemented in a much less expensive way in Cadence."]}),"\n",(0,r.jsx)(n.h2,{id:"stack-trace-query",children:"Stack Trace Query"}),"\n",(0,r.jsxs)(n.p,{children:["The Cadence client libraries expose some predefined queries out of the box. Currently the only supported built-in query is ",(0,r.jsx)(n.em,{children:"stack_trace"}),". This query returns stacks of all workflow owned threads. This is a great way to troubleshoot any workflow in production."]}),"\n",(0,r.jsx)(n.p,{children:"Example"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-shell-session",metastring:"wordWrap=true",children:'$ cadence --do samples-domain wf query -w -qt __stack_trace\n\n"coroutine 1 [blocked on selector-1.Select]:\\nmain.sampleSignalCounterWorkflow(0x1a99ae8, 0xc00009d700, 0x0, 0x0, 0x0)\\n\\t/Users/qlong/indeed/cadence-samples/cmd/samples/recipes/signalcounter/signal_counter_workflow.go:38 +0x1be\\nreflect.Value.call(0x1852ac0, 0x19cb608, 0x13, 0x1979180, 0x4, 0xc00045aa80, 0x2, 0x2, 0x2, 0x18, ...)\\n\\t/usr/local/Cellar/go/1.16.3/libexec/src/reflect/value.go:476 +0x8e7\\nreflect.Value.Call(0x1852ac0, 0x19cb608, 0x13, 0xc00045aa80, 0x2, 0x2, 0x1, 0x2, 0xc00045a720)\\n\\t/usr/local/Cellar/go/1.16.3/libexec/src/reflect/value.go:337 +0xb9\\ngo.uber.org/cadence/internal.(*workflowEnvironmentInterceptor).ExecuteWorkflow(0xc00045a720, 0x1a99ae8, 0xc00009d700, 0xc0001ca820, 0x20, 0xc00007fad0, 0x1, 0x1, 0x1, 0x1, ...)\\n\\t/Users/qlong/go/pkg/mod/go.uber.org/cadence@v0.17.1-0.20210708064625-c4a7e032cc13/internal/workflow.go:372 +0x2cb\\ngo.uber.org/cadence/internal.(*workflowExecutor).Execute(0xc000098d80, 0x1a99ae8, 0xc00009d700, 0xc0001b127e, 0x2, 0x2, 0xc00044cb01, 0xc000070101, 0xc000073738, 0x1729f25, ...)\\n\\t/Users/qlong/go/pkg/mod/go.uber.org/cadence@v0.17.1-0.20210708064625-c4a7e032cc13/internal/internal_worker.go:699 +0x28d\\ngo.uber.org/cadence/internal.(*syncWorkflowDefinition).Execute.func1(0x1a99ce0, 0xc00045a9f0)\\n\\t/Users/qlong/go/pkg/mod/go.uber.org/cadence@v0.17.1-0.20210708064625-c4a7e032cc13/internal/internal_workflow.go:466 +0x106"\n'})})]})}function d(e={}){const{wrapper:n}={...(0,c.R)(),...e.components};return n?(0,r.jsx)(n,{...e,children:(0,r.jsx)(u,{...e})}):u(e)}},8453:(e,n,o)=>{o.d(n,{R:()=>a,x:()=>s});var t=o(6540);const r={},c=t.createContext(r);function a(e){const n=t.useContext(c);return t.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function s(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:a(e.components),t.createElement(c.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/7373c0c0.447b3f38.js b/assets/js/7373c0c0.447b3f38.js new file mode 100644 index 000000000..8f3331d51 --- /dev/null +++ b/assets/js/7373c0c0.447b3f38.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[2779],{2123:(e,n,o)=>{o.r(n),o.d(n,{assets:()=>i,contentTitle:()=>s,default:()=>d,frontMatter:()=>a,metadata:()=>t,toc:()=>l});const t=JSON.parse('{"id":"concepts/queries","title":"Synchronous query","description":"Workflowworkflow_executionqueryworkflowqueryworkflow: type exposing different information to different external systems.","source":"@site/docs/03-concepts/04-queries.md","sourceDirName":"03-concepts","slug":"/concepts/queries","permalink":"/Cadence-Docs/docs/concepts/queries","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/03-concepts/04-queries.md","tags":[],"version":"current","sidebarPosition":4,"frontMatter":{"layout":"default","title":"Synchronous query","permalink":"/docs/concepts/queries"},"sidebar":"docsSidebar","previous":{"title":"Event handling","permalink":"/Cadence-Docs/docs/concepts/events"},"next":{"title":"Deployment topology","permalink":"/Cadence-Docs/docs/concepts/topology"}}');var r=o(4848),c=o(8453);const a={layout:"default",title:"Synchronous query",permalink:"/docs/concepts/queries"},s="Synchronous query",i={},l=[{value:"Stack Trace Query",id:"stack-trace-query",level:2}];function u(e){const n={code:"code",em:"em",h1:"h1",h2:"h2",header:"header",p:"p",pre:"pre",...(0,c.R)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(n.header,{children:(0,r.jsx)(n.h1,{id:"synchronous-query",children:"Synchronous query"})}),"\n",(0,r.jsx)(n.p,{children:"Workflow code is stateful with the Cadence framework preserving it over various software and hardware failures. The state is constantly mutated during workflow_execution. To expose this internal state to the external world Cadence provides a synchronous query feature. From the workflow implementer point of view the query is exposed as a synchronous callback that is invoked by external entities. Multiple such callbacks can be provided per workflow type exposing different information to different external systems."}),"\n",(0,r.jsxs)(n.p,{children:["To execute a query an external client calls a synchronous Cadence API providing ",(0,r.jsx)(n.em,{children:"domain, workflowID, query name"})," and optional ",(0,r.jsx)(n.em,{children:"query arguments"}),"."]}),"\n",(0,r.jsx)(n.p,{children:"Query callbacks must be read-only not mutating the workflow state in any way. The other limitation is that the query callback cannot contain any blocking code. Both above limitations rule out ability to invoke activities from the query handlers."}),"\n",(0,r.jsxs)(n.p,{children:["Cadence team is currently working on implementing ",(0,r.jsx)(n.em,{children:"update"})," feature that would be similar to query in the way it is invoked, but would support workflow state mutation and local_activity invocations. From user's point of view, ",(0,r.jsx)(n.em,{children:"update"})," is similar to signal + strong consistent query, but implemented in a much less expensive way in Cadence."]}),"\n",(0,r.jsx)(n.h2,{id:"stack-trace-query",children:"Stack Trace Query"}),"\n",(0,r.jsxs)(n.p,{children:["The Cadence client libraries expose some predefined queries out of the box. Currently the only supported built-in query is ",(0,r.jsx)(n.em,{children:"stack_trace"}),". This query returns stacks of all workflow owned threads. This is a great way to troubleshoot any workflow in production."]}),"\n",(0,r.jsx)(n.p,{children:"Example"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-shell-session",metastring:"wordWrap=true",children:'$ cadence --do samples-domain wf query -w -qt __stack_trace\n\n"coroutine 1 [blocked on selector-1.Select]:\\nmain.sampleSignalCounterWorkflow(0x1a99ae8, 0xc00009d700, 0x0, 0x0, 0x0)\\n\\t/Users/qlong/indeed/cadence-samples/cmd/samples/recipes/signalcounter/signal_counter_workflow.go:38 +0x1be\\nreflect.Value.call(0x1852ac0, 0x19cb608, 0x13, 0x1979180, 0x4, 0xc00045aa80, 0x2, 0x2, 0x2, 0x18, ...)\\n\\t/usr/local/Cellar/go/1.16.3/libexec/src/reflect/value.go:476 +0x8e7\\nreflect.Value.Call(0x1852ac0, 0x19cb608, 0x13, 0xc00045aa80, 0x2, 0x2, 0x1, 0x2, 0xc00045a720)\\n\\t/usr/local/Cellar/go/1.16.3/libexec/src/reflect/value.go:337 +0xb9\\ngo.uber.org/cadence/internal.(*workflowEnvironmentInterceptor).ExecuteWorkflow(0xc00045a720, 0x1a99ae8, 0xc00009d700, 0xc0001ca820, 0x20, 0xc00007fad0, 0x1, 0x1, 0x1, 0x1, ...)\\n\\t/Users/qlong/go/pkg/mod/go.uber.org/cadence@v0.17.1-0.20210708064625-c4a7e032cc13/internal/workflow.go:372 +0x2cb\\ngo.uber.org/cadence/internal.(*workflowExecutor).Execute(0xc000098d80, 0x1a99ae8, 0xc00009d700, 0xc0001b127e, 0x2, 0x2, 0xc00044cb01, 0xc000070101, 0xc000073738, 0x1729f25, ...)\\n\\t/Users/qlong/go/pkg/mod/go.uber.org/cadence@v0.17.1-0.20210708064625-c4a7e032cc13/internal/internal_worker.go:699 +0x28d\\ngo.uber.org/cadence/internal.(*syncWorkflowDefinition).Execute.func1(0x1a99ce0, 0xc00045a9f0)\\n\\t/Users/qlong/go/pkg/mod/go.uber.org/cadence@v0.17.1-0.20210708064625-c4a7e032cc13/internal/internal_workflow.go:466 +0x106"\n'})})]})}function d(e={}){const{wrapper:n}={...(0,c.R)(),...e.components};return n?(0,r.jsx)(n,{...e,children:(0,r.jsx)(u,{...e})}):u(e)}},8453:(e,n,o)=>{o.d(n,{R:()=>a,x:()=>s});var t=o(6540);const r={},c=t.createContext(r);function a(e){const n=t.useContext(c);return t.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function s(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:a(e.components),t.createElement(c.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/73759d73.12f54153.js b/assets/js/73759d73.12f54153.js new file mode 100644 index 000000000..fbdce315b --- /dev/null +++ b/assets/js/73759d73.12f54153.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[3364],{2855:(e,n,i)=>{i.r(n),i.d(n,{assets:()=>r,contentTitle:()=>a,default:()=>h,frontMatter:()=>l,metadata:()=>o,toc:()=>c});const o=JSON.parse('{"id":"java-client/implementing-workflows","title":"Implementing workflows","description":"A implementation implements a interface. Each time a new is started,","source":"@site/docs/04-java-client/03-implementing-workflows.md","sourceDirName":"04-java-client","slug":"/java-client/implementing-workflows","permalink":"/Cadence-Docs/docs/java-client/implementing-workflows","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/04-java-client/03-implementing-workflows.md","tags":[],"version":"current","sidebarPosition":3,"frontMatter":{"layout":"default","title":"Implementing workflows","permalink":"/docs/java-client/implementing-workflows"},"sidebar":"docsSidebar","previous":{"title":"Workflow interface","permalink":"/Cadence-Docs/docs/java-client/workflow-interface"},"next":{"title":"Starting workflows","permalink":"/Cadence-Docs/docs/java-client/starting-workflow-executions"}}');var t=i(4848),s=i(8453);const l={layout:"default",title:"Implementing workflows",permalink:"/docs/java-client/implementing-workflows"},a="Implementing workflows",r={},c=[{value:"Calling Activities",id:"calling-activities",level:2},{value:"Calling Activities Asynchronously",id:"calling-activities-asynchronously",level:2},{value:"Workflow Implementation Constraints",id:"workflow-implementation-constraints",level:2}];function d(e){const n={a:"a",code:"code",h1:"h1",h2:"h2",header:"header",li:"li",p:"p",pre:"pre",ul:"ul",...(0,s.R)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.header,{children:(0,t.jsx)(n.h1,{id:"implementing-workflows",children:"Implementing workflows"})}),"\n",(0,t.jsxs)(n.p,{children:["A workflow implementation implements a workflow interface. Each time a new workflow_execution is started,\na new instance of the workflow implementation object is created. Then, one of the methods\n(depending on which workflow type has been started) annotated with ",(0,t.jsx)(n.code,{children:"@WorkflowMethod"})," is invoked. As soon as this method\nreturns, the workflow_execution is closed. While workflow_execution is open, it can receive calls to signal and query methods.\nNo additional calls to workflow methods are allowed. The workflow object is stateful, so query and signal methods\ncan communicate with the other parts of the workflow through workflow object fields."]}),"\n",(0,t.jsx)(n.h2,{id:"calling-activities",children:"Calling Activities"}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.code,{children:"Workflow.newActivityStub"})," returns a client-side stub that implements an activity interface.\nIt takes activity type and activity options as arguments. Activity options are needed only if some of the required\ntimeouts are not specified through the ",(0,t.jsx)(n.code,{children:"@ActivityMethod"})," annotation."]}),"\n",(0,t.jsx)(n.p,{children:"Calling a method on this interface invokes an activity that implements this method.\nAn activity invocation synchronously blocks until the activity completes, fails, or times out. Even if activity\nexecution takes a few months, the workflow code still sees it as a single synchronous invocation.\nIt doesn't matter what happens to the processes that host the workflow. The business logic code\njust sees a single method call."}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-java",children:"public class FileProcessingWorkflowImpl implements FileProcessingWorkflow {\n\n private final FileProcessingActivities activities;\n\n public FileProcessingWorkflowImpl() {\n this.activities = Workflow.newActivityStub(FileProcessingActivities.class);\n }\n\n @Override\n public void processFile(Arguments args) {\n String localName = null;\n String processedName = null;\n try {\n localName = activities.download(args.getSourceBucketName(), args.getSourceFilename());\n processedName = activities.processFile(localName);\n activities.upload(args.getTargetBucketName(), args.getTargetFilename(), processedName);\n } finally {\n if (localName != null) { // File was downloaded.\n activities.deleteLocalFile(localName);\n }\n if (processedName != null) { // File was processed.\n activities.deleteLocalFile(processedName);\n }\n }\n }\n ...\n}\n"})}),"\n",(0,t.jsx)(n.p,{children:"If different activities need different options, like timeouts or a task_list, multiple client-side stubs can be created\nwith different options."}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-java",children:'public FileProcessingWorkflowImpl() {\n ActivityOptions options1 = new ActivityOptions.Builder()\n .setTaskList("taskList1")\n .build();\n this.store1 = Workflow.newActivityStub(FileProcessingActivities.class, options1);\n\n ActivityOptions options2 = new ActivityOptions.Builder()\n .setTaskList("taskList2")\n .build();\n this.store2 = Workflow.newActivityStub(FileProcessingActivities.class, options2);\n}\n'})}),"\n",(0,t.jsx)(n.h2,{id:"calling-activities-asynchronously",children:"Calling Activities Asynchronously"}),"\n",(0,t.jsxs)(n.p,{children:["Sometimes workflows need to perform certain operations in parallel.\nThe ",(0,t.jsx)(n.code,{children:"Async"})," class static methods allow you to invoke any activity asynchronously. The calls return a ",(0,t.jsx)(n.code,{children:"Promise"})," result immediately.\n",(0,t.jsx)(n.code,{children:"Promise"})," is similar to both Java ",(0,t.jsx)(n.code,{children:"Future"})," and ",(0,t.jsx)(n.code,{children:"CompletionStage"}),". The ",(0,t.jsx)(n.code,{children:"Promise"})," ",(0,t.jsx)(n.code,{children:"get"})," blocks until a result is available.\nIt also exposes the ",(0,t.jsx)(n.code,{children:"thenApply"})," and ",(0,t.jsx)(n.code,{children:"handle"})," methods. See the ",(0,t.jsx)(n.code,{children:"Promise"})," JavaDoc for technical details about differences with ",(0,t.jsx)(n.code,{children:"Future"}),"."]}),"\n",(0,t.jsx)(n.p,{children:"To convert a synchronous call:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-java",children:"String localName = activities.download(sourceBucket, sourceFile);\n"})}),"\n",(0,t.jsxs)(n.p,{children:["To asynchronous style, the method reference is passed to ",(0,t.jsx)(n.code,{children:"Async.function"})," or ",(0,t.jsx)(n.code,{children:"Async.procedure"}),"\nfollowed by activity arguments:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-java",children:"Promise localNamePromise = Async.function(activities::download, sourceBucket, sourceFile);\n"})}),"\n",(0,t.jsx)(n.p,{children:"Then to wait synchronously for the result:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-java",children:"String localName = localNamePromise.get();\n"})}),"\n",(0,t.jsx)(n.p,{children:"Here is the above example rewritten to call download and upload in parallel on multiple files:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-java",children:"public void processFile(Arguments args) {\n List> localNamePromises = new ArrayList<>();\n List processedNames = null;\n try {\n // Download all files in parallel.\n for (String sourceFilename : args.getSourceFilenames()) {\n Promise localName = Async.function(activities::download,\n args.getSourceBucketName(), sourceFilename);\n localNamePromises.add(localName);\n }\n // allOf converts a list of promises to a single promise that contains a list\n // of each promise value.\n Promise> localNamesPromise = Promise.allOf(localNamePromises);\n\n // All code until the next line wasn't blocking.\n // The promise get is a blocking call.\n List localNames = localNamesPromise.get();\n processedNames = activities.processFiles(localNames);\n\n // Upload all results in parallel.\n List> uploadedList = new ArrayList<>();\n for (String processedName : processedNames) {\n Promise uploaded = Async.procedure(activities::upload,\n args.getTargetBucketName(), args.getTargetFilename(), processedName);\n uploadedList.add(uploaded);\n }\n // Wait for all uploads to complete.\n Promise allUploaded = Promise.allOf(uploadedList);\n allUploaded.get(); // blocks until all promises are ready.\n } finally {\n for (Promise localNamePromise : localNamePromises) {\n // Skip files that haven't completed downloading.\n if (localNamePromise.isCompleted()) {\n activities.deleteLocalFile(localNamePromise.get());\n }\n }\n if (processedNames != null) {\n for (String processedName : processedNames) {\n activities.deleteLocalFile(processedName);\n }\n }\n }\n}\n"})}),"\n",(0,t.jsx)(n.h2,{id:"workflow-implementation-constraints",children:"Workflow Implementation Constraints"}),"\n",(0,t.jsxs)(n.p,{children:["Cadence uses the ",(0,t.jsx)(n.a,{href:"https://docs.microsoft.com/en-us/azure/architecture/patterns/event-sourcing",children:"Microsoft Azure Event Sourcing pattern"})," to recover\nthe state of a workflow object including its threads and local variable values.\nIn essence, every time a workflow state has to be restored, its code is re-executed from the beginning. When replaying, side\neffects (such as activity invocations) are ignored because they are already recorded in the workflow event_history.\nWhen writing workflow logic, the replay is not visible, so the code should be written since it executes only once.\nThis design puts the following constraints on the workflow implementation:"]}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"Do not use any mutable global variables because multiple instances of workflows are executed in parallel."}),"\n",(0,t.jsx)(n.li,{children:"Do not call any non-deterministic functions like non seeded random or UUID.randomUUID() directly from the workflow code."}),"\n"]}),"\n",(0,t.jsx)(n.p,{children:"Always do the following in workflows:"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"Don\u2019t perform any IO or service calls as they are not usually deterministic. Use activities for this."}),"\n",(0,t.jsxs)(n.li,{children:["Only use ",(0,t.jsx)(n.code,{children:"Workflow.currentTimeMillis()"})," to get the current time inside a workflow."]}),"\n",(0,t.jsxs)(n.li,{children:["Do not use native Java ",(0,t.jsx)(n.code,{children:"Thread"})," or any other multi-threaded classes like ",(0,t.jsx)(n.code,{children:"ThreadPoolExecutor"}),". Use ",(0,t.jsx)(n.code,{children:"Async.function"})," or ",(0,t.jsx)(n.code,{children:"Async.procedure"}),"\nto execute code asynchronously."]}),"\n",(0,t.jsxs)(n.li,{children:["Don't use any synchronization, locks, and other standard Java blocking concurrency-related classes besides those provided\nby the Workflow class. There is no need in explicit synchronization because multi-threaded code inside a workflow is\nexecuted one thread at a time and under a global lock.","\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:["Call ",(0,t.jsx)(n.code,{children:"WorkflowThread.sleep"})," instead of ",(0,t.jsx)(n.code,{children:"Thread.sleep"}),"."]}),"\n",(0,t.jsxs)(n.li,{children:["Use ",(0,t.jsx)(n.code,{children:"Promise"})," and ",(0,t.jsx)(n.code,{children:"CompletablePromise"})," instead of ",(0,t.jsx)(n.code,{children:"Future"})," and ",(0,t.jsx)(n.code,{children:"CompletableFuture"}),"."]}),"\n",(0,t.jsxs)(n.li,{children:["Use ",(0,t.jsx)(n.code,{children:"WorkflowQueue"})," instead of ",(0,t.jsx)(n.code,{children:"BlockingQueue"}),"."]}),"\n"]}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["Use ",(0,t.jsx)(n.code,{children:"Workflow.getVersion"})," when making any changes to the workflow code. Without this, any deployment of updated workflow code\nmight break already open workflows."]}),"\n",(0,t.jsx)(n.li,{children:"Don\u2019t access configuration APIs directly from a workflow because changes in the configuration might affect a workflow_execution path.\nPass it as an argument to a workflow function or use an activity to load it."}),"\n"]}),"\n",(0,t.jsxs)(n.p,{children:["Workflow method arguments and return values are serializable to a byte array using the provided\n",(0,t.jsx)(n.a,{href:"https://static.javadoc.io/com.uber.cadence/cadence-client/2.4.1/index.html?com/cadence-workflow/cadence/converter/DataConverter.html",children:"DataConverter"}),"\ninterface. The default implementation uses JSON serializer, but you can use any alternative serialization mechanism."]}),"\n",(0,t.jsx)(n.p,{children:"The values passed to workflows through invocation parameters or returned through a result value are recorded in the execution history.\nThe entire execution history is transferred from the Cadence service to workflow_workers with every event that the workflow logic needs to process.\nA large execution history can thus adversely impact the performance of your workflow.\nTherefore, be mindful of the amount of data that you transfer via activity invocation parameters or return values.\nOtherwise, no additional limitations exist on activity implementations."})]})}function h(e={}){const{wrapper:n}={...(0,s.R)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(d,{...e})}):d(e)}},8453:(e,n,i)=>{i.d(n,{R:()=>l,x:()=>a});var o=i(6540);const t={},s=o.createContext(t);function l(e){const n=o.useContext(s);return o.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function a(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(t):e.components||t:l(e.components),o.createElement(s.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/73759d73.b9fedb09.js b/assets/js/73759d73.b9fedb09.js deleted file mode 100644 index 30fd6ab6e..000000000 --- a/assets/js/73759d73.b9fedb09.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[3364],{2855:(e,n,i)=>{i.r(n),i.d(n,{assets:()=>r,contentTitle:()=>a,default:()=>h,frontMatter:()=>l,metadata:()=>o,toc:()=>c});const o=JSON.parse('{"id":"java-client/implementing-workflows","title":"Implementing workflows","description":"A implementation implements a interface. Each time a new is started,","source":"@site/docs/04-java-client/03-implementing-workflows.md","sourceDirName":"04-java-client","slug":"/java-client/implementing-workflows","permalink":"/docs/java-client/implementing-workflows","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/04-java-client/03-implementing-workflows.md","tags":[],"version":"current","sidebarPosition":3,"frontMatter":{"layout":"default","title":"Implementing workflows","permalink":"/docs/java-client/implementing-workflows"},"sidebar":"docsSidebar","previous":{"title":"Workflow interface","permalink":"/docs/java-client/workflow-interface"},"next":{"title":"Starting workflows","permalink":"/docs/java-client/starting-workflow-executions"}}');var t=i(4848),s=i(8453);const l={layout:"default",title:"Implementing workflows",permalink:"/docs/java-client/implementing-workflows"},a="Implementing workflows",r={},c=[{value:"Calling Activities",id:"calling-activities",level:2},{value:"Calling Activities Asynchronously",id:"calling-activities-asynchronously",level:2},{value:"Workflow Implementation Constraints",id:"workflow-implementation-constraints",level:2}];function d(e){const n={a:"a",code:"code",h1:"h1",h2:"h2",header:"header",li:"li",p:"p",pre:"pre",ul:"ul",...(0,s.R)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.header,{children:(0,t.jsx)(n.h1,{id:"implementing-workflows",children:"Implementing workflows"})}),"\n",(0,t.jsxs)(n.p,{children:["A workflow implementation implements a workflow interface. Each time a new workflow_execution is started,\na new instance of the workflow implementation object is created. Then, one of the methods\n(depending on which workflow type has been started) annotated with ",(0,t.jsx)(n.code,{children:"@WorkflowMethod"})," is invoked. As soon as this method\nreturns, the workflow_execution is closed. While workflow_execution is open, it can receive calls to signal and query methods.\nNo additional calls to workflow methods are allowed. The workflow object is stateful, so query and signal methods\ncan communicate with the other parts of the workflow through workflow object fields."]}),"\n",(0,t.jsx)(n.h2,{id:"calling-activities",children:"Calling Activities"}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.code,{children:"Workflow.newActivityStub"})," returns a client-side stub that implements an activity interface.\nIt takes activity type and activity options as arguments. Activity options are needed only if some of the required\ntimeouts are not specified through the ",(0,t.jsx)(n.code,{children:"@ActivityMethod"})," annotation."]}),"\n",(0,t.jsx)(n.p,{children:"Calling a method on this interface invokes an activity that implements this method.\nAn activity invocation synchronously blocks until the activity completes, fails, or times out. Even if activity\nexecution takes a few months, the workflow code still sees it as a single synchronous invocation.\nIt doesn't matter what happens to the processes that host the workflow. The business logic code\njust sees a single method call."}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-java",children:"public class FileProcessingWorkflowImpl implements FileProcessingWorkflow {\n\n private final FileProcessingActivities activities;\n\n public FileProcessingWorkflowImpl() {\n this.activities = Workflow.newActivityStub(FileProcessingActivities.class);\n }\n\n @Override\n public void processFile(Arguments args) {\n String localName = null;\n String processedName = null;\n try {\n localName = activities.download(args.getSourceBucketName(), args.getSourceFilename());\n processedName = activities.processFile(localName);\n activities.upload(args.getTargetBucketName(), args.getTargetFilename(), processedName);\n } finally {\n if (localName != null) { // File was downloaded.\n activities.deleteLocalFile(localName);\n }\n if (processedName != null) { // File was processed.\n activities.deleteLocalFile(processedName);\n }\n }\n }\n ...\n}\n"})}),"\n",(0,t.jsx)(n.p,{children:"If different activities need different options, like timeouts or a task_list, multiple client-side stubs can be created\nwith different options."}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-java",children:'public FileProcessingWorkflowImpl() {\n ActivityOptions options1 = new ActivityOptions.Builder()\n .setTaskList("taskList1")\n .build();\n this.store1 = Workflow.newActivityStub(FileProcessingActivities.class, options1);\n\n ActivityOptions options2 = new ActivityOptions.Builder()\n .setTaskList("taskList2")\n .build();\n this.store2 = Workflow.newActivityStub(FileProcessingActivities.class, options2);\n}\n'})}),"\n",(0,t.jsx)(n.h2,{id:"calling-activities-asynchronously",children:"Calling Activities Asynchronously"}),"\n",(0,t.jsxs)(n.p,{children:["Sometimes workflows need to perform certain operations in parallel.\nThe ",(0,t.jsx)(n.code,{children:"Async"})," class static methods allow you to invoke any activity asynchronously. The calls return a ",(0,t.jsx)(n.code,{children:"Promise"})," result immediately.\n",(0,t.jsx)(n.code,{children:"Promise"})," is similar to both Java ",(0,t.jsx)(n.code,{children:"Future"})," and ",(0,t.jsx)(n.code,{children:"CompletionStage"}),". The ",(0,t.jsx)(n.code,{children:"Promise"})," ",(0,t.jsx)(n.code,{children:"get"})," blocks until a result is available.\nIt also exposes the ",(0,t.jsx)(n.code,{children:"thenApply"})," and ",(0,t.jsx)(n.code,{children:"handle"})," methods. See the ",(0,t.jsx)(n.code,{children:"Promise"})," JavaDoc for technical details about differences with ",(0,t.jsx)(n.code,{children:"Future"}),"."]}),"\n",(0,t.jsx)(n.p,{children:"To convert a synchronous call:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-java",children:"String localName = activities.download(sourceBucket, sourceFile);\n"})}),"\n",(0,t.jsxs)(n.p,{children:["To asynchronous style, the method reference is passed to ",(0,t.jsx)(n.code,{children:"Async.function"})," or ",(0,t.jsx)(n.code,{children:"Async.procedure"}),"\nfollowed by activity arguments:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-java",children:"Promise localNamePromise = Async.function(activities::download, sourceBucket, sourceFile);\n"})}),"\n",(0,t.jsx)(n.p,{children:"Then to wait synchronously for the result:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-java",children:"String localName = localNamePromise.get();\n"})}),"\n",(0,t.jsx)(n.p,{children:"Here is the above example rewritten to call download and upload in parallel on multiple files:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-java",children:"public void processFile(Arguments args) {\n List> localNamePromises = new ArrayList<>();\n List processedNames = null;\n try {\n // Download all files in parallel.\n for (String sourceFilename : args.getSourceFilenames()) {\n Promise localName = Async.function(activities::download,\n args.getSourceBucketName(), sourceFilename);\n localNamePromises.add(localName);\n }\n // allOf converts a list of promises to a single promise that contains a list\n // of each promise value.\n Promise> localNamesPromise = Promise.allOf(localNamePromises);\n\n // All code until the next line wasn't blocking.\n // The promise get is a blocking call.\n List localNames = localNamesPromise.get();\n processedNames = activities.processFiles(localNames);\n\n // Upload all results in parallel.\n List> uploadedList = new ArrayList<>();\n for (String processedName : processedNames) {\n Promise uploaded = Async.procedure(activities::upload,\n args.getTargetBucketName(), args.getTargetFilename(), processedName);\n uploadedList.add(uploaded);\n }\n // Wait for all uploads to complete.\n Promise allUploaded = Promise.allOf(uploadedList);\n allUploaded.get(); // blocks until all promises are ready.\n } finally {\n for (Promise localNamePromise : localNamePromises) {\n // Skip files that haven't completed downloading.\n if (localNamePromise.isCompleted()) {\n activities.deleteLocalFile(localNamePromise.get());\n }\n }\n if (processedNames != null) {\n for (String processedName : processedNames) {\n activities.deleteLocalFile(processedName);\n }\n }\n }\n}\n"})}),"\n",(0,t.jsx)(n.h2,{id:"workflow-implementation-constraints",children:"Workflow Implementation Constraints"}),"\n",(0,t.jsxs)(n.p,{children:["Cadence uses the ",(0,t.jsx)(n.a,{href:"https://docs.microsoft.com/en-us/azure/architecture/patterns/event-sourcing",children:"Microsoft Azure Event Sourcing pattern"})," to recover\nthe state of a workflow object including its threads and local variable values.\nIn essence, every time a workflow state has to be restored, its code is re-executed from the beginning. When replaying, side\neffects (such as activity invocations) are ignored because they are already recorded in the workflow event_history.\nWhen writing workflow logic, the replay is not visible, so the code should be written since it executes only once.\nThis design puts the following constraints on the workflow implementation:"]}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"Do not use any mutable global variables because multiple instances of workflows are executed in parallel."}),"\n",(0,t.jsx)(n.li,{children:"Do not call any non-deterministic functions like non seeded random or UUID.randomUUID() directly from the workflow code."}),"\n"]}),"\n",(0,t.jsx)(n.p,{children:"Always do the following in workflows:"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"Don\u2019t perform any IO or service calls as they are not usually deterministic. Use activities for this."}),"\n",(0,t.jsxs)(n.li,{children:["Only use ",(0,t.jsx)(n.code,{children:"Workflow.currentTimeMillis()"})," to get the current time inside a workflow."]}),"\n",(0,t.jsxs)(n.li,{children:["Do not use native Java ",(0,t.jsx)(n.code,{children:"Thread"})," or any other multi-threaded classes like ",(0,t.jsx)(n.code,{children:"ThreadPoolExecutor"}),". Use ",(0,t.jsx)(n.code,{children:"Async.function"})," or ",(0,t.jsx)(n.code,{children:"Async.procedure"}),"\nto execute code asynchronously."]}),"\n",(0,t.jsxs)(n.li,{children:["Don't use any synchronization, locks, and other standard Java blocking concurrency-related classes besides those provided\nby the Workflow class. There is no need in explicit synchronization because multi-threaded code inside a workflow is\nexecuted one thread at a time and under a global lock.","\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:["Call ",(0,t.jsx)(n.code,{children:"WorkflowThread.sleep"})," instead of ",(0,t.jsx)(n.code,{children:"Thread.sleep"}),"."]}),"\n",(0,t.jsxs)(n.li,{children:["Use ",(0,t.jsx)(n.code,{children:"Promise"})," and ",(0,t.jsx)(n.code,{children:"CompletablePromise"})," instead of ",(0,t.jsx)(n.code,{children:"Future"})," and ",(0,t.jsx)(n.code,{children:"CompletableFuture"}),"."]}),"\n",(0,t.jsxs)(n.li,{children:["Use ",(0,t.jsx)(n.code,{children:"WorkflowQueue"})," instead of ",(0,t.jsx)(n.code,{children:"BlockingQueue"}),"."]}),"\n"]}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["Use ",(0,t.jsx)(n.code,{children:"Workflow.getVersion"})," when making any changes to the workflow code. Without this, any deployment of updated workflow code\nmight break already open workflows."]}),"\n",(0,t.jsx)(n.li,{children:"Don\u2019t access configuration APIs directly from a workflow because changes in the configuration might affect a workflow_execution path.\nPass it as an argument to a workflow function or use an activity to load it."}),"\n"]}),"\n",(0,t.jsxs)(n.p,{children:["Workflow method arguments and return values are serializable to a byte array using the provided\n",(0,t.jsx)(n.a,{href:"https://static.javadoc.io/com.uber.cadence/cadence-client/2.4.1/index.html?com/cadence-workflow/cadence/converter/DataConverter.html",children:"DataConverter"}),"\ninterface. The default implementation uses JSON serializer, but you can use any alternative serialization mechanism."]}),"\n",(0,t.jsx)(n.p,{children:"The values passed to workflows through invocation parameters or returned through a result value are recorded in the execution history.\nThe entire execution history is transferred from the Cadence service to workflow_workers with every event that the workflow logic needs to process.\nA large execution history can thus adversely impact the performance of your workflow.\nTherefore, be mindful of the amount of data that you transfer via activity invocation parameters or return values.\nOtherwise, no additional limitations exist on activity implementations."})]})}function h(e={}){const{wrapper:n}={...(0,s.R)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(d,{...e})}):d(e)}},8453:(e,n,i)=>{i.d(n,{R:()=>l,x:()=>a});var o=i(6540);const t={},s=o.createContext(t);function l(e){const n=o.useContext(s);return o.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function a(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(t):e.components||t:l(e.components),o.createElement(s.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/741d205a.c828b574.js b/assets/js/741d205a.c828b574.js deleted file mode 100644 index 3c0dfee01..000000000 --- a/assets/js/741d205a.c828b574.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[8941],{7438:a=>{a.exports=JSON.parse('{"author":{"name":"Sharan Foga","title":"Director of Operations & Customer Success @ Encube Technologies","url":"https://www.linkedin.com/in/sfoga/","page":{"permalink":"/blog/authors/sharanf"},"socials":{"linkedin":"https://www.linkedin.com/in/sfoga/","github":"https://github.com/sharanf"},"imageURL":"https://github.com/sharanf.png","key":"sharanf","count":19},"listMetadata":{"permalink":"/blog/authors/sharanf","page":1,"postsPerPage":10,"totalPages":2,"totalCount":19,"nextPage":"/blog/authors/sharanf/authors/2","blogDescription":"The latest news and updates from the Cadence team","blogTitle":"Cadence Blog"}}')}}]); \ No newline at end of file diff --git a/assets/js/7613fcd7.f715150c.js b/assets/js/7613fcd7.3220b068.js similarity index 54% rename from assets/js/7613fcd7.f715150c.js rename to assets/js/7613fcd7.3220b068.js index ab994b48c..ffcfd6c47 100644 --- a/assets/js/7613fcd7.f715150c.js +++ b/assets/js/7613fcd7.3220b068.js @@ -1 +1 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[2370],{1675:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>u,contentTitle:()=>i,default:()=>d,frontMatter:()=>s,metadata:()=>a,toc:()=>c});var a=n(7896),r=n(4848),o=n(8453);const s={title:"2023 Cadence Community Survey Results",date:new Date("2023-06-08T00:00:00.000Z"),authors:"enderdemirkaya",tags:["announcement"]},i=void 0,u={authorsImageUrls:[void 0]},c=[];function l(e){const t={a:"a",img:"img",p:"p",...(0,o.R)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsxs)(t.p,{children:["We released a user survey earlier this year to learn about who our users are, how they use Cadence, and how we can help them. It was shared from our ",(0,r.jsx)(t.a,{href:"https://uber-cadence.slack.com/",children:"Slack workspace"}),", ",(0,r.jsx)(t.a,{href:"https://cadenceworkflow.io",children:"cadenceworkflow.io"})," Blog and ",(0,r.jsx)(t.a,{href:"https://www.linkedin.com/company/cadenceworkflow/",children:"LinkedIn"}),". After collecting the feedback, we wanted to share the results with our community. Thank you everyone for filling it out! Your feedback is invaluable and it helps us shape our roadmap for the future."]}),"\n",(0,r.jsx)(t.p,{children:"Here are some highlights in text and you can check out the visuals to get more details:"}),"\n",(0,r.jsx)(t.p,{children:(0,r.jsx)(t.img,{alt:"using.png",src:n(6232).A+"",width:"661",height:"351"})}),"\n",(0,r.jsx)(t.p,{children:(0,r.jsx)(t.img,{alt:"job_role.png",src:n(9574).A+"",width:"692",height:"351"})}),"\n",(0,r.jsx)(t.p,{children:"Most of the people who replied to our survey were engineers who were already using Cadence, actively evaluating, or migrating from a similar technology. This was exciting to hear! Some of you have contacted us to learn more about benchmarks, scale, and ideal use cases. We will share more guidelines about this but until then, feel free to contact us over our Slack workspace for guidance."})]})}function d(e={}){const{wrapper:t}={...(0,o.R)(),...e.components};return t?(0,r.jsx)(t,{...e,children:(0,r.jsx)(l,{...e})}):l(e)}},9574:(e,t,n)=>{n.d(t,{A:()=>a});const a=n.p+"assets/images/job_role-fa7e2e7da9528b64de7e7be5ed191d10.png"},6232:(e,t,n)=>{n.d(t,{A:()=>a});const a=n.p+"assets/images/using-0b1f88906ffddbb98bebf54fb5967078.png"},8453:(e,t,n)=>{n.d(t,{R:()=>s,x:()=>i});var a=n(6540);const r={},o=a.createContext(r);function s(e){const t=a.useContext(o);return a.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function i(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:s(e.components),a.createElement(o.Provider,{value:t},e.children)}},7896:e=>{e.exports=JSON.parse('{"permalink":"/blog/2023/06/08/2023-06-08-survey-results/survey-results","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2023-06-08-survey-results/2023-06-08-survey-results.md","source":"@site/blog/2023-06-08-survey-results/2023-06-08-survey-results.md","title":"2023 Cadence Community Survey Results","description":"We released a user survey earlier this year to learn about who our users are, how they use Cadence, and how we can help them. It was shared from our Slack workspace, cadenceworkflow.io Blog and LinkedIn. After collecting the feedback, we wanted to share the results with our community. Thank you everyone for filling it out! Your feedback is invaluable and it helps us shape our roadmap for the future.","date":"2023-06-08T00:00:00.000Z","tags":[{"inline":false,"label":"Announcement","permalink":"/blog/tags/announcements","description":"Announcement tag description"}],"readingTime":3.255,"hasTruncateMarker":true,"authors":[{"name":"Ender Demirkaya","title":"Senior Manager at Uber, Cadence. Author of the Software Engineering Handbook","url":"https://www.linkedin.com/in/enderdemirkaya/","page":{"permalink":"/blog/authors/enderdemirkaya"},"socials":{"linkedin":"https://www.linkedin.com/in/enderdemirkaya/","github":"https://github.com/demirkayaender"},"imageURL":"https://github.com/demirkayaender.png","key":"enderdemirkaya"}],"frontMatter":{"title":"2023 Cadence Community Survey Results","date":"2023-06-08T00:00:00.000Z","authors":"enderdemirkaya","tags":["announcement"]},"unlisted":false,"prevItem":{"title":"Cadence Community Spotlight Update - June 2023","permalink":"/blog/2023/06/30/community-spotlight-june-2023"},"nextItem":{"title":"Cadence Community Spotlight Update - March 2023","permalink":"/blog/2023/03/31/community-spotlight-march-2023"}}')}}]); \ No newline at end of file +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[2370],{1675:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>c,contentTitle:()=>i,default:()=>d,frontMatter:()=>s,metadata:()=>a,toc:()=>u});var a=n(7896),r=n(4848),o=n(8453);const s={title:"2023 Cadence Community Survey Results",date:new Date("2023-06-08T00:00:00.000Z"),authors:"enderdemirkaya",tags:["announcement"]},i=void 0,c={authorsImageUrls:[void 0]},u=[];function l(e){const t={a:"a",img:"img",p:"p",...(0,o.R)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsxs)(t.p,{children:["We released a user survey earlier this year to learn about who our users are, how they use Cadence, and how we can help them. It was shared from our ",(0,r.jsx)(t.a,{href:"https://uber-cadence.slack.com/",children:"Slack workspace"}),", ",(0,r.jsx)(t.a,{href:"https://cadenceworkflow.io",children:"cadenceworkflow.io"})," Blog and ",(0,r.jsx)(t.a,{href:"https://www.linkedin.com/company/cadenceworkflow/",children:"LinkedIn"}),". After collecting the feedback, we wanted to share the results with our community. Thank you everyone for filling it out! Your feedback is invaluable and it helps us shape our roadmap for the future."]}),"\n",(0,r.jsx)(t.p,{children:"Here are some highlights in text and you can check out the visuals to get more details:"}),"\n",(0,r.jsx)(t.p,{children:(0,r.jsx)(t.img,{alt:"using.png",src:n(6232).A+"",width:"661",height:"351"})}),"\n",(0,r.jsx)(t.p,{children:(0,r.jsx)(t.img,{alt:"job_role.png",src:n(9574).A+"",width:"692",height:"351"})}),"\n",(0,r.jsx)(t.p,{children:"Most of the people who replied to our survey were engineers who were already using Cadence, actively evaluating, or migrating from a similar technology. This was exciting to hear! Some of you have contacted us to learn more about benchmarks, scale, and ideal use cases. We will share more guidelines about this but until then, feel free to contact us over our Slack workspace for guidance."})]})}function d(e={}){const{wrapper:t}={...(0,o.R)(),...e.components};return t?(0,r.jsx)(t,{...e,children:(0,r.jsx)(l,{...e})}):l(e)}},9574:(e,t,n)=>{n.d(t,{A:()=>a});const a=n.p+"assets/images/job_role-fa7e2e7da9528b64de7e7be5ed191d10.png"},6232:(e,t,n)=>{n.d(t,{A:()=>a});const a=n.p+"assets/images/using-0b1f88906ffddbb98bebf54fb5967078.png"},8453:(e,t,n)=>{n.d(t,{R:()=>s,x:()=>i});var a=n(6540);const r={},o=a.createContext(r);function s(e){const t=a.useContext(o);return a.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function i(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:s(e.components),a.createElement(o.Provider,{value:t},e.children)}},7896:e=>{e.exports=JSON.parse('{"permalink":"/Cadence-Docs/blog/2023/06/08/2023-06-08-survey-results/survey-results","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2023-06-08-survey-results/2023-06-08-survey-results.md","source":"@site/blog/2023-06-08-survey-results/2023-06-08-survey-results.md","title":"2023 Cadence Community Survey Results","description":"We released a user survey earlier this year to learn about who our users are, how they use Cadence, and how we can help them. It was shared from our Slack workspace, cadenceworkflow.io Blog and LinkedIn. After collecting the feedback, we wanted to share the results with our community. Thank you everyone for filling it out! Your feedback is invaluable and it helps us shape our roadmap for the future.","date":"2023-06-08T00:00:00.000Z","tags":[{"inline":false,"label":"Announcement","permalink":"/Cadence-Docs/blog/tags/announcements","description":"Announcement tag description"}],"readingTime":3.255,"hasTruncateMarker":true,"authors":[{"name":"Ender Demirkaya","title":"Senior Manager at Uber, Cadence. Author of the Software Engineering Handbook","url":"https://www.linkedin.com/in/enderdemirkaya/","page":{"permalink":"/Cadence-Docs/blog/authors/enderdemirkaya"},"socials":{"linkedin":"https://www.linkedin.com/in/enderdemirkaya/","github":"https://github.com/demirkayaender"},"imageURL":"https://github.com/demirkayaender.png","key":"enderdemirkaya"}],"frontMatter":{"title":"2023 Cadence Community Survey Results","date":"2023-06-08T00:00:00.000Z","authors":"enderdemirkaya","tags":["announcement"]},"unlisted":false,"prevItem":{"title":"Cadence Community Spotlight Update - June 2023","permalink":"/Cadence-Docs/blog/2023/06/30/community-spotlight-june-2023"},"nextItem":{"title":"Cadence Community Spotlight Update - March 2023","permalink":"/Cadence-Docs/blog/2023/03/31/community-spotlight-march-2023"}}')}}]); \ No newline at end of file diff --git a/assets/js/7684a5b2.2684a972.js b/assets/js/7684a5b2.2684a972.js deleted file mode 100644 index c32277780..000000000 --- a/assets/js/7684a5b2.2684a972.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[4422],{4778:(e,t,s)=>{s.r(t),s.d(t,{assets:()=>c,contentTitle:()=>i,default:()=>u,frontMatter:()=>r,metadata:()=>a,toc:()=>l});const a=JSON.parse('{"id":"use-cases/partitioned-scan","title":"Storage scan","description":"It is common to have large data sets partitioned across a large number of hosts or databases, or having billions of files in an Amazon S3 bucket.","source":"@site/docs/02-use-cases/05-partitioned-scan.md","sourceDirName":"02-use-cases","slug":"/use-cases/partitioned-scan","permalink":"/docs/use-cases/partitioned-scan","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/02-use-cases/05-partitioned-scan.md","tags":[],"version":"current","sidebarPosition":5,"frontMatter":{"layout":"default","title":"Storage scan","permalink":"/docs/use-cases/partitioned-scan"},"sidebar":"docsSidebar","previous":{"title":"Event driven application","permalink":"/docs/use-cases/event-driven"},"next":{"title":"Batch job","permalink":"/docs/use-cases/batch-job"}}');var n=s(4848),o=s(8453);const r={layout:"default",title:"Storage scan",permalink:"/docs/use-cases/partitioned-scan"},i="Storage scan",c={},l=[];function d(e){const t={h1:"h1",header:"header",li:"li",p:"p",ul:"ul",...(0,o.R)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(t.header,{children:(0,n.jsx)(t.h1,{id:"storage-scan",children:"Storage scan"})}),"\n",(0,n.jsx)(t.p,{children:"It is common to have large data sets partitioned across a large number of hosts or databases, or having billions of files in an Amazon S3 bucket.\nCadence is an ideal solution for implementing the full scan of such data in a scalable and resilient way. The standard pattern\nis to run an activity (or multiple parallel activities for partitioned data sets) that performs the scan and heartbeats its progress\nback to Cadence. In the case of a host failure, the activity is retried on a different host and continues execution from the last reported progress."}),"\n",(0,n.jsx)(t.p,{children:"A real-world example:"}),"\n",(0,n.jsxs)(t.ul,{children:["\n",(0,n.jsx)(t.li,{children:"Cadence internal system workflow that performs periodic scan of all workflow_execution records"}),"\n"]})]})}function u(e={}){const{wrapper:t}={...(0,o.R)(),...e.components};return t?(0,n.jsx)(t,{...e,children:(0,n.jsx)(d,{...e})}):d(e)}},8453:(e,t,s)=>{s.d(t,{R:()=>r,x:()=>i});var a=s(6540);const n={},o=a.createContext(n);function r(e){const t=a.useContext(o);return a.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function i(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(n):e.components||n:r(e.components),a.createElement(o.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/7684a5b2.97768783.js b/assets/js/7684a5b2.97768783.js new file mode 100644 index 000000000..28d255821 --- /dev/null +++ b/assets/js/7684a5b2.97768783.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[4422],{4778:(e,t,s)=>{s.r(t),s.d(t,{assets:()=>c,contentTitle:()=>i,default:()=>u,frontMatter:()=>r,metadata:()=>a,toc:()=>d});const a=JSON.parse('{"id":"use-cases/partitioned-scan","title":"Storage scan","description":"It is common to have large data sets partitioned across a large number of hosts or databases, or having billions of files in an Amazon S3 bucket.","source":"@site/docs/02-use-cases/05-partitioned-scan.md","sourceDirName":"02-use-cases","slug":"/use-cases/partitioned-scan","permalink":"/Cadence-Docs/docs/use-cases/partitioned-scan","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/02-use-cases/05-partitioned-scan.md","tags":[],"version":"current","sidebarPosition":5,"frontMatter":{"layout":"default","title":"Storage scan","permalink":"/docs/use-cases/partitioned-scan"},"sidebar":"docsSidebar","previous":{"title":"Event driven application","permalink":"/Cadence-Docs/docs/use-cases/event-driven"},"next":{"title":"Batch job","permalink":"/Cadence-Docs/docs/use-cases/batch-job"}}');var n=s(4848),o=s(8453);const r={layout:"default",title:"Storage scan",permalink:"/docs/use-cases/partitioned-scan"},i="Storage scan",c={},d=[];function l(e){const t={h1:"h1",header:"header",li:"li",p:"p",ul:"ul",...(0,o.R)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(t.header,{children:(0,n.jsx)(t.h1,{id:"storage-scan",children:"Storage scan"})}),"\n",(0,n.jsx)(t.p,{children:"It is common to have large data sets partitioned across a large number of hosts or databases, or having billions of files in an Amazon S3 bucket.\nCadence is an ideal solution for implementing the full scan of such data in a scalable and resilient way. The standard pattern\nis to run an activity (or multiple parallel activities for partitioned data sets) that performs the scan and heartbeats its progress\nback to Cadence. In the case of a host failure, the activity is retried on a different host and continues execution from the last reported progress."}),"\n",(0,n.jsx)(t.p,{children:"A real-world example:"}),"\n",(0,n.jsxs)(t.ul,{children:["\n",(0,n.jsx)(t.li,{children:"Cadence internal system workflow that performs periodic scan of all workflow_execution records"}),"\n"]})]})}function u(e={}){const{wrapper:t}={...(0,o.R)(),...e.components};return t?(0,n.jsx)(t,{...e,children:(0,n.jsx)(l,{...e})}):l(e)}},8453:(e,t,s)=>{s.d(t,{R:()=>r,x:()=>i});var a=s(6540);const n={},o=a.createContext(n);function r(e){const t=a.useContext(o);return a.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function i(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(n):e.components||n:r(e.components),a.createElement(o.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/76dc6352.34ab7350.js b/assets/js/76dc6352.34ab7350.js new file mode 100644 index 000000000..92d79ea61 --- /dev/null +++ b/assets/js/76dc6352.34ab7350.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[1347],{120:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>l,contentTitle:()=>r,default:()=>h,frontMatter:()=>o,metadata:()=>i,toc:()=>c});var i=n(9559),a=n(4848),s=n(8453);const o={title:"Minimizing blast radius in Cadence: Introducing Workflow ID-based Rate Limits",date:new Date("2024-09-05T00:00:00.000Z"),authors:"jakobht",tags:["deep-dive"]},r=void 0,l={authorsImageUrls:[void 0]},c=[{value:"Why Workflow ID-based Rate Limits?",id:"why-workflow-id-based-rate-limits",level:2}];function d(e){const t={a:"a",h2:"h2",li:"li",ol:"ol",p:"p",...(0,s.R)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsxs)(t.p,{children:["At Uber, we run several big multitenant Cadence clusters with hundreds of domains in each. The clusters being multi-tenant means potential ",(0,a.jsx)(t.a,{href:"https://en.wikipedia.org/wiki/Cloud_computing_issues#Performance_interference_and_noisy_neighbors",children:"noisy neighbor"})," effects between domains."]}),"\n",(0,a.jsx)(t.p,{children:"An essential aspect of avoiding this is managing how workflows interact with our infrastructure to prevent any single workflow from causing instability for the whole cluster. To this end, we are excited to introduce Workflow ID-based rate limits \u2014 a new feature designed to protect our clusters from problematic workflows and ensure stability across the board."}),"\n",(0,a.jsx)(t.h2,{id:"why-workflow-id-based-rate-limits",children:"Why Workflow ID-based Rate Limits?"}),"\n",(0,a.jsx)(t.p,{children:"We already have rate limits for how many requests can be sent to a domain. However, since Cadence is sharded on the workflow ID, a user-provided input, an overused workflow with a particular id might overwhelm a shard by making too many requests. There are two main ways this happens:"}),"\n",(0,a.jsxs)(t.ol,{children:["\n",(0,a.jsx)(t.li,{children:"A user starts, or signals the same workflow ID too aggressively,"}),"\n",(0,a.jsx)(t.li,{children:"A workflow starts too many activities over a short period of time (e.g. thousands of activities in seconds)."}),"\n"]})]})}function h(e={}){const{wrapper:t}={...(0,s.R)(),...e.components};return t?(0,a.jsx)(t,{...e,children:(0,a.jsx)(d,{...e})}):d(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>o,x:()=>r});var i=n(6540);const a={},s=i.createContext(a);function o(e){const t=i.useContext(s);return i.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function r(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:o(e.components),i.createElement(s.Provider,{value:t},e.children)}},9559:e=>{e.exports=JSON.parse('{"permalink":"/Cadence-Docs/blog/2024/09/05/workflow-specific-rate-limits","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2024-09-05-workflow-specific-rate-limits.md","source":"@site/blog/2024-09-05-workflow-specific-rate-limits.md","title":"Minimizing blast radius in Cadence: Introducing Workflow ID-based Rate Limits","description":"At Uber, we run several big multitenant Cadence clusters with hundreds of domains in each. The clusters being multi-tenant means potential noisy neighbor effects between domains.","date":"2024-09-05T00:00:00.000Z","tags":[{"inline":false,"label":"Deep Dives","permalink":"/Cadence-Docs/blog/tags/deep-dives","description":"Deep Dives tag description"}],"readingTime":6.335,"hasTruncateMarker":true,"authors":[{"name":"Jakob Haahr Taankvist","title":"Software Engineer II @ Uber","url":"https://www.linkedin.com/in/jakob-taankvist/","page":{"permalink":"/Cadence-Docs/blog/authors/jakobht"},"socials":{"linkedin":"https://www.linkedin.com/in/jakob-taankvist/","github":"https://github.com/jakobht"},"imageURL":"https://github.com/jakobht.png","key":"jakobht"}],"frontMatter":{"title":"Minimizing blast radius in Cadence: Introducing Workflow ID-based Rate Limits","date":"2024-09-05T00:00:00.000Z","authors":"jakobht","tags":["deep-dive"]},"unlisted":false,"prevItem":{"title":"Announcement: Cadence Helm Charts v0 Release","permalink":"/Cadence-Docs/blog/2024/10/01/announcing-cadence-helm-charts-v0"},"nextItem":{"title":"2024 Cadence Yearly Roadmap Update","permalink":"/Cadence-Docs/blog/2024/07/11/2024-07-11-yearly-roadmap-update/yearly-roadmap-update"}}')}}]); \ No newline at end of file diff --git a/assets/js/76dc6352.3a33489d.js b/assets/js/76dc6352.3a33489d.js deleted file mode 100644 index 8631ebe8d..000000000 --- a/assets/js/76dc6352.3a33489d.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[1347],{120:(e,t,i)=>{i.r(t),i.d(t,{assets:()=>l,contentTitle:()=>r,default:()=>h,frontMatter:()=>o,metadata:()=>n,toc:()=>d});var n=i(9559),a=i(4848),s=i(8453);const o={title:"Minimizing blast radius in Cadence: Introducing Workflow ID-based Rate Limits",date:new Date("2024-09-05T00:00:00.000Z"),authors:"jakobht",tags:["deep-dive"]},r=void 0,l={authorsImageUrls:[void 0]},d=[{value:"Why Workflow ID-based Rate Limits?",id:"why-workflow-id-based-rate-limits",level:2}];function c(e){const t={a:"a",h2:"h2",li:"li",ol:"ol",p:"p",...(0,s.R)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsxs)(t.p,{children:["At Uber, we run several big multitenant Cadence clusters with hundreds of domains in each. The clusters being multi-tenant means potential ",(0,a.jsx)(t.a,{href:"https://en.wikipedia.org/wiki/Cloud_computing_issues#Performance_interference_and_noisy_neighbors",children:"noisy neighbor"})," effects between domains."]}),"\n",(0,a.jsx)(t.p,{children:"An essential aspect of avoiding this is managing how workflows interact with our infrastructure to prevent any single workflow from causing instability for the whole cluster. To this end, we are excited to introduce Workflow ID-based rate limits \u2014 a new feature designed to protect our clusters from problematic workflows and ensure stability across the board."}),"\n",(0,a.jsx)(t.h2,{id:"why-workflow-id-based-rate-limits",children:"Why Workflow ID-based Rate Limits?"}),"\n",(0,a.jsx)(t.p,{children:"We already have rate limits for how many requests can be sent to a domain. However, since Cadence is sharded on the workflow ID, a user-provided input, an overused workflow with a particular id might overwhelm a shard by making too many requests. There are two main ways this happens:"}),"\n",(0,a.jsxs)(t.ol,{children:["\n",(0,a.jsx)(t.li,{children:"A user starts, or signals the same workflow ID too aggressively,"}),"\n",(0,a.jsx)(t.li,{children:"A workflow starts too many activities over a short period of time (e.g. thousands of activities in seconds)."}),"\n"]})]})}function h(e={}){const{wrapper:t}={...(0,s.R)(),...e.components};return t?(0,a.jsx)(t,{...e,children:(0,a.jsx)(c,{...e})}):c(e)}},8453:(e,t,i)=>{i.d(t,{R:()=>o,x:()=>r});var n=i(6540);const a={},s=n.createContext(a);function o(e){const t=n.useContext(s);return n.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function r(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:o(e.components),n.createElement(s.Provider,{value:t},e.children)}},9559:e=>{e.exports=JSON.parse('{"permalink":"/blog/2024/09/05/workflow-specific-rate-limits","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2024-09-05-workflow-specific-rate-limits.md","source":"@site/blog/2024-09-05-workflow-specific-rate-limits.md","title":"Minimizing blast radius in Cadence: Introducing Workflow ID-based Rate Limits","description":"At Uber, we run several big multitenant Cadence clusters with hundreds of domains in each. The clusters being multi-tenant means potential noisy neighbor effects between domains.","date":"2024-09-05T00:00:00.000Z","tags":[{"inline":false,"label":"Deep Dives","permalink":"/blog/tags/deep-dives","description":"Deep Dives tag description"}],"readingTime":6.335,"hasTruncateMarker":true,"authors":[{"name":"Jakob Haahr Taankvist","title":"Software Engineer II @ Uber","url":"https://www.linkedin.com/in/jakob-taankvist/","page":{"permalink":"/blog/authors/jakobht"},"socials":{"linkedin":"https://www.linkedin.com/in/jakob-taankvist/","github":"https://github.com/jakobht"},"imageURL":"https://github.com/jakobht.png","key":"jakobht"}],"frontMatter":{"title":"Minimizing blast radius in Cadence: Introducing Workflow ID-based Rate Limits","date":"2024-09-05T00:00:00.000Z","authors":"jakobht","tags":["deep-dive"]},"unlisted":false,"prevItem":{"title":"Announcement: Cadence Helm Charts v0 Release","permalink":"/blog/2024/10/01/announcing-cadence-helm-charts-v0"},"nextItem":{"title":"2024 Cadence Yearly Roadmap Update","permalink":"/blog/2024/07/11/2024-07-11-yearly-roadmap-update/yearly-roadmap-update"}}')}}]); \ No newline at end of file diff --git a/assets/js/775920c1.8add127c.js b/assets/js/775920c1.8add127c.js new file mode 100644 index 000000000..09ed2984e --- /dev/null +++ b/assets/js/775920c1.8add127c.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[7009],{1614:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>l,contentTitle:()=>c,default:()=>d,frontMatter:()=>s,metadata:()=>o,toc:()=>r});var o=t(4436),a=t(4848),i=t(8453);const s={title:"Cadence Community Spotlight Update - December 2022",date:new Date("2022-12-23T00:00:00.000Z"),authors:"sharanf",tags:["community-spotlight"]},c=void 0,l={authorsImageUrls:[void 0]},r=[{value:"Happy Holidays",id:"happy-holidays",level:2},{value:"Cadence in the News!",id:"cadence-in-the-news",level:2},{value:"Upcoming Events",id:"upcoming-events",level:2}];function h(e){const n={a:"a",h2:"h2",li:"li",p:"p",ul:"ul",...(0,i.R)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(n.p,{children:"I know we are a little early this month as many people will be taking some time out for holidays."}),"\n",(0,a.jsx)(n.h2,{id:"happy-holidays",children:"Happy Holidays"}),"\n",(0,a.jsx)(n.p,{children:"We'd like to wish everyone happy holidays and to thank you for being part of the Cadence community. It's been a busy year for Cadence as we have continued to build a strong, active community that works together to solve issues and generally support each other."}),"\n",(0,a.jsx)(n.p,{children:"Let's keep going!...This is a great way to build a sustainable community."}),"\n",(0,a.jsx)(n.p,{children:"We are sure that 2023 will be even more exciting as we continue to develop Cadence."}),"\n",(0,a.jsx)(n.h2,{id:"cadence-in-the-news",children:"Cadence in the News!"}),"\n",(0,a.jsx)(n.p,{children:"Below are a selection of Cadence related articles, blogs and whitepapers. Please take a look and feel free to share via your own social media channels."}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsxs)(n.li,{children:["\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.a,{href:"https://www.instaclustr.com/blog/cadence-iwf",children:"Cadence iWF"})}),"\n"]}),"\n",(0,a.jsxs)(n.li,{children:["\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.a,{href:"https://github.com/instaclustr/cadence-cookbooks-instafood/blob/main/cookbooks/child-workflows/child-workflows-megafood.md",children:"Child Workflow Cookbook"})}),"\n"]}),"\n",(0,a.jsxs)(n.li,{children:["\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.a,{href:"https://www.instaclustr.com/blog/cadence-connection-examples-using-tls/",children:"Cadence Connection Examples Using TLS"})}),"\n"]}),"\n"]}),"\n",(0,a.jsx)(n.h2,{id:"upcoming-events",children:"Upcoming Events"}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsx)(n.li,{children:(0,a.jsx)(n.a,{href:"https://calendar.google.com/calendar/u/0/embed?src=e6r40gp3c2r01054id7e99dlac@group.calendar.google.com&ctz=America/Los_Angeles",children:"Cadence Technical Office Hours - 30th January 2023 @ 9am PT"})}),"\n"]}),"\n",(0,a.jsxs)(n.p,{children:["If you have any news or topics you'd like us to include in our next update then please join our ",(0,a.jsx)(n.a,{href:"http://t.uber.com/cadence-slack",children:"Slack"}),"#community channel."]}),"\n",(0,a.jsxs)(n.p,{children:["Please remember that this update is for you - so if you have any comments or feedback that could help us improve it then please share it with us in the #community ",(0,a.jsx)(n.a,{href:"http://t.uber.com/cadence-slack",children:"Slack"})," channel."]})]})}function d(e={}){const{wrapper:n}={...(0,i.R)(),...e.components};return n?(0,a.jsx)(n,{...e,children:(0,a.jsx)(h,{...e})}):h(e)}},8453:(e,n,t)=>{t.d(n,{R:()=>s,x:()=>c});var o=t(6540);const a={},i=o.createContext(a);function s(e){const n=o.useContext(i);return o.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function c(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:s(e.components),o.createElement(i.Provider,{value:n},e.children)}},4436:e=>{e.exports=JSON.parse('{"permalink":"/Cadence-Docs/blog/2022/12/23/community-spotlight-december-2022","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2022-12-23-community-spotlight-december-2022.md","source":"@site/blog/2022-12-23-community-spotlight-december-2022.md","title":"Cadence Community Spotlight Update - December 2022","description":"I know we are a little early this month as many people will be taking some time out for holidays.","date":"2022-12-23T00:00:00.000Z","tags":[{"inline":false,"label":"Community Spotlight","permalink":"/Cadence-Docs/blog/tags/community-spotlights","description":"Community Spotlight tag description"}],"readingTime":1.08,"hasTruncateMarker":true,"authors":[{"name":"Sharan Foga","title":"Director of Operations & Customer Success @ Encube Technologies","url":"https://www.linkedin.com/in/sfoga/","page":{"permalink":"/Cadence-Docs/blog/authors/sharanf"},"socials":{"linkedin":"https://www.linkedin.com/in/sfoga/","github":"https://github.com/sharanf"},"imageURL":"https://github.com/sharanf.png","key":"sharanf"}],"frontMatter":{"title":"Cadence Community Spotlight Update - December 2022","date":"2022-12-23T00:00:00.000Z","authors":"sharanf","tags":["community-spotlight"]},"unlisted":false,"prevItem":{"title":"Cadence Community Spotlight Update - January 2023","permalink":"/Cadence-Docs/blog/2023/01/31/community-spotlight-january-2023"},"nextItem":{"title":"Cadence Community Spotlight Update - November 2022","permalink":"/Cadence-Docs/blog/2022/11/30/community-spotlight-november-2022"}}')}}]); \ No newline at end of file diff --git a/assets/js/775920c1.e89602fb.js b/assets/js/775920c1.e89602fb.js deleted file mode 100644 index a099c97fb..000000000 --- a/assets/js/775920c1.e89602fb.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[7009],{1614:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>c,contentTitle:()=>l,default:()=>d,frontMatter:()=>s,metadata:()=>o,toc:()=>r});var o=n(4436),a=n(4848),i=n(8453);const s={title:"Cadence Community Spotlight Update - December 2022",date:new Date("2022-12-23T00:00:00.000Z"),authors:"sharanf",tags:["community-spotlight"]},l=void 0,c={authorsImageUrls:[void 0]},r=[{value:"Happy Holidays",id:"happy-holidays",level:2},{value:"Cadence in the News!",id:"cadence-in-the-news",level:2},{value:"Upcoming Events",id:"upcoming-events",level:2}];function h(e){const t={a:"a",h2:"h2",li:"li",p:"p",ul:"ul",...(0,i.R)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(t.p,{children:"I know we are a little early this month as many people will be taking some time out for holidays."}),"\n",(0,a.jsx)(t.h2,{id:"happy-holidays",children:"Happy Holidays"}),"\n",(0,a.jsx)(t.p,{children:"We'd like to wish everyone happy holidays and to thank you for being part of the Cadence community. It's been a busy year for Cadence as we have continued to build a strong, active community that works together to solve issues and generally support each other."}),"\n",(0,a.jsx)(t.p,{children:"Let's keep going!...This is a great way to build a sustainable community."}),"\n",(0,a.jsx)(t.p,{children:"We are sure that 2023 will be even more exciting as we continue to develop Cadence."}),"\n",(0,a.jsx)(t.h2,{id:"cadence-in-the-news",children:"Cadence in the News!"}),"\n",(0,a.jsx)(t.p,{children:"Below are a selection of Cadence related articles, blogs and whitepapers. Please take a look and feel free to share via your own social media channels."}),"\n",(0,a.jsxs)(t.ul,{children:["\n",(0,a.jsxs)(t.li,{children:["\n",(0,a.jsx)(t.p,{children:(0,a.jsx)(t.a,{href:"https://www.instaclustr.com/blog/cadence-iwf",children:"Cadence iWF"})}),"\n"]}),"\n",(0,a.jsxs)(t.li,{children:["\n",(0,a.jsx)(t.p,{children:(0,a.jsx)(t.a,{href:"https://github.com/instaclustr/cadence-cookbooks-instafood/blob/main/cookbooks/child-workflows/child-workflows-megafood.md",children:"Child Workflow Cookbook"})}),"\n"]}),"\n",(0,a.jsxs)(t.li,{children:["\n",(0,a.jsx)(t.p,{children:(0,a.jsx)(t.a,{href:"https://www.instaclustr.com/blog/cadence-connection-examples-using-tls/",children:"Cadence Connection Examples Using TLS"})}),"\n"]}),"\n"]}),"\n",(0,a.jsx)(t.h2,{id:"upcoming-events",children:"Upcoming Events"}),"\n",(0,a.jsxs)(t.ul,{children:["\n",(0,a.jsx)(t.li,{children:(0,a.jsx)(t.a,{href:"https://calendar.google.com/calendar/u/0/embed?src=e6r40gp3c2r01054id7e99dlac@group.calendar.google.com&ctz=America/Los_Angeles",children:"Cadence Technical Office Hours - 30th January 2023 @ 9am PT"})}),"\n"]}),"\n",(0,a.jsxs)(t.p,{children:["If you have any news or topics you'd like us to include in our next update then please join our ",(0,a.jsx)(t.a,{href:"http://t.uber.com/cadence-slack",children:"Slack"}),"#community channel."]}),"\n",(0,a.jsxs)(t.p,{children:["Please remember that this update is for you - so if you have any comments or feedback that could help us improve it then please share it with us in the #community ",(0,a.jsx)(t.a,{href:"http://t.uber.com/cadence-slack",children:"Slack"})," channel."]})]})}function d(e={}){const{wrapper:t}={...(0,i.R)(),...e.components};return t?(0,a.jsx)(t,{...e,children:(0,a.jsx)(h,{...e})}):h(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>s,x:()=>l});var o=n(6540);const a={},i=o.createContext(a);function s(e){const t=o.useContext(i);return o.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function l(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:s(e.components),o.createElement(i.Provider,{value:t},e.children)}},4436:e=>{e.exports=JSON.parse('{"permalink":"/blog/2022/12/23/community-spotlight-december-2022","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2022-12-23-community-spotlight-december-2022.md","source":"@site/blog/2022-12-23-community-spotlight-december-2022.md","title":"Cadence Community Spotlight Update - December 2022","description":"I know we are a little early this month as many people will be taking some time out for holidays.","date":"2022-12-23T00:00:00.000Z","tags":[{"inline":false,"label":"Community Spotlight","permalink":"/blog/tags/community-spotlights","description":"Community Spotlight tag description"}],"readingTime":1.08,"hasTruncateMarker":true,"authors":[{"name":"Sharan Foga","title":"Director of Operations & Customer Success @ Encube Technologies","url":"https://www.linkedin.com/in/sfoga/","page":{"permalink":"/blog/authors/sharanf"},"socials":{"linkedin":"https://www.linkedin.com/in/sfoga/","github":"https://github.com/sharanf"},"imageURL":"https://github.com/sharanf.png","key":"sharanf"}],"frontMatter":{"title":"Cadence Community Spotlight Update - December 2022","date":"2022-12-23T00:00:00.000Z","authors":"sharanf","tags":["community-spotlight"]},"unlisted":false,"prevItem":{"title":"Cadence Community Spotlight Update - January 2023","permalink":"/blog/2023/01/31/community-spotlight-january-2023"},"nextItem":{"title":"Cadence Community Spotlight Update - November 2022","permalink":"/blog/2022/11/30/community-spotlight-november-2022"}}')}}]); \ No newline at end of file diff --git a/assets/js/77a860e9.19b7d9f8.js b/assets/js/77a860e9.19b7d9f8.js deleted file mode 100644 index 54830a01e..000000000 --- a/assets/js/77a860e9.19b7d9f8.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[5538],{6454:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>a,contentTitle:()=>l,default:()=>u,frontMatter:()=>i,metadata:()=>r,toc:()=>c});const r=JSON.parse('{"id":"java-client/distributed-cron","title":"Distributed CRON","description":"It is relatively straightforward to turn any Cadence into a Cron. All you need","source":"@site/docs/04-java-client/08-distributed-cron.md","sourceDirName":"04-java-client","slug":"/java-client/distributed-cron","permalink":"/docs/java-client/distributed-cron","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/04-java-client/08-distributed-cron.md","tags":[],"version":"current","sidebarPosition":8,"frontMatter":{"layout":"default","title":"Distributed CRON","permalink":"/docs/java-client/distributed-cron"},"sidebar":"docsSidebar","previous":{"title":"Versioning","permalink":"/docs/java-client/versioning"},"next":{"title":"Worker service","permalink":"/docs/java-client/workers"}}');var s=t(4848),o=t(8453);const i={layout:"default",title:"Distributed CRON",permalink:"/docs/java-client/distributed-cron"},l="Distributed CRON",a={},c=[{value:"Convert an existing cron workflow",id:"convert-an-existing-cron-workflow",level:2},{value:"Retrieve last successful result",id:"retrieve-last-successful-result",level:2}];function d(e){const n={a:"a",code:"code",h1:"h1",h2:"h2",header:"header",li:"li",p:"p",pre:"pre",ul:"ul",...(0,o.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(n.header,{children:(0,s.jsx)(n.h1,{id:"distributed-cron",children:"Distributed CRON"})}),"\n",(0,s.jsxs)(n.p,{children:["It is relatively straightforward to turn any Cadence workflow into a Cron workflow. All you need\nis to supply a cron schedule when starting the workflow using the CronSchedule\nparameter of\n",(0,s.jsx)(n.a,{href:"https://static.javadoc.io/com.uber.cadence/cadence-client/2.5.1/com/cadence-workflow/cadence/client/WorkflowOptions.html",children:"StartWorkflowOptions"}),"."]}),"\n",(0,s.jsxs)(n.p,{children:["You can also start a workflow using the Cadence CLI with an optional cron schedule using the ",(0,s.jsx)(n.code,{children:"--cron"})," argument."]}),"\n",(0,s.jsx)(n.p,{children:"For workflows with CronSchedule:"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:'CronSchedule is based on UTC time. For example cron schedule "15 8 * * *"\nwill run daily at 8:15am UTC. Another example "*/2 * * * 5-6" will schedule a workflow every two minutes on fridays\nand saturdays.'}),"\n",(0,s.jsx)(n.li,{children:"If a workflow failed and a RetryPolicy is supplied to the StartWorkflowOptions\nas well, the workflow will retry based on the RetryPolicy. While the workflow is\nretrying, the server will not schedule the next cron run."}),"\n",(0,s.jsx)(n.li,{children:"Cadence server only schedules the next cron run after the current run is\ncompleted. If the next schedule is due while a workflow is running (or retrying),\nthen it will skip that schedule."}),"\n",(0,s.jsx)(n.li,{children:"Cron workflows will not stop until they are terminated or cancelled."}),"\n"]}),"\n",(0,s.jsx)(n.p,{children:"Cadence supports the standard cron spec:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-java",children:"// CronSchedule - Optional cron schedule for workflow. If a cron schedule is specified, the workflow will run\n// as a cron based on the schedule. The scheduling will be based on UTC time. The schedule for the next run only happens\n// after the current run is completed/failed/timeout. If a RetryPolicy is also supplied, and the workflow failed\n// or timed out, the workflow will be retried based on the retry policy. While the workflow is retrying, it won't\n// schedule its next run. If the next schedule is due while the workflow is running (or retrying), then it will skip that\n// schedule. Cron workflow will not stop until it is terminated or cancelled (by returning cadence.CanceledError).\n// The cron spec is as follows:\n// \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 minute (0 - 59)\n// \u2502 \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 hour (0 - 23)\n// \u2502 \u2502 \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 day of the month (1 - 31)\n// \u2502 \u2502 \u2502 \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 month (1 - 12)\n// \u2502 \u2502 \u2502 \u2502 \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 day of the week (0 - 6) (Sunday to Saturday)\n// \u2502 \u2502 \u2502 \u2502 \u2502\n// \u2502 \u2502 \u2502 \u2502 \u2502\n// * * * * *\nCronSchedule string\n"})}),"\n",(0,s.jsxs)(n.p,{children:["Cadence also supports more ",(0,s.jsx)(n.a,{href:"https://pkg.go.dev/github.com/robfig/cron#hdr-CRON_Expression_Format",children:"advanced cron expressions"}),"."]}),"\n",(0,s.jsxs)(n.p,{children:["The ",(0,s.jsx)(n.a,{href:"https://crontab.guru/",children:"crontab guru site"})," is useful for testing your cron expressions."]}),"\n",(0,s.jsx)(n.h2,{id:"convert-an-existing-cron-workflow",children:"Convert an existing cron workflow"}),"\n",(0,s.jsxs)(n.p,{children:["Before CronSchedule was available, the previous approach to implementing cron\nworkflows was to use a delay timer as the last step and then return\n",(0,s.jsx)(n.code,{children:"ContinueAsNew"}),". One problem with that implementation is that if the workflow\nfails or times out, the cron would stop."]}),"\n",(0,s.jsxs)(n.p,{children:["To convert those workflows to make use of Cadence CronSchedule, all you need is to remove the delay timer and return without using\n",(0,s.jsx)(n.code,{children:"ContinueAsNew"}),". Then start the workflow with the desired CronSchedule."]}),"\n",(0,s.jsx)(n.h2,{id:"retrieve-last-successful-result",children:"Retrieve last successful result"}),"\n",(0,s.jsxs)(n.p,{children:["Sometimes it is useful to obtain the progress of previous successful runs.\nThis is supported by two new APIs in the client library:\n",(0,s.jsx)(n.code,{children:"HasLastCompletionResult"})," and ",(0,s.jsx)(n.code,{children:"GetLastCompletionResult"}),". Below is an example of how\nto use this in Java:"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-java",children:"public String cronWorkflow() {\n String lastProcessedFileName = Workflow.getLastCompletionResult(String.class);\n\n // Process work starting from the lastProcessedFileName.\n // Business logic implementation goes here.\n // Updates lastProcessedFileName to the new value.\n\n return lastProcessedFileName;\n}\n"})}),"\n",(0,s.jsx)(n.p,{children:"Note that this works even if one of the cron schedule runs failed. The\nnext schedule will still get the last successful result if it ever successfully\ncompleted at least once. For example, for a daily cron workflow, if the first day\nrun succeeds and the second day fails, then the third day run will still get\nthe result from first day's run using these APIs."})]})}function u(e={}){const{wrapper:n}={...(0,o.R)(),...e.components};return n?(0,s.jsx)(n,{...e,children:(0,s.jsx)(d,{...e})}):d(e)}},8453:(e,n,t)=>{t.d(n,{R:()=>i,x:()=>l});var r=t(6540);const s={},o=r.createContext(s);function i(e){const n=r.useContext(o);return r.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function l(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:i(e.components),r.createElement(o.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/77a860e9.8ac5975c.js b/assets/js/77a860e9.8ac5975c.js new file mode 100644 index 000000000..c492c137a --- /dev/null +++ b/assets/js/77a860e9.8ac5975c.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[5538],{6454:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>a,contentTitle:()=>l,default:()=>u,frontMatter:()=>i,metadata:()=>r,toc:()=>c});const r=JSON.parse('{"id":"java-client/distributed-cron","title":"Distributed CRON","description":"It is relatively straightforward to turn any Cadence into a Cron. All you need","source":"@site/docs/04-java-client/08-distributed-cron.md","sourceDirName":"04-java-client","slug":"/java-client/distributed-cron","permalink":"/Cadence-Docs/docs/java-client/distributed-cron","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/04-java-client/08-distributed-cron.md","tags":[],"version":"current","sidebarPosition":8,"frontMatter":{"layout":"default","title":"Distributed CRON","permalink":"/docs/java-client/distributed-cron"},"sidebar":"docsSidebar","previous":{"title":"Versioning","permalink":"/Cadence-Docs/docs/java-client/versioning"},"next":{"title":"Worker service","permalink":"/Cadence-Docs/docs/java-client/workers"}}');var s=t(4848),o=t(8453);const i={layout:"default",title:"Distributed CRON",permalink:"/docs/java-client/distributed-cron"},l="Distributed CRON",a={},c=[{value:"Convert an existing cron workflow",id:"convert-an-existing-cron-workflow",level:2},{value:"Retrieve last successful result",id:"retrieve-last-successful-result",level:2}];function d(e){const n={a:"a",code:"code",h1:"h1",h2:"h2",header:"header",li:"li",p:"p",pre:"pre",ul:"ul",...(0,o.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(n.header,{children:(0,s.jsx)(n.h1,{id:"distributed-cron",children:"Distributed CRON"})}),"\n",(0,s.jsxs)(n.p,{children:["It is relatively straightforward to turn any Cadence workflow into a Cron workflow. All you need\nis to supply a cron schedule when starting the workflow using the CronSchedule\nparameter of\n",(0,s.jsx)(n.a,{href:"https://static.javadoc.io/com.uber.cadence/cadence-client/2.5.1/com/cadence-workflow/cadence/client/WorkflowOptions.html",children:"StartWorkflowOptions"}),"."]}),"\n",(0,s.jsxs)(n.p,{children:["You can also start a workflow using the Cadence CLI with an optional cron schedule using the ",(0,s.jsx)(n.code,{children:"--cron"})," argument."]}),"\n",(0,s.jsx)(n.p,{children:"For workflows with CronSchedule:"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:'CronSchedule is based on UTC time. For example cron schedule "15 8 * * *"\nwill run daily at 8:15am UTC. Another example "*/2 * * * 5-6" will schedule a workflow every two minutes on fridays\nand saturdays.'}),"\n",(0,s.jsx)(n.li,{children:"If a workflow failed and a RetryPolicy is supplied to the StartWorkflowOptions\nas well, the workflow will retry based on the RetryPolicy. While the workflow is\nretrying, the server will not schedule the next cron run."}),"\n",(0,s.jsx)(n.li,{children:"Cadence server only schedules the next cron run after the current run is\ncompleted. If the next schedule is due while a workflow is running (or retrying),\nthen it will skip that schedule."}),"\n",(0,s.jsx)(n.li,{children:"Cron workflows will not stop until they are terminated or cancelled."}),"\n"]}),"\n",(0,s.jsx)(n.p,{children:"Cadence supports the standard cron spec:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-java",children:"// CronSchedule - Optional cron schedule for workflow. If a cron schedule is specified, the workflow will run\n// as a cron based on the schedule. The scheduling will be based on UTC time. The schedule for the next run only happens\n// after the current run is completed/failed/timeout. If a RetryPolicy is also supplied, and the workflow failed\n// or timed out, the workflow will be retried based on the retry policy. While the workflow is retrying, it won't\n// schedule its next run. If the next schedule is due while the workflow is running (or retrying), then it will skip that\n// schedule. Cron workflow will not stop until it is terminated or cancelled (by returning cadence.CanceledError).\n// The cron spec is as follows:\n// \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 minute (0 - 59)\n// \u2502 \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 hour (0 - 23)\n// \u2502 \u2502 \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 day of the month (1 - 31)\n// \u2502 \u2502 \u2502 \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 month (1 - 12)\n// \u2502 \u2502 \u2502 \u2502 \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 day of the week (0 - 6) (Sunday to Saturday)\n// \u2502 \u2502 \u2502 \u2502 \u2502\n// \u2502 \u2502 \u2502 \u2502 \u2502\n// * * * * *\nCronSchedule string\n"})}),"\n",(0,s.jsxs)(n.p,{children:["Cadence also supports more ",(0,s.jsx)(n.a,{href:"https://pkg.go.dev/github.com/robfig/cron#hdr-CRON_Expression_Format",children:"advanced cron expressions"}),"."]}),"\n",(0,s.jsxs)(n.p,{children:["The ",(0,s.jsx)(n.a,{href:"https://crontab.guru/",children:"crontab guru site"})," is useful for testing your cron expressions."]}),"\n",(0,s.jsx)(n.h2,{id:"convert-an-existing-cron-workflow",children:"Convert an existing cron workflow"}),"\n",(0,s.jsxs)(n.p,{children:["Before CronSchedule was available, the previous approach to implementing cron\nworkflows was to use a delay timer as the last step and then return\n",(0,s.jsx)(n.code,{children:"ContinueAsNew"}),". One problem with that implementation is that if the workflow\nfails or times out, the cron would stop."]}),"\n",(0,s.jsxs)(n.p,{children:["To convert those workflows to make use of Cadence CronSchedule, all you need is to remove the delay timer and return without using\n",(0,s.jsx)(n.code,{children:"ContinueAsNew"}),". Then start the workflow with the desired CronSchedule."]}),"\n",(0,s.jsx)(n.h2,{id:"retrieve-last-successful-result",children:"Retrieve last successful result"}),"\n",(0,s.jsxs)(n.p,{children:["Sometimes it is useful to obtain the progress of previous successful runs.\nThis is supported by two new APIs in the client library:\n",(0,s.jsx)(n.code,{children:"HasLastCompletionResult"})," and ",(0,s.jsx)(n.code,{children:"GetLastCompletionResult"}),". Below is an example of how\nto use this in Java:"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-java",children:"public String cronWorkflow() {\n String lastProcessedFileName = Workflow.getLastCompletionResult(String.class);\n\n // Process work starting from the lastProcessedFileName.\n // Business logic implementation goes here.\n // Updates lastProcessedFileName to the new value.\n\n return lastProcessedFileName;\n}\n"})}),"\n",(0,s.jsx)(n.p,{children:"Note that this works even if one of the cron schedule runs failed. The\nnext schedule will still get the last successful result if it ever successfully\ncompleted at least once. For example, for a daily cron workflow, if the first day\nrun succeeds and the second day fails, then the third day run will still get\nthe result from first day's run using these APIs."})]})}function u(e={}){const{wrapper:n}={...(0,o.R)(),...e.components};return n?(0,s.jsx)(n,{...e,children:(0,s.jsx)(d,{...e})}):d(e)}},8453:(e,n,t)=>{t.d(n,{R:()=>i,x:()=>l});var r=t(6540);const s={},o=r.createContext(s);function i(e){const n=r.useContext(o);return r.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function l(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:i(e.components),r.createElement(o.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/79f715ea.4cc73919.js b/assets/js/79f715ea.4cc73919.js deleted file mode 100644 index f6a1a43fa..000000000 --- a/assets/js/79f715ea.4cc73919.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[3314],{4316:(e,t,s)=>{s.r(t),s.d(t,{assets:()=>r,contentTitle:()=>c,default:()=>u,frontMatter:()=>i,metadata:()=>o,toc:()=>d});const o=JSON.parse('{"id":"use-cases/big-ml","title":"Big data and ML","description":"A lot of companies build custom ETL and ML training and deployment solutions. Cadence is a good fit for a control plane for such applications.","source":"@site/docs/02-use-cases/12-big-ml.md","sourceDirName":"02-use-cases","slug":"/use-cases/big-ml","permalink":"/docs/use-cases/big-ml","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/02-use-cases/12-big-ml.md","tags":[],"version":"current","sidebarPosition":12,"frontMatter":{"layout":"default","title":"Big data and ML","permalink":"/docs/use-cases/big-ml"},"sidebar":"docsSidebar","previous":{"title":"DSL workflows","permalink":"/docs/use-cases/dsl"},"next":{"title":"Introduction","permalink":"/docs/concepts/"}}');var n=s(4848),a=s(8453);const i={layout:"default",title:"Big data and ML",permalink:"/docs/use-cases/big-ml"},c="Big data and ML",r={},d=[];function l(e){const t={h1:"h1",header:"header",p:"p",...(0,a.R)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(t.header,{children:(0,n.jsx)(t.h1,{id:"big-data-and-ml",children:"Big data and ML"})}),"\n",(0,n.jsx)(t.p,{children:"A lot of companies build custom ETL and ML training and deployment solutions. Cadence is a good fit for a control plane for such applications."}),"\n",(0,n.jsx)(t.p,{children:"One important feature of Cadence is its ability to route task execution to a specific process or host. It is useful to control how ML models and other large files are allocated to hosts. For example, if an ML model is partitioned by city, the requests should be routed to hosts that contain the corresponding city model."})]})}function u(e={}){const{wrapper:t}={...(0,a.R)(),...e.components};return t?(0,n.jsx)(t,{...e,children:(0,n.jsx)(l,{...e})}):l(e)}},8453:(e,t,s)=>{s.d(t,{R:()=>i,x:()=>c});var o=s(6540);const n={},a=o.createContext(n);function i(e){const t=o.useContext(a);return o.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function c(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(n):e.components||n:i(e.components),o.createElement(a.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/79f715ea.f22e7e3d.js b/assets/js/79f715ea.f22e7e3d.js new file mode 100644 index 000000000..6a43970da --- /dev/null +++ b/assets/js/79f715ea.f22e7e3d.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[3314],{4316:(e,t,s)=>{s.r(t),s.d(t,{assets:()=>r,contentTitle:()=>i,default:()=>u,frontMatter:()=>c,metadata:()=>o,toc:()=>d});const o=JSON.parse('{"id":"use-cases/big-ml","title":"Big data and ML","description":"A lot of companies build custom ETL and ML training and deployment solutions. Cadence is a good fit for a control plane for such applications.","source":"@site/docs/02-use-cases/12-big-ml.md","sourceDirName":"02-use-cases","slug":"/use-cases/big-ml","permalink":"/Cadence-Docs/docs/use-cases/big-ml","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/02-use-cases/12-big-ml.md","tags":[],"version":"current","sidebarPosition":12,"frontMatter":{"layout":"default","title":"Big data and ML","permalink":"/docs/use-cases/big-ml"},"sidebar":"docsSidebar","previous":{"title":"DSL workflows","permalink":"/Cadence-Docs/docs/use-cases/dsl"},"next":{"title":"Introduction","permalink":"/Cadence-Docs/docs/concepts/"}}');var n=s(4848),a=s(8453);const c={layout:"default",title:"Big data and ML",permalink:"/docs/use-cases/big-ml"},i="Big data and ML",r={},d=[];function l(e){const t={h1:"h1",header:"header",p:"p",...(0,a.R)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(t.header,{children:(0,n.jsx)(t.h1,{id:"big-data-and-ml",children:"Big data and ML"})}),"\n",(0,n.jsx)(t.p,{children:"A lot of companies build custom ETL and ML training and deployment solutions. Cadence is a good fit for a control plane for such applications."}),"\n",(0,n.jsx)(t.p,{children:"One important feature of Cadence is its ability to route task execution to a specific process or host. It is useful to control how ML models and other large files are allocated to hosts. For example, if an ML model is partitioned by city, the requests should be routed to hosts that contain the corresponding city model."})]})}function u(e={}){const{wrapper:t}={...(0,a.R)(),...e.components};return t?(0,n.jsx)(t,{...e,children:(0,n.jsx)(l,{...e})}):l(e)}},8453:(e,t,s)=>{s.d(t,{R:()=>c,x:()=>i});var o=s(6540);const n={},a=o.createContext(n);function c(e){const t=o.useContext(a);return o.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function i(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(n):e.components||n:c(e.components),o.createElement(a.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/7a568d1f.7a793f0a.js b/assets/js/7a568d1f.7a793f0a.js new file mode 100644 index 000000000..c7efa5523 --- /dev/null +++ b/assets/js/7a568d1f.7a793f0a.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[9699],{3915:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>s,contentTitle:()=>l,default:()=>u,frontMatter:()=>i,metadata:()=>r,toc:()=>c});const r=JSON.parse('{"id":"java-client/queries","title":"Queries","description":"Query is to expose this internal state to the external world Cadence provides a synchronous feature. From the implementer point of view the is exposed as a synchronous callback that is invoked by external entities. Multiple such callbacks can be provided per type exposing different information to different external systems.","source":"@site/docs/04-java-client/11-queries.md","sourceDirName":"04-java-client","slug":"/java-client/queries","permalink":"/Cadence-Docs/docs/java-client/queries","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/04-java-client/11-queries.md","tags":[],"version":"current","sidebarPosition":11,"frontMatter":{"layout":"default","title":"Queries","permalink":"/docs/java-client/queries"},"sidebar":"docsSidebar","previous":{"title":"Signals","permalink":"/Cadence-Docs/docs/java-client/signals"},"next":{"title":"Retries","permalink":"/Cadence-Docs/docs/java-client/retries"}}');var o=t(4848),a=t(8453);const i={layout:"default",title:"Queries",permalink:"/docs/java-client/queries"},l="Queries",s={},c=[{value:"Built-in Query: Stack Trace",id:"built-in-query-stack-trace",level:2},{value:"Customized Query",id:"customized-query",level:2},{value:"Run Query from Command Line",id:"run-query-from-command-line",level:2},{value:"Run Query from external application code",id:"run-query-from-external-application-code",level:2},{value:"Consistent Query",id:"consistent-query",level:2}];function d(e){const n={a:"a",code:"code",h1:"h1",h2:"h2",header:"header",p:"p",pre:"pre",strong:"strong",...(0,a.R)(),...e.components};return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsx)(n.header,{children:(0,o.jsx)(n.h1,{id:"queries",children:"Queries"})}),"\n",(0,o.jsx)(n.p,{children:"Query is to expose this internal state to the external world Cadence provides a synchronous query feature. From the workflow implementer point of view the query is exposed as a synchronous callback that is invoked by external entities. Multiple such callbacks can be provided per workflow type exposing different information to different external systems."}),"\n",(0,o.jsx)(n.p,{children:"Query callbacks must be read-only not mutating the workflow state in any way. The other limitation is that the query callback cannot contain any blocking code. Both above limitations rule out ability to invoke activities from the query handlers."}),"\n",(0,o.jsx)(n.h2,{id:"built-in-query-stack-trace",children:"Built-in Query: Stack Trace"}),"\n",(0,o.jsx)(n.p,{children:"If a workflow_execution has been stuck at a state for longer than an expected period of time, you\nmight want to query the current call stack. You can use the Cadence CLI to perform this query. For\nexample:"}),"\n",(0,o.jsx)(n.p,{children:(0,o.jsx)(n.code,{children:"cadence-cli --domain samples-domain workflow query -w my_workflow_id -r my_run_id -qt __stack_trace"})}),"\n",(0,o.jsxs)(n.p,{children:["This command uses ",(0,o.jsx)(n.code,{children:"__stack_trace"}),", which is a built-in query type supported by the Cadence client\nlibrary. You can add custom query types to handle queries such as querying the current state of a\nworkflow, or querying how many activities the workflow has completed."]}),"\n",(0,o.jsx)(n.h2,{id:"customized-query",children:"Customized Query"}),"\n",(0,o.jsx)(n.p,{children:"Cadence provides a query feature that supports synchronously returning any information from a workflow to an external caller."}),"\n",(0,o.jsxs)(n.p,{children:["Interface ",(0,o.jsx)(n.a,{href:"https://www.javadoc.io/doc/com.uber.cadence/cadence-client/latest/com/cadence-workflow/cadence/workflow/QueryMethod.html",children:(0,o.jsx)(n.strong,{children:"QueryMethod"})})," indicates that the method is a query method. Query method can be used to query a workflow state by external process at any time during its execution. This annotation applies only to workflow interface methods."]}),"\n",(0,o.jsxs)(n.p,{children:["See the ",(0,o.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence-java-samples/blob/master/src/main/java/com/uber/cadence/samples/hello/HelloQuery.java",children:"workflow"})," example code :"]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-java",children:'public interface HelloWorld {\n @WorkflowMethod\n void sayHello(String name);\n\n @SignalMethod\n void updateGreeting(String greeting);\n\n @QueryMethod\n int getCount();\n}\n\npublic static class HelloWorldImpl implements HelloWorld {\n\n private String greeting = "Hello";\n private int count = 0;\n\n @Override\n public void sayHello(String name) {\n while (!"Bye".equals(greeting)) {\n logger.info(++count + ": " + greeting + " " + name + "!");\n String oldGreeting = greeting;\n Workflow.await(() -> !Objects.equals(greeting, oldGreeting));\n }\n logger.info(++count + ": " + greeting + " " + name + "!");\n }\n\n @Override\n public void updateGreeting(String greeting) {\n this.greeting = greeting;\n }\n\n @Override\n public int getCount() {\n return count;\n }\n}\n'})}),"\n",(0,o.jsxs)(n.p,{children:["The new ",(0,o.jsx)(n.code,{children:"getCount"})," method annotated with ",(0,o.jsx)(n.code,{children:"@QueryMethod"})," was added to the workflow interface definition. It is allowed\nto have multiple query methods per workflow interface."]}),"\n",(0,o.jsx)(n.p,{children:"The main restriction on the implementation of the query method is that it is not allowed to modify workflow state in any form.\nIt also is not allowed to block its thread in any way. It usually just returns a value derived from the fields of the workflow object."}),"\n",(0,o.jsx)(n.h2,{id:"run-query-from-command-line",children:"Run Query from Command Line"}),"\n",(0,o.jsx)(n.p,{children:"Let's run the updated worker and send a couple signals to it:"}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-bash",children:'cadence: docker run --network=host --rm ubercadence/cli:master --do test-domain workflow start --workflow_id "HelloQuery" --tasklist HelloWorldTaskList --workflow_type HelloWorld::sayHello --execution_timeout 3600 --input \\"World\\"\nStarted Workflow Id: HelloQuery, run Id: 1925f668-45b5-4405-8cba-74f7c68c3135\ncadence: docker run --network=host --rm ubercadence/cli:master --do test-domain workflow signal --workflow_id "HelloQuery" --name "HelloWorld::updateGreeting" --input \\"Hi\\"\nSignal workflow succeeded.\ncadence: docker run --network=host --rm ubercadence/cli:master --do test-domain workflow signal --workflow_id "HelloQuery" --name "HelloWorld::updateGreeting" --input \\"Welcome\\"\nSignal workflow succeeded.\n'})}),"\n",(0,o.jsx)(n.p,{children:"The worker output:"}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-bash",children:"17:35:50.485 [workflow-root] INFO c.u.c.samples.hello.GettingStarted - 1: Hello World!\n17:36:10.483 [workflow-root] INFO c.u.c.samples.hello.GettingStarted - 2: Hi World!\n17:36:16.204 [workflow-root] INFO c.u.c.samples.hello.GettingStarted - 3: Welcome World!\n"})}),"\n",(0,o.jsx)(n.p,{children:"Now let's query the workflow using the "}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-bash",children:'cadence: docker run --network=host --rm ubercadence/cli:master --do test-domain workflow query --workflow_id "HelloQuery" --query_type "HelloWorld::getCount"\n:query:Query: result as JSON:\n3\n'})}),"\n",(0,o.jsx)(n.p,{children:'One limitation of the query is that it requires a worker process running because it is executing callback code.\nAn interesting feature of the query is that it works for completed workflows as well. Let\'s complete the workflow by sending "Bye" and query it.'}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-bash",children:'cadence: docker run --network=host --rm ubercadence/cli:master --do test-domain workflow signal --workflow_id "HelloQuery" --name "HelloWorld::updateGreeting" --input \\"Bye\\"\nSignal workflow succeeded.\ncadence: docker run --network=host --rm ubercadence/cli:master --do test-domain workflow query --workflow_id "HelloQuery" --query_type "HelloWorld::getCount"\n:query:Query: result as JSON:\n4\n'})}),"\n",(0,o.jsx)(n.p,{children:"The Query method can accept parameters. This might be useful if only part of the workflow state should be returned."}),"\n",(0,o.jsx)(n.h2,{id:"run-query-from-external-application-code",children:"Run Query from external application code"}),"\n",(0,o.jsxs)(n.p,{children:["The ",(0,o.jsx)(n.a,{href:"https://www.javadoc.io/static/com.uber.cadence/cadence-client/2.7.9-alpha/com/cadence-workflow/cadence/client/WorkflowClient.html#newWorkflowStub-java.lang.Class-java.lang.String-",children:"WorkflowStub"})," without WorkflowOptions is for signal or ",(0,o.jsx)(n.a,{href:"/docs/java-client/queries",children:"query"})]}),"\n",(0,o.jsx)(n.h2,{id:"consistent-query",children:"Consistent Query"}),"\n",(0,o.jsx)(n.p,{children:"Query has two consistency levels, eventual and strong. Consider if you were to signal a workflow and then\nimmediately query the "}),"\n",(0,o.jsx)(n.p,{children:(0,o.jsx)(n.code,{children:"cadence-cli --domain samples-domain workflow signal -w my_workflow_id -r my_run_id -n signal_name -if ./input.json"})}),"\n",(0,o.jsx)(n.p,{children:(0,o.jsx)(n.code,{children:"cadence-cli --domain samples-domain workflow query -w my_workflow_id -r my_run_id -qt current_state"})}),"\n",(0,o.jsx)(n.p,{children:"In this example if signal were to change workflow state, query may or may not see that state update reflected\nin the query result. This is what it means for query to be eventually consistent."}),"\n",(0,o.jsx)(n.p,{children:"Query has another consistency level called strong consistency. A strongly consistent query is guaranteed\nto be based on workflow state which includes all events that came before the query was issued. An event\nis considered to have come before a query if the call creating the external event returned success before\nthe query was issued. External events which are created while the query is outstanding may or may not\nbe reflected in the workflow state the query result is based on."}),"\n",(0,o.jsx)(n.p,{children:"In order to run consistent query through the CLI do the following:"}),"\n",(0,o.jsx)(n.p,{children:(0,o.jsx)(n.code,{children:"cadence-cli --domain samples-domain workflow query -w my_workflow_id -r my_run_id -qt current_state --qcl strong"})}),"\n",(0,o.jsxs)(n.p,{children:["In order to run a query using application code, you need to use ",(0,o.jsx)(n.a,{href:"https://www.javadoc.io/doc/com.uber.cadence/cadence-client/latest/com/cadence-workflow/cadence/WorkflowService.Iface.html#SignalWorkflowExecution-com.uber.cadence.SignalWorkflowExecutionRequest-",children:"service client"}),"."]}),"\n",(0,o.jsx)(n.p,{children:"When using strongly consistent query you should expect higher latency than eventually consistent query."})]})}function u(e={}){const{wrapper:n}={...(0,a.R)(),...e.components};return n?(0,o.jsx)(n,{...e,children:(0,o.jsx)(d,{...e})}):d(e)}},8453:(e,n,t)=>{t.d(n,{R:()=>i,x:()=>l});var r=t(6540);const o={},a=r.createContext(o);function i(e){const n=r.useContext(a);return r.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function l(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:i(e.components),r.createElement(a.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/7a568d1f.7f4e451b.js b/assets/js/7a568d1f.7f4e451b.js deleted file mode 100644 index 7d7af1b58..000000000 --- a/assets/js/7a568d1f.7f4e451b.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[9699],{3915:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>s,contentTitle:()=>l,default:()=>u,frontMatter:()=>a,metadata:()=>r,toc:()=>c});const r=JSON.parse('{"id":"java-client/queries","title":"Queries","description":"Query is to expose this internal state to the external world Cadence provides a synchronous feature. From the implementer point of view the is exposed as a synchronous callback that is invoked by external entities. Multiple such callbacks can be provided per type exposing different information to different external systems.","source":"@site/docs/04-java-client/11-queries.md","sourceDirName":"04-java-client","slug":"/java-client/queries","permalink":"/docs/java-client/queries","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/04-java-client/11-queries.md","tags":[],"version":"current","sidebarPosition":11,"frontMatter":{"layout":"default","title":"Queries","permalink":"/docs/java-client/queries"},"sidebar":"docsSidebar","previous":{"title":"Signals","permalink":"/docs/java-client/signals"},"next":{"title":"Retries","permalink":"/docs/java-client/retries"}}');var o=t(4848),i=t(8453);const a={layout:"default",title:"Queries",permalink:"/docs/java-client/queries"},l="Queries",s={},c=[{value:"Built-in Query: Stack Trace",id:"built-in-query-stack-trace",level:2},{value:"Customized Query",id:"customized-query",level:2},{value:"Run Query from Command Line",id:"run-query-from-command-line",level:2},{value:"Run Query from external application code",id:"run-query-from-external-application-code",level:2},{value:"Consistent Query",id:"consistent-query",level:2}];function d(e){const n={a:"a",code:"code",h1:"h1",h2:"h2",header:"header",p:"p",pre:"pre",strong:"strong",...(0,i.R)(),...e.components};return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsx)(n.header,{children:(0,o.jsx)(n.h1,{id:"queries",children:"Queries"})}),"\n",(0,o.jsx)(n.p,{children:"Query is to expose this internal state to the external world Cadence provides a synchronous query feature. From the workflow implementer point of view the query is exposed as a synchronous callback that is invoked by external entities. Multiple such callbacks can be provided per workflow type exposing different information to different external systems."}),"\n",(0,o.jsx)(n.p,{children:"Query callbacks must be read-only not mutating the workflow state in any way. The other limitation is that the query callback cannot contain any blocking code. Both above limitations rule out ability to invoke activities from the query handlers."}),"\n",(0,o.jsx)(n.h2,{id:"built-in-query-stack-trace",children:"Built-in Query: Stack Trace"}),"\n",(0,o.jsx)(n.p,{children:"If a workflow_execution has been stuck at a state for longer than an expected period of time, you\nmight want to query the current call stack. You can use the Cadence CLI to perform this query. For\nexample:"}),"\n",(0,o.jsx)(n.p,{children:(0,o.jsx)(n.code,{children:"cadence-cli --domain samples-domain workflow query -w my_workflow_id -r my_run_id -qt __stack_trace"})}),"\n",(0,o.jsxs)(n.p,{children:["This command uses ",(0,o.jsx)(n.code,{children:"__stack_trace"}),", which is a built-in query type supported by the Cadence client\nlibrary. You can add custom query types to handle queries such as querying the current state of a\nworkflow, or querying how many activities the workflow has completed."]}),"\n",(0,o.jsx)(n.h2,{id:"customized-query",children:"Customized Query"}),"\n",(0,o.jsx)(n.p,{children:"Cadence provides a query feature that supports synchronously returning any information from a workflow to an external caller."}),"\n",(0,o.jsxs)(n.p,{children:["Interface ",(0,o.jsx)(n.a,{href:"https://www.javadoc.io/doc/com.uber.cadence/cadence-client/latest/com/cadence-workflow/cadence/workflow/QueryMethod.html",children:(0,o.jsx)(n.strong,{children:"QueryMethod"})})," indicates that the method is a query method. Query method can be used to query a workflow state by external process at any time during its execution. This annotation applies only to workflow interface methods."]}),"\n",(0,o.jsxs)(n.p,{children:["See the ",(0,o.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence-java-samples/blob/master/src/main/java/com/uber/cadence/samples/hello/HelloQuery.java",children:"workflow"})," example code :"]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-java",children:'public interface HelloWorld {\n @WorkflowMethod\n void sayHello(String name);\n\n @SignalMethod\n void updateGreeting(String greeting);\n\n @QueryMethod\n int getCount();\n}\n\npublic static class HelloWorldImpl implements HelloWorld {\n\n private String greeting = "Hello";\n private int count = 0;\n\n @Override\n public void sayHello(String name) {\n while (!"Bye".equals(greeting)) {\n logger.info(++count + ": " + greeting + " " + name + "!");\n String oldGreeting = greeting;\n Workflow.await(() -> !Objects.equals(greeting, oldGreeting));\n }\n logger.info(++count + ": " + greeting + " " + name + "!");\n }\n\n @Override\n public void updateGreeting(String greeting) {\n this.greeting = greeting;\n }\n\n @Override\n public int getCount() {\n return count;\n }\n}\n'})}),"\n",(0,o.jsxs)(n.p,{children:["The new ",(0,o.jsx)(n.code,{children:"getCount"})," method annotated with ",(0,o.jsx)(n.code,{children:"@QueryMethod"})," was added to the workflow interface definition. It is allowed\nto have multiple query methods per workflow interface."]}),"\n",(0,o.jsx)(n.p,{children:"The main restriction on the implementation of the query method is that it is not allowed to modify workflow state in any form.\nIt also is not allowed to block its thread in any way. It usually just returns a value derived from the fields of the workflow object."}),"\n",(0,o.jsx)(n.h2,{id:"run-query-from-command-line",children:"Run Query from Command Line"}),"\n",(0,o.jsx)(n.p,{children:"Let's run the updated worker and send a couple signals to it:"}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-bash",children:'cadence: docker run --network=host --rm ubercadence/cli:master --do test-domain workflow start --workflow_id "HelloQuery" --tasklist HelloWorldTaskList --workflow_type HelloWorld::sayHello --execution_timeout 3600 --input \\"World\\"\nStarted Workflow Id: HelloQuery, run Id: 1925f668-45b5-4405-8cba-74f7c68c3135\ncadence: docker run --network=host --rm ubercadence/cli:master --do test-domain workflow signal --workflow_id "HelloQuery" --name "HelloWorld::updateGreeting" --input \\"Hi\\"\nSignal workflow succeeded.\ncadence: docker run --network=host --rm ubercadence/cli:master --do test-domain workflow signal --workflow_id "HelloQuery" --name "HelloWorld::updateGreeting" --input \\"Welcome\\"\nSignal workflow succeeded.\n'})}),"\n",(0,o.jsx)(n.p,{children:"The worker output:"}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-bash",children:"17:35:50.485 [workflow-root] INFO c.u.c.samples.hello.GettingStarted - 1: Hello World!\n17:36:10.483 [workflow-root] INFO c.u.c.samples.hello.GettingStarted - 2: Hi World!\n17:36:16.204 [workflow-root] INFO c.u.c.samples.hello.GettingStarted - 3: Welcome World!\n"})}),"\n",(0,o.jsx)(n.p,{children:"Now let's query the workflow using the "}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-bash",children:'cadence: docker run --network=host --rm ubercadence/cli:master --do test-domain workflow query --workflow_id "HelloQuery" --query_type "HelloWorld::getCount"\n:query:Query: result as JSON:\n3\n'})}),"\n",(0,o.jsx)(n.p,{children:'One limitation of the query is that it requires a worker process running because it is executing callback code.\nAn interesting feature of the query is that it works for completed workflows as well. Let\'s complete the workflow by sending "Bye" and query it.'}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-bash",children:'cadence: docker run --network=host --rm ubercadence/cli:master --do test-domain workflow signal --workflow_id "HelloQuery" --name "HelloWorld::updateGreeting" --input \\"Bye\\"\nSignal workflow succeeded.\ncadence: docker run --network=host --rm ubercadence/cli:master --do test-domain workflow query --workflow_id "HelloQuery" --query_type "HelloWorld::getCount"\n:query:Query: result as JSON:\n4\n'})}),"\n",(0,o.jsx)(n.p,{children:"The Query method can accept parameters. This might be useful if only part of the workflow state should be returned."}),"\n",(0,o.jsx)(n.h2,{id:"run-query-from-external-application-code",children:"Run Query from external application code"}),"\n",(0,o.jsxs)(n.p,{children:["The ",(0,o.jsx)(n.a,{href:"https://www.javadoc.io/static/com.uber.cadence/cadence-client/2.7.9-alpha/com/cadence-workflow/cadence/client/WorkflowClient.html#newWorkflowStub-java.lang.Class-java.lang.String-",children:"WorkflowStub"})," without WorkflowOptions is for signal or ",(0,o.jsx)(n.a,{href:"/docs/java-client/queries",children:"query"})]}),"\n",(0,o.jsx)(n.h2,{id:"consistent-query",children:"Consistent Query"}),"\n",(0,o.jsx)(n.p,{children:"Query has two consistency levels, eventual and strong. Consider if you were to signal a workflow and then\nimmediately query the "}),"\n",(0,o.jsx)(n.p,{children:(0,o.jsx)(n.code,{children:"cadence-cli --domain samples-domain workflow signal -w my_workflow_id -r my_run_id -n signal_name -if ./input.json"})}),"\n",(0,o.jsx)(n.p,{children:(0,o.jsx)(n.code,{children:"cadence-cli --domain samples-domain workflow query -w my_workflow_id -r my_run_id -qt current_state"})}),"\n",(0,o.jsx)(n.p,{children:"In this example if signal were to change workflow state, query may or may not see that state update reflected\nin the query result. This is what it means for query to be eventually consistent."}),"\n",(0,o.jsx)(n.p,{children:"Query has another consistency level called strong consistency. A strongly consistent query is guaranteed\nto be based on workflow state which includes all events that came before the query was issued. An event\nis considered to have come before a query if the call creating the external event returned success before\nthe query was issued. External events which are created while the query is outstanding may or may not\nbe reflected in the workflow state the query result is based on."}),"\n",(0,o.jsx)(n.p,{children:"In order to run consistent query through the CLI do the following:"}),"\n",(0,o.jsx)(n.p,{children:(0,o.jsx)(n.code,{children:"cadence-cli --domain samples-domain workflow query -w my_workflow_id -r my_run_id -qt current_state --qcl strong"})}),"\n",(0,o.jsxs)(n.p,{children:["In order to run a query using application code, you need to use ",(0,o.jsx)(n.a,{href:"https://www.javadoc.io/doc/com.uber.cadence/cadence-client/latest/com/cadence-workflow/cadence/WorkflowService.Iface.html#SignalWorkflowExecution-com.uber.cadence.SignalWorkflowExecutionRequest-",children:"service client"}),"."]}),"\n",(0,o.jsx)(n.p,{children:"When using strongly consistent query you should expect higher latency than eventually consistent query."})]})}function u(e={}){const{wrapper:n}={...(0,i.R)(),...e.components};return n?(0,o.jsx)(n,{...e,children:(0,o.jsx)(d,{...e})}):d(e)}},8453:(e,n,t)=>{t.d(n,{R:()=>a,x:()=>l});var r=t(6540);const o={},i=r.createContext(o);function a(e){const n=r.useContext(i);return r.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function l(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:a(e.components),r.createElement(i.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/7afb0752.bdca23a0.js b/assets/js/7afb0752.bdca23a0.js new file mode 100644 index 000000000..617c54df3 --- /dev/null +++ b/assets/js/7afb0752.bdca23a0.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[8929],{861:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>c,contentTitle:()=>r,default:()=>d,frontMatter:()=>s,metadata:()=>a,toc:()=>l});var a=t(964),o=t(4848),i=t(8453);const s={title:"Cadence Community Spotlight Update - February 2023",date:new Date("2023-02-28T00:00:00.000Z"),authors:"sharanf",tags:["community-spotlight"]},r=void 0,c={authorsImageUrls:[void 0]},l=[{value:"Community Survey",id:"community-survey",level:2},{value:"Cadence and Temporal",id:"cadence-and-temporal",level:2},{value:"Cadence at DoorDash",id:"cadence-at-doordash",level:2},{value:"Cadence in the News!",id:"cadence-in-the-news",level:2},{value:"Upcoming Events",id:"upcoming-events",level:2}];function h(e){const n={a:"a",h2:"h2",li:"li",p:"p",ul:"ul",...(0,i.R)(),...e.components};return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsx)(n.p,{children:"Here\u2019s the latest in our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!"}),"\n",(0,o.jsx)(n.p,{children:"Please see below for a roundup of the highlights:"}),"\n",(0,o.jsx)(n.h2,{id:"community-survey",children:"Community Survey"}),"\n",(0,o.jsx)(n.p,{children:"We've been talking about doing a community survey for a while and during February we sent it out. We are still collating the results so it's not too late to send in your response."}),"\n",(0,o.jsx)(n.p,{children:"The survey takes 5 minutes and is your opportunity to provide feedback to the project and highlight areas you think we need to focus on."}),"\n",(0,o.jsxs)(n.p,{children:["Use this ",(0,o.jsx)(n.a,{href:"https://uber.surveymonkey.com/r/ZS83WJW",children:"Survey Link"})]}),"\n",(0,o.jsx)(n.p,{children:"Please take a few minutes to give us your opinion."}),"\n",(0,o.jsx)(n.h2,{id:"cadence-and-temporal",children:"Cadence and Temporal"}),"\n",(0,o.jsxs)(n.p,{children:["During user surveys we've had a few queries about whether Cadence and ",(0,o.jsx)(n.a,{href:"https://temporal.io/",children:"Temporal"})," are the same project. The answer is No - they are not the same project but they do share the same origin. At a high level Temporal is a fork of the Cadence project. Both Temporal and Cadence are now being developed by different communities so are independent."]}),"\n",(0,o.jsx)(n.h2,{id:"cadence-at-doordash",children:"Cadence at DoorDash"}),"\n",(0,o.jsxs)(n.p,{children:["Although published a few months ago we missed including an article by ",(0,o.jsx)(n.a,{href:"https://doordash.engineering/",children:"DoorDash"})," about how they are using Cadence to build real time event processing with ",(0,o.jsx)(n.a,{href:"https://flink.apache.org/",children:"Apache Flink"})," and ",(0,o.jsx)(n.a,{href:"https://kafka.apache.org/",children:"Apache Kafka"}),"."]}),"\n",(0,o.jsxs)(n.p,{children:["Here is the link to the article: ",(0,o.jsx)(n.a,{href:"https://doordash.engineering/2022/08/02/building-scalable-real-time-event-processing-with-kafka-and-flink/",children:"Building Scalable Real Time Event Processing with Kafka and Flink"})]}),"\n",(0,o.jsx)(n.p,{children:"Remember to let us know if you have news, articles or blog posts about Cadence that you'd like us to include in these monthly updates."}),"\n",(0,o.jsx)(n.h2,{id:"cadence-in-the-news",children:"Cadence in the News!"}),"\n",(0,o.jsx)(n.p,{children:"Below are a selection of Cadence related articles, blogs and whitepapers. Please take a look and feel free to share via your own social media channels."}),"\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsxs)(n.li,{children:["\n",(0,o.jsx)(n.p,{children:(0,o.jsx)(n.a,{href:"https://opensource.com/article/22/6/cadence-open-source-workflow-engine",children:"Getting Started with Cadence, an Open Source Workflow Engine"})}),"\n"]}),"\n",(0,o.jsxs)(n.li,{children:["\n",(0,o.jsx)(n.p,{children:(0,o.jsx)(n.a,{href:"https://thenewstack.io/meet-cadence-workflow-engine-for-taming-complex-processes/",children:"Meet Cadence: Workflow Engine for Taming Complex Processes"})}),"\n"]}),"\n"]}),"\n",(0,o.jsx)(n.h2,{id:"upcoming-events",children:"Upcoming Events"}),"\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsx)(n.li,{children:(0,o.jsx)(n.a,{href:"https://info.instaclustr.com/webinar-spinning-drones-cadence-kafka.html",children:"On Demand Webinar: Spinning Your Drones with Cadence and Apache Kafka"})}),"\n"]}),"\n",(0,o.jsxs)(n.p,{children:["If you have any news or topics you'd like us to include in our next update then please join our ",(0,o.jsx)(n.a,{href:"http://t.uber.com/cadence-slack",children:"Slack"}),"#community channel."]}),"\n",(0,o.jsxs)(n.p,{children:["Please remember that this update is for you - so if you have any comments or feedback that could help us improve it then please share it with us in the #community ",(0,o.jsx)(n.a,{href:"http://t.uber.com/cadence-slack",children:"Slack"})," channel."]})]})}function d(e={}){const{wrapper:n}={...(0,i.R)(),...e.components};return n?(0,o.jsx)(n,{...e,children:(0,o.jsx)(h,{...e})}):h(e)}},8453:(e,n,t)=>{t.d(n,{R:()=>s,x:()=>r});var a=t(6540);const o={},i=a.createContext(o);function s(e){const n=a.useContext(i);return a.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function r(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:s(e.components),a.createElement(i.Provider,{value:n},e.children)}},964:e=>{e.exports=JSON.parse('{"permalink":"/Cadence-Docs/blog/2023/02/28/community-spotlight-february","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2023-02-28-community-spotlight-february.md","source":"@site/blog/2023-02-28-community-spotlight-february.md","title":"Cadence Community Spotlight Update - February 2023","description":"Here\u2019s the latest in our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!","date":"2023-02-28T00:00:00.000Z","tags":[{"inline":false,"label":"Community Spotlight","permalink":"/Cadence-Docs/blog/tags/community-spotlights","description":"Community Spotlight tag description"}],"readingTime":1.875,"hasTruncateMarker":true,"authors":[{"name":"Sharan Foga","title":"Director of Operations & Customer Success @ Encube Technologies","url":"https://www.linkedin.com/in/sfoga/","page":{"permalink":"/Cadence-Docs/blog/authors/sharanf"},"socials":{"linkedin":"https://www.linkedin.com/in/sfoga/","github":"https://github.com/sharanf"},"imageURL":"https://github.com/sharanf.png","key":"sharanf"}],"frontMatter":{"title":"Cadence Community Spotlight Update - February 2023","date":"2023-02-28T00:00:00.000Z","authors":"sharanf","tags":["community-spotlight"]},"unlisted":false,"prevItem":{"title":"Cadence Community Spotlight Update - March 2024","permalink":"/Cadence-Docs/blog/2024/3/11/community-spotlight-update-march-2024"},"nextItem":{"title":"Cadence Community Spotlight Update - January 2023","permalink":"/Cadence-Docs/blog/2023/01/31/community-spotlight-january-2023"}}')}}]); \ No newline at end of file diff --git a/assets/js/7afb0752.eb7eb3f1.js b/assets/js/7afb0752.eb7eb3f1.js deleted file mode 100644 index f34f0d1ed..000000000 --- a/assets/js/7afb0752.eb7eb3f1.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[8929],{861:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>l,contentTitle:()=>r,default:()=>d,frontMatter:()=>s,metadata:()=>a,toc:()=>c});var a=t(964),i=t(4848),o=t(8453);const s={title:"Cadence Community Spotlight Update - February 2023",date:new Date("2023-02-28T00:00:00.000Z"),authors:"sharanf",tags:["community-spotlight"]},r=void 0,l={authorsImageUrls:[void 0]},c=[{value:"Community Survey",id:"community-survey",level:2},{value:"Cadence and Temporal",id:"cadence-and-temporal",level:2},{value:"Cadence at DoorDash",id:"cadence-at-doordash",level:2},{value:"Cadence in the News!",id:"cadence-in-the-news",level:2},{value:"Upcoming Events",id:"upcoming-events",level:2}];function h(e){const n={a:"a",h2:"h2",li:"li",p:"p",ul:"ul",...(0,o.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.p,{children:"Here\u2019s the latest in our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!"}),"\n",(0,i.jsx)(n.p,{children:"Please see below for a roundup of the highlights:"}),"\n",(0,i.jsx)(n.h2,{id:"community-survey",children:"Community Survey"}),"\n",(0,i.jsx)(n.p,{children:"We've been talking about doing a community survey for a while and during February we sent it out. We are still collating the results so it's not too late to send in your response."}),"\n",(0,i.jsx)(n.p,{children:"The survey takes 5 minutes and is your opportunity to provide feedback to the project and highlight areas you think we need to focus on."}),"\n",(0,i.jsxs)(n.p,{children:["Use this ",(0,i.jsx)(n.a,{href:"https://uber.surveymonkey.com/r/ZS83WJW",children:"Survey Link"})]}),"\n",(0,i.jsx)(n.p,{children:"Please take a few minutes to give us your opinion."}),"\n",(0,i.jsx)(n.h2,{id:"cadence-and-temporal",children:"Cadence and Temporal"}),"\n",(0,i.jsxs)(n.p,{children:["During user surveys we've had a few queries about whether Cadence and ",(0,i.jsx)(n.a,{href:"https://temporal.io/",children:"Temporal"})," are the same project. The answer is No - they are not the same project but they do share the same origin. At a high level Temporal is a fork of the Cadence project. Both Temporal and Cadence are now being developed by different communities so are independent."]}),"\n",(0,i.jsx)(n.h2,{id:"cadence-at-doordash",children:"Cadence at DoorDash"}),"\n",(0,i.jsxs)(n.p,{children:["Although published a few months ago we missed including an article by ",(0,i.jsx)(n.a,{href:"https://doordash.engineering/",children:"DoorDash"})," about how they are using Cadence to build real time event processing with ",(0,i.jsx)(n.a,{href:"https://flink.apache.org/",children:"Apache Flink"})," and ",(0,i.jsx)(n.a,{href:"https://kafka.apache.org/",children:"Apache Kafka"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["Here is the link to the article: ",(0,i.jsx)(n.a,{href:"https://doordash.engineering/2022/08/02/building-scalable-real-time-event-processing-with-kafka-and-flink/",children:"Building Scalable Real Time Event Processing with Kafka and Flink"})]}),"\n",(0,i.jsx)(n.p,{children:"Remember to let us know if you have news, articles or blog posts about Cadence that you'd like us to include in these monthly updates."}),"\n",(0,i.jsx)(n.h2,{id:"cadence-in-the-news",children:"Cadence in the News!"}),"\n",(0,i.jsx)(n.p,{children:"Below are a selection of Cadence related articles, blogs and whitepapers. Please take a look and feel free to share via your own social media channels."}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://opensource.com/article/22/6/cadence-open-source-workflow-engine",children:"Getting Started with Cadence, an Open Source Workflow Engine"})}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://thenewstack.io/meet-cadence-workflow-engine-for-taming-complex-processes/",children:"Meet Cadence: Workflow Engine for Taming Complex Processes"})}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.h2,{id:"upcoming-events",children:"Upcoming Events"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"https://info.instaclustr.com/webinar-spinning-drones-cadence-kafka.html",children:"On Demand Webinar: Spinning Your Drones with Cadence and Apache Kafka"})}),"\n"]}),"\n",(0,i.jsxs)(n.p,{children:["If you have any news or topics you'd like us to include in our next update then please join our ",(0,i.jsx)(n.a,{href:"http://t.uber.com/cadence-slack",children:"Slack"}),"#community channel."]}),"\n",(0,i.jsxs)(n.p,{children:["Please remember that this update is for you - so if you have any comments or feedback that could help us improve it then please share it with us in the #community ",(0,i.jsx)(n.a,{href:"http://t.uber.com/cadence-slack",children:"Slack"})," channel."]})]})}function d(e={}){const{wrapper:n}={...(0,o.R)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(h,{...e})}):h(e)}},8453:(e,n,t)=>{t.d(n,{R:()=>s,x:()=>r});var a=t(6540);const i={},o=a.createContext(i);function s(e){const n=a.useContext(o);return a.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function r(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:s(e.components),a.createElement(o.Provider,{value:n},e.children)}},964:e=>{e.exports=JSON.parse('{"permalink":"/blog/2023/02/28/community-spotlight-february","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2023-02-28-community-spotlight-february.md","source":"@site/blog/2023-02-28-community-spotlight-february.md","title":"Cadence Community Spotlight Update - February 2023","description":"Here\u2019s the latest in our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!","date":"2023-02-28T00:00:00.000Z","tags":[{"inline":false,"label":"Community Spotlight","permalink":"/blog/tags/community-spotlights","description":"Community Spotlight tag description"}],"readingTime":1.875,"hasTruncateMarker":true,"authors":[{"name":"Sharan Foga","title":"Director of Operations & Customer Success @ Encube Technologies","url":"https://www.linkedin.com/in/sfoga/","page":{"permalink":"/blog/authors/sharanf"},"socials":{"linkedin":"https://www.linkedin.com/in/sfoga/","github":"https://github.com/sharanf"},"imageURL":"https://github.com/sharanf.png","key":"sharanf"}],"frontMatter":{"title":"Cadence Community Spotlight Update - February 2023","date":"2023-02-28T00:00:00.000Z","authors":"sharanf","tags":["community-spotlight"]},"unlisted":false,"prevItem":{"title":"Cadence Community Spotlight Update - March 2024","permalink":"/blog/2024/3/11/community-spotlight-update-march-2024"},"nextItem":{"title":"Cadence Community Spotlight Update - January 2023","permalink":"/blog/2023/01/31/community-spotlight-january-2023"}}')}}]); \ No newline at end of file diff --git a/assets/js/7d996443.742a8a61.js b/assets/js/7d996443.742a8a61.js new file mode 100644 index 000000000..b7af33573 --- /dev/null +++ b/assets/js/7d996443.742a8a61.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[3685],{6611:(e,t,i)=>{i.r(t),i.d(t,{assets:()=>c,contentTitle:()=>a,default:()=>h,frontMatter:()=>s,metadata:()=>r,toc:()=>l});const r=JSON.parse('{"id":"workflow-troubleshooting/activity-failures","title":"Activity Failures","description":"An activity fails when it encounters an error during its execution. This results in ActivityTaskFailed event in the workflow execution with some details of the error. The different kinds of errors that can be seen in activity failures are listed here.","source":"@site/docs/08-workflow-troubleshooting/02-activity-failures.md","sourceDirName":"08-workflow-troubleshooting","slug":"/workflow-troubleshooting/activity-failures","permalink":"/Cadence-Docs/docs/workflow-troubleshooting/activity-failures","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/08-workflow-troubleshooting/02-activity-failures.md","tags":[],"version":"current","sidebarPosition":2,"frontMatter":{"layout":"default","title":"Activity Failures","permalink":"/docs/workflow-troubleshooting/activity-failures"},"sidebar":"docsSidebar","previous":{"title":"Timeouts","permalink":"/Cadence-Docs/docs/workflow-troubleshooting/timeouts"},"next":{"title":"Retries","permalink":"/Cadence-Docs/docs/workflow-troubleshooting/retries"}}');var o=i(4848),n=i(8453);const s={layout:"default",title:"Activity Failures",permalink:"/docs/workflow-troubleshooting/activity-failures"},a="Activity failures",c={},l=[{value:"Panic errors",id:"panic-errors",level:2},{value:"Custom errors",id:"custom-errors",level:2},{value:"Generic errors",id:"generic-errors",level:2}];function d(e){const t={a:"a",h1:"h1",h2:"h2",header:"header",p:"p",...(0,n.R)(),...e.components};return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsx)(t.header,{children:(0,o.jsx)(t.h1,{id:"activity-failures",children:"Activity failures"})}),"\n",(0,o.jsx)(t.p,{children:"An activity fails when it encounters an error during its execution. This results in ActivityTaskFailed event in the workflow execution with some details of the error. The different kinds of errors that can be seen in activity failures are listed here."}),"\n",(0,o.jsx)(t.h2,{id:"panic-errors",children:"Panic errors"}),"\n",(0,o.jsx)(t.p,{children:"Description: There is a issue in the activity code that is causing a panic."}),"\n",(0,o.jsx)(t.p,{children:"Mitigation: Panics are usually caused by nil pointer dereferences or out-of-range array access and should never be expected in a workflow. Check the stack trace provided in the error details to find where in the activity code, the panic is seen. Fix the rootcause of the panic."}),"\n",(0,o.jsx)(t.h2,{id:"custom-errors",children:"Custom errors"}),"\n",(0,o.jsx)(t.p,{children:"Description: This is a customised error returned by the activity."}),"\n",(0,o.jsx)(t.p,{children:"Mitigation: This is a way of facilitating error handling done within the activity code. Check your activity code to find where it returns a NewCustomError with some information. This is ideally an expected error scenario and should be handled within the workflow that executed the activity."}),"\n",(0,o.jsxs)(t.p,{children:["Read more about ",(0,o.jsx)(t.a,{href:"https://cadenceworkflow.io/docs/go-client/error-handling/",children:"error handling"})]}),"\n",(0,o.jsx)(t.h2,{id:"generic-errors",children:"Generic errors"}),"\n",(0,o.jsx)(t.p,{children:"Description: This is an error returned by the activity."}),"\n",(0,o.jsx)(t.p,{children:"Mitigation: This error is caused by something unexpected within the activity code, typically due to a downstream service that your activity communicates with. Cadence does not know anything about it and just puts all unknown errors in this category. Check your activity code to find the potential error cases. This is ideally an unexpected error scenario and should be debugged further to fix the rootcause."}),"\n",(0,o.jsxs)(t.p,{children:["Read more about ",(0,o.jsx)(t.a,{href:"https://cadenceworkflow.io/docs/go-client/error-handling/",children:"error handling"})]})]})}function h(e={}){const{wrapper:t}={...(0,n.R)(),...e.components};return t?(0,o.jsx)(t,{...e,children:(0,o.jsx)(d,{...e})}):d(e)}},8453:(e,t,i)=>{i.d(t,{R:()=>s,x:()=>a});var r=i(6540);const o={},n=r.createContext(o);function s(e){const t=r.useContext(n);return r.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function a(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:s(e.components),r.createElement(n.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/7d996443.a20315dc.js b/assets/js/7d996443.a20315dc.js deleted file mode 100644 index 62c28d1df..000000000 --- a/assets/js/7d996443.a20315dc.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[3685],{6611:(e,t,i)=>{i.r(t),i.d(t,{assets:()=>c,contentTitle:()=>a,default:()=>h,frontMatter:()=>s,metadata:()=>r,toc:()=>l});const r=JSON.parse('{"id":"workflow-troubleshooting/activity-failures","title":"Activity Failures","description":"An activity fails when it encounters an error during its execution. This results in ActivityTaskFailed event in the workflow execution with some details of the error. The different kinds of errors that can be seen in activity failures are listed here.","source":"@site/docs/08-workflow-troubleshooting/02-activity-failures.md","sourceDirName":"08-workflow-troubleshooting","slug":"/workflow-troubleshooting/activity-failures","permalink":"/docs/workflow-troubleshooting/activity-failures","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/08-workflow-troubleshooting/02-activity-failures.md","tags":[],"version":"current","sidebarPosition":2,"frontMatter":{"layout":"default","title":"Activity Failures","permalink":"/docs/workflow-troubleshooting/activity-failures"},"sidebar":"docsSidebar","previous":{"title":"Timeouts","permalink":"/docs/workflow-troubleshooting/timeouts"},"next":{"title":"Retries","permalink":"/docs/workflow-troubleshooting/retries"}}');var o=i(4848),n=i(8453);const s={layout:"default",title:"Activity Failures",permalink:"/docs/workflow-troubleshooting/activity-failures"},a="Activity failures",c={},l=[{value:"Panic errors",id:"panic-errors",level:2},{value:"Custom errors",id:"custom-errors",level:2},{value:"Generic errors",id:"generic-errors",level:2}];function d(e){const t={a:"a",h1:"h1",h2:"h2",header:"header",p:"p",...(0,n.R)(),...e.components};return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsx)(t.header,{children:(0,o.jsx)(t.h1,{id:"activity-failures",children:"Activity failures"})}),"\n",(0,o.jsx)(t.p,{children:"An activity fails when it encounters an error during its execution. This results in ActivityTaskFailed event in the workflow execution with some details of the error. The different kinds of errors that can be seen in activity failures are listed here."}),"\n",(0,o.jsx)(t.h2,{id:"panic-errors",children:"Panic errors"}),"\n",(0,o.jsx)(t.p,{children:"Description: There is a issue in the activity code that is causing a panic."}),"\n",(0,o.jsx)(t.p,{children:"Mitigation: Panics are usually caused by nil pointer dereferences or out-of-range array access and should never be expected in a workflow. Check the stack trace provided in the error details to find where in the activity code, the panic is seen. Fix the rootcause of the panic."}),"\n",(0,o.jsx)(t.h2,{id:"custom-errors",children:"Custom errors"}),"\n",(0,o.jsx)(t.p,{children:"Description: This is a customised error returned by the activity."}),"\n",(0,o.jsx)(t.p,{children:"Mitigation: This is a way of facilitating error handling done within the activity code. Check your activity code to find where it returns a NewCustomError with some information. This is ideally an expected error scenario and should be handled within the workflow that executed the activity."}),"\n",(0,o.jsxs)(t.p,{children:["Read more about ",(0,o.jsx)(t.a,{href:"https://cadenceworkflow.io/docs/go-client/error-handling/",children:"error handling"})]}),"\n",(0,o.jsx)(t.h2,{id:"generic-errors",children:"Generic errors"}),"\n",(0,o.jsx)(t.p,{children:"Description: This is an error returned by the activity."}),"\n",(0,o.jsx)(t.p,{children:"Mitigation: This error is caused by something unexpected within the activity code, typically due to a downstream service that your activity communicates with. Cadence does not know anything about it and just puts all unknown errors in this category. Check your activity code to find the potential error cases. This is ideally an unexpected error scenario and should be debugged further to fix the rootcause."}),"\n",(0,o.jsxs)(t.p,{children:["Read more about ",(0,o.jsx)(t.a,{href:"https://cadenceworkflow.io/docs/go-client/error-handling/",children:"error handling"})]})]})}function h(e={}){const{wrapper:t}={...(0,n.R)(),...e.components};return t?(0,o.jsx)(t,{...e,children:(0,o.jsx)(d,{...e})}):d(e)}},8453:(e,t,i)=>{i.d(t,{R:()=>s,x:()=>a});var r=i(6540);const o={},n=r.createContext(o);function s(e){const t=r.useContext(n);return r.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function a(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:s(e.components),r.createElement(n.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/7f8511d4.df3eb1df.js b/assets/js/7f8511d4.df3eb1df.js deleted file mode 100644 index 5ce88318d..000000000 --- a/assets/js/7f8511d4.df3eb1df.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[8363],{84:(e,n,s)=>{s.r(n),s.d(n,{assets:()=>i,contentTitle:()=>c,default:()=>h,frontMatter:()=>a,metadata:()=>r,toc:()=>l});const r=JSON.parse('{"id":"get-started/server-installation","title":"Server Installation","description":"To get started with Cadence, you need to set up three components successfully.","source":"@site/docs/01-get-started/01-server-installation.md","sourceDirName":"01-get-started","slug":"/get-started/server-installation","permalink":"/docs/get-started/server-installation","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/01-get-started/01-server-installation.md","tags":[],"version":"current","sidebarPosition":1,"frontMatter":{"layout":"default","title":"Server Installation","permalink":"/docs/get-started/installation"},"sidebar":"docsSidebar","previous":{"title":"Overview","permalink":"/docs/get-started/"},"next":{"title":"Java hello world","permalink":"/docs/get-started/java-hello-world"}}');var t=s(4848),o=s(8453);const a={layout:"default",title:"Server Installation",permalink:"/docs/get-started/installation"},c="Install Cadence Service Locally",i={},l=[{value:"0. Prerequisite - Install docker",id:"0-prerequisite---install-docker",level:2},{value:"1. Run Cadence Server Using Docker Compose",id:"1-run-cadence-server-using-docker-compose",level:2},{value:"2. Register a Domain Using the CLI",id:"2-register-a-domain-using-the-cli",level:2},{value:"What's Next",id:"whats-next",level:2},{value:"Troubleshooting",id:"troubleshooting",level:2}];function d(e){const n={a:"a",code:"code",h1:"h1",h2:"h2",header:"header",li:"li",p:"p",pre:"pre",ul:"ul",...(0,o.R)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.header,{children:(0,t.jsx)(n.h1,{id:"install-cadence-service-locally",children:"Install Cadence Service Locally"})}),"\n",(0,t.jsx)(n.p,{children:"To get started with Cadence, you need to set up three components successfully."}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"A Cadence server hosting dependencies that Cadence relies on such as Cassandra, Elastic Search, etc"}),"\n",(0,t.jsx)(n.li,{children:"A Cadence domain for you workflow application"}),"\n",(0,t.jsx)(n.li,{children:"A Cadence worker service hosting your workflows"}),"\n"]}),"\n",(0,t.jsx)(n.h2,{id:"0-prerequisite---install-docker",children:"0. Prerequisite - Install docker"}),"\n",(0,t.jsxs)(n.p,{children:["Follow the Docker installation instructions found here: ",(0,t.jsx)(n.a,{href:"https://docs.docker.com/engine/installation/",children:"https://docs.docker.com/engine/installation/"})]}),"\n",(0,t.jsx)(n.h2,{id:"1-run-cadence-server-using-docker-compose",children:"1. Run Cadence Server Using Docker Compose"}),"\n",(0,t.jsx)(n.p,{children:"Download the Cadence docker-compose file:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-bash",children:"curl -O https://raw.githubusercontent.com/cadence-workflow/cadence/master/docker/docker-compose.yml && curl -O https://raw.githubusercontent.com/cadence-workflow/cadence/master/docker/prometheus/prometheus.yml\n"})}),"\n",(0,t.jsx)(n.p,{children:"Then start Cadence Service by running:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-bash",children:"docker-compose up\n"})}),"\n",(0,t.jsx)(n.p,{children:"Please keep this process running at background."}),"\n",(0,t.jsx)(n.h2,{id:"2-register-a-domain-using-the-cli",children:"2. Register a Domain Using the CLI"}),"\n",(0,t.jsxs)(n.p,{children:["In a new terminal, create a new domain called ",(0,t.jsx)(n.code,{children:"test-domain"})," (or choose whatever name you like) by running:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-bash",children:"docker run --network=host --rm ubercadence/cli:master --do test-domain domain register -rd 1\n"})}),"\n",(0,t.jsx)(n.p,{children:"Check that the domain is indeed registered:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-shell-session",children:"$ docker run --network=host --rm ubercadence/cli:master --do test-domain domain describe\nName: test-domain\nDescription:\nOwnerEmail:\nDomainData: map[]\nStatus: REGISTERED\nRetentionInDays: 1\nEmitMetrics: false\nActiveClusterName: active\nClusters: active\nArchivalStatus: DISABLED\nBad binaries to reset:\n+-----------------+----------+------------+--------+\n| BINARY CHECKSUM | OPERATOR | START TIME | REASON |\n+-----------------+----------+------------+--------+\n+-----------------+----------+------------+--------+\n$\n"})}),"\n",(0,t.jsx)(n.p,{children:"Please remember the domains you created because they will be used in your worker implementation and Cadence CLI commands."}),"\n",(0,t.jsx)(n.h2,{id:"whats-next",children:"What's Next"}),"\n",(0,t.jsx)(n.p,{children:"So far you've successfully finished two prerequisites to your Cadence application. The next steps are to implement a simple worker service that hosts your workflows and to run your very first hello world Cadence workflow."}),"\n",(0,t.jsxs)(n.p,{children:["Go to ",(0,t.jsx)(n.a,{href:"/docs/get-started/java-hello-world",children:"Java HelloWorld"})," or ",(0,t.jsx)(n.a,{href:"/docs/get-started/golang-hello-world",children:"Golang HelloWorld"}),"."]}),"\n",(0,t.jsx)(n.h2,{id:"troubleshooting",children:"Troubleshooting"}),"\n",(0,t.jsxs)(n.p,{children:["There can be various reasons that ",(0,t.jsx)(n.code,{children:"docker-compose up"})," cannot succeed:"]}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:["In case of the image being too old, update the docker image by ",(0,t.jsx)(n.code,{children:"docker pull ubercadence/server:master-auto-setup"})," and retry"]}),"\n",(0,t.jsxs)(n.li,{children:["In case of the local docker env is messed up: ",(0,t.jsx)(n.code,{children:"docker system prune --all"})," and retry (see ",(0,t.jsx)(n.a,{href:"https://docs.docker.com/config/pruning/",children:"details about it"})," )"]}),"\n",(0,t.jsxs)(n.li,{children:["See logs of different container:","\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:["If Cassandra is not able to get up: ",(0,t.jsx)(n.code,{children:"docker logs -f docker_cassandra_1"})]}),"\n",(0,t.jsxs)(n.li,{children:["If Cadence is not able to get up: ",(0,t.jsx)(n.code,{children:"docker logs -f docker_cadence_1"})]}),"\n",(0,t.jsxs)(n.li,{children:["If Cadence Web is not able to get up: ",(0,t.jsx)(n.code,{children:"docker logs -f docker_cadence-web_1"})]}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,t.jsxs)(n.p,{children:["If the above is still not working, ",(0,t.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence/issues/new/choose",children:"open an issue in Server(main) repo"}),"."]})]})}function h(e={}){const{wrapper:n}={...(0,o.R)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(d,{...e})}):d(e)}},8453:(e,n,s)=>{s.d(n,{R:()=>a,x:()=>c});var r=s(6540);const t={},o=r.createContext(t);function a(e){const n=r.useContext(o);return r.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function c(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(t):e.components||t:a(e.components),r.createElement(o.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/7f8511d4.fe265c26.js b/assets/js/7f8511d4.fe265c26.js new file mode 100644 index 000000000..6b74fd79a --- /dev/null +++ b/assets/js/7f8511d4.fe265c26.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[8363],{84:(e,n,s)=>{s.r(n),s.d(n,{assets:()=>i,contentTitle:()=>c,default:()=>h,frontMatter:()=>a,metadata:()=>r,toc:()=>l});const r=JSON.parse('{"id":"get-started/server-installation","title":"Server Installation","description":"To get started with Cadence, you need to set up three components successfully.","source":"@site/docs/01-get-started/01-server-installation.md","sourceDirName":"01-get-started","slug":"/get-started/server-installation","permalink":"/Cadence-Docs/docs/get-started/server-installation","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/01-get-started/01-server-installation.md","tags":[],"version":"current","sidebarPosition":1,"frontMatter":{"layout":"default","title":"Server Installation","permalink":"/docs/get-started/installation"},"sidebar":"docsSidebar","previous":{"title":"Overview","permalink":"/Cadence-Docs/docs/get-started/"},"next":{"title":"Java hello world","permalink":"/Cadence-Docs/docs/get-started/java-hello-world"}}');var t=s(4848),o=s(8453);const a={layout:"default",title:"Server Installation",permalink:"/docs/get-started/installation"},c="Install Cadence Service Locally",i={},l=[{value:"0. Prerequisite - Install docker",id:"0-prerequisite---install-docker",level:2},{value:"1. Run Cadence Server Using Docker Compose",id:"1-run-cadence-server-using-docker-compose",level:2},{value:"2. Register a Domain Using the CLI",id:"2-register-a-domain-using-the-cli",level:2},{value:"What's Next",id:"whats-next",level:2},{value:"Troubleshooting",id:"troubleshooting",level:2}];function d(e){const n={a:"a",code:"code",h1:"h1",h2:"h2",header:"header",li:"li",p:"p",pre:"pre",ul:"ul",...(0,o.R)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.header,{children:(0,t.jsx)(n.h1,{id:"install-cadence-service-locally",children:"Install Cadence Service Locally"})}),"\n",(0,t.jsx)(n.p,{children:"To get started with Cadence, you need to set up three components successfully."}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"A Cadence server hosting dependencies that Cadence relies on such as Cassandra, Elastic Search, etc"}),"\n",(0,t.jsx)(n.li,{children:"A Cadence domain for you workflow application"}),"\n",(0,t.jsx)(n.li,{children:"A Cadence worker service hosting your workflows"}),"\n"]}),"\n",(0,t.jsx)(n.h2,{id:"0-prerequisite---install-docker",children:"0. Prerequisite - Install docker"}),"\n",(0,t.jsxs)(n.p,{children:["Follow the Docker installation instructions found here: ",(0,t.jsx)(n.a,{href:"https://docs.docker.com/engine/installation/",children:"https://docs.docker.com/engine/installation/"})]}),"\n",(0,t.jsx)(n.h2,{id:"1-run-cadence-server-using-docker-compose",children:"1. Run Cadence Server Using Docker Compose"}),"\n",(0,t.jsx)(n.p,{children:"Download the Cadence docker-compose file:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-bash",children:"curl -O https://raw.githubusercontent.com/cadence-workflow/cadence/master/docker/docker-compose.yml && curl -O https://raw.githubusercontent.com/cadence-workflow/cadence/master/docker/prometheus/prometheus.yml\n"})}),"\n",(0,t.jsx)(n.p,{children:"Then start Cadence Service by running:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-bash",children:"docker-compose up\n"})}),"\n",(0,t.jsx)(n.p,{children:"Please keep this process running at background."}),"\n",(0,t.jsx)(n.h2,{id:"2-register-a-domain-using-the-cli",children:"2. Register a Domain Using the CLI"}),"\n",(0,t.jsxs)(n.p,{children:["In a new terminal, create a new domain called ",(0,t.jsx)(n.code,{children:"test-domain"})," (or choose whatever name you like) by running:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-bash",children:"docker run --network=host --rm ubercadence/cli:master --do test-domain domain register -rd 1\n"})}),"\n",(0,t.jsx)(n.p,{children:"Check that the domain is indeed registered:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-shell-session",children:"$ docker run --network=host --rm ubercadence/cli:master --do test-domain domain describe\nName: test-domain\nDescription:\nOwnerEmail:\nDomainData: map[]\nStatus: REGISTERED\nRetentionInDays: 1\nEmitMetrics: false\nActiveClusterName: active\nClusters: active\nArchivalStatus: DISABLED\nBad binaries to reset:\n+-----------------+----------+------------+--------+\n| BINARY CHECKSUM | OPERATOR | START TIME | REASON |\n+-----------------+----------+------------+--------+\n+-----------------+----------+------------+--------+\n$\n"})}),"\n",(0,t.jsx)(n.p,{children:"Please remember the domains you created because they will be used in your worker implementation and Cadence CLI commands."}),"\n",(0,t.jsx)(n.h2,{id:"whats-next",children:"What's Next"}),"\n",(0,t.jsx)(n.p,{children:"So far you've successfully finished two prerequisites to your Cadence application. The next steps are to implement a simple worker service that hosts your workflows and to run your very first hello world Cadence workflow."}),"\n",(0,t.jsxs)(n.p,{children:["Go to ",(0,t.jsx)(n.a,{href:"/docs/get-started/java-hello-world",children:"Java HelloWorld"})," or ",(0,t.jsx)(n.a,{href:"/docs/get-started/golang-hello-world",children:"Golang HelloWorld"}),"."]}),"\n",(0,t.jsx)(n.h2,{id:"troubleshooting",children:"Troubleshooting"}),"\n",(0,t.jsxs)(n.p,{children:["There can be various reasons that ",(0,t.jsx)(n.code,{children:"docker-compose up"})," cannot succeed:"]}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:["In case of the image being too old, update the docker image by ",(0,t.jsx)(n.code,{children:"docker pull ubercadence/server:master-auto-setup"})," and retry"]}),"\n",(0,t.jsxs)(n.li,{children:["In case of the local docker env is messed up: ",(0,t.jsx)(n.code,{children:"docker system prune --all"})," and retry (see ",(0,t.jsx)(n.a,{href:"https://docs.docker.com/config/pruning/",children:"details about it"})," )"]}),"\n",(0,t.jsxs)(n.li,{children:["See logs of different container:","\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:["If Cassandra is not able to get up: ",(0,t.jsx)(n.code,{children:"docker logs -f docker_cassandra_1"})]}),"\n",(0,t.jsxs)(n.li,{children:["If Cadence is not able to get up: ",(0,t.jsx)(n.code,{children:"docker logs -f docker_cadence_1"})]}),"\n",(0,t.jsxs)(n.li,{children:["If Cadence Web is not able to get up: ",(0,t.jsx)(n.code,{children:"docker logs -f docker_cadence-web_1"})]}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,t.jsxs)(n.p,{children:["If the above is still not working, ",(0,t.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence/issues/new/choose",children:"open an issue in Server(main) repo"}),"."]})]})}function h(e={}){const{wrapper:n}={...(0,o.R)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(d,{...e})}):d(e)}},8453:(e,n,s)=>{s.d(n,{R:()=>a,x:()=>c});var r=s(6540);const t={},o=r.createContext(t);function a(e){const n=r.useContext(o);return r.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function c(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(t):e.components||t:a(e.components),r.createElement(o.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/7fda255c.046cc7e7.js b/assets/js/7fda255c.059ce0cc.js similarity index 83% rename from assets/js/7fda255c.046cc7e7.js rename to assets/js/7fda255c.059ce0cc.js index f8a35b036..d0455e41e 100644 --- a/assets/js/7fda255c.046cc7e7.js +++ b/assets/js/7fda255c.059ce0cc.js @@ -1 +1 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[4978],{7786:(e,i,n)=>{n.r(i),n.d(i,{assets:()=>c,contentTitle:()=>s,default:()=>h,frontMatter:()=>a,metadata:()=>t,toc:()=>l});var t=n(9426),r=n(4848),o=n(8453);const a={title:"Cadence non-derministic errors common question Q&A (part 1)",date:new Date("2024-03-10T00:00:00.000Z"),authors:"chopincode",tags:["deep-dive"]},s=void 0,c={authorsImageUrls:[void 0]},l=[{value:"If I change code logic inside an Cadence activity (for example, my activity is calling database A but now I want it to call database B), will it trigger an non-deterministic error?",id:"if-i-change-code-logic-inside-an-cadence-activity-for-example-my-activity-is-calling-database-a-but-now-i-want-it-to-call-database-b--will-it-trigger-an-non-deterministic-error",level:3},{value:"Does changing the workflow definition trigger non-determinstic errors?",id:"does-changing-the-workflow-definition-trigger-non-determinstic-errors",level:3},{value:"Does changing activity definitions trigger non-determinstic errors?",id:"does-changing-activity-definitions-trigger-non-determinstic-errors",level:3},{value:"What changes inside workflows may potentially trigger non-deterministic errors?",id:"what-changes-inside-workflows-may-potentially-trigger-non-deterministic-errors",level:3},{value:"Are Cadence signals replayed? If definition of signal is changed, will it trigger non-deterministic errors?",id:"are-cadence-signals-replayed-if-definition-of-signal-is-changed-will-it-trigger-non-deterministic-errors",level:3},{value:"If I have new business requirement and really need to change the definition of a workflow, what should I do?",id:"if-i-have-new-business-requirement-and-really-need-to-change-the-definition-of-a-workflow-what-should-i-do",level:3},{value:"Does changes to local activities' definition trigger non-deterministic errors?",id:"does-changes-to-local-activities-definition-trigger-non-deterministic-errors",level:3}];function d(e){const i={a:"a",h3:"h3",li:"li",p:"p",ul:"ul",...(0,o.R)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(i.h3,{id:"if-i-change-code-logic-inside-an-cadence-activity-for-example-my-activity-is-calling-database-a-but-now-i-want-it-to-call-database-b--will-it-trigger-an-non-deterministic-error",children:"If I change code logic inside an Cadence activity (for example, my activity is calling database A but now I want it to call database B), will it trigger an non-deterministic error?"}),"\n",(0,r.jsxs)(i.p,{children:[(0,r.jsx)("b",{children:"NO"}),". This change will not trigger non-deterministic error."]}),"\n",(0,r.jsx)(i.p,{children:"An Activity is the smallest unit of execution for Cadence and what happens inside activities are not recorded as historical events and therefore will not be replayed. In short, this change is deterministic and it is fine to modify logic inside activities."}),"\n",(0,r.jsx)(i.h3,{id:"does-changing-the-workflow-definition-trigger-non-determinstic-errors",children:"Does changing the workflow definition trigger non-determinstic errors?"}),"\n",(0,r.jsxs)(i.p,{children:[(0,r.jsx)("b",{children:"YES"}),". This is a very typical non-deterministic error."]}),"\n",(0,r.jsx)(i.p,{children:"When a new workflow code change is deployed, Cadence will find if it is compatible with\nCadence history. Changes to workflow definition will fail the replay process of Cadence\nas it finds the new workflow definition imcompatible with previous historical events."}),"\n",(0,r.jsx)(i.p,{children:"Here is a list of common workflow definition changes."}),"\n",(0,r.jsxs)(i.ul,{children:["\n",(0,r.jsx)(i.li,{children:"Changing workflow parameter counts"}),"\n",(0,r.jsx)(i.li,{children:"Changing workflow parameter types"}),"\n",(0,r.jsx)(i.li,{children:"Changing workflow return types"}),"\n"]}),"\n",(0,r.jsx)(i.p,{children:"The following changes are not categorized as definition changes and therefore will not\ntrigger non-deterministic errors."}),"\n",(0,r.jsxs)(i.ul,{children:["\n",(0,r.jsx)(i.li,{children:"Changes of workflow return values"}),"\n",(0,r.jsx)(i.li,{children:"Changing workflow parameter names as they are just positional"}),"\n"]}),"\n",(0,r.jsx)(i.h3,{id:"does-changing-activity-definitions-trigger-non-determinstic-errors",children:"Does changing activity definitions trigger non-determinstic errors?"}),"\n",(0,r.jsxs)(i.p,{children:[(0,r.jsx)("b",{children:"YES"}),". Similar to workflow definition change, this is also a very typical non-deterministic error."]}),"\n",(0,r.jsx)(i.p,{children:"Activities are also recorded and replayed by Cadence. Therefore, changes to activity must also be compatible with Cadence history. The following changes are common ones that trigger non-deterministic errors."}),"\n",(0,r.jsxs)(i.ul,{children:["\n",(0,r.jsx)(i.li,{children:"Changing activity parameter counts"}),"\n",(0,r.jsx)(i.li,{children:"Changing activity parameter types"}),"\n",(0,r.jsx)(i.li,{children:"Changing activity return types"}),"\n"]}),"\n",(0,r.jsx)(i.p,{children:"As activity paremeters are also positional, these two changes will NOT trigger non-deterministic errors."}),"\n",(0,r.jsxs)(i.ul,{children:["\n",(0,r.jsx)(i.li,{children:"Changes of activity return values"}),"\n",(0,r.jsx)(i.li,{children:"Changing activity parameter names"}),"\n"]}),"\n",(0,r.jsx)(i.p,{children:"Activity return values inside workflows are not recorded and replayed."}),"\n",(0,r.jsx)(i.h3,{id:"what-changes-inside-workflows-may-potentially-trigger-non-deterministic-errors",children:"What changes inside workflows may potentially trigger non-deterministic errors?"}),"\n",(0,r.jsx)(i.p,{children:"Cadence records each execution of a workflow and activity execution inside each of them.Therefore, new changes must be compatible with execution orders inside the workflow. The following changes will fail the non-deterministic check."}),"\n",(0,r.jsxs)(i.ul,{children:["\n",(0,r.jsx)(i.li,{children:"Append another activity"}),"\n",(0,r.jsx)(i.li,{children:"Delete an existing activity"}),"\n",(0,r.jsx)(i.li,{children:"Reordering activities"}),"\n"]}),"\n",(0,r.jsx)(i.p,{children:"If you really need to change the activity implementation based on new business requirements, you may consider using versioning your workflow."}),"\n",(0,r.jsx)(i.h3,{id:"are-cadence-signals-replayed-if-definition-of-signal-is-changed-will-it-trigger-non-deterministic-errors",children:"Are Cadence signals replayed? If definition of signal is changed, will it trigger non-deterministic errors?"}),"\n",(0,r.jsx)(i.p,{children:"Yes. If a signal is used in a workflow, it becomes a critical component of your workflow. Because signals also involve I/O to your workflow, it is also recorded and replayed. Modifications on signal definitions or usage may yield to non-deterministic errors, for instance, changing return type of a signal."}),"\n",(0,r.jsx)(i.h3,{id:"if-i-have-new-business-requirement-and-really-need-to-change-the-definition-of-a-workflow-what-should-i-do",children:"If I have new business requirement and really need to change the definition of a workflow, what should I do?"}),"\n",(0,r.jsxs)(i.p,{children:["You may introduce a new workflow registered to your worker and divert traffic to it or use versioning for your workflow. Check out ",(0,r.jsx)(i.a,{href:"https://cadenceworkflow.io/docs/go-client/workflow-versioning/",children:"Cadence website"})," for more information about versioning."]}),"\n",(0,r.jsx)(i.h3,{id:"does-changes-to-local-activities-definition-trigger-non-deterministic-errors",children:"Does changes to local activities' definition trigger non-deterministic errors?"}),"\n",(0,r.jsx)(i.p,{children:"Yes. Local activities are recorded and therefore replayed by Cadence. Imcompatible changes on local activity definitions will yield to non-deterministic errors."})]})}function h(e={}){const{wrapper:i}={...(0,o.R)(),...e.components};return i?(0,r.jsx)(i,{...e,children:(0,r.jsx)(d,{...e})}):d(e)}},8453:(e,i,n)=>{n.d(i,{R:()=>a,x:()=>s});var t=n(6540);const r={},o=t.createContext(r);function a(e){const i=t.useContext(o);return t.useMemo((function(){return"function"==typeof e?e(i):{...i,...e}}),[i,e])}function s(e){let i;return i=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:a(e.components),t.createElement(o.Provider,{value:i},e.children)}},9426:e=>{e.exports=JSON.parse('{"permalink":"/blog/2024/02/15/cadence-non-deterministic-common-qa","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2024-02-15-cadence-non-deterministic-common-qa.md","source":"@site/blog/2024-02-15-cadence-non-deterministic-common-qa.md","title":"Cadence non-derministic errors common question Q&A (part 1)","description":"If I change code logic inside an Cadence activity (for example, my activity is calling database A but now I want it to call database B), will it trigger an non-deterministic error?","date":"2024-03-10T00:00:00.000Z","tags":[{"inline":false,"label":"Deep Dives","permalink":"/blog/tags/deep-dives","description":"Deep Dives tag description"}],"readingTime":2.625,"hasTruncateMarker":true,"authors":[{"name":"Chris Qin","title":"Applications Developer @ Uber","url":"https://www.linkedin.com/in/chrisqin0610/","page":{"permalink":"/blog/authors/chopincode"},"socials":{"linkedin":"https://www.linkedin.com/in/chrisqin0610/","github":"https://github.com/chopincode"},"imageURL":"https://github.com/chopincode.png","key":"chopincode"}],"frontMatter":{"title":"Cadence non-derministic errors common question Q&A (part 1)","date":"2024-03-10T00:00:00.000Z","authors":"chopincode","tags":["deep-dive"]},"unlisted":false,"prevItem":{"title":"2024 Cadence Yearly Roadmap Update","permalink":"/blog/2024/07/11/2024-07-11-yearly-roadmap-update/yearly-roadmap-update"},"nextItem":{"title":"Cadence Community Spotlight Update - November 2023","permalink":"/blog/2023/11/30/community-spotlight-update-november-2023"}}')}}]); \ No newline at end of file +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[4978],{7786:(e,i,n)=>{n.r(i),n.d(i,{assets:()=>c,contentTitle:()=>s,default:()=>h,frontMatter:()=>a,metadata:()=>t,toc:()=>l});var t=n(9426),r=n(4848),o=n(8453);const a={title:"Cadence non-derministic errors common question Q&A (part 1)",date:new Date("2024-03-10T00:00:00.000Z"),authors:"chopincode",tags:["deep-dive"]},s=void 0,c={authorsImageUrls:[void 0]},l=[{value:"If I change code logic inside an Cadence activity (for example, my activity is calling database A but now I want it to call database B), will it trigger an non-deterministic error?",id:"if-i-change-code-logic-inside-an-cadence-activity-for-example-my-activity-is-calling-database-a-but-now-i-want-it-to-call-database-b--will-it-trigger-an-non-deterministic-error",level:3},{value:"Does changing the workflow definition trigger non-determinstic errors?",id:"does-changing-the-workflow-definition-trigger-non-determinstic-errors",level:3},{value:"Does changing activity definitions trigger non-determinstic errors?",id:"does-changing-activity-definitions-trigger-non-determinstic-errors",level:3},{value:"What changes inside workflows may potentially trigger non-deterministic errors?",id:"what-changes-inside-workflows-may-potentially-trigger-non-deterministic-errors",level:3},{value:"Are Cadence signals replayed? If definition of signal is changed, will it trigger non-deterministic errors?",id:"are-cadence-signals-replayed-if-definition-of-signal-is-changed-will-it-trigger-non-deterministic-errors",level:3},{value:"If I have new business requirement and really need to change the definition of a workflow, what should I do?",id:"if-i-have-new-business-requirement-and-really-need-to-change-the-definition-of-a-workflow-what-should-i-do",level:3},{value:"Does changes to local activities' definition trigger non-deterministic errors?",id:"does-changes-to-local-activities-definition-trigger-non-deterministic-errors",level:3}];function d(e){const i={a:"a",h3:"h3",li:"li",p:"p",ul:"ul",...(0,o.R)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(i.h3,{id:"if-i-change-code-logic-inside-an-cadence-activity-for-example-my-activity-is-calling-database-a-but-now-i-want-it-to-call-database-b--will-it-trigger-an-non-deterministic-error",children:"If I change code logic inside an Cadence activity (for example, my activity is calling database A but now I want it to call database B), will it trigger an non-deterministic error?"}),"\n",(0,r.jsxs)(i.p,{children:[(0,r.jsx)("b",{children:"NO"}),". This change will not trigger non-deterministic error."]}),"\n",(0,r.jsx)(i.p,{children:"An Activity is the smallest unit of execution for Cadence and what happens inside activities are not recorded as historical events and therefore will not be replayed. In short, this change is deterministic and it is fine to modify logic inside activities."}),"\n",(0,r.jsx)(i.h3,{id:"does-changing-the-workflow-definition-trigger-non-determinstic-errors",children:"Does changing the workflow definition trigger non-determinstic errors?"}),"\n",(0,r.jsxs)(i.p,{children:[(0,r.jsx)("b",{children:"YES"}),". This is a very typical non-deterministic error."]}),"\n",(0,r.jsx)(i.p,{children:"When a new workflow code change is deployed, Cadence will find if it is compatible with\nCadence history. Changes to workflow definition will fail the replay process of Cadence\nas it finds the new workflow definition imcompatible with previous historical events."}),"\n",(0,r.jsx)(i.p,{children:"Here is a list of common workflow definition changes."}),"\n",(0,r.jsxs)(i.ul,{children:["\n",(0,r.jsx)(i.li,{children:"Changing workflow parameter counts"}),"\n",(0,r.jsx)(i.li,{children:"Changing workflow parameter types"}),"\n",(0,r.jsx)(i.li,{children:"Changing workflow return types"}),"\n"]}),"\n",(0,r.jsx)(i.p,{children:"The following changes are not categorized as definition changes and therefore will not\ntrigger non-deterministic errors."}),"\n",(0,r.jsxs)(i.ul,{children:["\n",(0,r.jsx)(i.li,{children:"Changes of workflow return values"}),"\n",(0,r.jsx)(i.li,{children:"Changing workflow parameter names as they are just positional"}),"\n"]}),"\n",(0,r.jsx)(i.h3,{id:"does-changing-activity-definitions-trigger-non-determinstic-errors",children:"Does changing activity definitions trigger non-determinstic errors?"}),"\n",(0,r.jsxs)(i.p,{children:[(0,r.jsx)("b",{children:"YES"}),". Similar to workflow definition change, this is also a very typical non-deterministic error."]}),"\n",(0,r.jsx)(i.p,{children:"Activities are also recorded and replayed by Cadence. Therefore, changes to activity must also be compatible with Cadence history. The following changes are common ones that trigger non-deterministic errors."}),"\n",(0,r.jsxs)(i.ul,{children:["\n",(0,r.jsx)(i.li,{children:"Changing activity parameter counts"}),"\n",(0,r.jsx)(i.li,{children:"Changing activity parameter types"}),"\n",(0,r.jsx)(i.li,{children:"Changing activity return types"}),"\n"]}),"\n",(0,r.jsx)(i.p,{children:"As activity paremeters are also positional, these two changes will NOT trigger non-deterministic errors."}),"\n",(0,r.jsxs)(i.ul,{children:["\n",(0,r.jsx)(i.li,{children:"Changes of activity return values"}),"\n",(0,r.jsx)(i.li,{children:"Changing activity parameter names"}),"\n"]}),"\n",(0,r.jsx)(i.p,{children:"Activity return values inside workflows are not recorded and replayed."}),"\n",(0,r.jsx)(i.h3,{id:"what-changes-inside-workflows-may-potentially-trigger-non-deterministic-errors",children:"What changes inside workflows may potentially trigger non-deterministic errors?"}),"\n",(0,r.jsx)(i.p,{children:"Cadence records each execution of a workflow and activity execution inside each of them.Therefore, new changes must be compatible with execution orders inside the workflow. The following changes will fail the non-deterministic check."}),"\n",(0,r.jsxs)(i.ul,{children:["\n",(0,r.jsx)(i.li,{children:"Append another activity"}),"\n",(0,r.jsx)(i.li,{children:"Delete an existing activity"}),"\n",(0,r.jsx)(i.li,{children:"Reordering activities"}),"\n"]}),"\n",(0,r.jsx)(i.p,{children:"If you really need to change the activity implementation based on new business requirements, you may consider using versioning your workflow."}),"\n",(0,r.jsx)(i.h3,{id:"are-cadence-signals-replayed-if-definition-of-signal-is-changed-will-it-trigger-non-deterministic-errors",children:"Are Cadence signals replayed? If definition of signal is changed, will it trigger non-deterministic errors?"}),"\n",(0,r.jsx)(i.p,{children:"Yes. If a signal is used in a workflow, it becomes a critical component of your workflow. Because signals also involve I/O to your workflow, it is also recorded and replayed. Modifications on signal definitions or usage may yield to non-deterministic errors, for instance, changing return type of a signal."}),"\n",(0,r.jsx)(i.h3,{id:"if-i-have-new-business-requirement-and-really-need-to-change-the-definition-of-a-workflow-what-should-i-do",children:"If I have new business requirement and really need to change the definition of a workflow, what should I do?"}),"\n",(0,r.jsxs)(i.p,{children:["You may introduce a new workflow registered to your worker and divert traffic to it or use versioning for your workflow. Check out ",(0,r.jsx)(i.a,{href:"https://cadenceworkflow.io/docs/go-client/workflow-versioning/",children:"Cadence website"})," for more information about versioning."]}),"\n",(0,r.jsx)(i.h3,{id:"does-changes-to-local-activities-definition-trigger-non-deterministic-errors",children:"Does changes to local activities' definition trigger non-deterministic errors?"}),"\n",(0,r.jsx)(i.p,{children:"Yes. Local activities are recorded and therefore replayed by Cadence. Imcompatible changes on local activity definitions will yield to non-deterministic errors."})]})}function h(e={}){const{wrapper:i}={...(0,o.R)(),...e.components};return i?(0,r.jsx)(i,{...e,children:(0,r.jsx)(d,{...e})}):d(e)}},8453:(e,i,n)=>{n.d(i,{R:()=>a,x:()=>s});var t=n(6540);const r={},o=t.createContext(r);function a(e){const i=t.useContext(o);return t.useMemo((function(){return"function"==typeof e?e(i):{...i,...e}}),[i,e])}function s(e){let i;return i=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:a(e.components),t.createElement(o.Provider,{value:i},e.children)}},9426:e=>{e.exports=JSON.parse('{"permalink":"/Cadence-Docs/blog/2024/02/15/cadence-non-deterministic-common-qa","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2024-02-15-cadence-non-deterministic-common-qa.md","source":"@site/blog/2024-02-15-cadence-non-deterministic-common-qa.md","title":"Cadence non-derministic errors common question Q&A (part 1)","description":"If I change code logic inside an Cadence activity (for example, my activity is calling database A but now I want it to call database B), will it trigger an non-deterministic error?","date":"2024-03-10T00:00:00.000Z","tags":[{"inline":false,"label":"Deep Dives","permalink":"/Cadence-Docs/blog/tags/deep-dives","description":"Deep Dives tag description"}],"readingTime":2.625,"hasTruncateMarker":true,"authors":[{"name":"Chris Qin","title":"Applications Developer @ Uber","url":"https://www.linkedin.com/in/chrisqin0610/","page":{"permalink":"/Cadence-Docs/blog/authors/chopincode"},"socials":{"linkedin":"https://www.linkedin.com/in/chrisqin0610/","github":"https://github.com/chopincode"},"imageURL":"https://github.com/chopincode.png","key":"chopincode"}],"frontMatter":{"title":"Cadence non-derministic errors common question Q&A (part 1)","date":"2024-03-10T00:00:00.000Z","authors":"chopincode","tags":["deep-dive"]},"unlisted":false,"prevItem":{"title":"2024 Cadence Yearly Roadmap Update","permalink":"/Cadence-Docs/blog/2024/07/11/2024-07-11-yearly-roadmap-update/yearly-roadmap-update"},"nextItem":{"title":"Cadence Community Spotlight Update - November 2023","permalink":"/Cadence-Docs/blog/2023/11/30/community-spotlight-update-november-2023"}}')}}]); \ No newline at end of file diff --git a/assets/js/80db4ed1.0a1913d6.js b/assets/js/80db4ed1.0a1913d6.js deleted file mode 100644 index 2f44948db..000000000 --- a/assets/js/80db4ed1.0a1913d6.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[3333],{1575:t=>{t.exports=JSON.parse('{"tag":{"label":"Community Spotlight","permalink":"/blog/tags/community-spotlights","description":"Community Spotlight tag description","allTagsPath":"/blog/tags","count":20,"unlisted":false},"listMetadata":{"permalink":"/blog/tags/community-spotlights","page":1,"postsPerPage":10,"totalPages":2,"totalCount":20,"nextPage":"/blog/tags/community-spotlights/page/2","blogDescription":"The latest news and updates from the Cadence team","blogTitle":"Cadence Blog"}}')}}]); \ No newline at end of file diff --git a/assets/js/80e02aec.21eee472.js b/assets/js/80e02aec.722ce13d.js similarity index 53% rename from assets/js/80e02aec.21eee472.js rename to assets/js/80e02aec.722ce13d.js index d0ce14318..410da4b14 100644 --- a/assets/js/80e02aec.21eee472.js +++ b/assets/js/80e02aec.722ce13d.js @@ -1 +1 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[1963],{2447:(e,o,t)=>{t.r(o),t.d(o,{assets:()=>l,contentTitle:()=>r,default:()=>h,frontMatter:()=>s,metadata:()=>n,toc:()=>c});var n=t(9390),a=t(4848),i=t(8453);const s={title:"Zonal Isolation for Cadence Workflows",subtitle:"test",date:new Date("2024-10-14T00:00:00.000Z"),authors:"shaddoll",tags:["deep-dive","cadence-operations"]},r=void 0,l={authorsImageUrls:[void 0]},c=[{value:"What is Zonal Isolation for Cadence Workflows?",id:"what-is-zonal-isolation-for-cadence-workflows",level:2}];function d(e){const o={h2:"h2",li:"li",ol:"ol",p:"p",strong:"strong",...(0,i.R)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(o.p,{children:"At Uber, we want to achieve regional resilience such that losing a zone within a region can be tolerated without requiring a cross-region failover. We also want to make sure that losing a zone only affects a subset of workload, at most, rather than everything. However, in Cadence-based systems, the workload in a region is distributed randomly across all workers in the region at a \u201ctask-level granularity\u201d, which means a workflow may be worked on by any worker in the region where the domain is active. To achieve this goal, we introduced Zonal Isolation for Cadence Workflows - a feature designed to pin workflows to the zone they are started in, so that zonal isolation can be achieved at a workflow-level."}),"\n",(0,a.jsx)(o.h2,{id:"what-is-zonal-isolation-for-cadence-workflows",children:"What is Zonal Isolation for Cadence Workflows?"}),"\n",(0,a.jsx)(o.p,{children:"At high-level, Zonal Isolation for Cadence Workflows can be thought in 2 levels:"}),"\n",(0,a.jsxs)(o.ol,{children:["\n",(0,a.jsxs)(o.li,{children:[(0,a.jsx)(o.strong,{children:"Task-level isolation:"})," All decision tasks and activity tasks of a workflow are only processed by workers from the zone where the workflow was started"]}),"\n",(0,a.jsxs)(o.li,{children:[(0,a.jsx)(o.strong,{children:"Infrastructure-level isolation:"})," Within a regional Cadence cluster, workflows are handled by server instances in the same zone where they were started, and the corresponding data is stored in that zone as well."]}),"\n"]}),"\n",(0,a.jsx)(o.p,{children:"Infrastructure-level isolation is quite challenging to implement as it requires significant changes to the core design of the Cadence server. Due to the complexity involved, support for this feature is not planned for the foreseeable future."}),"\n",(0,a.jsx)(o.p,{children:"As a result, the focus remains on achieving task-level zonal isolation outside the Cadence server, which offers a more practical and immediate way to improve system resilience. It provides the capability of ensuring that an unhealthy zone (i.e. bad deployment of workers) only affect a subset of workflows (started from a certain zone) rather than every workflow in a Cadence domain."})]})}function h(e={}){const{wrapper:o}={...(0,i.R)(),...e.components};return o?(0,a.jsx)(o,{...e,children:(0,a.jsx)(d,{...e})}):d(e)}},8453:(e,o,t)=>{t.d(o,{R:()=>s,x:()=>r});var n=t(6540);const a={},i=n.createContext(a);function s(e){const o=n.useContext(i);return n.useMemo((function(){return"function"==typeof e?e(o):{...o,...e}}),[o,e])}function r(e){let o;return o=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:s(e.components),n.createElement(i.Provider,{value:o},e.children)}},9390:e=>{e.exports=JSON.parse('{"permalink":"/blog/zonal-isolation-v1/zonal-isolation-v1","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/zonal-isolation-v1/zonal-isolation-v1.md","source":"@site/blog/zonal-isolation-v1/zonal-isolation-v1.md","title":"Zonal Isolation for Cadence Workflows","description":"At Uber, we want to achieve regional resilience such that losing a zone within a region can be tolerated without requiring a cross-region failover. We also want to make sure that losing a zone only affects a subset of workload, at most, rather than everything. However, in Cadence-based systems, the workload in a region is distributed randomly across all workers in the region at a \u201ctask-level granularity\u201d, which means a workflow may be worked on by any worker in the region where the domain is active. To achieve this goal, we introduced Zonal Isolation for Cadence Workflows - a feature designed to pin workflows to the zone they are started in, so that zonal isolation can be achieved at a workflow-level.","date":"2024-10-14T00:00:00.000Z","tags":[{"inline":false,"label":"Deep Dives","permalink":"/blog/tags/deep-dives","description":"Deep Dives tag description"},{"inline":false,"label":"Cadence Operations","permalink":"/blog/tags/cadence-operations","description":"Cadence Operations tag description"}],"readingTime":7.985,"hasTruncateMarker":true,"authors":[{"name":"Zijian Chen","title":"Software Engineer @ Uber","url":"https://www.linkedin.com/in/zijian-chen-5868938b/","page":{"permalink":"/blog/authors/shaddoll"},"socials":{"linkedin":"https://www.linkedin.com/in/zijian-chen-5868938b/","github":"https://github.com/Shaddoll"},"imageURL":"https://github.com/Shaddoll.png","key":"shaddoll"}],"frontMatter":{"title":"Zonal Isolation for Cadence Workflows","subtitle":"test","date":"2024-10-14T00:00:00.000Z","authors":"shaddoll","tags":["deep-dive","cadence-operations"]},"unlisted":false,"prevItem":{"title":"Cadence Repositories Have Moved!","permalink":"/blog/2024/11/18/cadence-workflows-github-organization"},"nextItem":{"title":"Announcement: Cadence Helm Charts v0 Release","permalink":"/blog/2024/10/01/announcing-cadence-helm-charts-v0"}}')}}]); \ No newline at end of file +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[1963],{2447:(e,o,n)=>{n.r(o),n.d(o,{assets:()=>l,contentTitle:()=>r,default:()=>h,frontMatter:()=>s,metadata:()=>t,toc:()=>c});var t=n(9390),a=n(4848),i=n(8453);const s={title:"Zonal Isolation for Cadence Workflows",subtitle:"test",date:new Date("2024-10-14T00:00:00.000Z"),authors:"shaddoll",tags:["deep-dive","cadence-operations"]},r=void 0,l={authorsImageUrls:[void 0]},c=[{value:"What is Zonal Isolation for Cadence Workflows?",id:"what-is-zonal-isolation-for-cadence-workflows",level:2}];function d(e){const o={h2:"h2",li:"li",ol:"ol",p:"p",strong:"strong",...(0,i.R)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(o.p,{children:"At Uber, we want to achieve regional resilience such that losing a zone within a region can be tolerated without requiring a cross-region failover. We also want to make sure that losing a zone only affects a subset of workload, at most, rather than everything. However, in Cadence-based systems, the workload in a region is distributed randomly across all workers in the region at a \u201ctask-level granularity\u201d, which means a workflow may be worked on by any worker in the region where the domain is active. To achieve this goal, we introduced Zonal Isolation for Cadence Workflows - a feature designed to pin workflows to the zone they are started in, so that zonal isolation can be achieved at a workflow-level."}),"\n",(0,a.jsx)(o.h2,{id:"what-is-zonal-isolation-for-cadence-workflows",children:"What is Zonal Isolation for Cadence Workflows?"}),"\n",(0,a.jsx)(o.p,{children:"At high-level, Zonal Isolation for Cadence Workflows can be thought in 2 levels:"}),"\n",(0,a.jsxs)(o.ol,{children:["\n",(0,a.jsxs)(o.li,{children:[(0,a.jsx)(o.strong,{children:"Task-level isolation:"})," All decision tasks and activity tasks of a workflow are only processed by workers from the zone where the workflow was started"]}),"\n",(0,a.jsxs)(o.li,{children:[(0,a.jsx)(o.strong,{children:"Infrastructure-level isolation:"})," Within a regional Cadence cluster, workflows are handled by server instances in the same zone where they were started, and the corresponding data is stored in that zone as well."]}),"\n"]}),"\n",(0,a.jsx)(o.p,{children:"Infrastructure-level isolation is quite challenging to implement as it requires significant changes to the core design of the Cadence server. Due to the complexity involved, support for this feature is not planned for the foreseeable future."}),"\n",(0,a.jsx)(o.p,{children:"As a result, the focus remains on achieving task-level zonal isolation outside the Cadence server, which offers a more practical and immediate way to improve system resilience. It provides the capability of ensuring that an unhealthy zone (i.e. bad deployment of workers) only affect a subset of workflows (started from a certain zone) rather than every workflow in a Cadence domain."})]})}function h(e={}){const{wrapper:o}={...(0,i.R)(),...e.components};return o?(0,a.jsx)(o,{...e,children:(0,a.jsx)(d,{...e})}):d(e)}},8453:(e,o,n)=>{n.d(o,{R:()=>s,x:()=>r});var t=n(6540);const a={},i=t.createContext(a);function s(e){const o=t.useContext(i);return t.useMemo((function(){return"function"==typeof e?e(o):{...o,...e}}),[o,e])}function r(e){let o;return o=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:s(e.components),t.createElement(i.Provider,{value:o},e.children)}},9390:e=>{e.exports=JSON.parse('{"permalink":"/Cadence-Docs/blog/zonal-isolation-v1/zonal-isolation-v1","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/zonal-isolation-v1/zonal-isolation-v1.md","source":"@site/blog/zonal-isolation-v1/zonal-isolation-v1.md","title":"Zonal Isolation for Cadence Workflows","description":"At Uber, we want to achieve regional resilience such that losing a zone within a region can be tolerated without requiring a cross-region failover. We also want to make sure that losing a zone only affects a subset of workload, at most, rather than everything. However, in Cadence-based systems, the workload in a region is distributed randomly across all workers in the region at a \u201ctask-level granularity\u201d, which means a workflow may be worked on by any worker in the region where the domain is active. To achieve this goal, we introduced Zonal Isolation for Cadence Workflows - a feature designed to pin workflows to the zone they are started in, so that zonal isolation can be achieved at a workflow-level.","date":"2024-10-14T00:00:00.000Z","tags":[{"inline":false,"label":"Deep Dives","permalink":"/Cadence-Docs/blog/tags/deep-dives","description":"Deep Dives tag description"},{"inline":false,"label":"Cadence Operations","permalink":"/Cadence-Docs/blog/tags/cadence-operations","description":"Cadence Operations tag description"}],"readingTime":7.985,"hasTruncateMarker":true,"authors":[{"name":"Zijian Chen","title":"Software Engineer @ Uber","url":"https://www.linkedin.com/in/zijian-chen-5868938b/","page":{"permalink":"/Cadence-Docs/blog/authors/shaddoll"},"socials":{"linkedin":"https://www.linkedin.com/in/zijian-chen-5868938b/","github":"https://github.com/Shaddoll"},"imageURL":"https://github.com/Shaddoll.png","key":"shaddoll"}],"frontMatter":{"title":"Zonal Isolation for Cadence Workflows","subtitle":"test","date":"2024-10-14T00:00:00.000Z","authors":"shaddoll","tags":["deep-dive","cadence-operations"]},"unlisted":false,"prevItem":{"title":"Cadence Repositories Have Moved!","permalink":"/Cadence-Docs/blog/2024/11/18/cadence-workflows-github-organization"},"nextItem":{"title":"Announcement: Cadence Helm Charts v0 Release","permalink":"/Cadence-Docs/blog/2024/10/01/announcing-cadence-helm-charts-v0"}}')}}]); \ No newline at end of file diff --git a/assets/js/814003d2.6882937e.js b/assets/js/814003d2.6882937e.js deleted file mode 100644 index 70e3e5cb6..000000000 --- a/assets/js/814003d2.6882937e.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[751],{5092:(e,i,n)=>{n.r(i),n.d(i,{assets:()=>l,contentTitle:()=>s,default:()=>d,frontMatter:()=>o,metadata:()=>r,toc:()=>c});const r=JSON.parse('{"id":"concepts/archival","title":"Archival","description":"Archivalworkflow","source":"@site/docs/03-concepts/07-archival.md","sourceDirName":"03-concepts","slug":"/concepts/archival","permalink":"/docs/concepts/archival","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/03-concepts/07-archival.md","tags":[],"version":"current","sidebarPosition":7,"frontMatter":{"layout":"default","title":"Archival","permalink":"/docs/concepts/archival"},"sidebar":"docsSidebar","previous":{"title":"Task lists","permalink":"/docs/concepts/task-lists"},"next":{"title":"Cross DC replication","permalink":"/docs/concepts/cross-dc-replication"}}');var a=n(4848),t=n(8453);const o={layout:"default",title:"Archival",permalink:"/docs/concepts/archival"},s="Archival",l={},c=[{value:"Concepts",id:"concepts",level:2},{value:"Configuring Archival",id:"configuring-archival",level:2},{value:"Cluster Level Archival Config",id:"cluster-level-archival-config",level:3},{value:"Domain Level Archival Config",id:"domain-level-archival-config",level:3},{value:"Running Locally",id:"running-locally",level:2},{value:"Running in Production",id:"running-in-production",level:2},{value:"FAQ",id:"faq",level:2},{value:"When does archival happen?",id:"when-does-archival-happen",level:3},{value:"What's the query syntax for visibility archival?",id:"whats-the-query-syntax-for-visibility-archival",level:3},{value:"How does archival interact with global domains?",id:"how-does-archival-interact-with-global-domains",level:3},{value:"Can I specify multiple archival URIs?",id:"can-i-specify-multiple-archival-uris",level:3},{value:"How does archival work with PII?",id:"how-does-archival-work-with-pii",level:3},{value:"Planned Future Work",id:"planned-future-work",level:2}];function h(e){const i={a:"a",code:"code",h1:"h1",h2:"h2",h3:"h3",header:"header",li:"li",ol:"ol",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,t.R)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(i.header,{children:(0,a.jsx)(i.h1,{id:"archival",children:"Archival"})}),"\n",(0,a.jsx)(i.p,{children:"Archival is a feature that automatically moves workflow histories (history archival) and visibility records (visibility archival) from persistence to a secondary data store after the retention period, thus allowing users to keep workflow history and visibility records as long as necessary without overwhelming Cadence primary data store. There are two reasons you may consider turning on archival for your domain:"}),"\n",(0,a.jsxs)(i.ol,{children:["\n",(0,a.jsxs)(i.li,{children:[(0,a.jsx)(i.strong,{children:"Compliance:"})," For legal reasons histories may need to be stored for a long period of time."]}),"\n",(0,a.jsxs)(i.li,{children:[(0,a.jsx)(i.strong,{children:"Debugging:"})," Old histories can still be accessed for debugging."]}),"\n"]}),"\n",(0,a.jsx)(i.p,{children:"The current implementation of the Archival feature has two limitations:"}),"\n",(0,a.jsxs)(i.ol,{children:["\n",(0,a.jsxs)(i.li,{children:[(0,a.jsx)(i.strong,{children:"RunID Required:"})," In order to retrieve an archived workflow history, both workflowID and runID are required."]}),"\n",(0,a.jsxs)(i.li,{children:[(0,a.jsx)(i.strong,{children:"Best Effort:"})," It is possible that a history or visibility record is deleted from Cadence primary persistence without being archived first. These cases are rare but are possible with the current state of archival. Please check the FAQ section for how to get notified when this happens."]}),"\n"]}),"\n",(0,a.jsx)(i.h2,{id:"concepts",children:"Concepts"}),"\n",(0,a.jsxs)(i.ul,{children:["\n",(0,a.jsxs)(i.li,{children:[(0,a.jsx)(i.strong,{children:"Archiver:"})," Archiver is the component that is responsible for archiving and retrieving workflow histories and visibility records. Its interface is generic and supports different kinds of archival locations: local file system, S3, Kafka, etc. Check ",(0,a.jsx)(i.a,{href:"https://github.com/cadence-workflow/cadence/blob/master/common/archiver/README.md",children:"this README"})," if you would like to add a new archiver implementation for your data store."]}),"\n",(0,a.jsxs)(i.li,{children:[(0,a.jsx)(i.strong,{children:"URI:"})," An URI is used to specify the archival location. Based on the scheme part of an URI, the corresponding archiver will be selected by the system to perform the archival operation."]}),"\n"]}),"\n",(0,a.jsx)(i.h2,{id:"configuring-archival",children:"Configuring Archival"}),"\n",(0,a.jsx)(i.p,{children:"Archival is controlled by both domain level config and cluster level config. History and visibility archival have separate domain/cluster configs, but they share the same purpose."}),"\n",(0,a.jsx)(i.h3,{id:"cluster-level-archival-config",children:"Cluster Level Archival Config"}),"\n",(0,a.jsx)(i.p,{children:"A Cadence cluster can be in one of three archival states:"}),"\n",(0,a.jsxs)(i.ul,{children:["\n",(0,a.jsxs)(i.li,{children:[(0,a.jsx)(i.strong,{children:"Disabled:"})," No archivals will occur and the archivers will be not initialized on service startup."]}),"\n",(0,a.jsxs)(i.li,{children:[(0,a.jsx)(i.strong,{children:"Paused:"})," This state is not yet implemented. Currently setting cluster to paused is the same as setting it to disabled."]}),"\n",(0,a.jsxs)(i.li,{children:[(0,a.jsx)(i.strong,{children:"Enabled:"})," Archivals will occur."]}),"\n"]}),"\n",(0,a.jsx)(i.p,{children:"Enabling the cluster for archival simply means workflow histories will be archived. There is another config which controls whether archived histories or visibility records can be accessed. Both configs have defaults defined in the static yaml and can be overwritten via dynamic config. Note, however, dynamic config will take effect only when archival is enabled in static yaml."}),"\n",(0,a.jsx)(i.h3,{id:"domain-level-archival-config",children:"Domain Level Archival Config"}),"\n",(0,a.jsx)(i.p,{children:"A domain includes two pieces of archival related config:"}),"\n",(0,a.jsxs)(i.ul,{children:["\n",(0,a.jsxs)(i.li,{children:[(0,a.jsx)(i.strong,{children:"Status:"})," Either enabled or disabled. If a domain is in the disabled state, no archivals will occur for that domain."]}),"\n",(0,a.jsxs)(i.li,{children:[(0,a.jsx)(i.strong,{children:"URI:"})," The scheme and location where histories or visibility records will be archived to. When a domain enables archival for the first time URI is set and can never be changed. If URI is not specified when first enabling a domain for archival, a default URI from the static config will be used."]}),"\n"]}),"\n",(0,a.jsx)(i.h2,{id:"running-locally",children:"Running Locally"}),"\n",(0,a.jsx)(i.p,{children:"You can follow the steps below to run and test the archival feature locally:"}),"\n",(0,a.jsxs)(i.ol,{children:["\n",(0,a.jsx)(i.li,{children:(0,a.jsx)(i.code,{children:"./cadence-server start"})}),"\n",(0,a.jsx)(i.li,{children:(0,a.jsx)(i.code,{children:"./cadence --do samples-domain domain register --gd false --history_archival_status enabled --visibility_archival_status enabled --retention 0"})}),"\n",(0,a.jsxs)(i.li,{children:["Run the ",(0,a.jsx)(i.a,{href:"https://github.com/cadence-workflow/cadence-samples",children:"helloworld cadence-sample"})," by following the README"]}),"\n",(0,a.jsx)(i.li,{children:"Copy the workflowID the completed workflow from log output"}),"\n",(0,a.jsxs)(i.li,{children:["Retrieve runID through archived visibility record ",(0,a.jsx)(i.code,{children:"./cadence --do samples-domain wf listarchived -q 'WorkflowID = \"\"'"})]}),"\n",(0,a.jsxs)(i.li,{children:["Retrieve archived history ",(0,a.jsx)(i.code,{children:"./cadence --do samples-domain wf show --wid --rid "})]}),"\n"]}),"\n",(0,a.jsxs)(i.p,{children:["In step 2, we registered a new domain and enabled both history and visibility archival feature for that domain. Since we didn't provide an archival URI when registering the new domain, the default URI specified in ",(0,a.jsx)(i.code,{children:"config/development.yaml"})," is used. The default URI is ",(0,a.jsx)(i.code,{children:"file:///tmp/cadence_archival/development"})," for history archival and ",(0,a.jsx)(i.code,{children:'"file:///tmp/cadence_vis_archival/development"'})," for visibility archival. You can find the archived workflow history under the ",(0,a.jsx)(i.code,{children:"/tmp/cadence_archival/development"})," directory and archived visibility record under the ",(0,a.jsx)(i.code,{children:"/tmp/cadence_vis_archival/development"})," directory."]}),"\n",(0,a.jsx)(i.h2,{id:"running-in-production",children:"Running in Production"}),"\n",(0,a.jsxs)(i.p,{children:["Cadence supports uploading workflow histories to Google Cloud and Amazon S3 for archival in production.\nCheck documentation in ",(0,a.jsx)(i.a,{href:"https://github.com/cadence-workflow/cadence/tree/master/common/archiver/gcloud",children:"GCloud archival component"})," and ",(0,a.jsx)(i.a,{href:"https://github.com/cadence-workflow/cadence/tree/master/common/archiver/s3store",children:"S3 archival component"}),"."]}),"\n",(0,a.jsx)(i.p,{children:"Below is an example of Amazon S3 archival configuration:"}),"\n",(0,a.jsx)(i.pre,{children:(0,a.jsx)(i.code,{className:"language-yaml",children:'archival:\n history:\n status: "enabled"\n enableRead: true\n provider:\n s3store:\n region: "us-east-2"\n visibility:\n status: "enabled"\n enableRead: true\n provider:\n s3store:\n region: "us-east-2"\ndomainDefaults:\n archival:\n history:\n status: "enabled"\n URI: "s3://put-name-of-your-s3-bucket-here"\n visibility:\n status: "enabled"\n URI: "s3://put-name-of-your-s3-bucket-here" # most proably the same as the previous URI\n'})}),"\n",(0,a.jsx)(i.h2,{id:"faq",children:"FAQ"}),"\n",(0,a.jsx)(i.h3,{id:"when-does-archival-happen",children:"When does archival happen?"}),"\n",(0,a.jsx)(i.p,{children:"In theory, we would like both history and visibility archival happen after workflow closes and retention period passes. However, due to some limitations in the implementation, only history archival happens after the retention period, while visibility archival happens immediately after workflow closes. Please treat this as an implementation details inside Cadence and do not relay on this fact. Archived data should only be checked after the retention period, and we may change the way we do visibility archival in the future."}),"\n",(0,a.jsx)(i.h3,{id:"whats-the-query-syntax-for-visibility-archival",children:"What's the query syntax for visibility archival?"}),"\n",(0,a.jsxs)(i.p,{children:["The ",(0,a.jsx)(i.code,{children:"listArchived"})," CLI command and API accept a SQL-like query for retrieving archived visibility records, similar to how the ",(0,a.jsx)(i.code,{children:"listWorkflow"})," command works. Unfortunately, since different Archiver implementations have very different capability, there's currently no universal query syntax that works for all Archiver implementations. Please check the README (for example, ",(0,a.jsx)(i.a,{href:"https://github.com/cadence-workflow/cadence/tree/master/common/archiver/s3store",children:"S3"})," and ",(0,a.jsx)(i.a,{href:"https://github.com/cadence-workflow/cadence/tree/master/common/archiver/gcloud",children:"GCP"}),") of the Archiver used by your domain for the supported query syntax and limitations."]}),"\n",(0,a.jsx)(i.h3,{id:"how-does-archival-interact-with-global-domains",children:"How does archival interact with global domains?"}),"\n",(0,a.jsx)(i.p,{children:"If you have a global domain, when archival occurs it will first run on the active cluster and some time later it will run on the standby cluster when replication happens.\nFor history archival, Cadence will check if upload operation has been performed and skip duplicate efforts.\nFor visibility archival, there's no such check and duplicated visibility records will be uploaded. Depending on the Archiver implementation, those duplicated upload may consume more space in the underlying storage and duplicated entries may be returned."}),"\n",(0,a.jsx)(i.h3,{id:"can-i-specify-multiple-archival-uris",children:"Can I specify multiple archival URIs?"}),"\n",(0,a.jsx)(i.p,{children:"Each domain can only have one URI for history archival and one URI for visibility archival. Different domains, however, can have different URIs (with different schemes)."}),"\n",(0,a.jsx)(i.h3,{id:"how-does-archival-work-with-pii",children:"How does archival work with PII?"}),"\n",(0,a.jsx)(i.p,{children:"No cadence workflow should ever operate on clear text PII. Cadence can be thought of as a database and just as one would not store PII in a database PII should not be stored in Cadence. This is even more important when archival is enabled because these histories can be kept forever."}),"\n",(0,a.jsx)(i.h2,{id:"planned-future-work",children:"Planned Future Work"}),"\n",(0,a.jsxs)(i.ul,{children:["\n",(0,a.jsx)(i.li,{children:"Support retriving archived workflow histories without providing runID."}),"\n",(0,a.jsx)(i.li,{children:"Provide guarantee that no history or visibility record is deleted from primary persistence before being archived."}),"\n",(0,a.jsxs)(i.li,{children:["Implement ",(0,a.jsx)(i.strong,{children:"Paused"})," state. In this state no archivals will occur but histories or visibility record also will not be deleted from persistence.\nOnce enabled again from paused state, all skipped archivals will occur."]}),"\n"]})]})}function d(e={}){const{wrapper:i}={...(0,t.R)(),...e.components};return i?(0,a.jsx)(i,{...e,children:(0,a.jsx)(h,{...e})}):h(e)}},8453:(e,i,n)=>{n.d(i,{R:()=>o,x:()=>s});var r=n(6540);const a={},t=r.createContext(a);function o(e){const i=r.useContext(t);return r.useMemo((function(){return"function"==typeof e?e(i):{...i,...e}}),[i,e])}function s(e){let i;return i=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:o(e.components),r.createElement(t.Provider,{value:i},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/814003d2.7159ace6.js b/assets/js/814003d2.7159ace6.js new file mode 100644 index 000000000..9cf6219d0 --- /dev/null +++ b/assets/js/814003d2.7159ace6.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[751],{5092:(e,i,n)=>{n.r(i),n.d(i,{assets:()=>l,contentTitle:()=>s,default:()=>d,frontMatter:()=>o,metadata:()=>r,toc:()=>c});const r=JSON.parse('{"id":"concepts/archival","title":"Archival","description":"Archivalworkflow","source":"@site/docs/03-concepts/07-archival.md","sourceDirName":"03-concepts","slug":"/concepts/archival","permalink":"/Cadence-Docs/docs/concepts/archival","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/03-concepts/07-archival.md","tags":[],"version":"current","sidebarPosition":7,"frontMatter":{"layout":"default","title":"Archival","permalink":"/docs/concepts/archival"},"sidebar":"docsSidebar","previous":{"title":"Task lists","permalink":"/Cadence-Docs/docs/concepts/task-lists"},"next":{"title":"Cross DC replication","permalink":"/Cadence-Docs/docs/concepts/cross-dc-replication"}}');var a=n(4848),t=n(8453);const o={layout:"default",title:"Archival",permalink:"/docs/concepts/archival"},s="Archival",l={},c=[{value:"Concepts",id:"concepts",level:2},{value:"Configuring Archival",id:"configuring-archival",level:2},{value:"Cluster Level Archival Config",id:"cluster-level-archival-config",level:3},{value:"Domain Level Archival Config",id:"domain-level-archival-config",level:3},{value:"Running Locally",id:"running-locally",level:2},{value:"Running in Production",id:"running-in-production",level:2},{value:"FAQ",id:"faq",level:2},{value:"When does archival happen?",id:"when-does-archival-happen",level:3},{value:"What's the query syntax for visibility archival?",id:"whats-the-query-syntax-for-visibility-archival",level:3},{value:"How does archival interact with global domains?",id:"how-does-archival-interact-with-global-domains",level:3},{value:"Can I specify multiple archival URIs?",id:"can-i-specify-multiple-archival-uris",level:3},{value:"How does archival work with PII?",id:"how-does-archival-work-with-pii",level:3},{value:"Planned Future Work",id:"planned-future-work",level:2}];function h(e){const i={a:"a",code:"code",h1:"h1",h2:"h2",h3:"h3",header:"header",li:"li",ol:"ol",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,t.R)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(i.header,{children:(0,a.jsx)(i.h1,{id:"archival",children:"Archival"})}),"\n",(0,a.jsx)(i.p,{children:"Archival is a feature that automatically moves workflow histories (history archival) and visibility records (visibility archival) from persistence to a secondary data store after the retention period, thus allowing users to keep workflow history and visibility records as long as necessary without overwhelming Cadence primary data store. There are two reasons you may consider turning on archival for your domain:"}),"\n",(0,a.jsxs)(i.ol,{children:["\n",(0,a.jsxs)(i.li,{children:[(0,a.jsx)(i.strong,{children:"Compliance:"})," For legal reasons histories may need to be stored for a long period of time."]}),"\n",(0,a.jsxs)(i.li,{children:[(0,a.jsx)(i.strong,{children:"Debugging:"})," Old histories can still be accessed for debugging."]}),"\n"]}),"\n",(0,a.jsx)(i.p,{children:"The current implementation of the Archival feature has two limitations:"}),"\n",(0,a.jsxs)(i.ol,{children:["\n",(0,a.jsxs)(i.li,{children:[(0,a.jsx)(i.strong,{children:"RunID Required:"})," In order to retrieve an archived workflow history, both workflowID and runID are required."]}),"\n",(0,a.jsxs)(i.li,{children:[(0,a.jsx)(i.strong,{children:"Best Effort:"})," It is possible that a history or visibility record is deleted from Cadence primary persistence without being archived first. These cases are rare but are possible with the current state of archival. Please check the FAQ section for how to get notified when this happens."]}),"\n"]}),"\n",(0,a.jsx)(i.h2,{id:"concepts",children:"Concepts"}),"\n",(0,a.jsxs)(i.ul,{children:["\n",(0,a.jsxs)(i.li,{children:[(0,a.jsx)(i.strong,{children:"Archiver:"})," Archiver is the component that is responsible for archiving and retrieving workflow histories and visibility records. Its interface is generic and supports different kinds of archival locations: local file system, S3, Kafka, etc. Check ",(0,a.jsx)(i.a,{href:"https://github.com/cadence-workflow/cadence/blob/master/common/archiver/README.md",children:"this README"})," if you would like to add a new archiver implementation for your data store."]}),"\n",(0,a.jsxs)(i.li,{children:[(0,a.jsx)(i.strong,{children:"URI:"})," An URI is used to specify the archival location. Based on the scheme part of an URI, the corresponding archiver will be selected by the system to perform the archival operation."]}),"\n"]}),"\n",(0,a.jsx)(i.h2,{id:"configuring-archival",children:"Configuring Archival"}),"\n",(0,a.jsx)(i.p,{children:"Archival is controlled by both domain level config and cluster level config. History and visibility archival have separate domain/cluster configs, but they share the same purpose."}),"\n",(0,a.jsx)(i.h3,{id:"cluster-level-archival-config",children:"Cluster Level Archival Config"}),"\n",(0,a.jsx)(i.p,{children:"A Cadence cluster can be in one of three archival states:"}),"\n",(0,a.jsxs)(i.ul,{children:["\n",(0,a.jsxs)(i.li,{children:[(0,a.jsx)(i.strong,{children:"Disabled:"})," No archivals will occur and the archivers will be not initialized on service startup."]}),"\n",(0,a.jsxs)(i.li,{children:[(0,a.jsx)(i.strong,{children:"Paused:"})," This state is not yet implemented. Currently setting cluster to paused is the same as setting it to disabled."]}),"\n",(0,a.jsxs)(i.li,{children:[(0,a.jsx)(i.strong,{children:"Enabled:"})," Archivals will occur."]}),"\n"]}),"\n",(0,a.jsx)(i.p,{children:"Enabling the cluster for archival simply means workflow histories will be archived. There is another config which controls whether archived histories or visibility records can be accessed. Both configs have defaults defined in the static yaml and can be overwritten via dynamic config. Note, however, dynamic config will take effect only when archival is enabled in static yaml."}),"\n",(0,a.jsx)(i.h3,{id:"domain-level-archival-config",children:"Domain Level Archival Config"}),"\n",(0,a.jsx)(i.p,{children:"A domain includes two pieces of archival related config:"}),"\n",(0,a.jsxs)(i.ul,{children:["\n",(0,a.jsxs)(i.li,{children:[(0,a.jsx)(i.strong,{children:"Status:"})," Either enabled or disabled. If a domain is in the disabled state, no archivals will occur for that domain."]}),"\n",(0,a.jsxs)(i.li,{children:[(0,a.jsx)(i.strong,{children:"URI:"})," The scheme and location where histories or visibility records will be archived to. When a domain enables archival for the first time URI is set and can never be changed. If URI is not specified when first enabling a domain for archival, a default URI from the static config will be used."]}),"\n"]}),"\n",(0,a.jsx)(i.h2,{id:"running-locally",children:"Running Locally"}),"\n",(0,a.jsx)(i.p,{children:"You can follow the steps below to run and test the archival feature locally:"}),"\n",(0,a.jsxs)(i.ol,{children:["\n",(0,a.jsx)(i.li,{children:(0,a.jsx)(i.code,{children:"./cadence-server start"})}),"\n",(0,a.jsx)(i.li,{children:(0,a.jsx)(i.code,{children:"./cadence --do samples-domain domain register --gd false --history_archival_status enabled --visibility_archival_status enabled --retention 0"})}),"\n",(0,a.jsxs)(i.li,{children:["Run the ",(0,a.jsx)(i.a,{href:"https://github.com/cadence-workflow/cadence-samples",children:"helloworld cadence-sample"})," by following the README"]}),"\n",(0,a.jsx)(i.li,{children:"Copy the workflowID the completed workflow from log output"}),"\n",(0,a.jsxs)(i.li,{children:["Retrieve runID through archived visibility record ",(0,a.jsx)(i.code,{children:"./cadence --do samples-domain wf listarchived -q 'WorkflowID = \"\"'"})]}),"\n",(0,a.jsxs)(i.li,{children:["Retrieve archived history ",(0,a.jsx)(i.code,{children:"./cadence --do samples-domain wf show --wid --rid "})]}),"\n"]}),"\n",(0,a.jsxs)(i.p,{children:["In step 2, we registered a new domain and enabled both history and visibility archival feature for that domain. Since we didn't provide an archival URI when registering the new domain, the default URI specified in ",(0,a.jsx)(i.code,{children:"config/development.yaml"})," is used. The default URI is ",(0,a.jsx)(i.code,{children:"file:///tmp/cadence_archival/development"})," for history archival and ",(0,a.jsx)(i.code,{children:'"file:///tmp/cadence_vis_archival/development"'})," for visibility archival. You can find the archived workflow history under the ",(0,a.jsx)(i.code,{children:"/tmp/cadence_archival/development"})," directory and archived visibility record under the ",(0,a.jsx)(i.code,{children:"/tmp/cadence_vis_archival/development"})," directory."]}),"\n",(0,a.jsx)(i.h2,{id:"running-in-production",children:"Running in Production"}),"\n",(0,a.jsxs)(i.p,{children:["Cadence supports uploading workflow histories to Google Cloud and Amazon S3 for archival in production.\nCheck documentation in ",(0,a.jsx)(i.a,{href:"https://github.com/cadence-workflow/cadence/tree/master/common/archiver/gcloud",children:"GCloud archival component"})," and ",(0,a.jsx)(i.a,{href:"https://github.com/cadence-workflow/cadence/tree/master/common/archiver/s3store",children:"S3 archival component"}),"."]}),"\n",(0,a.jsx)(i.p,{children:"Below is an example of Amazon S3 archival configuration:"}),"\n",(0,a.jsx)(i.pre,{children:(0,a.jsx)(i.code,{className:"language-yaml",children:'archival:\n history:\n status: "enabled"\n enableRead: true\n provider:\n s3store:\n region: "us-east-2"\n visibility:\n status: "enabled"\n enableRead: true\n provider:\n s3store:\n region: "us-east-2"\ndomainDefaults:\n archival:\n history:\n status: "enabled"\n URI: "s3://put-name-of-your-s3-bucket-here"\n visibility:\n status: "enabled"\n URI: "s3://put-name-of-your-s3-bucket-here" # most proably the same as the previous URI\n'})}),"\n",(0,a.jsx)(i.h2,{id:"faq",children:"FAQ"}),"\n",(0,a.jsx)(i.h3,{id:"when-does-archival-happen",children:"When does archival happen?"}),"\n",(0,a.jsx)(i.p,{children:"In theory, we would like both history and visibility archival happen after workflow closes and retention period passes. However, due to some limitations in the implementation, only history archival happens after the retention period, while visibility archival happens immediately after workflow closes. Please treat this as an implementation details inside Cadence and do not relay on this fact. Archived data should only be checked after the retention period, and we may change the way we do visibility archival in the future."}),"\n",(0,a.jsx)(i.h3,{id:"whats-the-query-syntax-for-visibility-archival",children:"What's the query syntax for visibility archival?"}),"\n",(0,a.jsxs)(i.p,{children:["The ",(0,a.jsx)(i.code,{children:"listArchived"})," CLI command and API accept a SQL-like query for retrieving archived visibility records, similar to how the ",(0,a.jsx)(i.code,{children:"listWorkflow"})," command works. Unfortunately, since different Archiver implementations have very different capability, there's currently no universal query syntax that works for all Archiver implementations. Please check the README (for example, ",(0,a.jsx)(i.a,{href:"https://github.com/cadence-workflow/cadence/tree/master/common/archiver/s3store",children:"S3"})," and ",(0,a.jsx)(i.a,{href:"https://github.com/cadence-workflow/cadence/tree/master/common/archiver/gcloud",children:"GCP"}),") of the Archiver used by your domain for the supported query syntax and limitations."]}),"\n",(0,a.jsx)(i.h3,{id:"how-does-archival-interact-with-global-domains",children:"How does archival interact with global domains?"}),"\n",(0,a.jsx)(i.p,{children:"If you have a global domain, when archival occurs it will first run on the active cluster and some time later it will run on the standby cluster when replication happens.\nFor history archival, Cadence will check if upload operation has been performed and skip duplicate efforts.\nFor visibility archival, there's no such check and duplicated visibility records will be uploaded. Depending on the Archiver implementation, those duplicated upload may consume more space in the underlying storage and duplicated entries may be returned."}),"\n",(0,a.jsx)(i.h3,{id:"can-i-specify-multiple-archival-uris",children:"Can I specify multiple archival URIs?"}),"\n",(0,a.jsx)(i.p,{children:"Each domain can only have one URI for history archival and one URI for visibility archival. Different domains, however, can have different URIs (with different schemes)."}),"\n",(0,a.jsx)(i.h3,{id:"how-does-archival-work-with-pii",children:"How does archival work with PII?"}),"\n",(0,a.jsx)(i.p,{children:"No cadence workflow should ever operate on clear text PII. Cadence can be thought of as a database and just as one would not store PII in a database PII should not be stored in Cadence. This is even more important when archival is enabled because these histories can be kept forever."}),"\n",(0,a.jsx)(i.h2,{id:"planned-future-work",children:"Planned Future Work"}),"\n",(0,a.jsxs)(i.ul,{children:["\n",(0,a.jsx)(i.li,{children:"Support retriving archived workflow histories without providing runID."}),"\n",(0,a.jsx)(i.li,{children:"Provide guarantee that no history or visibility record is deleted from primary persistence before being archived."}),"\n",(0,a.jsxs)(i.li,{children:["Implement ",(0,a.jsx)(i.strong,{children:"Paused"})," state. In this state no archivals will occur but histories or visibility record also will not be deleted from persistence.\nOnce enabled again from paused state, all skipped archivals will occur."]}),"\n"]})]})}function d(e={}){const{wrapper:i}={...(0,t.R)(),...e.components};return i?(0,a.jsx)(i,{...e,children:(0,a.jsx)(h,{...e})}):h(e)}},8453:(e,i,n)=>{n.d(i,{R:()=>o,x:()=>s});var r=n(6540);const a={},t=r.createContext(a);function o(e){const i=r.useContext(t);return r.useMemo((function(){return"function"==typeof e?e(i):{...i,...e}}),[i,e])}function s(e){let i;return i=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:o(e.components),r.createElement(t.Provider,{value:i},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/814f3328.721bb31b.js b/assets/js/814f3328.721bb31b.js deleted file mode 100644 index 438c15ef2..000000000 --- a/assets/js/814f3328.721bb31b.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[7472],{5513:e=>{e.exports=JSON.parse('{"title":"Recent Posts","items":[{"title":"Cadence Repositories Have Moved!","permalink":"/blog/2024/11/18/cadence-workflows-github-organization","unlisted":false,"date":"2024-11-18T14:00:00.000Z"},{"title":"Zonal Isolation for Cadence Workflows","permalink":"/blog/zonal-isolation-v1/zonal-isolation-v1","unlisted":false,"date":"2024-10-14T00:00:00.000Z"},{"title":"Announcement: Cadence Helm Charts v0 Release","permalink":"/blog/2024/10/01/announcing-cadence-helm-charts-v0","unlisted":false,"date":"2024-10-01T00:00:00.000Z"},{"title":"Minimizing blast radius in Cadence: Introducing Workflow ID-based Rate Limits","permalink":"/blog/2024/09/05/workflow-specific-rate-limits","unlisted":false,"date":"2024-09-05T00:00:00.000Z"},{"title":"2024 Cadence Yearly Roadmap Update","permalink":"/blog/2024/07/11/2024-07-11-yearly-roadmap-update/yearly-roadmap-update","unlisted":false,"date":"2024-07-11T00:00:00.000Z"},{"title":"Cadence non-derministic errors common question Q&A (part 1)","permalink":"/blog/2024/02/15/cadence-non-deterministic-common-qa","unlisted":false,"date":"2024-03-10T00:00:00.000Z"},{"title":"Cadence Community Spotlight Update - November 2023","permalink":"/blog/2023/11/30/community-spotlight-update-november-2023","unlisted":false,"date":"2023-11-30T00:00:00.000Z"},{"title":"Cadence Community Spotlight Update - August 2023","permalink":"/blog/2023/08/31/community-spotlight-august-2023","unlisted":false,"date":"2023-08-31T00:00:00.000Z"},{"title":"Non-deterministic errors, replayers and shadowers","permalink":"/blog/2023/08/28/nondeterministic-errors-replayers-shadowers","unlisted":false,"date":"2023-08-27T00:00:00.000Z"},{"title":"Cadence Community Spotlight Update - July 2023","permalink":"/blog/2023/07/31/community-spotlight-july-2023","unlisted":false,"date":"2023-07-31T00:00:00.000Z"},{"title":"Write your first workflow with Cadence","permalink":"/blog/2023/07/16/2023-07-16-write-your-first-workflow-with-cadence/write-your-first-workflow-with-cadence","unlisted":false,"date":"2023-07-16T00:00:00.000Z"},{"title":"Bad practices and Anti-patterns with Cadence (Part 1)","permalink":"/blog/2023/07/10/cadence-bad-practices-part-1","unlisted":false,"date":"2023-07-10T00:00:00.000Z"},{"title":"Implement a Cadence worker service from scratch","permalink":"/blog/2023/07/05/implement-cadence-worker-from-scratch","unlisted":false,"date":"2023-07-05T00:00:00.000Z"},{"title":"Understanding components of Cadence application","permalink":"/blog/2023/06/28/components-of-cadence-application-setup","unlisted":false,"date":"2023-07-01T00:00:00.000Z"},{"title":"Cadence Community Spotlight Update - June 2023","permalink":"/blog/2023/06/30/community-spotlight-june-2023","unlisted":false,"date":"2023-06-30T00:00:00.000Z"},{"title":"2023 Cadence Community Survey Results","permalink":"/blog/2023/06/08/2023-06-08-survey-results/survey-results","unlisted":false,"date":"2023-06-08T00:00:00.000Z"},{"title":"Cadence Community Spotlight Update - March 2023","permalink":"/blog/2023/03/31/community-spotlight-march-2023","unlisted":false,"date":"2023-03-31T00:00:00.000Z"},{"title":"Cadence Community Spotlight Update - March 2024","permalink":"/blog/2024/3/11/community-spotlight-update-march-2024","unlisted":false,"date":"2023-03-11T00:00:00.000Z"},{"title":"Cadence Community Spotlight Update - February 2023","permalink":"/blog/2023/02/28/community-spotlight-february","unlisted":false,"date":"2023-02-28T00:00:00.000Z"},{"title":"Cadence Community Spotlight Update - January 2023","permalink":"/blog/2023/01/31/community-spotlight-january-2023","unlisted":false,"date":"2023-01-31T00:00:00.000Z"},{"title":"Cadence Community Spotlight Update - December 2022","permalink":"/blog/2022/12/23/community-spotlight-december-2022","unlisted":false,"date":"2022-12-23T00:00:00.000Z"},{"title":"Cadence Community Spotlight Update - November 2022","permalink":"/blog/2022/11/30/community-spotlight-november-2022","unlisted":false,"date":"2022-11-30T00:00:00.000Z"},{"title":"Cadence Community Spotlight Update - October 2022","permalink":"/blog/2022/10/31/community-spotlight-october-2022","unlisted":false,"date":"2022-10-31T00:00:00.000Z"},{"title":"Cadence Community Spotlight Update - September 2022","permalink":"/blog/2022/09/30/community-spotlight-september-2022","unlisted":false,"date":"2022-10-11T00:00:00.000Z"},{"title":"Cadence Community Spotlight Update - August 2022","permalink":"/blog/2022/08/31/community-spotlight-august-2022","unlisted":false,"date":"2022-08-31T00:00:00.000Z"},{"title":"Cadence Community Spotlight Update - July 2022","permalink":"/blog/2022/07/31/community-spotlight-update-july-2022","unlisted":false,"date":"2022-07-31T00:00:00.000Z"},{"title":"Cadence Community Spotlight Update - June 2022","permalink":"/blog/2022/06/30/community-spotlight-update-june-2022","unlisted":false,"date":"2022-06-30T00:00:00.000Z"},{"title":"Cadence Community Spotlight Update - May 2022","permalink":"/blog/2022/05/31/community-spotlight-update-may-2022","unlisted":false,"date":"2022-05-31T00:00:00.000Z"},{"title":"Cadence Community Spotlight Update - April 2022","permalink":"/blog/2022/04/30/community-spotlight-update-april-2022","unlisted":false,"date":"2022-04-30T00:00:00.000Z"},{"title":"Cadence Community Spotlight Update - March 2022","permalink":"/blog/2022/03/31/community-spotlight-update-march-2022","unlisted":false,"date":"2022-03-31T00:00:00.000Z"},{"title":"Cadence Community Spotlight Update - February 2022","permalink":"/blog/2022/02/28/community-spotlight-february-2022","unlisted":false,"date":"2022-02-28T00:00:00.000Z"},{"title":"Cadence Community Spotlight Update - January 2022","permalink":"/blog/2022/01/31/community-spotlight-january-2022","unlisted":false,"date":"2022-01-31T00:00:00.000Z"},{"title":"Moving to gRPC","permalink":"/blog/2021/10/19/2021-10-19-moving-to-grpc/moving-to-grpc","unlisted":false,"date":"2021-10-19T00:00:00.000Z"},{"title":"Announcing Cadence OSS office hours and community sync up","permalink":"/blog/2021/10/13/announcing-cadence-oss-office-hours-and-community-sync-up","unlisted":false,"date":"2021-10-13T00:00:00.000Z"},{"title":"Long-term commitment and support for the Cadence project, and its community","permalink":"/blog/2021/09/30/long-term-commitment-and-support-for-the-cadence-project-and-its-community","unlisted":false,"date":"2021-09-30T00:00:00.000Z"}]}')}}]); \ No newline at end of file diff --git a/assets/js/814f3328.e2306031.js b/assets/js/814f3328.e2306031.js new file mode 100644 index 000000000..6f22ad52b --- /dev/null +++ b/assets/js/814f3328.e2306031.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[7472],{5513:e=>{e.exports=JSON.parse('{"title":"Recent Posts","items":[{"title":"Cadence Repositories Have Moved!","permalink":"/Cadence-Docs/blog/2024/11/18/cadence-workflows-github-organization","unlisted":false,"date":"2024-11-18T14:00:00.000Z"},{"title":"Zonal Isolation for Cadence Workflows","permalink":"/Cadence-Docs/blog/zonal-isolation-v1/zonal-isolation-v1","unlisted":false,"date":"2024-10-14T00:00:00.000Z"},{"title":"Announcement: Cadence Helm Charts v0 Release","permalink":"/Cadence-Docs/blog/2024/10/01/announcing-cadence-helm-charts-v0","unlisted":false,"date":"2024-10-01T00:00:00.000Z"},{"title":"Minimizing blast radius in Cadence: Introducing Workflow ID-based Rate Limits","permalink":"/Cadence-Docs/blog/2024/09/05/workflow-specific-rate-limits","unlisted":false,"date":"2024-09-05T00:00:00.000Z"},{"title":"2024 Cadence Yearly Roadmap Update","permalink":"/Cadence-Docs/blog/2024/07/11/2024-07-11-yearly-roadmap-update/yearly-roadmap-update","unlisted":false,"date":"2024-07-11T00:00:00.000Z"},{"title":"Cadence non-derministic errors common question Q&A (part 1)","permalink":"/Cadence-Docs/blog/2024/02/15/cadence-non-deterministic-common-qa","unlisted":false,"date":"2024-03-10T00:00:00.000Z"},{"title":"Cadence Community Spotlight Update - November 2023","permalink":"/Cadence-Docs/blog/2023/11/30/community-spotlight-update-november-2023","unlisted":false,"date":"2023-11-30T00:00:00.000Z"},{"title":"Cadence Community Spotlight Update - August 2023","permalink":"/Cadence-Docs/blog/2023/08/31/community-spotlight-august-2023","unlisted":false,"date":"2023-08-31T00:00:00.000Z"},{"title":"Non-deterministic errors, replayers and shadowers","permalink":"/Cadence-Docs/blog/2023/08/28/nondeterministic-errors-replayers-shadowers","unlisted":false,"date":"2023-08-27T00:00:00.000Z"},{"title":"Cadence Community Spotlight Update - July 2023","permalink":"/Cadence-Docs/blog/2023/07/31/community-spotlight-july-2023","unlisted":false,"date":"2023-07-31T00:00:00.000Z"},{"title":"Write your first workflow with Cadence","permalink":"/Cadence-Docs/blog/2023/07/16/2023-07-16-write-your-first-workflow-with-cadence/write-your-first-workflow-with-cadence","unlisted":false,"date":"2023-07-16T00:00:00.000Z"},{"title":"Bad practices and Anti-patterns with Cadence (Part 1)","permalink":"/Cadence-Docs/blog/2023/07/10/cadence-bad-practices-part-1","unlisted":false,"date":"2023-07-10T00:00:00.000Z"},{"title":"Implement a Cadence worker service from scratch","permalink":"/Cadence-Docs/blog/2023/07/05/implement-cadence-worker-from-scratch","unlisted":false,"date":"2023-07-05T00:00:00.000Z"},{"title":"Understanding components of Cadence application","permalink":"/Cadence-Docs/blog/2023/06/28/components-of-cadence-application-setup","unlisted":false,"date":"2023-07-01T00:00:00.000Z"},{"title":"Cadence Community Spotlight Update - June 2023","permalink":"/Cadence-Docs/blog/2023/06/30/community-spotlight-june-2023","unlisted":false,"date":"2023-06-30T00:00:00.000Z"},{"title":"2023 Cadence Community Survey Results","permalink":"/Cadence-Docs/blog/2023/06/08/2023-06-08-survey-results/survey-results","unlisted":false,"date":"2023-06-08T00:00:00.000Z"},{"title":"Cadence Community Spotlight Update - March 2023","permalink":"/Cadence-Docs/blog/2023/03/31/community-spotlight-march-2023","unlisted":false,"date":"2023-03-31T00:00:00.000Z"},{"title":"Cadence Community Spotlight Update - March 2024","permalink":"/Cadence-Docs/blog/2024/3/11/community-spotlight-update-march-2024","unlisted":false,"date":"2023-03-11T00:00:00.000Z"},{"title":"Cadence Community Spotlight Update - February 2023","permalink":"/Cadence-Docs/blog/2023/02/28/community-spotlight-february","unlisted":false,"date":"2023-02-28T00:00:00.000Z"},{"title":"Cadence Community Spotlight Update - January 2023","permalink":"/Cadence-Docs/blog/2023/01/31/community-spotlight-january-2023","unlisted":false,"date":"2023-01-31T00:00:00.000Z"},{"title":"Cadence Community Spotlight Update - December 2022","permalink":"/Cadence-Docs/blog/2022/12/23/community-spotlight-december-2022","unlisted":false,"date":"2022-12-23T00:00:00.000Z"},{"title":"Cadence Community Spotlight Update - November 2022","permalink":"/Cadence-Docs/blog/2022/11/30/community-spotlight-november-2022","unlisted":false,"date":"2022-11-30T00:00:00.000Z"},{"title":"Cadence Community Spotlight Update - October 2022","permalink":"/Cadence-Docs/blog/2022/10/31/community-spotlight-october-2022","unlisted":false,"date":"2022-10-31T00:00:00.000Z"},{"title":"Cadence Community Spotlight Update - September 2022","permalink":"/Cadence-Docs/blog/2022/09/30/community-spotlight-september-2022","unlisted":false,"date":"2022-10-11T00:00:00.000Z"},{"title":"Cadence Community Spotlight Update - August 2022","permalink":"/Cadence-Docs/blog/2022/08/31/community-spotlight-august-2022","unlisted":false,"date":"2022-08-31T00:00:00.000Z"},{"title":"Cadence Community Spotlight Update - July 2022","permalink":"/Cadence-Docs/blog/2022/07/31/community-spotlight-update-july-2022","unlisted":false,"date":"2022-07-31T00:00:00.000Z"},{"title":"Cadence Community Spotlight Update - June 2022","permalink":"/Cadence-Docs/blog/2022/06/30/community-spotlight-update-june-2022","unlisted":false,"date":"2022-06-30T00:00:00.000Z"},{"title":"Cadence Community Spotlight Update - May 2022","permalink":"/Cadence-Docs/blog/2022/05/31/community-spotlight-update-may-2022","unlisted":false,"date":"2022-05-31T00:00:00.000Z"},{"title":"Cadence Community Spotlight Update - April 2022","permalink":"/Cadence-Docs/blog/2022/04/30/community-spotlight-update-april-2022","unlisted":false,"date":"2022-04-30T00:00:00.000Z"},{"title":"Cadence Community Spotlight Update - March 2022","permalink":"/Cadence-Docs/blog/2022/03/31/community-spotlight-update-march-2022","unlisted":false,"date":"2022-03-31T00:00:00.000Z"},{"title":"Cadence Community Spotlight Update - February 2022","permalink":"/Cadence-Docs/blog/2022/02/28/community-spotlight-february-2022","unlisted":false,"date":"2022-02-28T00:00:00.000Z"},{"title":"Cadence Community Spotlight Update - January 2022","permalink":"/Cadence-Docs/blog/2022/01/31/community-spotlight-january-2022","unlisted":false,"date":"2022-01-31T00:00:00.000Z"},{"title":"Moving to gRPC","permalink":"/Cadence-Docs/blog/2021/10/19/2021-10-19-moving-to-grpc/moving-to-grpc","unlisted":false,"date":"2021-10-19T00:00:00.000Z"},{"title":"Announcing Cadence OSS office hours and community sync up","permalink":"/Cadence-Docs/blog/2021/10/13/announcing-cadence-oss-office-hours-and-community-sync-up","unlisted":false,"date":"2021-10-13T00:00:00.000Z"},{"title":"Long-term commitment and support for the Cadence project, and its community","permalink":"/Cadence-Docs/blog/2021/09/30/long-term-commitment-and-support-for-the-cadence-project-and-its-community","unlisted":false,"date":"2021-09-30T00:00:00.000Z"}]}')}}]); \ No newline at end of file diff --git a/assets/js/82c81335.1a93aeed.js b/assets/js/82c81335.1a93aeed.js deleted file mode 100644 index 2c91d8654..000000000 --- a/assets/js/82c81335.1a93aeed.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[1584],{8417:e=>{e.exports=JSON.parse('{"tag":{"label":"Testing","permalink":"/blog/tags/testing","description":"Testing tag description","allTagsPath":"/blog/tags","count":1,"unlisted":false},"listMetadata":{"permalink":"/blog/tags/testing","page":1,"postsPerPage":10,"totalPages":1,"totalCount":1,"blogDescription":"The latest news and updates from the Cadence team","blogTitle":"Cadence Blog"}}')}}]); \ No newline at end of file diff --git a/assets/js/848b9863.5c957d7e.js b/assets/js/848b9863.5c957d7e.js deleted file mode 100644 index dcc8d895b..000000000 --- a/assets/js/848b9863.5c957d7e.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[7207],{4738:(e,t,r)=>{r.r(t),r.d(t,{assets:()=>c,contentTitle:()=>i,default:()=>k,frontMatter:()=>a,metadata:()=>n,toc:()=>l});const n=JSON.parse('{"id":"java-client/workers","title":"Worker service","description":"A or service is a service that hosts the and implementations. The polls the Cadence service fortaskstask, and communicates execution results back to the Cadence service.Worker: services are developed, deployed, and operated by Cadence customers.","source":"@site/docs/04-java-client/09-workers.md","sourceDirName":"04-java-client","slug":"/java-client/workers","permalink":"/docs/java-client/workers","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/04-java-client/09-workers.md","tags":[],"version":"current","sidebarPosition":9,"frontMatter":{"layout":"default","title":"Worker service","permalink":"/docs/java-client/workers"},"sidebar":"docsSidebar","previous":{"title":"Distributed CRON","permalink":"/docs/java-client/distributed-cron"},"next":{"title":"Signals","permalink":"/docs/java-client/signals"}}');var o=r(4848),s=r(8453);const a={layout:"default",title:"Worker service",permalink:"/docs/java-client/workers"},i="Worker service",c={},l=[];function d(e){const t={a:"a",code:"code",em:"em",h1:"h1",header:"header",p:"p",pre:"pre",...(0,s.R)(),...e.components};return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsx)(t.header,{children:(0,o.jsx)(t.h1,{id:"worker-service",children:"Worker service"})}),"\n",(0,o.jsxs)(t.p,{children:["A worker or ",(0,o.jsx)(t.em,{children:"worker service"})," is a service that hosts the workflow and activity implementations. The worker polls the ",(0,o.jsx)(t.em,{children:"Cadence service"})," for tasks, performs those tasks, and communicates task execution results back to the ",(0,o.jsx)(t.em,{children:"Cadence service"}),". Worker services are developed, deployed, and operated by Cadence customers."]}),"\n",(0,o.jsx)(t.p,{children:"You can run a Cadence worker in a new or an existing service. Use the framework APIs to start the Cadence worker and link in all activity and workflow implementations that you require the service to execute."}),"\n",(0,o.jsx)(t.pre,{children:(0,o.jsx)(t.code,{className:"language-java",children:" WorkerFactory factory = WorkerFactory.newInstance(workflowClient,\n WorkerFactoryOptions.newBuilder()\n .setMaxWorkflowThreadCount(1000)\n .setStickyCacheSize(100)\n .setDisableStickyExecution(false)\n .build());\n Worker worker = factory.newWorker(TASK_LIST,\n WorkerOptions.newBuilder()\n .setMaxConcurrentActivityExecutionSize(100)\n .setMaxConcurrentWorkflowExecutionSize(100)\n .build());\n\n // Workflows are stateful. So you need a type to create instances.\n worker.registerWorkflowImplementationTypes(GreetingWorkflowImpl.class);\n // Activities are stateless and thread safe. So a shared instance is used.\n worker.registerActivitiesImplementations(new GreetingActivitiesImpl());\n // Start listening to the workflow and activity task lists.\n factory.start();\n"})}),"\n",(0,o.jsx)(t.p,{children:"The code is slightly different if you are using client version prior to 3.0.0:"}),"\n",(0,o.jsx)(t.pre,{children:(0,o.jsx)(t.code,{className:"language-java",children:"Worker.Factory factory = new Worker.Factory(DOMAIN,\n new Worker.FactoryOptions.Builder()\n .setMaxWorkflowThreadCount(1000)\n .setCacheMaximumSize(100)\n .setDisableStickyExecution(false)\n .build());\n Worker worker = factory.newWorker(TASK_LIST,\n new WorkerOptions.Builder()\n .setMaxConcurrentActivityExecutionSize(100)\n .setMaxConcurrentWorkflowExecutionSize(100)\n .build());\n // Workflows are stateful. So you need a type to create instances.\n worker.registerWorkflowImplementationTypes(GreetingWorkflowImpl.class);\n // Activities are stateless and thread safe. So a shared instance is used.\n worker.registerActivitiesImplementations(new GreetingActivitiesImpl());\n // Start listening to the workflow and activity task lists.\n factory.start();\n"})}),"\n",(0,o.jsxs)(t.p,{children:["The ",(0,o.jsx)(t.a,{href:"https://www.javadoc.io/static/com.uber.cadence/cadence-client/2.7.9-alpha/com/cadence-workflow/cadence/worker/WorkerFactoryOptions.html",children:"WorkerFactoryOptions"})," includes those that need to be shared across workers on the hosts like thread pool, sticky cache."]}),"\n",(0,o.jsxs)(t.p,{children:["In ",(0,o.jsx)(t.a,{href:"https://www.javadoc.io/static/com.uber.cadence/cadence-client/2.7.9-alpha/com/cadence-workflow/cadence/worker/WorkerOptions.Builder.html",children:"WorkerOptions"})," you can customize things like pollerOptions, activities per second."]})]})}function k(e={}){const{wrapper:t}={...(0,s.R)(),...e.components};return t?(0,o.jsx)(t,{...e,children:(0,o.jsx)(d,{...e})}):d(e)}},8453:(e,t,r)=>{r.d(t,{R:()=>a,x:()=>i});var n=r(6540);const o={},s=n.createContext(o);function a(e){const t=n.useContext(s);return n.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function i(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:a(e.components),n.createElement(s.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/848b9863.5ea04886.js b/assets/js/848b9863.5ea04886.js new file mode 100644 index 000000000..35d74f02d --- /dev/null +++ b/assets/js/848b9863.5ea04886.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[7207],{4738:(e,t,r)=>{r.r(t),r.d(t,{assets:()=>c,contentTitle:()=>i,default:()=>k,frontMatter:()=>a,metadata:()=>n,toc:()=>l});const n=JSON.parse('{"id":"java-client/workers","title":"Worker service","description":"A or service is a service that hosts the and implementations. The polls the Cadence service fortaskstask, and communicates execution results back to the Cadence service.Worker: services are developed, deployed, and operated by Cadence customers.","source":"@site/docs/04-java-client/09-workers.md","sourceDirName":"04-java-client","slug":"/java-client/workers","permalink":"/Cadence-Docs/docs/java-client/workers","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/04-java-client/09-workers.md","tags":[],"version":"current","sidebarPosition":9,"frontMatter":{"layout":"default","title":"Worker service","permalink":"/docs/java-client/workers"},"sidebar":"docsSidebar","previous":{"title":"Distributed CRON","permalink":"/Cadence-Docs/docs/java-client/distributed-cron"},"next":{"title":"Signals","permalink":"/Cadence-Docs/docs/java-client/signals"}}');var o=r(4848),s=r(8453);const a={layout:"default",title:"Worker service",permalink:"/docs/java-client/workers"},i="Worker service",c={},l=[];function d(e){const t={a:"a",code:"code",em:"em",h1:"h1",header:"header",p:"p",pre:"pre",...(0,s.R)(),...e.components};return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsx)(t.header,{children:(0,o.jsx)(t.h1,{id:"worker-service",children:"Worker service"})}),"\n",(0,o.jsxs)(t.p,{children:["A worker or ",(0,o.jsx)(t.em,{children:"worker service"})," is a service that hosts the workflow and activity implementations. The worker polls the ",(0,o.jsx)(t.em,{children:"Cadence service"})," for tasks, performs those tasks, and communicates task execution results back to the ",(0,o.jsx)(t.em,{children:"Cadence service"}),". Worker services are developed, deployed, and operated by Cadence customers."]}),"\n",(0,o.jsx)(t.p,{children:"You can run a Cadence worker in a new or an existing service. Use the framework APIs to start the Cadence worker and link in all activity and workflow implementations that you require the service to execute."}),"\n",(0,o.jsx)(t.pre,{children:(0,o.jsx)(t.code,{className:"language-java",children:" WorkerFactory factory = WorkerFactory.newInstance(workflowClient,\n WorkerFactoryOptions.newBuilder()\n .setMaxWorkflowThreadCount(1000)\n .setStickyCacheSize(100)\n .setDisableStickyExecution(false)\n .build());\n Worker worker = factory.newWorker(TASK_LIST,\n WorkerOptions.newBuilder()\n .setMaxConcurrentActivityExecutionSize(100)\n .setMaxConcurrentWorkflowExecutionSize(100)\n .build());\n\n // Workflows are stateful. So you need a type to create instances.\n worker.registerWorkflowImplementationTypes(GreetingWorkflowImpl.class);\n // Activities are stateless and thread safe. So a shared instance is used.\n worker.registerActivitiesImplementations(new GreetingActivitiesImpl());\n // Start listening to the workflow and activity task lists.\n factory.start();\n"})}),"\n",(0,o.jsx)(t.p,{children:"The code is slightly different if you are using client version prior to 3.0.0:"}),"\n",(0,o.jsx)(t.pre,{children:(0,o.jsx)(t.code,{className:"language-java",children:"Worker.Factory factory = new Worker.Factory(DOMAIN,\n new Worker.FactoryOptions.Builder()\n .setMaxWorkflowThreadCount(1000)\n .setCacheMaximumSize(100)\n .setDisableStickyExecution(false)\n .build());\n Worker worker = factory.newWorker(TASK_LIST,\n new WorkerOptions.Builder()\n .setMaxConcurrentActivityExecutionSize(100)\n .setMaxConcurrentWorkflowExecutionSize(100)\n .build());\n // Workflows are stateful. So you need a type to create instances.\n worker.registerWorkflowImplementationTypes(GreetingWorkflowImpl.class);\n // Activities are stateless and thread safe. So a shared instance is used.\n worker.registerActivitiesImplementations(new GreetingActivitiesImpl());\n // Start listening to the workflow and activity task lists.\n factory.start();\n"})}),"\n",(0,o.jsxs)(t.p,{children:["The ",(0,o.jsx)(t.a,{href:"https://www.javadoc.io/static/com.uber.cadence/cadence-client/2.7.9-alpha/com/cadence-workflow/cadence/worker/WorkerFactoryOptions.html",children:"WorkerFactoryOptions"})," includes those that need to be shared across workers on the hosts like thread pool, sticky cache."]}),"\n",(0,o.jsxs)(t.p,{children:["In ",(0,o.jsx)(t.a,{href:"https://www.javadoc.io/static/com.uber.cadence/cadence-client/2.7.9-alpha/com/cadence-workflow/cadence/worker/WorkerOptions.Builder.html",children:"WorkerOptions"})," you can customize things like pollerOptions, activities per second."]})]})}function k(e={}){const{wrapper:t}={...(0,s.R)(),...e.components};return t?(0,o.jsx)(t,{...e,children:(0,o.jsx)(d,{...e})}):d(e)}},8453:(e,t,r)=>{r.d(t,{R:()=>a,x:()=>i});var n=r(6540);const o={},s=n.createContext(o);function a(e){const t=n.useContext(s);return n.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function i(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:a(e.components),n.createElement(s.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/8498.b45384a3.js b/assets/js/8498.095e3977.js similarity index 99% rename from assets/js/8498.b45384a3.js rename to assets/js/8498.095e3977.js index 4eb9d3868..2868834ed 100644 --- a/assets/js/8498.b45384a3.js +++ b/assets/js/8498.095e3977.js @@ -1 +1 @@ -(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[8498],{7293:(e,t,n)=>{"use strict";n.d(t,{A:()=>S});var s=n(6540),o=n(4848);function a(e){const{mdxAdmonitionTitle:t,rest:n}=function(e){const t=s.Children.toArray(e),n=t.find((e=>s.isValidElement(e)&&"mdxAdmonitionTitle"===e.type)),a=t.filter((e=>e!==n)),c=n?.props.children;return{mdxAdmonitionTitle:c,rest:a.length>0?(0,o.jsx)(o.Fragment,{children:a}):null}}(e.children),a=e.title??t;return{...e,...a&&{title:a},children:n}}var c=n(4164),r=n(1312),i=n(7559);const l="admonition_xJq3",d="admonitionHeading_Gvgb",u="admonitionIcon_Rf37",m="admonitionContent_BuS1";function h(e){let{type:t,className:n,children:s}=e;return(0,o.jsx)("div",{className:(0,c.A)(i.G.common.admonition,i.G.common.admonitionType(t),l,n),children:s})}function p(e){let{icon:t,title:n}=e;return(0,o.jsxs)("div",{className:d,children:[(0,o.jsx)("span",{className:u,children:t}),n]})}function f(e){let{children:t}=e;return t?(0,o.jsx)("div",{className:m,children:t}):null}function x(e){const{type:t,icon:n,title:s,children:a,className:c}=e;return(0,o.jsxs)(h,{type:t,className:c,children:[s||n?(0,o.jsx)(p,{title:s,icon:n}):null,(0,o.jsx)(f,{children:a})]})}function j(e){return(0,o.jsx)("svg",{viewBox:"0 0 14 16",...e,children:(0,o.jsx)("path",{fillRule:"evenodd",d:"M6.3 5.69a.942.942 0 0 1-.28-.7c0-.28.09-.52.28-.7.19-.18.42-.28.7-.28.28 0 .52.09.7.28.18.19.28.42.28.7 0 .28-.09.52-.28.7a1 1 0 0 1-.7.3c-.28 0-.52-.11-.7-.3zM8 7.99c-.02-.25-.11-.48-.31-.69-.2-.19-.42-.3-.69-.31H6c-.27.02-.48.13-.69.31-.2.2-.3.44-.31.69h1v3c.02.27.11.5.31.69.2.2.42.31.69.31h1c.27 0 .48-.11.69-.31.2-.19.3-.42.31-.69H8V7.98v.01zM7 2.3c-3.14 0-5.7 2.54-5.7 5.68 0 3.14 2.56 5.7 5.7 5.7s5.7-2.55 5.7-5.7c0-3.15-2.56-5.69-5.7-5.69v.01zM7 .98c3.86 0 7 3.14 7 7s-3.14 7-7 7-7-3.12-7-7 3.14-7 7-7z"})})}const b={icon:(0,o.jsx)(j,{}),title:(0,o.jsx)(r.A,{id:"theme.admonition.note",description:"The default label used for the Note admonition (:::note)",children:"note"})};function g(e){return(0,o.jsx)(x,{...b,...e,className:(0,c.A)("alert alert--secondary",e.className),children:e.children})}function v(e){return(0,o.jsx)("svg",{viewBox:"0 0 12 16",...e,children:(0,o.jsx)("path",{fillRule:"evenodd",d:"M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"})})}const y={icon:(0,o.jsx)(v,{}),title:(0,o.jsx)(r.A,{id:"theme.admonition.tip",description:"The default label used for the Tip admonition (:::tip)",children:"tip"})};function N(e){return(0,o.jsx)(x,{...y,...e,className:(0,c.A)("alert alert--success",e.className),children:e.children})}function A(e){return(0,o.jsx)("svg",{viewBox:"0 0 14 16",...e,children:(0,o.jsx)("path",{fillRule:"evenodd",d:"M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"})})}const k={icon:(0,o.jsx)(A,{}),title:(0,o.jsx)(r.A,{id:"theme.admonition.info",description:"The default label used for the Info admonition (:::info)",children:"info"})};function B(e){return(0,o.jsx)(x,{...k,...e,className:(0,c.A)("alert alert--info",e.className),children:e.children})}function w(e){return(0,o.jsx)("svg",{viewBox:"0 0 16 16",...e,children:(0,o.jsx)("path",{fillRule:"evenodd",d:"M8.893 1.5c-.183-.31-.52-.5-.887-.5s-.703.19-.886.5L.138 13.499a.98.98 0 0 0 0 1.001c.193.31.53.501.886.501h13.964c.367 0 .704-.19.877-.5a1.03 1.03 0 0 0 .01-1.002L8.893 1.5zm.133 11.497H6.987v-2.003h2.039v2.003zm0-3.004H6.987V5.987h2.039v4.006z"})})}const C={icon:(0,o.jsx)(w,{}),title:(0,o.jsx)(r.A,{id:"theme.admonition.warning",description:"The default label used for the Warning admonition (:::warning)",children:"warning"})};function E(e){return(0,o.jsx)("svg",{viewBox:"0 0 12 16",...e,children:(0,o.jsx)("path",{fillRule:"evenodd",d:"M5.05.31c.81 2.17.41 3.38-.52 4.31C3.55 5.67 1.98 6.45.9 7.98c-1.45 2.05-1.7 6.53 3.53 7.7-2.2-1.16-2.67-4.52-.3-6.61-.61 2.03.53 3.33 1.94 2.86 1.39-.47 2.3.53 2.27 1.67-.02.78-.31 1.44-1.13 1.81 3.42-.59 4.78-3.42 4.78-5.56 0-2.84-2.53-3.22-1.25-5.61-1.52.13-2.03 1.13-1.89 2.75.09 1.08-1.02 1.8-1.86 1.33-.67-.41-.66-1.19-.06-1.78C8.18 5.31 8.68 2.45 5.05.32L5.03.3l.02.01z"})})}const T={icon:(0,o.jsx)(E,{}),title:(0,o.jsx)(r.A,{id:"theme.admonition.danger",description:"The default label used for the Danger admonition (:::danger)",children:"danger"})};const L={icon:(0,o.jsx)(w,{}),title:(0,o.jsx)(r.A,{id:"theme.admonition.caution",description:"The default label used for the Caution admonition (:::caution)",children:"caution"})};const _={...{note:g,tip:N,info:B,warning:function(e){return(0,o.jsx)(x,{...C,...e,className:(0,c.A)("alert alert--warning",e.className),children:e.children})},danger:function(e){return(0,o.jsx)(x,{...T,...e,className:(0,c.A)("alert alert--danger",e.className),children:e.children})}},...{secondary:e=>(0,o.jsx)(g,{title:"secondary",...e}),important:e=>(0,o.jsx)(B,{title:"important",...e}),success:e=>(0,o.jsx)(N,{title:"success",...e}),caution:function(e){return(0,o.jsx)(x,{...L,...e,className:(0,c.A)("alert alert--warning",e.className),children:e.children})}}};function S(e){const t=a(e),n=(s=t.type,_[s]||(console.warn(`No admonition component found for admonition type "${s}". Using Info as fallback.`),_.info));var s;return(0,o.jsx)(n,{...t})}},4336:(e,t,n)=>{"use strict";n.d(t,{A:()=>x});n(6540);var s=n(4164),o=n(1312),a=n(7559),c=n(8774);const r={iconEdit:"iconEdit_Z9Sw"};var i=n(4848);function l(e){let{className:t,...n}=e;return(0,i.jsx)("svg",{fill:"currentColor",height:"20",width:"20",viewBox:"0 0 40 40",className:(0,s.A)(r.iconEdit,t),"aria-hidden":"true",...n,children:(0,i.jsx)("g",{children:(0,i.jsx)("path",{d:"m34.5 11.7l-3 3.1-6.3-6.3 3.1-3q0.5-0.5 1.2-0.5t1.1 0.5l3.9 3.9q0.5 0.4 0.5 1.1t-0.5 1.2z m-29.5 17.1l18.4-18.5 6.3 6.3-18.4 18.4h-6.3v-6.2z"})})})}function d(e){let{editUrl:t}=e;return(0,i.jsxs)(c.A,{to:t,className:a.G.common.editThisPage,children:[(0,i.jsx)(l,{}),(0,i.jsx)(o.A,{id:"theme.common.editThisPage",description:"The link label to edit the current page",children:"Edit this page"})]})}var u=n(6266);function m(e){let{lastUpdatedAt:t}=e;const n=new Date(t),s=(0,u.i)({day:"numeric",month:"short",year:"numeric",timeZone:"UTC"}).format(n);return(0,i.jsx)(o.A,{id:"theme.lastUpdated.atDate",description:"The words used to describe on which date a page has been last updated",values:{date:(0,i.jsx)("b",{children:(0,i.jsx)("time",{dateTime:n.toISOString(),itemProp:"dateModified",children:s})})},children:" on {date}"})}function h(e){let{lastUpdatedBy:t}=e;return(0,i.jsx)(o.A,{id:"theme.lastUpdated.byUser",description:"The words used to describe by who the page has been last updated",values:{user:(0,i.jsx)("b",{children:t})},children:" by {user}"})}function p(e){let{lastUpdatedAt:t,lastUpdatedBy:n}=e;return(0,i.jsxs)("span",{className:a.G.common.lastUpdated,children:[(0,i.jsx)(o.A,{id:"theme.lastUpdated.lastUpdatedAtBy",description:"The sentence used to display when a page has been last updated, and by who",values:{atDate:t?(0,i.jsx)(m,{lastUpdatedAt:t}):"",byUser:n?(0,i.jsx)(h,{lastUpdatedBy:n}):""},children:"Last updated{atDate}{byUser}"}),!1]})}const f={lastUpdated:"lastUpdated_JAkA"};function x(e){let{className:t,editUrl:n,lastUpdatedAt:o,lastUpdatedBy:a}=e;return(0,i.jsxs)("div",{className:(0,s.A)("row",t),children:[(0,i.jsx)("div",{className:"col",children:n&&(0,i.jsx)(d,{editUrl:n})}),(0,i.jsx)("div",{className:(0,s.A)("col",f.lastUpdated),children:(o||a)&&(0,i.jsx)(p,{lastUpdatedAt:o,lastUpdatedBy:a})})]})}},8509:(e,t,n)=>{"use strict";n.d(t,{A:()=>ue});var s=n(6540),o=n(8453),a=n(5260),c=n(2303),r=n(4164),i=n(5293),l=n(6342);function d(){const{prism:e}=(0,l.p)(),{colorMode:t}=(0,i.G)(),n=e.theme,s=e.darkTheme||n;return"dark"===t?s:n}var u=n(7559),m=n(8426),h=n.n(m);const p=/title=(?["'])(?.*?)\1/,f=/\{(?<range>[\d,-]+)\}/,x={js:{start:"\\/\\/",end:""},jsBlock:{start:"\\/\\*",end:"\\*\\/"},jsx:{start:"\\{\\s*\\/\\*",end:"\\*\\/\\s*\\}"},bash:{start:"#",end:""},html:{start:"\x3c!--",end:"--\x3e"}},j={...x,lua:{start:"--",end:""},wasm:{start:"\\;\\;",end:""},tex:{start:"%",end:""},vb:{start:"['\u2018\u2019]",end:""},vbnet:{start:"(?:_\\s*)?['\u2018\u2019]",end:""},rem:{start:"[Rr][Ee][Mm]\\b",end:""},f90:{start:"!",end:""},ml:{start:"\\(\\*",end:"\\*\\)"},cobol:{start:"\\*>",end:""}},b=Object.keys(x);function g(e,t){const n=e.map((e=>{const{start:n,end:s}=j[e];return`(?:${n}\\s*(${t.flatMap((e=>[e.line,e.block?.start,e.block?.end].filter(Boolean))).join("|")})\\s*${s})`})).join("|");return new RegExp(`^\\s*(?:${n})\\s*$`)}function v(e,t){let n=e.replace(/\n$/,"");const{language:s,magicComments:o,metastring:a}=t;if(a&&f.test(a)){const e=a.match(f).groups.range;if(0===o.length)throw new Error(`A highlight range has been given in code block's metastring (\`\`\` ${a}), but no magic comment config is available. Docusaurus applies the first magic comment entry's className for metastring ranges.`);const t=o[0].className,s=h()(e).filter((e=>e>0)).map((e=>[e-1,[t]]));return{lineClassNames:Object.fromEntries(s),code:n}}if(void 0===s)return{lineClassNames:{},code:n};const c=function(e,t){switch(e){case"js":case"javascript":case"ts":case"typescript":return g(["js","jsBlock"],t);case"jsx":case"tsx":return g(["js","jsBlock","jsx"],t);case"html":return g(["js","jsBlock","html"],t);case"python":case"py":case"bash":return g(["bash"],t);case"markdown":case"md":return g(["html","jsx","bash"],t);case"tex":case"latex":case"matlab":return g(["tex"],t);case"lua":case"haskell":case"sql":return g(["lua"],t);case"wasm":return g(["wasm"],t);case"vb":case"vba":case"visual-basic":return g(["vb","rem"],t);case"vbnet":return g(["vbnet","rem"],t);case"batch":return g(["rem"],t);case"basic":return g(["rem","f90"],t);case"fsharp":return g(["js","ml"],t);case"ocaml":case"sml":return g(["ml"],t);case"fortran":return g(["f90"],t);case"cobol":return g(["cobol"],t);default:return g(b,t)}}(s,o),r=n.split("\n"),i=Object.fromEntries(o.map((e=>[e.className,{start:0,range:""}]))),l=Object.fromEntries(o.filter((e=>e.line)).map((e=>{let{className:t,line:n}=e;return[n,t]}))),d=Object.fromEntries(o.filter((e=>e.block)).map((e=>{let{className:t,block:n}=e;return[n.start,t]}))),u=Object.fromEntries(o.filter((e=>e.block)).map((e=>{let{className:t,block:n}=e;return[n.end,t]})));for(let h=0;h<r.length;){const e=r[h].match(c);if(!e){h+=1;continue}const t=e.slice(1).find((e=>void 0!==e));l[t]?i[l[t]].range+=`${h},`:d[t]?i[d[t]].start=h:u[t]&&(i[u[t]].range+=`${i[u[t]].start}-${h-1},`),r.splice(h,1)}n=r.join("\n");const m={};return Object.entries(i).forEach((e=>{let[t,{range:n}]=e;h()(n).forEach((e=>{m[e]??=[],m[e].push(t)}))})),{lineClassNames:m,code:n}}const y="codeBlockContainer_Ckt0";var N=n(4848);function A(e){let{as:t,...n}=e;const s=function(e){const t={color:"--prism-color",backgroundColor:"--prism-background-color"},n={};return Object.entries(e.plain).forEach((e=>{let[s,o]=e;const a=t[s];a&&"string"==typeof o&&(n[a]=o)})),n}(d());return(0,N.jsx)(t,{...n,style:s,className:(0,r.A)(n.className,y,u.G.common.codeBlock)})}const k={codeBlockContent:"codeBlockContent_biex",codeBlockTitle:"codeBlockTitle_Ktv7",codeBlock:"codeBlock_bY9V",codeBlockStandalone:"codeBlockStandalone_MEMb",codeBlockLines:"codeBlockLines_e6Vv",codeBlockLinesWithNumbering:"codeBlockLinesWithNumbering_o6Pm",buttonGroup:"buttonGroup__atx"};function B(e){let{children:t,className:n}=e;return(0,N.jsx)(A,{as:"pre",tabIndex:0,className:(0,r.A)(k.codeBlockStandalone,"thin-scrollbar",n),children:(0,N.jsx)("code",{className:k.codeBlockLines,children:t})})}var w=n(9532);const C={attributes:!0,characterData:!0,childList:!0,subtree:!0};function E(e,t){const[n,o]=(0,s.useState)(),a=(0,s.useCallback)((()=>{o(e.current?.closest("[role=tabpanel][hidden]"))}),[e,o]);(0,s.useEffect)((()=>{a()}),[a]),function(e,t,n){void 0===n&&(n=C);const o=(0,w._q)(t),a=(0,w.Be)(n);(0,s.useEffect)((()=>{const t=new MutationObserver(o);return e&&t.observe(e,a),()=>t.disconnect()}),[e,o,a])}(n,(e=>{e.forEach((e=>{"attributes"===e.type&&"hidden"===e.attributeName&&(t(),a())}))}),{attributes:!0,characterData:!1,childList:!1,subtree:!1})}var T=n(1765);const L="codeLine_lJS_",_="codeLineNumber_Tfdd",S="codeLineContent_feaV";function U(e){let{line:t,classNames:n,showLineNumbers:s,getLineProps:o,getTokenProps:a}=e;1===t.length&&"\n"===t[0].content&&(t[0].content="");const c=o({line:t,className:(0,r.A)(n,s&&L)}),i=t.map(((e,t)=>(0,N.jsx)("span",{...a({token:e})},t)));return(0,N.jsxs)("span",{...c,children:[s?(0,N.jsxs)(N.Fragment,{children:[(0,N.jsx)("span",{className:_}),(0,N.jsx)("span",{className:S,children:i})]}):i,(0,N.jsx)("br",{})]})}var M=n(1312);function z(e){return(0,N.jsx)("svg",{viewBox:"0 0 24 24",...e,children:(0,N.jsx)("path",{fill:"currentColor",d:"M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"})})}function H(e){return(0,N.jsx)("svg",{viewBox:"0 0 24 24",...e,children:(0,N.jsx)("path",{fill:"currentColor",d:"M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"})})}const I={copyButtonCopied:"copyButtonCopied_obH4",copyButtonIcons:"copyButtonIcons_eSgA",copyButtonIcon:"copyButtonIcon_y97N",copyButtonSuccessIcon:"copyButtonSuccessIcon_LjdS"};function R(e){let{code:t,className:n}=e;const[o,a]=(0,s.useState)(!1),c=(0,s.useRef)(void 0),i=(0,s.useCallback)((()=>{!function(e,t){let{target:n=document.body}=void 0===t?{}:t;if("string"!=typeof e)throw new TypeError(`Expected parameter \`text\` to be a \`string\`, got \`${typeof e}\`.`);const s=document.createElement("textarea"),o=document.activeElement;s.value=e,s.setAttribute("readonly",""),s.style.contain="strict",s.style.position="absolute",s.style.left="-9999px",s.style.fontSize="12pt";const a=document.getSelection(),c=a.rangeCount>0&&a.getRangeAt(0);n.append(s),s.select(),s.selectionStart=0,s.selectionEnd=e.length;let r=!1;try{r=document.execCommand("copy")}catch{}s.remove(),c&&(a.removeAllRanges(),a.addRange(c)),o&&o.focus()}(t),a(!0),c.current=window.setTimeout((()=>{a(!1)}),1e3)}),[t]);return(0,s.useEffect)((()=>()=>window.clearTimeout(c.current)),[]),(0,N.jsx)("button",{type:"button","aria-label":o?(0,M.T)({id:"theme.CodeBlock.copied",message:"Copied",description:"The copied button label on code blocks"}):(0,M.T)({id:"theme.CodeBlock.copyButtonAriaLabel",message:"Copy code to clipboard",description:"The ARIA label for copy code blocks button"}),title:(0,M.T)({id:"theme.CodeBlock.copy",message:"Copy",description:"The copy button label on code blocks"}),className:(0,r.A)("clean-btn",n,I.copyButton,o&&I.copyButtonCopied),onClick:i,children:(0,N.jsxs)("span",{className:I.copyButtonIcons,"aria-hidden":"true",children:[(0,N.jsx)(z,{className:I.copyButtonIcon}),(0,N.jsx)(H,{className:I.copyButtonSuccessIcon})]})})}function V(e){return(0,N.jsx)("svg",{viewBox:"0 0 24 24",...e,children:(0,N.jsx)("path",{fill:"currentColor",d:"M4 19h6v-2H4v2zM20 5H4v2h16V5zm-3 6H4v2h13.25c1.1 0 2 .9 2 2s-.9 2-2 2H15v-2l-3 3l3 3v-2h2c2.21 0 4-1.79 4-4s-1.79-4-4-4z"})})}const $="wordWrapButtonIcon_Bwma",D="wordWrapButtonEnabled_EoeP";function P(e){let{className:t,onClick:n,isEnabled:s}=e;const o=(0,M.T)({id:"theme.CodeBlock.wordWrapToggle",message:"Toggle word wrap",description:"The title attribute for toggle word wrapping button of code block lines"});return(0,N.jsx)("button",{type:"button",onClick:n,className:(0,r.A)("clean-btn",t,s&&D),"aria-label":o,title:o,children:(0,N.jsx)(V,{className:$,"aria-hidden":"true"})})}function W(e){let{children:t,className:n="",metastring:o,title:a,showLineNumbers:c,language:i}=e;const{prism:{defaultLanguage:u,magicComments:m}}=(0,l.p)(),h=function(e){return e?.toLowerCase()}(i??function(e){const t=e.split(" ").find((e=>e.startsWith("language-")));return t?.replace(/language-/,"")}(n)??u),f=d(),x=function(){const[e,t]=(0,s.useState)(!1),[n,o]=(0,s.useState)(!1),a=(0,s.useRef)(null),c=(0,s.useCallback)((()=>{const n=a.current.querySelector("code");e?n.removeAttribute("style"):(n.style.whiteSpace="pre-wrap",n.style.overflowWrap="anywhere"),t((e=>!e))}),[a,e]),r=(0,s.useCallback)((()=>{const{scrollWidth:e,clientWidth:t}=a.current,n=e>t||a.current.querySelector("code").hasAttribute("style");o(n)}),[a]);return E(a,r),(0,s.useEffect)((()=>{r()}),[e,r]),(0,s.useEffect)((()=>(window.addEventListener("resize",r,{passive:!0}),()=>{window.removeEventListener("resize",r)})),[r]),{codeBlockRef:a,isEnabled:e,isCodeScrollable:n,toggle:c}}(),j=function(e){return e?.match(p)?.groups.title??""}(o)||a,{lineClassNames:b,code:g}=v(t,{metastring:o,language:h,magicComments:m}),y=c??function(e){return Boolean(e?.includes("showLineNumbers"))}(o);return(0,N.jsxs)(A,{as:"div",className:(0,r.A)(n,h&&!n.includes(`language-${h}`)&&`language-${h}`),children:[j&&(0,N.jsx)("div",{className:k.codeBlockTitle,children:j}),(0,N.jsxs)("div",{className:k.codeBlockContent,children:[(0,N.jsx)(T.f4,{theme:f,code:g,language:h??"text",children:e=>{let{className:t,style:n,tokens:s,getLineProps:o,getTokenProps:a}=e;return(0,N.jsx)("pre",{tabIndex:0,ref:x.codeBlockRef,className:(0,r.A)(t,k.codeBlock,"thin-scrollbar"),style:n,children:(0,N.jsx)("code",{className:(0,r.A)(k.codeBlockLines,y&&k.codeBlockLinesWithNumbering),children:s.map(((e,t)=>(0,N.jsx)(U,{line:e,getLineProps:o,getTokenProps:a,classNames:b[t],showLineNumbers:y},t)))})})}}),(0,N.jsxs)("div",{className:k.buttonGroup,children:[(x.isEnabled||x.isCodeScrollable)&&(0,N.jsx)(P,{className:k.codeButton,onClick:()=>x.toggle(),isEnabled:x.isEnabled}),(0,N.jsx)(R,{className:k.codeButton,code:g})]})]})]})}function q(e){let{children:t,...n}=e;const o=(0,c.A)(),a=function(e){return s.Children.toArray(e).some((e=>(0,s.isValidElement)(e)))?e:Array.isArray(e)?e.join(""):e}(t),r="string"==typeof a?W:B;return(0,N.jsx)(r,{...n,children:a},String(o))}function G(e){return(0,N.jsx)("code",{...e})}var O=n(8774);var F=n(3427),Z=n(1422);const J="details_lb9f",Y="isBrowser_bmU9",K="collapsibleContent_i85q";function Q(e){return!!e&&("SUMMARY"===e.tagName||Q(e.parentElement))}function X(e,t){return!!e&&(e===t||X(e.parentElement,t))}function ee(e){let{summary:t,children:n,...o}=e;(0,F.A)().collectAnchor(o.id);const a=(0,c.A)(),i=(0,s.useRef)(null),{collapsed:l,setCollapsed:d}=(0,Z.u)({initialState:!o.open}),[u,m]=(0,s.useState)(o.open),h=s.isValidElement(t)?t:(0,N.jsx)("summary",{children:t??"Details"});return(0,N.jsxs)("details",{...o,ref:i,open:u,"data-collapsed":l,className:(0,r.A)(J,a&&Y,o.className),onMouseDown:e=>{Q(e.target)&&e.detail>1&&e.preventDefault()},onClick:e=>{e.stopPropagation();const t=e.target;Q(t)&&X(t,i.current)&&(e.preventDefault(),l?(d(!1),m(!0)):d(!0))},children:[h,(0,N.jsx)(Z.N,{lazy:!1,collapsed:l,disableSSRStyle:!0,onCollapseTransitionEnd:e=>{d(e),m(!e)},children:(0,N.jsx)("div",{className:K,children:n})})]})}const te="details_b_Ee";function ne(e){let{...t}=e;return(0,N.jsx)(ee,{...t,className:(0,r.A)("alert alert--info",te,t.className)})}function se(e){const t=s.Children.toArray(e.children),n=t.find((e=>s.isValidElement(e)&&"summary"===e.type)),o=(0,N.jsx)(N.Fragment,{children:t.filter((e=>e!==n))});return(0,N.jsx)(ne,{...e,summary:n,children:o})}var oe=n(1107);function ae(e){return(0,N.jsx)(oe.A,{...e})}const ce="containsTaskList_mC6p";function re(e){if(void 0!==e)return(0,r.A)(e,e?.includes("contains-task-list")&&ce)}const ie="img_ev3q";var le=n(7293);const de={Head:a.A,details:se,Details:se,code:function(e){return function(e){return void 0!==e.children&&s.Children.toArray(e.children).every((e=>"string"==typeof e&&!e.includes("\n")))}(e)?(0,N.jsx)(G,{...e}):(0,N.jsx)(q,{...e})},a:function(e){return(0,N.jsx)(O.A,{...e})},pre:function(e){return(0,N.jsx)(N.Fragment,{children:e.children})},ul:function(e){return(0,N.jsx)("ul",{...e,className:re(e.className)})},li:function(e){return(0,F.A)().collectAnchor(e.id),(0,N.jsx)("li",{...e})},img:function(e){return(0,N.jsx)("img",{decoding:"async",loading:"lazy",...e,className:(t=e.className,(0,r.A)(t,ie))});var t},h1:e=>(0,N.jsx)(ae,{as:"h1",...e}),h2:e=>(0,N.jsx)(ae,{as:"h2",...e}),h3:e=>(0,N.jsx)(ae,{as:"h3",...e}),h4:e=>(0,N.jsx)(ae,{as:"h4",...e}),h5:e=>(0,N.jsx)(ae,{as:"h5",...e}),h6:e=>(0,N.jsx)(ae,{as:"h6",...e}),admonition:le.A,mermaid:()=>null};function ue(e){let{children:t}=e;return(0,N.jsx)(o.x,{components:de,children:t})}},6266:(e,t,n)=>{"use strict";n.d(t,{i:()=>o});var s=n(4586);function o(e){void 0===e&&(e={});const{i18n:{currentLocale:t}}=(0,s.A)(),n=function(){const{i18n:{currentLocale:e,localeConfigs:t}}=(0,s.A)();return t[e].calendar}();return new Intl.DateTimeFormat(t,{calendar:n,...e})}},8426:(e,t)=>{function n(e){let t,n=[];for(let s of e.split(",").map((e=>e.trim())))if(/^-?\d+$/.test(s))n.push(parseInt(s,10));else if(t=s.match(/^(-?\d+)(-|\.\.\.?|\u2025|\u2026|\u22EF)(-?\d+)$/)){let[e,s,o,a]=t;if(s&&a){s=parseInt(s),a=parseInt(a);const e=s<a?1:-1;"-"!==o&&".."!==o&&"\u2025"!==o||(a+=e);for(let t=s;t!==a;t+=e)n.push(t)}}return n}t.default=n,e.exports=n},8453:(e,t,n)=>{"use strict";n.d(t,{R:()=>c,x:()=>r});var s=n(6540);const o={},a=s.createContext(o);function c(e){const t=s.useContext(a);return s.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function r(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:c(e.components),s.createElement(a.Provider,{value:t},e.children)}}}]); \ No newline at end of file +(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[8498],{7293:(e,t,n)=>{"use strict";n.d(t,{A:()=>S});var s=n(6540),o=n(4848);function a(e){const{mdxAdmonitionTitle:t,rest:n}=function(e){const t=s.Children.toArray(e),n=t.find((e=>s.isValidElement(e)&&"mdxAdmonitionTitle"===e.type)),a=t.filter((e=>e!==n)),c=n?.props.children;return{mdxAdmonitionTitle:c,rest:a.length>0?(0,o.jsx)(o.Fragment,{children:a}):null}}(e.children),a=e.title??t;return{...e,...a&&{title:a},children:n}}var c=n(4164),r=n(1312),i=n(7559);const l="admonition_xJq3",d="admonitionHeading_Gvgb",u="admonitionIcon_Rf37",m="admonitionContent_BuS1";function h(e){let{type:t,className:n,children:s}=e;return(0,o.jsx)("div",{className:(0,c.A)(i.G.common.admonition,i.G.common.admonitionType(t),l,n),children:s})}function p(e){let{icon:t,title:n}=e;return(0,o.jsxs)("div",{className:d,children:[(0,o.jsx)("span",{className:u,children:t}),n]})}function f(e){let{children:t}=e;return t?(0,o.jsx)("div",{className:m,children:t}):null}function x(e){const{type:t,icon:n,title:s,children:a,className:c}=e;return(0,o.jsxs)(h,{type:t,className:c,children:[s||n?(0,o.jsx)(p,{title:s,icon:n}):null,(0,o.jsx)(f,{children:a})]})}function j(e){return(0,o.jsx)("svg",{viewBox:"0 0 14 16",...e,children:(0,o.jsx)("path",{fillRule:"evenodd",d:"M6.3 5.69a.942.942 0 0 1-.28-.7c0-.28.09-.52.28-.7.19-.18.42-.28.7-.28.28 0 .52.09.7.28.18.19.28.42.28.7 0 .28-.09.52-.28.7a1 1 0 0 1-.7.3c-.28 0-.52-.11-.7-.3zM8 7.99c-.02-.25-.11-.48-.31-.69-.2-.19-.42-.3-.69-.31H6c-.27.02-.48.13-.69.31-.2.2-.3.44-.31.69h1v3c.02.27.11.5.31.69.2.2.42.31.69.31h1c.27 0 .48-.11.69-.31.2-.19.3-.42.31-.69H8V7.98v.01zM7 2.3c-3.14 0-5.7 2.54-5.7 5.68 0 3.14 2.56 5.7 5.7 5.7s5.7-2.55 5.7-5.7c0-3.15-2.56-5.69-5.7-5.69v.01zM7 .98c3.86 0 7 3.14 7 7s-3.14 7-7 7-7-3.12-7-7 3.14-7 7-7z"})})}const b={icon:(0,o.jsx)(j,{}),title:(0,o.jsx)(r.A,{id:"theme.admonition.note",description:"The default label used for the Note admonition (:::note)",children:"note"})};function g(e){return(0,o.jsx)(x,{...b,...e,className:(0,c.A)("alert alert--secondary",e.className),children:e.children})}function v(e){return(0,o.jsx)("svg",{viewBox:"0 0 12 16",...e,children:(0,o.jsx)("path",{fillRule:"evenodd",d:"M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"})})}const y={icon:(0,o.jsx)(v,{}),title:(0,o.jsx)(r.A,{id:"theme.admonition.tip",description:"The default label used for the Tip admonition (:::tip)",children:"tip"})};function N(e){return(0,o.jsx)(x,{...y,...e,className:(0,c.A)("alert alert--success",e.className),children:e.children})}function A(e){return(0,o.jsx)("svg",{viewBox:"0 0 14 16",...e,children:(0,o.jsx)("path",{fillRule:"evenodd",d:"M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"})})}const k={icon:(0,o.jsx)(A,{}),title:(0,o.jsx)(r.A,{id:"theme.admonition.info",description:"The default label used for the Info admonition (:::info)",children:"info"})};function B(e){return(0,o.jsx)(x,{...k,...e,className:(0,c.A)("alert alert--info",e.className),children:e.children})}function w(e){return(0,o.jsx)("svg",{viewBox:"0 0 16 16",...e,children:(0,o.jsx)("path",{fillRule:"evenodd",d:"M8.893 1.5c-.183-.31-.52-.5-.887-.5s-.703.19-.886.5L.138 13.499a.98.98 0 0 0 0 1.001c.193.31.53.501.886.501h13.964c.367 0 .704-.19.877-.5a1.03 1.03 0 0 0 .01-1.002L8.893 1.5zm.133 11.497H6.987v-2.003h2.039v2.003zm0-3.004H6.987V5.987h2.039v4.006z"})})}const C={icon:(0,o.jsx)(w,{}),title:(0,o.jsx)(r.A,{id:"theme.admonition.warning",description:"The default label used for the Warning admonition (:::warning)",children:"warning"})};function E(e){return(0,o.jsx)("svg",{viewBox:"0 0 12 16",...e,children:(0,o.jsx)("path",{fillRule:"evenodd",d:"M5.05.31c.81 2.17.41 3.38-.52 4.31C3.55 5.67 1.98 6.45.9 7.98c-1.45 2.05-1.7 6.53 3.53 7.7-2.2-1.16-2.67-4.52-.3-6.61-.61 2.03.53 3.33 1.94 2.86 1.39-.47 2.3.53 2.27 1.67-.02.78-.31 1.44-1.13 1.81 3.42-.59 4.78-3.42 4.78-5.56 0-2.84-2.53-3.22-1.25-5.61-1.52.13-2.03 1.13-1.89 2.75.09 1.08-1.02 1.8-1.86 1.33-.67-.41-.66-1.19-.06-1.78C8.18 5.31 8.68 2.45 5.05.32L5.03.3l.02.01z"})})}const T={icon:(0,o.jsx)(E,{}),title:(0,o.jsx)(r.A,{id:"theme.admonition.danger",description:"The default label used for the Danger admonition (:::danger)",children:"danger"})};const L={icon:(0,o.jsx)(w,{}),title:(0,o.jsx)(r.A,{id:"theme.admonition.caution",description:"The default label used for the Caution admonition (:::caution)",children:"caution"})};const _={...{note:g,tip:N,info:B,warning:function(e){return(0,o.jsx)(x,{...C,...e,className:(0,c.A)("alert alert--warning",e.className),children:e.children})},danger:function(e){return(0,o.jsx)(x,{...T,...e,className:(0,c.A)("alert alert--danger",e.className),children:e.children})}},...{secondary:e=>(0,o.jsx)(g,{title:"secondary",...e}),important:e=>(0,o.jsx)(B,{title:"important",...e}),success:e=>(0,o.jsx)(N,{title:"success",...e}),caution:function(e){return(0,o.jsx)(x,{...L,...e,className:(0,c.A)("alert alert--warning",e.className),children:e.children})}}};function S(e){const t=a(e),n=(s=t.type,_[s]||(console.warn(`No admonition component found for admonition type "${s}". Using Info as fallback.`),_.info));var s;return(0,o.jsx)(n,{...t})}},4336:(e,t,n)=>{"use strict";n.d(t,{A:()=>x});n(6540);var s=n(4164),o=n(1312),a=n(7559),c=n(8774);const r={iconEdit:"iconEdit_Z9Sw"};var i=n(4848);function l(e){let{className:t,...n}=e;return(0,i.jsx)("svg",{fill:"currentColor",height:"20",width:"20",viewBox:"0 0 40 40",className:(0,s.A)(r.iconEdit,t),"aria-hidden":"true",...n,children:(0,i.jsx)("g",{children:(0,i.jsx)("path",{d:"m34.5 11.7l-3 3.1-6.3-6.3 3.1-3q0.5-0.5 1.2-0.5t1.1 0.5l3.9 3.9q0.5 0.4 0.5 1.1t-0.5 1.2z m-29.5 17.1l18.4-18.5 6.3 6.3-18.4 18.4h-6.3v-6.2z"})})})}function d(e){let{editUrl:t}=e;return(0,i.jsxs)(c.A,{to:t,className:a.G.common.editThisPage,children:[(0,i.jsx)(l,{}),(0,i.jsx)(o.A,{id:"theme.common.editThisPage",description:"The link label to edit the current page",children:"Edit this page"})]})}var u=n(6266);function m(e){let{lastUpdatedAt:t}=e;const n=new Date(t),s=(0,u.i)({day:"numeric",month:"short",year:"numeric",timeZone:"UTC"}).format(n);return(0,i.jsx)(o.A,{id:"theme.lastUpdated.atDate",description:"The words used to describe on which date a page has been last updated",values:{date:(0,i.jsx)("b",{children:(0,i.jsx)("time",{dateTime:n.toISOString(),itemProp:"dateModified",children:s})})},children:" on {date}"})}function h(e){let{lastUpdatedBy:t}=e;return(0,i.jsx)(o.A,{id:"theme.lastUpdated.byUser",description:"The words used to describe by who the page has been last updated",values:{user:(0,i.jsx)("b",{children:t})},children:" by {user}"})}function p(e){let{lastUpdatedAt:t,lastUpdatedBy:n}=e;return(0,i.jsxs)("span",{className:a.G.common.lastUpdated,children:[(0,i.jsx)(o.A,{id:"theme.lastUpdated.lastUpdatedAtBy",description:"The sentence used to display when a page has been last updated, and by who",values:{atDate:t?(0,i.jsx)(m,{lastUpdatedAt:t}):"",byUser:n?(0,i.jsx)(h,{lastUpdatedBy:n}):""},children:"Last updated{atDate}{byUser}"}),!1]})}const f={lastUpdated:"lastUpdated_JAkA"};function x(e){let{className:t,editUrl:n,lastUpdatedAt:o,lastUpdatedBy:a}=e;return(0,i.jsxs)("div",{className:(0,s.A)("row",t),children:[(0,i.jsx)("div",{className:"col",children:n&&(0,i.jsx)(d,{editUrl:n})}),(0,i.jsx)("div",{className:(0,s.A)("col",f.lastUpdated),children:(o||a)&&(0,i.jsx)(p,{lastUpdatedAt:o,lastUpdatedBy:a})})]})}},8509:(e,t,n)=>{"use strict";n.d(t,{A:()=>ue});var s=n(6540),o=n(8453),a=n(5260),c=n(2303),r=n(4164),i=n(5293),l=n(6342);function d(){const{prism:e}=(0,l.p)(),{colorMode:t}=(0,i.G)(),n=e.theme,s=e.darkTheme||n;return"dark"===t?s:n}var u=n(7559),m=n(6045),h=n.n(m);const p=/title=(?<quote>["'])(?<title>.*?)\1/,f=/\{(?<range>[\d,-]+)\}/,x={js:{start:"\\/\\/",end:""},jsBlock:{start:"\\/\\*",end:"\\*\\/"},jsx:{start:"\\{\\s*\\/\\*",end:"\\*\\/\\s*\\}"},bash:{start:"#",end:""},html:{start:"\x3c!--",end:"--\x3e"}},j={...x,lua:{start:"--",end:""},wasm:{start:"\\;\\;",end:""},tex:{start:"%",end:""},vb:{start:"['\u2018\u2019]",end:""},vbnet:{start:"(?:_\\s*)?['\u2018\u2019]",end:""},rem:{start:"[Rr][Ee][Mm]\\b",end:""},f90:{start:"!",end:""},ml:{start:"\\(\\*",end:"\\*\\)"},cobol:{start:"\\*>",end:""}},b=Object.keys(x);function g(e,t){const n=e.map((e=>{const{start:n,end:s}=j[e];return`(?:${n}\\s*(${t.flatMap((e=>[e.line,e.block?.start,e.block?.end].filter(Boolean))).join("|")})\\s*${s})`})).join("|");return new RegExp(`^\\s*(?:${n})\\s*$`)}function v(e,t){let n=e.replace(/\n$/,"");const{language:s,magicComments:o,metastring:a}=t;if(a&&f.test(a)){const e=a.match(f).groups.range;if(0===o.length)throw new Error(`A highlight range has been given in code block's metastring (\`\`\` ${a}), but no magic comment config is available. Docusaurus applies the first magic comment entry's className for metastring ranges.`);const t=o[0].className,s=h()(e).filter((e=>e>0)).map((e=>[e-1,[t]]));return{lineClassNames:Object.fromEntries(s),code:n}}if(void 0===s)return{lineClassNames:{},code:n};const c=function(e,t){switch(e){case"js":case"javascript":case"ts":case"typescript":return g(["js","jsBlock"],t);case"jsx":case"tsx":return g(["js","jsBlock","jsx"],t);case"html":return g(["js","jsBlock","html"],t);case"python":case"py":case"bash":return g(["bash"],t);case"markdown":case"md":return g(["html","jsx","bash"],t);case"tex":case"latex":case"matlab":return g(["tex"],t);case"lua":case"haskell":case"sql":return g(["lua"],t);case"wasm":return g(["wasm"],t);case"vb":case"vba":case"visual-basic":return g(["vb","rem"],t);case"vbnet":return g(["vbnet","rem"],t);case"batch":return g(["rem"],t);case"basic":return g(["rem","f90"],t);case"fsharp":return g(["js","ml"],t);case"ocaml":case"sml":return g(["ml"],t);case"fortran":return g(["f90"],t);case"cobol":return g(["cobol"],t);default:return g(b,t)}}(s,o),r=n.split("\n"),i=Object.fromEntries(o.map((e=>[e.className,{start:0,range:""}]))),l=Object.fromEntries(o.filter((e=>e.line)).map((e=>{let{className:t,line:n}=e;return[n,t]}))),d=Object.fromEntries(o.filter((e=>e.block)).map((e=>{let{className:t,block:n}=e;return[n.start,t]}))),u=Object.fromEntries(o.filter((e=>e.block)).map((e=>{let{className:t,block:n}=e;return[n.end,t]})));for(let h=0;h<r.length;){const e=r[h].match(c);if(!e){h+=1;continue}const t=e.slice(1).find((e=>void 0!==e));l[t]?i[l[t]].range+=`${h},`:d[t]?i[d[t]].start=h:u[t]&&(i[u[t]].range+=`${i[u[t]].start}-${h-1},`),r.splice(h,1)}n=r.join("\n");const m={};return Object.entries(i).forEach((e=>{let[t,{range:n}]=e;h()(n).forEach((e=>{m[e]??=[],m[e].push(t)}))})),{lineClassNames:m,code:n}}const y="codeBlockContainer_Ckt0";var N=n(4848);function A(e){let{as:t,...n}=e;const s=function(e){const t={color:"--prism-color",backgroundColor:"--prism-background-color"},n={};return Object.entries(e.plain).forEach((e=>{let[s,o]=e;const a=t[s];a&&"string"==typeof o&&(n[a]=o)})),n}(d());return(0,N.jsx)(t,{...n,style:s,className:(0,r.A)(n.className,y,u.G.common.codeBlock)})}const k={codeBlockContent:"codeBlockContent_biex",codeBlockTitle:"codeBlockTitle_Ktv7",codeBlock:"codeBlock_bY9V",codeBlockStandalone:"codeBlockStandalone_MEMb",codeBlockLines:"codeBlockLines_e6Vv",codeBlockLinesWithNumbering:"codeBlockLinesWithNumbering_o6Pm",buttonGroup:"buttonGroup__atx"};function B(e){let{children:t,className:n}=e;return(0,N.jsx)(A,{as:"pre",tabIndex:0,className:(0,r.A)(k.codeBlockStandalone,"thin-scrollbar",n),children:(0,N.jsx)("code",{className:k.codeBlockLines,children:t})})}var w=n(9532);const C={attributes:!0,characterData:!0,childList:!0,subtree:!0};function E(e,t){const[n,o]=(0,s.useState)(),a=(0,s.useCallback)((()=>{o(e.current?.closest("[role=tabpanel][hidden]"))}),[e,o]);(0,s.useEffect)((()=>{a()}),[a]),function(e,t,n){void 0===n&&(n=C);const o=(0,w._q)(t),a=(0,w.Be)(n);(0,s.useEffect)((()=>{const t=new MutationObserver(o);return e&&t.observe(e,a),()=>t.disconnect()}),[e,o,a])}(n,(e=>{e.forEach((e=>{"attributes"===e.type&&"hidden"===e.attributeName&&(t(),a())}))}),{attributes:!0,characterData:!1,childList:!1,subtree:!1})}var T=n(1765);const L="codeLine_lJS_",_="codeLineNumber_Tfdd",S="codeLineContent_feaV";function U(e){let{line:t,classNames:n,showLineNumbers:s,getLineProps:o,getTokenProps:a}=e;1===t.length&&"\n"===t[0].content&&(t[0].content="");const c=o({line:t,className:(0,r.A)(n,s&&L)}),i=t.map(((e,t)=>(0,N.jsx)("span",{...a({token:e})},t)));return(0,N.jsxs)("span",{...c,children:[s?(0,N.jsxs)(N.Fragment,{children:[(0,N.jsx)("span",{className:_}),(0,N.jsx)("span",{className:S,children:i})]}):i,(0,N.jsx)("br",{})]})}var M=n(1312);function z(e){return(0,N.jsx)("svg",{viewBox:"0 0 24 24",...e,children:(0,N.jsx)("path",{fill:"currentColor",d:"M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"})})}function H(e){return(0,N.jsx)("svg",{viewBox:"0 0 24 24",...e,children:(0,N.jsx)("path",{fill:"currentColor",d:"M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"})})}const I={copyButtonCopied:"copyButtonCopied_obH4",copyButtonIcons:"copyButtonIcons_eSgA",copyButtonIcon:"copyButtonIcon_y97N",copyButtonSuccessIcon:"copyButtonSuccessIcon_LjdS"};function R(e){let{code:t,className:n}=e;const[o,a]=(0,s.useState)(!1),c=(0,s.useRef)(void 0),i=(0,s.useCallback)((()=>{!function(e,t){let{target:n=document.body}=void 0===t?{}:t;if("string"!=typeof e)throw new TypeError(`Expected parameter \`text\` to be a \`string\`, got \`${typeof e}\`.`);const s=document.createElement("textarea"),o=document.activeElement;s.value=e,s.setAttribute("readonly",""),s.style.contain="strict",s.style.position="absolute",s.style.left="-9999px",s.style.fontSize="12pt";const a=document.getSelection(),c=a.rangeCount>0&&a.getRangeAt(0);n.append(s),s.select(),s.selectionStart=0,s.selectionEnd=e.length;let r=!1;try{r=document.execCommand("copy")}catch{}s.remove(),c&&(a.removeAllRanges(),a.addRange(c)),o&&o.focus()}(t),a(!0),c.current=window.setTimeout((()=>{a(!1)}),1e3)}),[t]);return(0,s.useEffect)((()=>()=>window.clearTimeout(c.current)),[]),(0,N.jsx)("button",{type:"button","aria-label":o?(0,M.T)({id:"theme.CodeBlock.copied",message:"Copied",description:"The copied button label on code blocks"}):(0,M.T)({id:"theme.CodeBlock.copyButtonAriaLabel",message:"Copy code to clipboard",description:"The ARIA label for copy code blocks button"}),title:(0,M.T)({id:"theme.CodeBlock.copy",message:"Copy",description:"The copy button label on code blocks"}),className:(0,r.A)("clean-btn",n,I.copyButton,o&&I.copyButtonCopied),onClick:i,children:(0,N.jsxs)("span",{className:I.copyButtonIcons,"aria-hidden":"true",children:[(0,N.jsx)(z,{className:I.copyButtonIcon}),(0,N.jsx)(H,{className:I.copyButtonSuccessIcon})]})})}function V(e){return(0,N.jsx)("svg",{viewBox:"0 0 24 24",...e,children:(0,N.jsx)("path",{fill:"currentColor",d:"M4 19h6v-2H4v2zM20 5H4v2h16V5zm-3 6H4v2h13.25c1.1 0 2 .9 2 2s-.9 2-2 2H15v-2l-3 3l3 3v-2h2c2.21 0 4-1.79 4-4s-1.79-4-4-4z"})})}const $="wordWrapButtonIcon_Bwma",D="wordWrapButtonEnabled_EoeP";function P(e){let{className:t,onClick:n,isEnabled:s}=e;const o=(0,M.T)({id:"theme.CodeBlock.wordWrapToggle",message:"Toggle word wrap",description:"The title attribute for toggle word wrapping button of code block lines"});return(0,N.jsx)("button",{type:"button",onClick:n,className:(0,r.A)("clean-btn",t,s&&D),"aria-label":o,title:o,children:(0,N.jsx)(V,{className:$,"aria-hidden":"true"})})}function W(e){let{children:t,className:n="",metastring:o,title:a,showLineNumbers:c,language:i}=e;const{prism:{defaultLanguage:u,magicComments:m}}=(0,l.p)(),h=function(e){return e?.toLowerCase()}(i??function(e){const t=e.split(" ").find((e=>e.startsWith("language-")));return t?.replace(/language-/,"")}(n)??u),f=d(),x=function(){const[e,t]=(0,s.useState)(!1),[n,o]=(0,s.useState)(!1),a=(0,s.useRef)(null),c=(0,s.useCallback)((()=>{const n=a.current.querySelector("code");e?n.removeAttribute("style"):(n.style.whiteSpace="pre-wrap",n.style.overflowWrap="anywhere"),t((e=>!e))}),[a,e]),r=(0,s.useCallback)((()=>{const{scrollWidth:e,clientWidth:t}=a.current,n=e>t||a.current.querySelector("code").hasAttribute("style");o(n)}),[a]);return E(a,r),(0,s.useEffect)((()=>{r()}),[e,r]),(0,s.useEffect)((()=>(window.addEventListener("resize",r,{passive:!0}),()=>{window.removeEventListener("resize",r)})),[r]),{codeBlockRef:a,isEnabled:e,isCodeScrollable:n,toggle:c}}(),j=function(e){return e?.match(p)?.groups.title??""}(o)||a,{lineClassNames:b,code:g}=v(t,{metastring:o,language:h,magicComments:m}),y=c??function(e){return Boolean(e?.includes("showLineNumbers"))}(o);return(0,N.jsxs)(A,{as:"div",className:(0,r.A)(n,h&&!n.includes(`language-${h}`)&&`language-${h}`),children:[j&&(0,N.jsx)("div",{className:k.codeBlockTitle,children:j}),(0,N.jsxs)("div",{className:k.codeBlockContent,children:[(0,N.jsx)(T.f4,{theme:f,code:g,language:h??"text",children:e=>{let{className:t,style:n,tokens:s,getLineProps:o,getTokenProps:a}=e;return(0,N.jsx)("pre",{tabIndex:0,ref:x.codeBlockRef,className:(0,r.A)(t,k.codeBlock,"thin-scrollbar"),style:n,children:(0,N.jsx)("code",{className:(0,r.A)(k.codeBlockLines,y&&k.codeBlockLinesWithNumbering),children:s.map(((e,t)=>(0,N.jsx)(U,{line:e,getLineProps:o,getTokenProps:a,classNames:b[t],showLineNumbers:y},t)))})})}}),(0,N.jsxs)("div",{className:k.buttonGroup,children:[(x.isEnabled||x.isCodeScrollable)&&(0,N.jsx)(P,{className:k.codeButton,onClick:()=>x.toggle(),isEnabled:x.isEnabled}),(0,N.jsx)(R,{className:k.codeButton,code:g})]})]})]})}function q(e){let{children:t,...n}=e;const o=(0,c.A)(),a=function(e){return s.Children.toArray(e).some((e=>(0,s.isValidElement)(e)))?e:Array.isArray(e)?e.join(""):e}(t),r="string"==typeof a?W:B;return(0,N.jsx)(r,{...n,children:a},String(o))}function G(e){return(0,N.jsx)("code",{...e})}var O=n(8774);var F=n(3427),Z=n(1422);const J="details_lb9f",Y="isBrowser_bmU9",K="collapsibleContent_i85q";function Q(e){return!!e&&("SUMMARY"===e.tagName||Q(e.parentElement))}function X(e,t){return!!e&&(e===t||X(e.parentElement,t))}function ee(e){let{summary:t,children:n,...o}=e;(0,F.A)().collectAnchor(o.id);const a=(0,c.A)(),i=(0,s.useRef)(null),{collapsed:l,setCollapsed:d}=(0,Z.u)({initialState:!o.open}),[u,m]=(0,s.useState)(o.open),h=s.isValidElement(t)?t:(0,N.jsx)("summary",{children:t??"Details"});return(0,N.jsxs)("details",{...o,ref:i,open:u,"data-collapsed":l,className:(0,r.A)(J,a&&Y,o.className),onMouseDown:e=>{Q(e.target)&&e.detail>1&&e.preventDefault()},onClick:e=>{e.stopPropagation();const t=e.target;Q(t)&&X(t,i.current)&&(e.preventDefault(),l?(d(!1),m(!0)):d(!0))},children:[h,(0,N.jsx)(Z.N,{lazy:!1,collapsed:l,disableSSRStyle:!0,onCollapseTransitionEnd:e=>{d(e),m(!e)},children:(0,N.jsx)("div",{className:K,children:n})})]})}const te="details_b_Ee";function ne(e){let{...t}=e;return(0,N.jsx)(ee,{...t,className:(0,r.A)("alert alert--info",te,t.className)})}function se(e){const t=s.Children.toArray(e.children),n=t.find((e=>s.isValidElement(e)&&"summary"===e.type)),o=(0,N.jsx)(N.Fragment,{children:t.filter((e=>e!==n))});return(0,N.jsx)(ne,{...e,summary:n,children:o})}var oe=n(1107);function ae(e){return(0,N.jsx)(oe.A,{...e})}const ce="containsTaskList_mC6p";function re(e){if(void 0!==e)return(0,r.A)(e,e?.includes("contains-task-list")&&ce)}const ie="img_ev3q";var le=n(7293);const de={Head:a.A,details:se,Details:se,code:function(e){return function(e){return void 0!==e.children&&s.Children.toArray(e.children).every((e=>"string"==typeof e&&!e.includes("\n")))}(e)?(0,N.jsx)(G,{...e}):(0,N.jsx)(q,{...e})},a:function(e){return(0,N.jsx)(O.A,{...e})},pre:function(e){return(0,N.jsx)(N.Fragment,{children:e.children})},ul:function(e){return(0,N.jsx)("ul",{...e,className:re(e.className)})},li:function(e){return(0,F.A)().collectAnchor(e.id),(0,N.jsx)("li",{...e})},img:function(e){return(0,N.jsx)("img",{decoding:"async",loading:"lazy",...e,className:(t=e.className,(0,r.A)(t,ie))});var t},h1:e=>(0,N.jsx)(ae,{as:"h1",...e}),h2:e=>(0,N.jsx)(ae,{as:"h2",...e}),h3:e=>(0,N.jsx)(ae,{as:"h3",...e}),h4:e=>(0,N.jsx)(ae,{as:"h4",...e}),h5:e=>(0,N.jsx)(ae,{as:"h5",...e}),h6:e=>(0,N.jsx)(ae,{as:"h6",...e}),admonition:le.A,mermaid:()=>null};function ue(e){let{children:t}=e;return(0,N.jsx)(o.x,{components:de,children:t})}},6266:(e,t,n)=>{"use strict";n.d(t,{i:()=>o});var s=n(4586);function o(e){void 0===e&&(e={});const{i18n:{currentLocale:t}}=(0,s.A)(),n=function(){const{i18n:{currentLocale:e,localeConfigs:t}}=(0,s.A)();return t[e].calendar}();return new Intl.DateTimeFormat(t,{calendar:n,...e})}},6045:(e,t)=>{function n(e){let t,n=[];for(let s of e.split(",").map((e=>e.trim())))if(/^-?\d+$/.test(s))n.push(parseInt(s,10));else if(t=s.match(/^(-?\d+)(-|\.\.\.?|\u2025|\u2026|\u22EF)(-?\d+)$/)){let[e,s,o,a]=t;if(s&&a){s=parseInt(s),a=parseInt(a);const e=s<a?1:-1;"-"!==o&&".."!==o&&"\u2025"!==o||(a+=e);for(let t=s;t!==a;t+=e)n.push(t)}}return n}t.default=n,e.exports=n},8453:(e,t,n)=>{"use strict";n.d(t,{R:()=>c,x:()=>r});var s=n(6540);const o={},a=s.createContext(o);function c(e){const t=s.useContext(a);return s.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function r(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:c(e.components),s.createElement(a.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/849b28af.21ef411d.js b/assets/js/849b28af.891b9b7f.js similarity index 86% rename from assets/js/849b28af.21ef411d.js rename to assets/js/849b28af.891b9b7f.js index fe4a6455e..d42376719 100644 --- a/assets/js/849b28af.21ef411d.js +++ b/assets/js/849b28af.891b9b7f.js @@ -1 +1 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[9881],{7705:(e,t,i)=>{i.r(t),i.d(t,{assets:()=>l,contentTitle:()=>a,default:()=>c,frontMatter:()=>r,metadata:()=>n,toc:()=>h});var n=i(9559),s=i(4848),o=i(8453);const r={title:"Minimizing blast radius in Cadence: Introducing Workflow ID-based Rate Limits",date:new Date("2024-09-05T00:00:00.000Z"),authors:"jakobht",tags:["deep-dive"]},a=void 0,l={authorsImageUrls:[void 0]},h=[{value:"Why Workflow ID-based Rate Limits?",id:"why-workflow-id-based-rate-limits",level:2},{value:"Why <em>not</em> Shard Rate Limits?",id:"why-not-shard-rate-limits",level:2},{value:"How Does It Work?",id:"how-does-it-work",level:2},{value:"How do I Enable It?",id:"how-do-i-enable-it",level:3},{value:"Monitoring and Troubleshooting",id:"monitoring-and-troubleshooting",level:2},{value:"Conclusion",id:"conclusion",level:2}];function d(e){const t={a:"a",br:"br",code:"code",em:"em",h2:"h2",h3:"h3",li:"li",ol:"ol",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,o.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsxs)(t.p,{children:["At Uber, we run several big multitenant Cadence clusters with hundreds of domains in each. The clusters being multi-tenant means potential ",(0,s.jsx)(t.a,{href:"https://en.wikipedia.org/wiki/Cloud_computing_issues#Performance_interference_and_noisy_neighbors",children:"noisy neighbor"})," effects between domains."]}),"\n",(0,s.jsx)(t.p,{children:"An essential aspect of avoiding this is managing how workflows interact with our infrastructure to prevent any single workflow from causing instability for the whole cluster. To this end, we are excited to introduce Workflow ID-based rate limits \u2014 a new feature designed to protect our clusters from problematic workflows and ensure stability across the board."}),"\n",(0,s.jsx)(t.h2,{id:"why-workflow-id-based-rate-limits",children:"Why Workflow ID-based Rate Limits?"}),"\n",(0,s.jsx)(t.p,{children:"We already have rate limits for how many requests can be sent to a domain. However, since Cadence is sharded on the workflow ID, a user-provided input, an overused workflow with a particular id might overwhelm a shard by making too many requests. There are two main ways this happens:"}),"\n",(0,s.jsxs)(t.ol,{children:["\n",(0,s.jsx)(t.li,{children:"A user starts, or signals the same workflow ID too aggressively,"}),"\n",(0,s.jsx)(t.li,{children:"A workflow starts too many activities over a short period of time (e.g. thousands of activities in seconds)."}),"\n"]}),"\n",(0,s.jsx)(t.p,{children:"For example, the following workflow would cause issues for Cadence. It would create huge amounts of traffic to a single shard in a very small time frame:"}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-go",children:"func Workflow(ctx workflow.Context, input sampleInput) (string, error) {\n\t...\n\tfor _, elem := range longList {\n\t\terr := workflow.ExecuteActivity(ctx, QuickActivity, elem).Get(ctx, nil)\n\t}\n\t...\n}\n"})}),"\n",(0,s.jsxs)(t.p,{children:["This heavy load creates what we call ",(0,s.jsx)(t.em,{children:"hot shards"}),". Hot shards degrade performance not just for the workflow causing the issue, but for all workflows that interact with the affected shard. This can grow to a point where the whole cluster becomes unstable."]}),"\n",(0,s.jsx)(t.p,{children:"Now, with Workflow ID-based rate limits, we limit the number of external calls and actions per second for each individual workflow, reducing the blast radius (impact on the cluster) of a badly behaved workflow to an absolute minimum where only the offending workflow is impacted."}),"\n",(0,s.jsxs)(t.h2,{id:"why-not-shard-rate-limits",children:["Why ",(0,s.jsx)(t.em,{children:"not"})," Shard Rate Limits?"]}),"\n",(0,s.jsx)(t.p,{children:"An obvious question is \u201cwhy don\u2019t we rate limit the requests to the shard?\u201d. After all, the shard is what we want to protect. We have several reasons for choosing to rate limit the workflow ID instead of the shard:"}),"\n",(0,s.jsxs)(t.ul,{children:["\n",(0,s.jsxs)(t.li,{children:[(0,s.jsx)(t.strong,{children:"Hashing"})," The workflow ID to shard is random. This means that rate limiting a workflow is a good proxy for rate limiting a shard. The likelihood that many requests from different workflows hit the same shard is very low."]}),"\n",(0,s.jsxs)(t.li,{children:[(0,s.jsx)(t.strong,{children:"Communication"})," It is easy to explain to a user that their domain is rate limited because they are sending too many requests to a specific workflow ID. Shards are an internal implementation detail that users should not have to worry about."]}),"\n",(0,s.jsxs)(t.li,{children:[(0,s.jsx)(t.strong,{children:"Noisy neighbors"})," Shards are shared across the different domains in a Cadence cluster. If a user is sending too many requests to a shard, we would choose to rate limit requests to that shard. Since other users in other domains are also using the shard, they will also be rate limited.\nRate limiting users of a healthy domain because of requests from a completely different domain goes against the isolation the domains are meant to ensure."]}),"\n"]}),"\n",(0,s.jsx)(t.h2,{id:"how-does-it-work",children:"How Does It Work?"}),"\n",(0,s.jsx)(t.p,{children:"Workflow ID-based rate limits are set for all workflow IDs in a domain. If the external limit for a domain is e.g. set to 100 it means that any single workflow ID in that domain can at most be signaled 100 times a second. The rate limits are implemented in two main areas:"}),"\n",(0,s.jsxs)(t.ol,{children:["\n",(0,s.jsxs)(t.li,{children:["\n",(0,s.jsxs)(t.p,{children:[(0,s.jsx)(t.strong,{children:"External Calls"})," Cadence limits the number of requests per second for each workflow ID, which includes operations like starting, querying, or signaling a workflow. If this limit is exceeded, a ServiceBusyError with message \u201cToo many requests for the workflow ID\u201d is triggered, indicating that the rate limit for the workflow has been reached."]}),"\n"]}),"\n",(0,s.jsxs)(t.li,{children:["\n",(0,s.jsxs)(t.p,{children:[(0,s.jsx)(t.strong,{children:"Actions Within a Workflow"})," This limit controls the number of tasks processed per second within a workflow, focusing on managing decision tasks and activity tasks. When these limits are reached, Cadence slows down task processing without requiring any intervention from the user, though they might notice an increase in task execution time, eventually causing timeouts."]}),"\n"]}),"\n"]}),"\n",(0,s.jsx)(t.h3,{id:"how-do-i-enable-it",children:"How do I Enable It?"}),"\n",(0,s.jsx)(t.p,{children:"The limits are controlled using six dynamic config properties, three for the internal limits, and a corresponding three for the external limits, all with a domain filter, so the limits can be controlled for each domain."}),"\n",(0,s.jsxs)(t.ul,{children:["\n",(0,s.jsxs)(t.li,{children:["history.workflowIDCacheInternalEnabled",(0,s.jsx)(t.br,{}),"\n","history.workflowIDCacheExternalEnabled","\n",(0,s.jsxs)(t.ul,{children:["\n",(0,s.jsx)(t.li,{children:"Controls if the statistics needed to do the rate limiting should be collected. The feature keeps an in-memory record in the history service for each workflow ID."}),"\n"]}),"\n"]}),"\n",(0,s.jsxs)(t.li,{children:["history.workflowIDInternalRPS",(0,s.jsx)(t.br,{}),"\n","history.workflowIDExternalRPS","\n",(0,s.jsxs)(t.ul,{children:["\n",(0,s.jsx)(t.li,{children:"Sets the number of requests allowed per second per workflow in a particular domain."}),"\n"]}),"\n"]}),"\n",(0,s.jsxs)(t.li,{children:["history.workflowIDExternalRateLimitEnabled",(0,s.jsx)(t.br,{}),"\n","history.workflowIDInternalRateLimitEnabled","\n",(0,s.jsxs)(t.ul,{children:["\n",(0,s.jsxs)(t.li,{children:["Set whether rate limiting should happen. Setting this to false allows us to see which domains ",(0,s.jsx)(t.em,{children:"would have"})," been rate limited and adjust them before enforcing the limits."]}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,s.jsx)(t.p,{children:"An example configuration using the file based dynamic configuration could look like this:"}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-yaml",children:"history.workflowIDCacheExternalEnabled:\n- value: true\n constraints: {}\nhistory.workflowIDExternalRateLimitEnabled:\n- value: false\n constraints:\n domainName: samples-domain\n- value: true\n constraints: {}\nhistory.workflowIDExternalRPS:\n- value: 100\n constraints: {}\n"})}),"\n",(0,s.jsx)(t.p,{children:"Here only the external rate limits are enabled. The internal rate limits have the same structure. We see that \u200cthe rate limiting is enabled for all domains, with a max RPS of 100. The domain samples-domain is however running in shadow mode, so its requests are not rate limited, but metrics and logs are still emitted."}),"\n",(0,s.jsx)(t.p,{children:"The exact RPS to set for a specific domain and cluster, depends on many things, such as the number of shards, the selected persistent layer, the general load on the cluster etc."}),"\n",(0,s.jsx)(t.h2,{id:"monitoring-and-troubleshooting",children:"Monitoring and Troubleshooting"}),"\n",(0,s.jsx)(t.p,{children:"The new feature introduces both new metrics and new logs. The new logs help us find workflows that are being rate limited, while the new metrics let us see if domains are being rate limited, and how close to being rate limited they are."}),"\n",(0,s.jsx)(t.p,{children:"There are four new metrics, two for internal limits and two corresponding metrics for external limits, all emitted from history."}),"\n",(0,s.jsxs)(t.ul,{children:["\n",(0,s.jsxs)(t.li,{children:["workflow_id_external_requests_ratelimited",(0,s.jsx)(t.br,{}),"\n","workflow_id_internal_requests_ratelimited","\n",(0,s.jsxs)(t.ul,{children:["\n",(0,s.jsx)(t.li,{children:"This is a counter that counts the number of rate limited requests. The metric is tagged with the domain, so we can track the rate limiting per domain."}),"\n"]}),"\n"]}),"\n",(0,s.jsxs)(t.li,{children:["workflow_id_external_requests_max_requests_per_second",(0,s.jsx)(t.br,{}),"\n","workflow_id_internal_requests_max_requests_per_second","\n",(0,s.jsxs)(t.ul,{children:["\n",(0,s.jsx)(t.li,{children:"This is a timer metric. The upper series gives the max number of requests to a single workflow ID. This is again tagged with the domain, so we can for each domain see how close its workflows are to the limit."}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,s.jsx)(t.p,{children:"These metrics let us monitor and alert on the new rate limits. Additionally, when breaking a rate limit, the history service will emit an info log with the message \u201cRate limiting workflowID\u201d, these logs are tagged with the workflowID that is being limited, so it is easy to find the offending workflow. An example log would look like this:"}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-json",children:'{\n "level":"info",\n "ts":"2024-09-02T08:47:12.843Z",\n "msg":"Rate limiting workflowID",\n "service":"cadence-history",\n "request-type":"external",\n "wf-domain-id":"fc0c7fcb-5796-4c80-b0d7-10bbbc66614e",\n "wf-domain-name":"samples-domain",\n "wf-id":"test",\n "logging-call-at":"cache.go:175"\n}\n'})}),"\n",(0,s.jsx)(t.h2,{id:"conclusion",children:"Conclusion"}),"\n",(0,s.jsx)(t.p,{children:"Implementing these rate limits highly improves the reliability of a Cadence cluster, as users now cannot send too many requests to a single shard. This fine-grained control helps in maintaining optimal performance and enhances the ability to forecast and mitigate potential issues before they impact the service."}),"\n",(0,s.jsx)(t.p,{children:"Workflow ID-based rate limits are a significant step forward in our ongoing effort to provide a robust and efficient workflow management service. By preventing hot shards and ensuring equitable resource distribution, we can offer more reliable performance, even under peak loads. We encourage all Cadence users to familiarize themselves with these new limits and adjust their workflow configurations to achieve optimal results."})]})}function c(e={}){const{wrapper:t}={...(0,o.R)(),...e.components};return t?(0,s.jsx)(t,{...e,children:(0,s.jsx)(d,{...e})}):d(e)}},8453:(e,t,i)=>{i.d(t,{R:()=>r,x:()=>a});var n=i(6540);const s={},o=n.createContext(s);function r(e){const t=n.useContext(o);return n.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function a(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:r(e.components),n.createElement(o.Provider,{value:t},e.children)}},9559:e=>{e.exports=JSON.parse('{"permalink":"/blog/2024/09/05/workflow-specific-rate-limits","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2024-09-05-workflow-specific-rate-limits.md","source":"@site/blog/2024-09-05-workflow-specific-rate-limits.md","title":"Minimizing blast radius in Cadence: Introducing Workflow ID-based Rate Limits","description":"At Uber, we run several big multitenant Cadence clusters with hundreds of domains in each. The clusters being multi-tenant means potential noisy neighbor effects between domains.","date":"2024-09-05T00:00:00.000Z","tags":[{"inline":false,"label":"Deep Dives","permalink":"/blog/tags/deep-dives","description":"Deep Dives tag description"}],"readingTime":6.335,"hasTruncateMarker":true,"authors":[{"name":"Jakob Haahr Taankvist","title":"Software Engineer II @ Uber","url":"https://www.linkedin.com/in/jakob-taankvist/","page":{"permalink":"/blog/authors/jakobht"},"socials":{"linkedin":"https://www.linkedin.com/in/jakob-taankvist/","github":"https://github.com/jakobht"},"imageURL":"https://github.com/jakobht.png","key":"jakobht"}],"frontMatter":{"title":"Minimizing blast radius in Cadence: Introducing Workflow ID-based Rate Limits","date":"2024-09-05T00:00:00.000Z","authors":"jakobht","tags":["deep-dive"]},"unlisted":false,"prevItem":{"title":"Announcement: Cadence Helm Charts v0 Release","permalink":"/blog/2024/10/01/announcing-cadence-helm-charts-v0"},"nextItem":{"title":"2024 Cadence Yearly Roadmap Update","permalink":"/blog/2024/07/11/2024-07-11-yearly-roadmap-update/yearly-roadmap-update"}}')}}]); \ No newline at end of file +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[9881],{7705:(e,t,i)=>{i.r(t),i.d(t,{assets:()=>l,contentTitle:()=>a,default:()=>c,frontMatter:()=>r,metadata:()=>n,toc:()=>d});var n=i(9559),s=i(4848),o=i(8453);const r={title:"Minimizing blast radius in Cadence: Introducing Workflow ID-based Rate Limits",date:new Date("2024-09-05T00:00:00.000Z"),authors:"jakobht",tags:["deep-dive"]},a=void 0,l={authorsImageUrls:[void 0]},d=[{value:"Why Workflow ID-based Rate Limits?",id:"why-workflow-id-based-rate-limits",level:2},{value:"Why <em>not</em> Shard Rate Limits?",id:"why-not-shard-rate-limits",level:2},{value:"How Does It Work?",id:"how-does-it-work",level:2},{value:"How do I Enable It?",id:"how-do-i-enable-it",level:3},{value:"Monitoring and Troubleshooting",id:"monitoring-and-troubleshooting",level:2},{value:"Conclusion",id:"conclusion",level:2}];function h(e){const t={a:"a",br:"br",code:"code",em:"em",h2:"h2",h3:"h3",li:"li",ol:"ol",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,o.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsxs)(t.p,{children:["At Uber, we run several big multitenant Cadence clusters with hundreds of domains in each. The clusters being multi-tenant means potential ",(0,s.jsx)(t.a,{href:"https://en.wikipedia.org/wiki/Cloud_computing_issues#Performance_interference_and_noisy_neighbors",children:"noisy neighbor"})," effects between domains."]}),"\n",(0,s.jsx)(t.p,{children:"An essential aspect of avoiding this is managing how workflows interact with our infrastructure to prevent any single workflow from causing instability for the whole cluster. To this end, we are excited to introduce Workflow ID-based rate limits \u2014 a new feature designed to protect our clusters from problematic workflows and ensure stability across the board."}),"\n",(0,s.jsx)(t.h2,{id:"why-workflow-id-based-rate-limits",children:"Why Workflow ID-based Rate Limits?"}),"\n",(0,s.jsx)(t.p,{children:"We already have rate limits for how many requests can be sent to a domain. However, since Cadence is sharded on the workflow ID, a user-provided input, an overused workflow with a particular id might overwhelm a shard by making too many requests. There are two main ways this happens:"}),"\n",(0,s.jsxs)(t.ol,{children:["\n",(0,s.jsx)(t.li,{children:"A user starts, or signals the same workflow ID too aggressively,"}),"\n",(0,s.jsx)(t.li,{children:"A workflow starts too many activities over a short period of time (e.g. thousands of activities in seconds)."}),"\n"]}),"\n",(0,s.jsx)(t.p,{children:"For example, the following workflow would cause issues for Cadence. It would create huge amounts of traffic to a single shard in a very small time frame:"}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-go",children:"func Workflow(ctx workflow.Context, input sampleInput) (string, error) {\n\t...\n\tfor _, elem := range longList {\n\t\terr := workflow.ExecuteActivity(ctx, QuickActivity, elem).Get(ctx, nil)\n\t}\n\t...\n}\n"})}),"\n",(0,s.jsxs)(t.p,{children:["This heavy load creates what we call ",(0,s.jsx)(t.em,{children:"hot shards"}),". Hot shards degrade performance not just for the workflow causing the issue, but for all workflows that interact with the affected shard. This can grow to a point where the whole cluster becomes unstable."]}),"\n",(0,s.jsx)(t.p,{children:"Now, with Workflow ID-based rate limits, we limit the number of external calls and actions per second for each individual workflow, reducing the blast radius (impact on the cluster) of a badly behaved workflow to an absolute minimum where only the offending workflow is impacted."}),"\n",(0,s.jsxs)(t.h2,{id:"why-not-shard-rate-limits",children:["Why ",(0,s.jsx)(t.em,{children:"not"})," Shard Rate Limits?"]}),"\n",(0,s.jsx)(t.p,{children:"An obvious question is \u201cwhy don\u2019t we rate limit the requests to the shard?\u201d. After all, the shard is what we want to protect. We have several reasons for choosing to rate limit the workflow ID instead of the shard:"}),"\n",(0,s.jsxs)(t.ul,{children:["\n",(0,s.jsxs)(t.li,{children:[(0,s.jsx)(t.strong,{children:"Hashing"})," The workflow ID to shard is random. This means that rate limiting a workflow is a good proxy for rate limiting a shard. The likelihood that many requests from different workflows hit the same shard is very low."]}),"\n",(0,s.jsxs)(t.li,{children:[(0,s.jsx)(t.strong,{children:"Communication"})," It is easy to explain to a user that their domain is rate limited because they are sending too many requests to a specific workflow ID. Shards are an internal implementation detail that users should not have to worry about."]}),"\n",(0,s.jsxs)(t.li,{children:[(0,s.jsx)(t.strong,{children:"Noisy neighbors"})," Shards are shared across the different domains in a Cadence cluster. If a user is sending too many requests to a shard, we would choose to rate limit requests to that shard. Since other users in other domains are also using the shard, they will also be rate limited.\nRate limiting users of a healthy domain because of requests from a completely different domain goes against the isolation the domains are meant to ensure."]}),"\n"]}),"\n",(0,s.jsx)(t.h2,{id:"how-does-it-work",children:"How Does It Work?"}),"\n",(0,s.jsx)(t.p,{children:"Workflow ID-based rate limits are set for all workflow IDs in a domain. If the external limit for a domain is e.g. set to 100 it means that any single workflow ID in that domain can at most be signaled 100 times a second. The rate limits are implemented in two main areas:"}),"\n",(0,s.jsxs)(t.ol,{children:["\n",(0,s.jsxs)(t.li,{children:["\n",(0,s.jsxs)(t.p,{children:[(0,s.jsx)(t.strong,{children:"External Calls"})," Cadence limits the number of requests per second for each workflow ID, which includes operations like starting, querying, or signaling a workflow. If this limit is exceeded, a ServiceBusyError with message \u201cToo many requests for the workflow ID\u201d is triggered, indicating that the rate limit for the workflow has been reached."]}),"\n"]}),"\n",(0,s.jsxs)(t.li,{children:["\n",(0,s.jsxs)(t.p,{children:[(0,s.jsx)(t.strong,{children:"Actions Within a Workflow"})," This limit controls the number of tasks processed per second within a workflow, focusing on managing decision tasks and activity tasks. When these limits are reached, Cadence slows down task processing without requiring any intervention from the user, though they might notice an increase in task execution time, eventually causing timeouts."]}),"\n"]}),"\n"]}),"\n",(0,s.jsx)(t.h3,{id:"how-do-i-enable-it",children:"How do I Enable It?"}),"\n",(0,s.jsx)(t.p,{children:"The limits are controlled using six dynamic config properties, three for the internal limits, and a corresponding three for the external limits, all with a domain filter, so the limits can be controlled for each domain."}),"\n",(0,s.jsxs)(t.ul,{children:["\n",(0,s.jsxs)(t.li,{children:["history.workflowIDCacheInternalEnabled",(0,s.jsx)(t.br,{}),"\n","history.workflowIDCacheExternalEnabled","\n",(0,s.jsxs)(t.ul,{children:["\n",(0,s.jsx)(t.li,{children:"Controls if the statistics needed to do the rate limiting should be collected. The feature keeps an in-memory record in the history service for each workflow ID."}),"\n"]}),"\n"]}),"\n",(0,s.jsxs)(t.li,{children:["history.workflowIDInternalRPS",(0,s.jsx)(t.br,{}),"\n","history.workflowIDExternalRPS","\n",(0,s.jsxs)(t.ul,{children:["\n",(0,s.jsx)(t.li,{children:"Sets the number of requests allowed per second per workflow in a particular domain."}),"\n"]}),"\n"]}),"\n",(0,s.jsxs)(t.li,{children:["history.workflowIDExternalRateLimitEnabled",(0,s.jsx)(t.br,{}),"\n","history.workflowIDInternalRateLimitEnabled","\n",(0,s.jsxs)(t.ul,{children:["\n",(0,s.jsxs)(t.li,{children:["Set whether rate limiting should happen. Setting this to false allows us to see which domains ",(0,s.jsx)(t.em,{children:"would have"})," been rate limited and adjust them before enforcing the limits."]}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,s.jsx)(t.p,{children:"An example configuration using the file based dynamic configuration could look like this:"}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-yaml",children:"history.workflowIDCacheExternalEnabled:\n- value: true\n constraints: {}\nhistory.workflowIDExternalRateLimitEnabled:\n- value: false\n constraints:\n domainName: samples-domain\n- value: true\n constraints: {}\nhistory.workflowIDExternalRPS:\n- value: 100\n constraints: {}\n"})}),"\n",(0,s.jsx)(t.p,{children:"Here only the external rate limits are enabled. The internal rate limits have the same structure. We see that \u200cthe rate limiting is enabled for all domains, with a max RPS of 100. The domain samples-domain is however running in shadow mode, so its requests are not rate limited, but metrics and logs are still emitted."}),"\n",(0,s.jsx)(t.p,{children:"The exact RPS to set for a specific domain and cluster, depends on many things, such as the number of shards, the selected persistent layer, the general load on the cluster etc."}),"\n",(0,s.jsx)(t.h2,{id:"monitoring-and-troubleshooting",children:"Monitoring and Troubleshooting"}),"\n",(0,s.jsx)(t.p,{children:"The new feature introduces both new metrics and new logs. The new logs help us find workflows that are being rate limited, while the new metrics let us see if domains are being rate limited, and how close to being rate limited they are."}),"\n",(0,s.jsx)(t.p,{children:"There are four new metrics, two for internal limits and two corresponding metrics for external limits, all emitted from history."}),"\n",(0,s.jsxs)(t.ul,{children:["\n",(0,s.jsxs)(t.li,{children:["workflow_id_external_requests_ratelimited",(0,s.jsx)(t.br,{}),"\n","workflow_id_internal_requests_ratelimited","\n",(0,s.jsxs)(t.ul,{children:["\n",(0,s.jsx)(t.li,{children:"This is a counter that counts the number of rate limited requests. The metric is tagged with the domain, so we can track the rate limiting per domain."}),"\n"]}),"\n"]}),"\n",(0,s.jsxs)(t.li,{children:["workflow_id_external_requests_max_requests_per_second",(0,s.jsx)(t.br,{}),"\n","workflow_id_internal_requests_max_requests_per_second","\n",(0,s.jsxs)(t.ul,{children:["\n",(0,s.jsx)(t.li,{children:"This is a timer metric. The upper series gives the max number of requests to a single workflow ID. This is again tagged with the domain, so we can for each domain see how close its workflows are to the limit."}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,s.jsx)(t.p,{children:"These metrics let us monitor and alert on the new rate limits. Additionally, when breaking a rate limit, the history service will emit an info log with the message \u201cRate limiting workflowID\u201d, these logs are tagged with the workflowID that is being limited, so it is easy to find the offending workflow. An example log would look like this:"}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-json",children:'{\n "level":"info",\n "ts":"2024-09-02T08:47:12.843Z",\n "msg":"Rate limiting workflowID",\n "service":"cadence-history",\n "request-type":"external",\n "wf-domain-id":"fc0c7fcb-5796-4c80-b0d7-10bbbc66614e",\n "wf-domain-name":"samples-domain",\n "wf-id":"test",\n "logging-call-at":"cache.go:175"\n}\n'})}),"\n",(0,s.jsx)(t.h2,{id:"conclusion",children:"Conclusion"}),"\n",(0,s.jsx)(t.p,{children:"Implementing these rate limits highly improves the reliability of a Cadence cluster, as users now cannot send too many requests to a single shard. This fine-grained control helps in maintaining optimal performance and enhances the ability to forecast and mitigate potential issues before they impact the service."}),"\n",(0,s.jsx)(t.p,{children:"Workflow ID-based rate limits are a significant step forward in our ongoing effort to provide a robust and efficient workflow management service. By preventing hot shards and ensuring equitable resource distribution, we can offer more reliable performance, even under peak loads. We encourage all Cadence users to familiarize themselves with these new limits and adjust their workflow configurations to achieve optimal results."})]})}function c(e={}){const{wrapper:t}={...(0,o.R)(),...e.components};return t?(0,s.jsx)(t,{...e,children:(0,s.jsx)(h,{...e})}):h(e)}},8453:(e,t,i)=>{i.d(t,{R:()=>r,x:()=>a});var n=i(6540);const s={},o=n.createContext(s);function r(e){const t=n.useContext(o);return n.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function a(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:r(e.components),n.createElement(o.Provider,{value:t},e.children)}},9559:e=>{e.exports=JSON.parse('{"permalink":"/Cadence-Docs/blog/2024/09/05/workflow-specific-rate-limits","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2024-09-05-workflow-specific-rate-limits.md","source":"@site/blog/2024-09-05-workflow-specific-rate-limits.md","title":"Minimizing blast radius in Cadence: Introducing Workflow ID-based Rate Limits","description":"At Uber, we run several big multitenant Cadence clusters with hundreds of domains in each. The clusters being multi-tenant means potential noisy neighbor effects between domains.","date":"2024-09-05T00:00:00.000Z","tags":[{"inline":false,"label":"Deep Dives","permalink":"/Cadence-Docs/blog/tags/deep-dives","description":"Deep Dives tag description"}],"readingTime":6.335,"hasTruncateMarker":true,"authors":[{"name":"Jakob Haahr Taankvist","title":"Software Engineer II @ Uber","url":"https://www.linkedin.com/in/jakob-taankvist/","page":{"permalink":"/Cadence-Docs/blog/authors/jakobht"},"socials":{"linkedin":"https://www.linkedin.com/in/jakob-taankvist/","github":"https://github.com/jakobht"},"imageURL":"https://github.com/jakobht.png","key":"jakobht"}],"frontMatter":{"title":"Minimizing blast radius in Cadence: Introducing Workflow ID-based Rate Limits","date":"2024-09-05T00:00:00.000Z","authors":"jakobht","tags":["deep-dive"]},"unlisted":false,"prevItem":{"title":"Announcement: Cadence Helm Charts v0 Release","permalink":"/Cadence-Docs/blog/2024/10/01/announcing-cadence-helm-charts-v0"},"nextItem":{"title":"2024 Cadence Yearly Roadmap Update","permalink":"/Cadence-Docs/blog/2024/07/11/2024-07-11-yearly-roadmap-update/yearly-roadmap-update"}}')}}]); \ No newline at end of file diff --git a/assets/js/86c2314d.8b8de600.js b/assets/js/86c2314d.8b8de600.js deleted file mode 100644 index db2b7a7f0..000000000 --- a/assets/js/86c2314d.8b8de600.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[7262],{8251:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>l,contentTitle:()=>s,default:()=>h,frontMatter:()=>r,metadata:()=>o,toc:()=>d});const o=JSON.parse('{"id":"go-client/index","title":"Introduction","description":"Overview","source":"@site/docs/05-go-client/index.md","sourceDirName":"05-go-client","slug":"/go-client/","permalink":"/docs/go-client/","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/05-go-client/index.md","tags":[],"version":"current","frontMatter":{"layout":"default","title":"Introduction","permalink":"/docs/go-client"},"sidebar":"docsSidebar","previous":{"title":"Workflow Replay and Shadowing","permalink":"/docs/java-client/workflow-replay-shadowing"},"next":{"title":"Worker service","permalink":"/docs/go-client/workers"}}');var c=t(4848),i=t(8453);const r={layout:"default",title:"Introduction",permalink:"/docs/go-client"},s="Go client",l={},d=[{value:"Overview",id:"overview",level:2},{value:"Links",id:"links",level:2}];function a(e){const n={a:"a",code:"code",h1:"h1",h2:"h2",header:"header",li:"li",p:"p",ul:"ul",...(0,i.R)(),...e.components};return(0,c.jsxs)(c.Fragment,{children:[(0,c.jsx)(n.header,{children:(0,c.jsx)(n.h1,{id:"go-client",children:"Go client"})}),"\n",(0,c.jsx)(n.h2,{id:"overview",children:"Overview"}),"\n",(0,c.jsx)(n.p,{children:"Go client attempts to follow Go language conventions. The conversion of a Go program to the fault-oblivious workflow function is expected to be pretty mechanical."}),"\n",(0,c.jsxs)(n.p,{children:["Cadence requires determinism of the workflow code. It supports deterministic execution of the multithreaded code and constructs like ",(0,c.jsx)(n.code,{children:"select"})," that are non-deterministic by Go design. The Cadence solution is to provide corresponding constructs in the form of interfaces that have similar capability but support deterministic execution."]}),"\n",(0,c.jsxs)(n.p,{children:["For example, instead of native Go channels, workflow code must use the ",(0,c.jsx)(n.code,{children:"workflow.Channel"})," interface. Instead of ",(0,c.jsx)(n.code,{children:"select"}),", the ",(0,c.jsx)(n.code,{children:"workflow.Selector"})," interface must be used."]}),"\n",(0,c.jsxs)(n.p,{children:["For more information, see ",(0,c.jsx)(n.a,{href:"/docs/go-client/create-workflows",children:"Creating Workflows"}),"."]}),"\n",(0,c.jsx)(n.h2,{id:"links",children:"Links"}),"\n",(0,c.jsxs)(n.ul,{children:["\n",(0,c.jsxs)(n.li,{children:["GitHub project: ",(0,c.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence-go-client",children:"https://github.com/cadence-workflow/cadence-go-client"})]}),"\n",(0,c.jsxs)(n.li,{children:["Samples: ",(0,c.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence-samples",children:"https://github.com/cadence-workflow/cadence-samples"})]}),"\n",(0,c.jsxs)(n.li,{children:["GoDoc documentation: ",(0,c.jsx)(n.a,{href:"https://godoc.org/go.uber.org/cadence",children:"https://godoc.org/go.uber.org/cadence"})]}),"\n"]})]})}function h(e={}){const{wrapper:n}={...(0,i.R)(),...e.components};return n?(0,c.jsx)(n,{...e,children:(0,c.jsx)(a,{...e})}):a(e)}},8453:(e,n,t)=>{t.d(n,{R:()=>r,x:()=>s});var o=t(6540);const c={},i=o.createContext(c);function r(e){const n=o.useContext(i);return o.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function s(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(c):e.components||c:r(e.components),o.createElement(i.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/86c2314d.cdd3c4f8.js b/assets/js/86c2314d.cdd3c4f8.js new file mode 100644 index 000000000..5bd194960 --- /dev/null +++ b/assets/js/86c2314d.cdd3c4f8.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[7262],{8251:(e,n,o)=>{o.r(n),o.d(n,{assets:()=>l,contentTitle:()=>s,default:()=>h,frontMatter:()=>r,metadata:()=>t,toc:()=>d});const t=JSON.parse('{"id":"go-client/index","title":"Introduction","description":"Overview","source":"@site/docs/05-go-client/index.md","sourceDirName":"05-go-client","slug":"/go-client/","permalink":"/Cadence-Docs/docs/go-client/","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/05-go-client/index.md","tags":[],"version":"current","frontMatter":{"layout":"default","title":"Introduction","permalink":"/docs/go-client"},"sidebar":"docsSidebar","previous":{"title":"Workflow Replay and Shadowing","permalink":"/Cadence-Docs/docs/java-client/workflow-replay-shadowing"},"next":{"title":"Worker service","permalink":"/Cadence-Docs/docs/go-client/workers"}}');var c=o(4848),i=o(8453);const r={layout:"default",title:"Introduction",permalink:"/docs/go-client"},s="Go client",l={},d=[{value:"Overview",id:"overview",level:2},{value:"Links",id:"links",level:2}];function a(e){const n={a:"a",code:"code",h1:"h1",h2:"h2",header:"header",li:"li",p:"p",ul:"ul",...(0,i.R)(),...e.components};return(0,c.jsxs)(c.Fragment,{children:[(0,c.jsx)(n.header,{children:(0,c.jsx)(n.h1,{id:"go-client",children:"Go client"})}),"\n",(0,c.jsx)(n.h2,{id:"overview",children:"Overview"}),"\n",(0,c.jsx)(n.p,{children:"Go client attempts to follow Go language conventions. The conversion of a Go program to the fault-oblivious workflow function is expected to be pretty mechanical."}),"\n",(0,c.jsxs)(n.p,{children:["Cadence requires determinism of the workflow code. It supports deterministic execution of the multithreaded code and constructs like ",(0,c.jsx)(n.code,{children:"select"})," that are non-deterministic by Go design. The Cadence solution is to provide corresponding constructs in the form of interfaces that have similar capability but support deterministic execution."]}),"\n",(0,c.jsxs)(n.p,{children:["For example, instead of native Go channels, workflow code must use the ",(0,c.jsx)(n.code,{children:"workflow.Channel"})," interface. Instead of ",(0,c.jsx)(n.code,{children:"select"}),", the ",(0,c.jsx)(n.code,{children:"workflow.Selector"})," interface must be used."]}),"\n",(0,c.jsxs)(n.p,{children:["For more information, see ",(0,c.jsx)(n.a,{href:"/docs/go-client/create-workflows",children:"Creating Workflows"}),"."]}),"\n",(0,c.jsx)(n.h2,{id:"links",children:"Links"}),"\n",(0,c.jsxs)(n.ul,{children:["\n",(0,c.jsxs)(n.li,{children:["GitHub project: ",(0,c.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence-go-client",children:"https://github.com/cadence-workflow/cadence-go-client"})]}),"\n",(0,c.jsxs)(n.li,{children:["Samples: ",(0,c.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence-samples",children:"https://github.com/cadence-workflow/cadence-samples"})]}),"\n",(0,c.jsxs)(n.li,{children:["GoDoc documentation: ",(0,c.jsx)(n.a,{href:"https://godoc.org/go.uber.org/cadence",children:"https://godoc.org/go.uber.org/cadence"})]}),"\n"]})]})}function h(e={}){const{wrapper:n}={...(0,i.R)(),...e.components};return n?(0,c.jsx)(n,{...e,children:(0,c.jsx)(a,{...e})}):a(e)}},8453:(e,n,o)=>{o.d(n,{R:()=>r,x:()=>s});var t=o(6540);const c={},i=t.createContext(c);function r(e){const n=t.useContext(i);return t.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function s(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(c):e.components||c:r(e.components),t.createElement(i.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/87d83cd2.b8386a4e.js b/assets/js/87d83cd2.6b71d628.js similarity index 54% rename from assets/js/87d83cd2.b8386a4e.js rename to assets/js/87d83cd2.6b71d628.js index b16c5ab9b..22afb1adb 100644 --- a/assets/js/87d83cd2.b8386a4e.js +++ b/assets/js/87d83cd2.6b71d628.js @@ -1 +1 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[9928],{994:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>r,contentTitle:()=>l,default:()=>d,frontMatter:()=>s,metadata:()=>o,toc:()=>c});var o=n(4436),a=n(4848),i=n(8453);const s={title:"Cadence Community Spotlight Update - December 2022",date:new Date("2022-12-23T00:00:00.000Z"),authors:"sharanf",tags:["community-spotlight"]},l=void 0,r={authorsImageUrls:[void 0]},c=[{value:"Happy Holidays",id:"happy-holidays",level:2},{value:"Cadence in the News!",id:"cadence-in-the-news",level:2}];function h(e){const t={a:"a",h2:"h2",li:"li",p:"p",ul:"ul",...(0,i.R)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(t.p,{children:"I know we are a little early this month as many people will be taking some time out for holidays."}),"\n",(0,a.jsx)(t.h2,{id:"happy-holidays",children:"Happy Holidays"}),"\n",(0,a.jsx)(t.p,{children:"We'd like to wish everyone happy holidays and to thank you for being part of the Cadence community. It's been a busy year for Cadence as we have continued to build a strong, active community that works together to solve issues and generally support each other."}),"\n",(0,a.jsx)(t.p,{children:"Let's keep going!...This is a great way to build a sustainable community."}),"\n",(0,a.jsx)(t.p,{children:"We are sure that 2023 will be even more exciting as we continue to develop Cadence."}),"\n",(0,a.jsx)(t.h2,{id:"cadence-in-the-news",children:"Cadence in the News!"}),"\n",(0,a.jsx)(t.p,{children:"Below are a selection of Cadence related articles, blogs and whitepapers. Please take a look and feel free to share via your own social media channels."}),"\n",(0,a.jsxs)(t.ul,{children:["\n",(0,a.jsxs)(t.li,{children:["\n",(0,a.jsx)(t.p,{children:(0,a.jsx)(t.a,{href:"https://www.instaclustr.com/blog/cadence-iwf",children:"Cadence iWF"})}),"\n"]}),"\n",(0,a.jsxs)(t.li,{children:["\n",(0,a.jsx)(t.p,{children:(0,a.jsx)(t.a,{href:"https://github.com/instaclustr/cadence-cookbooks-instafood/blob/main/cookbooks/child-workflows/child-workflows-megafood.md",children:"Child Workflow Cookbook"})}),"\n"]}),"\n",(0,a.jsxs)(t.li,{children:["\n",(0,a.jsx)(t.p,{children:(0,a.jsx)(t.a,{href:"https://www.instaclustr.com/blog/cadence-connection-examples-using-tls/",children:"Cadence Connection Examples Using TLS"})}),"\n"]}),"\n"]})]})}function d(e={}){const{wrapper:t}={...(0,i.R)(),...e.components};return t?(0,a.jsx)(t,{...e,children:(0,a.jsx)(h,{...e})}):h(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>s,x:()=>l});var o=n(6540);const a={},i=o.createContext(a);function s(e){const t=o.useContext(i);return o.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function l(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:s(e.components),o.createElement(i.Provider,{value:t},e.children)}},4436:e=>{e.exports=JSON.parse('{"permalink":"/blog/2022/12/23/community-spotlight-december-2022","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2022-12-23-community-spotlight-december-2022.md","source":"@site/blog/2022-12-23-community-spotlight-december-2022.md","title":"Cadence Community Spotlight Update - December 2022","description":"I know we are a little early this month as many people will be taking some time out for holidays.","date":"2022-12-23T00:00:00.000Z","tags":[{"inline":false,"label":"Community Spotlight","permalink":"/blog/tags/community-spotlights","description":"Community Spotlight tag description"}],"readingTime":1.08,"hasTruncateMarker":true,"authors":[{"name":"Sharan Foga","title":"Director of Operations & Customer Success @ Encube Technologies","url":"https://www.linkedin.com/in/sfoga/","page":{"permalink":"/blog/authors/sharanf"},"socials":{"linkedin":"https://www.linkedin.com/in/sfoga/","github":"https://github.com/sharanf"},"imageURL":"https://github.com/sharanf.png","key":"sharanf"}],"frontMatter":{"title":"Cadence Community Spotlight Update - December 2022","date":"2022-12-23T00:00:00.000Z","authors":"sharanf","tags":["community-spotlight"]},"unlisted":false,"prevItem":{"title":"Cadence Community Spotlight Update - January 2023","permalink":"/blog/2023/01/31/community-spotlight-january-2023"},"nextItem":{"title":"Cadence Community Spotlight Update - November 2022","permalink":"/blog/2022/11/30/community-spotlight-november-2022"}}')}}]); \ No newline at end of file +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[9928],{994:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>c,contentTitle:()=>l,default:()=>h,frontMatter:()=>s,metadata:()=>o,toc:()=>r});var o=n(4436),a=n(4848),i=n(8453);const s={title:"Cadence Community Spotlight Update - December 2022",date:new Date("2022-12-23T00:00:00.000Z"),authors:"sharanf",tags:["community-spotlight"]},l=void 0,c={authorsImageUrls:[void 0]},r=[{value:"Happy Holidays",id:"happy-holidays",level:2},{value:"Cadence in the News!",id:"cadence-in-the-news",level:2}];function d(e){const t={a:"a",h2:"h2",li:"li",p:"p",ul:"ul",...(0,i.R)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(t.p,{children:"I know we are a little early this month as many people will be taking some time out for holidays."}),"\n",(0,a.jsx)(t.h2,{id:"happy-holidays",children:"Happy Holidays"}),"\n",(0,a.jsx)(t.p,{children:"We'd like to wish everyone happy holidays and to thank you for being part of the Cadence community. It's been a busy year for Cadence as we have continued to build a strong, active community that works together to solve issues and generally support each other."}),"\n",(0,a.jsx)(t.p,{children:"Let's keep going!...This is a great way to build a sustainable community."}),"\n",(0,a.jsx)(t.p,{children:"We are sure that 2023 will be even more exciting as we continue to develop Cadence."}),"\n",(0,a.jsx)(t.h2,{id:"cadence-in-the-news",children:"Cadence in the News!"}),"\n",(0,a.jsx)(t.p,{children:"Below are a selection of Cadence related articles, blogs and whitepapers. Please take a look and feel free to share via your own social media channels."}),"\n",(0,a.jsxs)(t.ul,{children:["\n",(0,a.jsxs)(t.li,{children:["\n",(0,a.jsx)(t.p,{children:(0,a.jsx)(t.a,{href:"https://www.instaclustr.com/blog/cadence-iwf",children:"Cadence iWF"})}),"\n"]}),"\n",(0,a.jsxs)(t.li,{children:["\n",(0,a.jsx)(t.p,{children:(0,a.jsx)(t.a,{href:"https://github.com/instaclustr/cadence-cookbooks-instafood/blob/main/cookbooks/child-workflows/child-workflows-megafood.md",children:"Child Workflow Cookbook"})}),"\n"]}),"\n",(0,a.jsxs)(t.li,{children:["\n",(0,a.jsx)(t.p,{children:(0,a.jsx)(t.a,{href:"https://www.instaclustr.com/blog/cadence-connection-examples-using-tls/",children:"Cadence Connection Examples Using TLS"})}),"\n"]}),"\n"]})]})}function h(e={}){const{wrapper:t}={...(0,i.R)(),...e.components};return t?(0,a.jsx)(t,{...e,children:(0,a.jsx)(d,{...e})}):d(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>s,x:()=>l});var o=n(6540);const a={},i=o.createContext(a);function s(e){const t=o.useContext(i);return o.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function l(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:s(e.components),o.createElement(i.Provider,{value:t},e.children)}},4436:e=>{e.exports=JSON.parse('{"permalink":"/Cadence-Docs/blog/2022/12/23/community-spotlight-december-2022","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2022-12-23-community-spotlight-december-2022.md","source":"@site/blog/2022-12-23-community-spotlight-december-2022.md","title":"Cadence Community Spotlight Update - December 2022","description":"I know we are a little early this month as many people will be taking some time out for holidays.","date":"2022-12-23T00:00:00.000Z","tags":[{"inline":false,"label":"Community Spotlight","permalink":"/Cadence-Docs/blog/tags/community-spotlights","description":"Community Spotlight tag description"}],"readingTime":1.08,"hasTruncateMarker":true,"authors":[{"name":"Sharan Foga","title":"Director of Operations & Customer Success @ Encube Technologies","url":"https://www.linkedin.com/in/sfoga/","page":{"permalink":"/Cadence-Docs/blog/authors/sharanf"},"socials":{"linkedin":"https://www.linkedin.com/in/sfoga/","github":"https://github.com/sharanf"},"imageURL":"https://github.com/sharanf.png","key":"sharanf"}],"frontMatter":{"title":"Cadence Community Spotlight Update - December 2022","date":"2022-12-23T00:00:00.000Z","authors":"sharanf","tags":["community-spotlight"]},"unlisted":false,"prevItem":{"title":"Cadence Community Spotlight Update - January 2023","permalink":"/Cadence-Docs/blog/2023/01/31/community-spotlight-january-2023"},"nextItem":{"title":"Cadence Community Spotlight Update - November 2022","permalink":"/Cadence-Docs/blog/2022/11/30/community-spotlight-november-2022"}}')}}]); \ No newline at end of file diff --git a/assets/js/88d84d8e.c9d7ea2f.js b/assets/js/88d84d8e.bd47e9b5.js similarity index 79% rename from assets/js/88d84d8e.c9d7ea2f.js rename to assets/js/88d84d8e.bd47e9b5.js index 64288d445..b24e25830 100644 --- a/assets/js/88d84d8e.c9d7ea2f.js +++ b/assets/js/88d84d8e.bd47e9b5.js @@ -1 +1 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[1094],{9003:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>c,contentTitle:()=>r,default:()=>d,frontMatter:()=>s,metadata:()=>o,toc:()=>l});var o=t(3914),a=t(4848),i=t(8453);const s={title:"Cadence Community Spotlight Update - March 2022",date:new Date("2022-03-31T00:00:00.000Z"),authors:"sharanf",tags:["community-spotlight"]},r=void 0,c={authorsImageUrls:[void 0]},l=[{value:"Updated Cadence Topology Diagram",id:"updated-cadence-topology-diagram",level:2},{value:"Monthly Cadence Technical Office Hours",id:"monthly-cadence-technical-office-hours",level:2},{value:"Some Cadence Statistics",id:"some-cadence-statistics",level:2},{value:"Using StackOverflow to Respond to Support Questions",id:"using-stackoverflow-to-respond-to-support-questions",level:2},{value:"Cadence in the News!",id:"cadence-in-the-news",level:2},{value:"Upcoming Events",id:"upcoming-events",level:2}];function h(e){const n={a:"a",h2:"h2",li:"li",p:"p",ul:"ul",...(0,i.R)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(n.p,{children:"Welcome to our Cadence Community Spotlight update!"}),"\n",(0,a.jsx)(n.p,{children:"This is the latest in our series of monthly blog posts focused on the Cadence community and news about what you have been doing with Cadence."}),"\n",(0,a.jsx)(n.p,{children:"Please see below for a short activity roundup of what has happened recently in the community."}),"\n",(0,a.jsx)(n.h2,{id:"updated-cadence-topology-diagram",children:"Updated Cadence Topology Diagram"}),"\n",(0,a.jsxs)(n.p,{children:["Did you know that we have an updated Cadence Service diagram on the website? Well we do - and you can find it on our ",(0,a.jsx)(n.a,{href:"https://cadenceworkflow.io/docs/concepts/topology/#overview",children:"Deployment Topology"})," page. We are always looking for information that helps makes it easier for people to understand how Cadence works."]}),"\n",(0,a.jsx)(n.p,{children:"Special thanks to Ben Slater for updating the diagram and also to Ender, Emrah and Long for helping review it."}),"\n",(0,a.jsx)(n.h2,{id:"monthly-cadence-technical-office-hours",children:"Monthly Cadence Technical Office Hours"}),"\n",(0,a.jsx)(n.p,{children:"Every month we hold a Technical Office Hours session via Zoom where you can speak directly with some of our Cadence experts. If you have a question about Cadence or are facing a particular issue getting it setup then please come along and chat to one of our experts!"}),"\n",(0,a.jsx)(n.p,{children:"Meetings are held on the last Monday of every month so make sure you mark the dates in your calendars. Our next session will be on the 25th April at 9am PT so hope to see you there!"}),"\n",(0,a.jsxs)(n.p,{children:["The ",(0,a.jsx)(n.a,{href:"https://calendar.google.com/calendar/u/0/embed?src=e6r40gp3c2r01054id7e99dlac@group.calendar.google.com&ctz=America/Los_Angeles",children:"Cadence Community Calendar"})," contains the Zoom link for the meeting and details of any other events planned so please check it regularly."]}),"\n",(0,a.jsx)(n.h2,{id:"some-cadence-statistics",children:"Some Cadence Statistics"}),"\n",(0,a.jsx)(n.p,{children:"This month we thought it would be interesting to post some statistics about the Cadence community."}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsx)(n.li,{children:"1722 - the number of members in our #general Slack channel"}),"\n",(0,a.jsx)(n.li,{children:"24 - the number of questions asked in our #support Slack channel during the month"}),"\n",(0,a.jsx)(n.li,{children:"5 - the number of questions asked about Cadence in StackOverflow during the month"}),"\n",(0,a.jsx)(n.li,{children:"105 - the number of contributors to the Cadence git repo"}),"\n",(0,a.jsx)(n.li,{children:"9 - the number of community members who responded to a question during the month"}),"\n"]}),"\n",(0,a.jsx)(n.h2,{id:"using-stackoverflow-to-respond-to-support-questions",children:"Using StackOverflow to Respond to Support Questions"}),"\n",(0,a.jsx)(n.p,{children:"We have over 1700 members in our #support channel on our Cadence Slack where some of you have been asking questions about Cadence. The community has been responding and provided some great answers that we don\u2019t want to lose!"}),"\n",(0,a.jsx)(n.p,{children:"It can be difficult searching the Slack #support channel for a specific problem and we want to make sure that we capture all these great answers so that they can help others in the community."}),"\n",(0,a.jsxs)(n.p,{children:["So if possible we would like you to start posting your Cadence questions on ",(0,a.jsx)(n.a,{href:"https://stackoverflow.com/",children:"StackOverflow"}),"."]}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsx)(n.li,{children:"Create your question in StackOverflow"}),"\n",(0,a.jsx)(n.li,{children:"Post the StackOverflow question link in the Cadence Slack #support channel"}),"\n",(0,a.jsx)(n.li,{children:"A response to your question will be posted to StackOverflow"}),"\n"]}),"\n",(0,a.jsx)(n.p,{children:"Other community members will be able to search StackOverflow for the details of the your question and see the response. We hope that this will make it easier for people to find answers to common questions."}),"\n",(0,a.jsx)(n.h2,{id:"cadence-in-the-news",children:"Cadence in the News!"}),"\n",(0,a.jsx)(n.p,{children:"Below are a selection of Cadence related articles, blogs and whitepapers. Please take a look and feel free to share via your own social media channels."}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsxs)(n.li,{children:["\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.a,{href:"https://betterprogramming.pub/create-distributed-scalable-durable-and-highly-available-software-with-cadence-9f4fa6b1376b",children:"Create Distributed, Scalable, Durable, and Highly Available Software\u2014 With Cadence"})}),"\n"]}),"\n",(0,a.jsxs)(n.li,{children:["\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.a,{href:"https://www.instaclustr.com/blog/spinning-your-drones-with-cadence-introduction/",children:"Spinning Your Drones with Cadence - Introduction"})}),"\n"]}),"\n",(0,a.jsxs)(n.li,{children:["\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.a,{href:"https://www.globenewswire.com/news-release/2022/04/04/2415472/0/en/Instaclustr-Announces-General-Availability-of-Instaclustr-Managed-Cadence.html",children:"Instaclustr Announces General Availability of Managed Cadence"})}),"\n"]}),"\n",(0,a.jsxs)(n.li,{children:["\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.a,{href:"https://www.youtube.com/watch?v=Vzc_LWmJ8lE&feature=youtu.be",children:"Introducing Managed Cadence on the Instaclustr Platform"})}),"\n"]}),"\n",(0,a.jsxs)(n.li,{children:["\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.a,{href:"https://info.instaclustr.com/rs/620-JHM-287/images/Understanding_Cadence_for%20Ops_and_SRE_WhitePaper.pdf",children:"Whitepaper: Understanding Cadence for Ops and SREs"})}),"\n"]}),"\n"]}),"\n",(0,a.jsx)(n.h2,{id:"upcoming-events",children:"Upcoming Events"}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsxs)(n.li,{children:["\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.a,{href:"https://calendar.google.com/calendar/u/0/embed?src=e6r40gp3c2r01054id7e99dlac@group.calendar.google.com&ctz=America/Los_Angeles",children:"Cadence Technical Office Hours - 25th April 2022 @ 9am PT\n"})}),"\n"]}),"\n",(0,a.jsxs)(n.li,{children:["\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.a,{href:"https://info.instaclustr.com/webinar-spinning-workflows-cadence.html",children:"Webinar : Spinning up Your Workflows with Cadence"})}),"\n"]}),"\n"]}),"\n",(0,a.jsxs)(n.p,{children:["If you have any news or topics you'd like us to include in our next update then please join our ",(0,a.jsx)(n.a,{href:"http://t.uber.com/cadence-slack",children:"Slack"}),"#community channel."]}),"\n",(0,a.jsxs)(n.p,{children:["Please remember that this update is for you - so if you have any comments or feedback that could help us improve it then please share it with us in the #community ",(0,a.jsx)(n.a,{href:"http://t.uber.com/cadence-slack",children:"Slack"})," channel."]})]})}function d(e={}){const{wrapper:n}={...(0,i.R)(),...e.components};return n?(0,a.jsx)(n,{...e,children:(0,a.jsx)(h,{...e})}):h(e)}},8453:(e,n,t)=>{t.d(n,{R:()=>s,x:()=>r});var o=t(6540);const a={},i=o.createContext(a);function s(e){const n=o.useContext(i);return o.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function r(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:s(e.components),o.createElement(i.Provider,{value:n},e.children)}},3914:e=>{e.exports=JSON.parse('{"permalink":"/blog/2022/03/31/community-spotlight-update-march-2022","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2022-03-31-community-spotlight-update-march-2022.md","source":"@site/blog/2022-03-31-community-spotlight-update-march-2022.md","title":"Cadence Community Spotlight Update - March 2022","description":"Welcome to our Cadence Community Spotlight update!","date":"2022-03-31T00:00:00.000Z","tags":[{"inline":false,"label":"Community Spotlight","permalink":"/blog/tags/community-spotlights","description":"Community Spotlight tag description"}],"readingTime":3.235,"hasTruncateMarker":true,"authors":[{"name":"Sharan Foga","title":"Director of Operations & Customer Success @ Encube Technologies","url":"https://www.linkedin.com/in/sfoga/","page":{"permalink":"/blog/authors/sharanf"},"socials":{"linkedin":"https://www.linkedin.com/in/sfoga/","github":"https://github.com/sharanf"},"imageURL":"https://github.com/sharanf.png","key":"sharanf"}],"frontMatter":{"title":"Cadence Community Spotlight Update - March 2022","date":"2022-03-31T00:00:00.000Z","authors":"sharanf","tags":["community-spotlight"]},"unlisted":false,"prevItem":{"title":"Cadence Community Spotlight Update - April 2022","permalink":"/blog/2022/04/30/community-spotlight-update-april-2022"},"nextItem":{"title":"Cadence Community Spotlight Update - February 2022","permalink":"/blog/2022/02/28/community-spotlight-february-2022"}}')}}]); \ No newline at end of file +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[1094],{9003:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>c,contentTitle:()=>r,default:()=>d,frontMatter:()=>i,metadata:()=>o,toc:()=>l});var o=t(3914),a=t(4848),s=t(8453);const i={title:"Cadence Community Spotlight Update - March 2022",date:new Date("2022-03-31T00:00:00.000Z"),authors:"sharanf",tags:["community-spotlight"]},r=void 0,c={authorsImageUrls:[void 0]},l=[{value:"Updated Cadence Topology Diagram",id:"updated-cadence-topology-diagram",level:2},{value:"Monthly Cadence Technical Office Hours",id:"monthly-cadence-technical-office-hours",level:2},{value:"Some Cadence Statistics",id:"some-cadence-statistics",level:2},{value:"Using StackOverflow to Respond to Support Questions",id:"using-stackoverflow-to-respond-to-support-questions",level:2},{value:"Cadence in the News!",id:"cadence-in-the-news",level:2},{value:"Upcoming Events",id:"upcoming-events",level:2}];function h(e){const n={a:"a",h2:"h2",li:"li",p:"p",ul:"ul",...(0,s.R)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(n.p,{children:"Welcome to our Cadence Community Spotlight update!"}),"\n",(0,a.jsx)(n.p,{children:"This is the latest in our series of monthly blog posts focused on the Cadence community and news about what you have been doing with Cadence."}),"\n",(0,a.jsx)(n.p,{children:"Please see below for a short activity roundup of what has happened recently in the community."}),"\n",(0,a.jsx)(n.h2,{id:"updated-cadence-topology-diagram",children:"Updated Cadence Topology Diagram"}),"\n",(0,a.jsxs)(n.p,{children:["Did you know that we have an updated Cadence Service diagram on the website? Well we do - and you can find it on our ",(0,a.jsx)(n.a,{href:"https://cadenceworkflow.io/docs/concepts/topology/#overview",children:"Deployment Topology"})," page. We are always looking for information that helps makes it easier for people to understand how Cadence works."]}),"\n",(0,a.jsx)(n.p,{children:"Special thanks to Ben Slater for updating the diagram and also to Ender, Emrah and Long for helping review it."}),"\n",(0,a.jsx)(n.h2,{id:"monthly-cadence-technical-office-hours",children:"Monthly Cadence Technical Office Hours"}),"\n",(0,a.jsx)(n.p,{children:"Every month we hold a Technical Office Hours session via Zoom where you can speak directly with some of our Cadence experts. If you have a question about Cadence or are facing a particular issue getting it setup then please come along and chat to one of our experts!"}),"\n",(0,a.jsx)(n.p,{children:"Meetings are held on the last Monday of every month so make sure you mark the dates in your calendars. Our next session will be on the 25th April at 9am PT so hope to see you there!"}),"\n",(0,a.jsxs)(n.p,{children:["The ",(0,a.jsx)(n.a,{href:"https://calendar.google.com/calendar/u/0/embed?src=e6r40gp3c2r01054id7e99dlac@group.calendar.google.com&ctz=America/Los_Angeles",children:"Cadence Community Calendar"})," contains the Zoom link for the meeting and details of any other events planned so please check it regularly."]}),"\n",(0,a.jsx)(n.h2,{id:"some-cadence-statistics",children:"Some Cadence Statistics"}),"\n",(0,a.jsx)(n.p,{children:"This month we thought it would be interesting to post some statistics about the Cadence community."}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsx)(n.li,{children:"1722 - the number of members in our #general Slack channel"}),"\n",(0,a.jsx)(n.li,{children:"24 - the number of questions asked in our #support Slack channel during the month"}),"\n",(0,a.jsx)(n.li,{children:"5 - the number of questions asked about Cadence in StackOverflow during the month"}),"\n",(0,a.jsx)(n.li,{children:"105 - the number of contributors to the Cadence git repo"}),"\n",(0,a.jsx)(n.li,{children:"9 - the number of community members who responded to a question during the month"}),"\n"]}),"\n",(0,a.jsx)(n.h2,{id:"using-stackoverflow-to-respond-to-support-questions",children:"Using StackOverflow to Respond to Support Questions"}),"\n",(0,a.jsx)(n.p,{children:"We have over 1700 members in our #support channel on our Cadence Slack where some of you have been asking questions about Cadence. The community has been responding and provided some great answers that we don\u2019t want to lose!"}),"\n",(0,a.jsx)(n.p,{children:"It can be difficult searching the Slack #support channel for a specific problem and we want to make sure that we capture all these great answers so that they can help others in the community."}),"\n",(0,a.jsxs)(n.p,{children:["So if possible we would like you to start posting your Cadence questions on ",(0,a.jsx)(n.a,{href:"https://stackoverflow.com/",children:"StackOverflow"}),"."]}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsx)(n.li,{children:"Create your question in StackOverflow"}),"\n",(0,a.jsx)(n.li,{children:"Post the StackOverflow question link in the Cadence Slack #support channel"}),"\n",(0,a.jsx)(n.li,{children:"A response to your question will be posted to StackOverflow"}),"\n"]}),"\n",(0,a.jsx)(n.p,{children:"Other community members will be able to search StackOverflow for the details of the your question and see the response. We hope that this will make it easier for people to find answers to common questions."}),"\n",(0,a.jsx)(n.h2,{id:"cadence-in-the-news",children:"Cadence in the News!"}),"\n",(0,a.jsx)(n.p,{children:"Below are a selection of Cadence related articles, blogs and whitepapers. Please take a look and feel free to share via your own social media channels."}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsxs)(n.li,{children:["\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.a,{href:"https://betterprogramming.pub/create-distributed-scalable-durable-and-highly-available-software-with-cadence-9f4fa6b1376b",children:"Create Distributed, Scalable, Durable, and Highly Available Software\u2014 With Cadence"})}),"\n"]}),"\n",(0,a.jsxs)(n.li,{children:["\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.a,{href:"https://www.instaclustr.com/blog/spinning-your-drones-with-cadence-introduction/",children:"Spinning Your Drones with Cadence - Introduction"})}),"\n"]}),"\n",(0,a.jsxs)(n.li,{children:["\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.a,{href:"https://www.globenewswire.com/news-release/2022/04/04/2415472/0/en/Instaclustr-Announces-General-Availability-of-Instaclustr-Managed-Cadence.html",children:"Instaclustr Announces General Availability of Managed Cadence"})}),"\n"]}),"\n",(0,a.jsxs)(n.li,{children:["\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.a,{href:"https://www.youtube.com/watch?v=Vzc_LWmJ8lE&feature=youtu.be",children:"Introducing Managed Cadence on the Instaclustr Platform"})}),"\n"]}),"\n",(0,a.jsxs)(n.li,{children:["\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.a,{href:"https://info.instaclustr.com/rs/620-JHM-287/images/Understanding_Cadence_for%20Ops_and_SRE_WhitePaper.pdf",children:"Whitepaper: Understanding Cadence for Ops and SREs"})}),"\n"]}),"\n"]}),"\n",(0,a.jsx)(n.h2,{id:"upcoming-events",children:"Upcoming Events"}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsxs)(n.li,{children:["\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.a,{href:"https://calendar.google.com/calendar/u/0/embed?src=e6r40gp3c2r01054id7e99dlac@group.calendar.google.com&ctz=America/Los_Angeles",children:"Cadence Technical Office Hours - 25th April 2022 @ 9am PT\n"})}),"\n"]}),"\n",(0,a.jsxs)(n.li,{children:["\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.a,{href:"https://info.instaclustr.com/webinar-spinning-workflows-cadence.html",children:"Webinar : Spinning up Your Workflows with Cadence"})}),"\n"]}),"\n"]}),"\n",(0,a.jsxs)(n.p,{children:["If you have any news or topics you'd like us to include in our next update then please join our ",(0,a.jsx)(n.a,{href:"http://t.uber.com/cadence-slack",children:"Slack"}),"#community channel."]}),"\n",(0,a.jsxs)(n.p,{children:["Please remember that this update is for you - so if you have any comments or feedback that could help us improve it then please share it with us in the #community ",(0,a.jsx)(n.a,{href:"http://t.uber.com/cadence-slack",children:"Slack"})," channel."]})]})}function d(e={}){const{wrapper:n}={...(0,s.R)(),...e.components};return n?(0,a.jsx)(n,{...e,children:(0,a.jsx)(h,{...e})}):h(e)}},8453:(e,n,t)=>{t.d(n,{R:()=>i,x:()=>r});var o=t(6540);const a={},s=o.createContext(a);function i(e){const n=o.useContext(s);return o.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function r(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:i(e.components),o.createElement(s.Provider,{value:n},e.children)}},3914:e=>{e.exports=JSON.parse('{"permalink":"/Cadence-Docs/blog/2022/03/31/community-spotlight-update-march-2022","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2022-03-31-community-spotlight-update-march-2022.md","source":"@site/blog/2022-03-31-community-spotlight-update-march-2022.md","title":"Cadence Community Spotlight Update - March 2022","description":"Welcome to our Cadence Community Spotlight update!","date":"2022-03-31T00:00:00.000Z","tags":[{"inline":false,"label":"Community Spotlight","permalink":"/Cadence-Docs/blog/tags/community-spotlights","description":"Community Spotlight tag description"}],"readingTime":3.235,"hasTruncateMarker":true,"authors":[{"name":"Sharan Foga","title":"Director of Operations & Customer Success @ Encube Technologies","url":"https://www.linkedin.com/in/sfoga/","page":{"permalink":"/Cadence-Docs/blog/authors/sharanf"},"socials":{"linkedin":"https://www.linkedin.com/in/sfoga/","github":"https://github.com/sharanf"},"imageURL":"https://github.com/sharanf.png","key":"sharanf"}],"frontMatter":{"title":"Cadence Community Spotlight Update - March 2022","date":"2022-03-31T00:00:00.000Z","authors":"sharanf","tags":["community-spotlight"]},"unlisted":false,"prevItem":{"title":"Cadence Community Spotlight Update - April 2022","permalink":"/Cadence-Docs/blog/2022/04/30/community-spotlight-update-april-2022"},"nextItem":{"title":"Cadence Community Spotlight Update - February 2022","permalink":"/Cadence-Docs/blog/2022/02/28/community-spotlight-february-2022"}}')}}]); \ No newline at end of file diff --git a/assets/js/8a72c69a.01ff779c.js b/assets/js/8a72c69a.01ff779c.js new file mode 100644 index 000000000..a2805d974 --- /dev/null +++ b/assets/js/8a72c69a.01ff779c.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[4196],{3475:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>s,contentTitle:()=>a,default:()=>p,frontMatter:()=>c,metadata:()=>o,toc:()=>d});var o=n(5105),r=n(4848),i=n(8453);const c={title:"Write your first workflow with Cadence",date:new Date("2023-07-16T00:00:00.000Z"),authors:"chopincode",tags:["deep-dive","introduction-to-cadence"]},a=void 0,s={authorsImageUrls:[void 0]},d=[];function l(e){const t={a:"a",code:"code",p:"p",pre:"pre",...(0,i.R)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsxs)(t.p,{children:["We have covered ",(0,r.jsx)(t.a,{href:"/blog/2023/06/28/components-of-cadence-application-setup",children:"basic components of Cadence"})," and ",(0,r.jsx)(t.a,{href:"/blog/2023/07/05/implement-cadence-worker-from-scratch",children:"how to implement a Cadence worker on local environment"})," in previous blogs. In this blog, let's write your very first HelloWorld workflow with Cadence. I've started the Cadence backend server in background and registered a domain named ",(0,r.jsx)(t.code,{children:"test-domain"}),". You may use the code snippet for the worker service in ",(0,r.jsx)(t.a,{href:"/blog/2023/07/05/implement-cadence-worker-from-scratch",children:"this blog"})," Let's first write a activity, which takes a single string argument and print a log in the console."]}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{className:"language-go",children:'func helloWorldActivity(ctx context.Context, name string) (string, error) {\n\tlogger := activity.GetLogger(ctx)\n\tlogger.Info("helloworld activity started")\n\treturn "Hello " + name + "!", nil\n}\n'})})]})}function p(e={}){const{wrapper:t}={...(0,i.R)(),...e.components};return t?(0,r.jsx)(t,{...e,children:(0,r.jsx)(l,{...e})}):l(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>c,x:()=>a});var o=n(6540);const r={},i=o.createContext(r);function c(e){const t=o.useContext(i);return o.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function a(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:c(e.components),o.createElement(i.Provider,{value:t},e.children)}},5105:e=>{e.exports=JSON.parse('{"permalink":"/Cadence-Docs/blog/2023/07/16/2023-07-16-write-your-first-workflow-with-cadence/write-your-first-workflow-with-cadence","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2023-07-16-write-your-first-workflow-with-cadence/2023-07-16-write-your-first-workflow-with-cadence.md","source":"@site/blog/2023-07-16-write-your-first-workflow-with-cadence/2023-07-16-write-your-first-workflow-with-cadence.md","title":"Write your first workflow with Cadence","description":"We have covered basic components of Cadence and how to implement a Cadence worker on local environment in previous blogs. In this blog, let\'s write your very first HelloWorld workflow with Cadence. I\'ve started the Cadence backend server in background and registered a domain named test-domain. You may use the code snippet for the worker service in this blog Let\'s first write a activity, which takes a single string argument and print a log in the console.","date":"2023-07-16T00:00:00.000Z","tags":[{"inline":false,"label":"Deep Dives","permalink":"/Cadence-Docs/blog/tags/deep-dives","description":"Deep Dives tag description"},{"inline":false,"label":"Introduction to Cadence","permalink":"/Cadence-Docs/blog/tags/introduction-to-cadence","description":"Introduction to Cadence tag description"}],"readingTime":2.075,"hasTruncateMarker":true,"authors":[{"name":"Chris Qin","title":"Applications Developer @ Uber","url":"https://www.linkedin.com/in/chrisqin0610/","page":{"permalink":"/Cadence-Docs/blog/authors/chopincode"},"socials":{"linkedin":"https://www.linkedin.com/in/chrisqin0610/","github":"https://github.com/chopincode"},"imageURL":"https://github.com/chopincode.png","key":"chopincode"}],"frontMatter":{"title":"Write your first workflow with Cadence","date":"2023-07-16T00:00:00.000Z","authors":"chopincode","tags":["deep-dive","introduction-to-cadence"]},"unlisted":false,"prevItem":{"title":"Cadence Community Spotlight Update - July 2023","permalink":"/Cadence-Docs/blog/2023/07/31/community-spotlight-july-2023"},"nextItem":{"title":"Bad practices and Anti-patterns with Cadence (Part 1)","permalink":"/Cadence-Docs/blog/2023/07/10/cadence-bad-practices-part-1"}}')}}]); \ No newline at end of file diff --git a/assets/js/8a72c69a.5d2091f8.js b/assets/js/8a72c69a.5d2091f8.js deleted file mode 100644 index 9152ef1e9..000000000 --- a/assets/js/8a72c69a.5d2091f8.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[4196],{3475:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>s,contentTitle:()=>a,default:()=>p,frontMatter:()=>c,metadata:()=>o,toc:()=>d});var o=n(5105),r=n(4848),i=n(8453);const c={title:"Write your first workflow with Cadence",date:new Date("2023-07-16T00:00:00.000Z"),authors:"chopincode",tags:["deep-dive","introduction-to-cadence"]},a=void 0,s={authorsImageUrls:[void 0]},d=[];function l(e){const t={a:"a",code:"code",p:"p",pre:"pre",...(0,i.R)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsxs)(t.p,{children:["We have covered ",(0,r.jsx)(t.a,{href:"/blog/2023/06/28/components-of-cadence-application-setup",children:"basic components of Cadence"})," and ",(0,r.jsx)(t.a,{href:"/blog/2023/07/05/implement-cadence-worker-from-scratch",children:"how to implement a Cadence worker on local environment"})," in previous blogs. In this blog, let's write your very first HelloWorld workflow with Cadence. I've started the Cadence backend server in background and registered a domain named ",(0,r.jsx)(t.code,{children:"test-domain"}),". You may use the code snippet for the worker service in ",(0,r.jsx)(t.a,{href:"/blog/2023/07/05/implement-cadence-worker-from-scratch",children:"this blog"})," Let's first write a activity, which takes a single string argument and print a log in the console."]}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{className:"language-go",children:'func helloWorldActivity(ctx context.Context, name string) (string, error) {\n\tlogger := activity.GetLogger(ctx)\n\tlogger.Info("helloworld activity started")\n\treturn "Hello " + name + "!", nil\n}\n'})})]})}function p(e={}){const{wrapper:t}={...(0,i.R)(),...e.components};return t?(0,r.jsx)(t,{...e,children:(0,r.jsx)(l,{...e})}):l(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>c,x:()=>a});var o=n(6540);const r={},i=o.createContext(r);function c(e){const t=o.useContext(i);return o.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function a(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:c(e.components),o.createElement(i.Provider,{value:t},e.children)}},5105:e=>{e.exports=JSON.parse('{"permalink":"/blog/2023/07/16/2023-07-16-write-your-first-workflow-with-cadence/write-your-first-workflow-with-cadence","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2023-07-16-write-your-first-workflow-with-cadence/2023-07-16-write-your-first-workflow-with-cadence.md","source":"@site/blog/2023-07-16-write-your-first-workflow-with-cadence/2023-07-16-write-your-first-workflow-with-cadence.md","title":"Write your first workflow with Cadence","description":"We have covered basic components of Cadence and how to implement a Cadence worker on local environment in previous blogs. In this blog, let\'s write your very first HelloWorld workflow with Cadence. I\'ve started the Cadence backend server in background and registered a domain named test-domain. You may use the code snippet for the worker service in this blog Let\'s first write a activity, which takes a single string argument and print a log in the console.","date":"2023-07-16T00:00:00.000Z","tags":[{"inline":false,"label":"Deep Dives","permalink":"/blog/tags/deep-dives","description":"Deep Dives tag description"},{"inline":false,"label":"Introduction to Cadence","permalink":"/blog/tags/introduction-to-cadence","description":"Introduction to Cadence tag description"}],"readingTime":2.075,"hasTruncateMarker":true,"authors":[{"name":"Chris Qin","title":"Applications Developer @ Uber","url":"https://www.linkedin.com/in/chrisqin0610/","page":{"permalink":"/blog/authors/chopincode"},"socials":{"linkedin":"https://www.linkedin.com/in/chrisqin0610/","github":"https://github.com/chopincode"},"imageURL":"https://github.com/chopincode.png","key":"chopincode"}],"frontMatter":{"title":"Write your first workflow with Cadence","date":"2023-07-16T00:00:00.000Z","authors":"chopincode","tags":["deep-dive","introduction-to-cadence"]},"unlisted":false,"prevItem":{"title":"Cadence Community Spotlight Update - July 2023","permalink":"/blog/2023/07/31/community-spotlight-july-2023"},"nextItem":{"title":"Bad practices and Anti-patterns with Cadence (Part 1)","permalink":"/blog/2023/07/10/cadence-bad-practices-part-1"}}')}}]); \ No newline at end of file diff --git a/assets/js/8d2e039e.b41be10f.js b/assets/js/8d2e039e.b41be10f.js new file mode 100644 index 000000000..2b4ee7040 --- /dev/null +++ b/assets/js/8d2e039e.b41be10f.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[4505],{1316:(e,o,t)=>{t.r(o),t.d(o,{assets:()=>c,contentTitle:()=>l,default:()=>d,frontMatter:()=>i,metadata:()=>r,toc:()=>a});const r=JSON.parse('{"id":"workflow-troubleshooting/index","title":"Overview","description":"This document will serve as a guide for troubleshooting a workflow for potential issues.","source":"@site/docs/08-workflow-troubleshooting/index.md","sourceDirName":"08-workflow-troubleshooting","slug":"/workflow-troubleshooting/","permalink":"/Cadence-Docs/docs/workflow-troubleshooting/","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/08-workflow-troubleshooting/index.md","tags":[],"version":"current","frontMatter":{"layout":"default","title":"Overview","permalink":"/docs/workflow-troubleshooting"},"sidebar":"docsSidebar","previous":{"title":"Cluster Migration","permalink":"/Cadence-Docs/docs/operation-guide/migration"},"next":{"title":"Timeouts","permalink":"/Cadence-Docs/docs/workflow-troubleshooting/timeouts"}}');var n=t(4848),s=t(8453);const i={layout:"default",title:"Overview",permalink:"/docs/workflow-troubleshooting"},l="Workflow Troubleshooting Overview",c={},a=[];function u(e){const o={h1:"h1",header:"header",p:"p",...(0,s.R)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(o.header,{children:(0,n.jsx)(o.h1,{id:"workflow-troubleshooting-overview",children:"Workflow Troubleshooting Overview"})}),"\n",(0,n.jsx)(o.p,{children:"This document will serve as a guide for troubleshooting a workflow for potential issues."})]})}function d(e={}){const{wrapper:o}={...(0,s.R)(),...e.components};return o?(0,n.jsx)(o,{...e,children:(0,n.jsx)(u,{...e})}):u(e)}},8453:(e,o,t)=>{t.d(o,{R:()=>i,x:()=>l});var r=t(6540);const n={},s=r.createContext(n);function i(e){const o=r.useContext(s);return r.useMemo((function(){return"function"==typeof e?e(o):{...o,...e}}),[o,e])}function l(e){let o;return o=e.disableParentContext?"function"==typeof e.components?e.components(n):e.components||n:i(e.components),r.createElement(s.Provider,{value:o},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/8d2e039e.e6f31b8f.js b/assets/js/8d2e039e.e6f31b8f.js deleted file mode 100644 index 639b2518c..000000000 --- a/assets/js/8d2e039e.e6f31b8f.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[4505],{1316:(e,o,t)=>{t.r(o),t.d(o,{assets:()=>c,contentTitle:()=>l,default:()=>d,frontMatter:()=>i,metadata:()=>r,toc:()=>u});const r=JSON.parse('{"id":"workflow-troubleshooting/index","title":"Overview","description":"This document will serve as a guide for troubleshooting a workflow for potential issues.","source":"@site/docs/08-workflow-troubleshooting/index.md","sourceDirName":"08-workflow-troubleshooting","slug":"/workflow-troubleshooting/","permalink":"/docs/workflow-troubleshooting/","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/08-workflow-troubleshooting/index.md","tags":[],"version":"current","frontMatter":{"layout":"default","title":"Overview","permalink":"/docs/workflow-troubleshooting"},"sidebar":"docsSidebar","previous":{"title":"Cluster Migration","permalink":"/docs/operation-guide/migration"},"next":{"title":"Timeouts","permalink":"/docs/workflow-troubleshooting/timeouts"}}');var n=t(4848),s=t(8453);const i={layout:"default",title:"Overview",permalink:"/docs/workflow-troubleshooting"},l="Workflow Troubleshooting Overview",c={},u=[];function a(e){const o={h1:"h1",header:"header",p:"p",...(0,s.R)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(o.header,{children:(0,n.jsx)(o.h1,{id:"workflow-troubleshooting-overview",children:"Workflow Troubleshooting Overview"})}),"\n",(0,n.jsx)(o.p,{children:"This document will serve as a guide for troubleshooting a workflow for potential issues."})]})}function d(e={}){const{wrapper:o}={...(0,s.R)(),...e.components};return o?(0,n.jsx)(o,{...e,children:(0,n.jsx)(a,{...e})}):a(e)}},8453:(e,o,t)=>{t.d(o,{R:()=>i,x:()=>l});var r=t(6540);const n={},s=r.createContext(n);function i(e){const o=r.useContext(s);return r.useMemo((function(){return"function"==typeof e?e(o):{...o,...e}}),[o,e])}function l(e){let o;return o=e.disableParentContext?"function"==typeof e.components?e.components(n):e.components||n:i(e.components),r.createElement(s.Provider,{value:o},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/8ea09047.84ab407b.js b/assets/js/8ea09047.84ab407b.js deleted file mode 100644 index 4dc851119..000000000 --- a/assets/js/8ea09047.84ab407b.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[9385],{600:e=>{e.exports=JSON.parse('{"metadata":{"permalink":"/blog/page/2","page":2,"postsPerPage":10,"totalPages":4,"totalCount":35,"previousPage":"/blog","nextPage":"/blog/page/3","blogDescription":"The latest news and updates from the Cadence team","blogTitle":"Cadence Blog"}}')}}]); \ No newline at end of file diff --git a/assets/js/8edf5fa8.c9891f16.js b/assets/js/8edf5fa8.2282b2fb.js similarity index 81% rename from assets/js/8edf5fa8.c9891f16.js rename to assets/js/8edf5fa8.2282b2fb.js index f8f04ed28..d702a193f 100644 --- a/assets/js/8edf5fa8.c9891f16.js +++ b/assets/js/8edf5fa8.2282b2fb.js @@ -1 +1 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[5910],{7629:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>l,contentTitle:()=>r,default:()=>h,frontMatter:()=>s,metadata:()=>a,toc:()=>c});var a=t(2087),i=t(4848),o=t(8453);const s={title:"Cadence Community Spotlight Update - March 2024",date:new Date("2023-03-11T00:00:00.000Z"),authors:"kcorbett-netapp",tags:["community-spotlight"]},r=void 0,l={authorsImageUrls:[void 0]},c=[{value:"Proposal for Cadence Plugin System",id:"proposal-for-cadence-plugin-system",level:2},{value:"Admin API Permissions Rethinking",id:"admin-api-permissions-rethinking",level:2},{value:"New Java Samples for Cadence: Signal Workflow Interactions",id:"new-java-samples-for-cadence-signal-workflow-interactions",level:2},{value:"New GoLang client & Cadence Web Enhancements",id:"new-golang-client--cadence-web-enhancements",level:2},{value:"Release Updates: v1.2.6 & v1.2.7",id:"release-updates-v126--v127",level:2},{value:"Cadence in the News!",id:"cadence-in-the-news",level:2},{value:"Recent Events",id:"recent-events",level:2}];function d(e){const n={a:"a",br:"br",h2:"h2",li:"li",p:"p",ul:"ul",...(0,o.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsxs)(n.p,{children:["Welcome back to the latest in our regular Cadence community spotlight updates where we aim to deliver you news from in and around the Cadence community!\nIt\u2019s been a few months since our ",(0,i.jsx)(n.a,{href:"https://cadenceworkflow.io/blog/2023/11/30/community-spotlight-update-november-2023/",children:"last update"}),", so I have a bunch of exciting updates to share."]}),"\n",(0,i.jsx)(n.p,{children:"Let\u2019s get started!"}),"\n",(0,i.jsx)(n.h2,{id:"proposal-for-cadence-plugin-system",children:"Proposal for Cadence Plugin System"}),"\n",(0,i.jsxs)(n.p,{children:["Community member ",(0,i.jsx)(n.a,{href:"https://lt.linkedin.com/in/mantassidlauskas",children:"Mantas Sidlauskas"})," drafted a thorough proposal around putting together a plugin system in Cadence. Aimed at enhancing the flexibility of integrating various components like storage, document search, and archival, this system encourages the use of external plugins, promoting innovation and reducing dependency complications. Your insights and feedback are crucial; learn more and contribute your thoughts at the link below:"]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence/issues/5593",children:"Cadence Plugin System Proposal"})}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"A huge thank you to Mantas for initiating this work. This is an excellent example of how we can collaborate together to bring about new features that benefit us all."}),"\n",(0,i.jsx)(n.h2,{id:"admin-api-permissions-rethinking",children:"Admin API Permissions Rethinking"}),"\n",(0,i.jsxs)(n.p,{children:["The community is deliberating on the permission requirements for the Admin API DescribeCluster endpoint. This vital discussion aims to ensure Cadence web's accessibility across different user levels. We're exploring various solutions and your participation would greatly influence the decision-making process. Feel free to chime in ",(0,i.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence/issues/5683",children:"here"}),"!"]}),"\n",(0,i.jsx)(n.h2,{id:"new-java-samples-for-cadence-signal-workflow-interactions",children:"New Java Samples for Cadence: Signal Workflow Interactions"}),"\n",(0,i.jsxs)(n.p,{children:["In some exciting news for Java enthusiasts, a new sample has been added to the Cadence Java Samples repository, demonstrating how to initiate and interact with a signal workflow using the Cadence client. This practical example is a huge win for developers looking to deepen their understanding of workflow signaling in Java. Explore the new sample and expand your Cadence toolkit ",(0,i.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence-java-samples/pull/78",children:"here"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"new-golang-client--cadence-web-enhancements",children:"New GoLang client & Cadence Web Enhancements"}),"\n",(0,i.jsx)(n.p,{children:"Updates to the Cadence GoLang Client and Cadence Web have been rolled out, bringing new features and improvements that streamline user experiences. Highlights include upgraded Cassandra images, refined workflow interceptors, and more intuitive Cadence Web interfaces. Discover the full scope of updates on our GitHub repositories."}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence-go-client/releases",children:"GoLang Client Releases"})}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence-web/releases",children:"Cadence Web Releases"})}),"\n"]}),"\n",(0,i.jsx)(n.h2,{id:"release-updates-v126--v127",children:"Release Updates: v1.2.6 & v1.2.7"}),"\n",(0,i.jsxs)(n.p,{children:["Cadence recently saw the release of versions v1.2.6 and v1.2.7, featuring significant improvements and fixes that enhance the overall Cadence experience. These updates reflect a commitment to respond to the community's valuable feedback. Check out the detailed release notes on the ",(0,i.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence/releases",children:"GitHub releases page"}),"!"]}),"\n",(0,i.jsx)(n.h2,{id:"cadence-in-the-news",children:"Cadence in the News!"}),"\n",(0,i.jsx)(n.p,{children:"Below is a selection of Cadence related articles and blogs. Take a look and feel free to share your own with us via your own social media channels!"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"https://www.instaclustr.com/blog/how-to-avoid-domain-update-too-frequent-error-in-multi-region-cadence/",children:"How to Avoid \u201cDomain update too frequent\u201d Error in Multi-Region Cadence"})}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"https://levelup.gitconnected.com/build-a-digital-collectibles-portal-using-flow-and-cadence-part-1-2783f2902ef6",children:"Build a Digital Collectibles Portal Using Flow and Cadence (Part 1)"})}),"\n"]}),"\n",(0,i.jsx)(n.h2,{id:"recent-events",children:"Recent Events"}),"\n",(0,i.jsxs)(n.p,{children:['Check out this recent webinar, "Building with Cadence: Quantifiable Efficiency," available on-demand now. Discover the robust features of Cadence and how it can streamline the development of distributed applications through an engaging demonstration by ',(0,i.jsx)(n.a,{href:"https://au.linkedin.com/in/john-del-castillo-28b87b90?trk=people-guest_people_search-card",children:"John Del Castillo"}),"."]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"https://netapp.zoom.us/webinar/register/WN_jT5fxSldRhuzV0NSllBd7g#/registration",children:"On Demand: Building with Cadence: Quantifiable Efficiency"})}),"\n"]}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.br,{}),"\n",(0,i.jsx)(n.br,{}),"\n",(0,i.jsx)(n.br,{}),"\n","That\u2019s all for this month!"]}),"\n",(0,i.jsxs)(n.p,{children:["Your engagement and contributions are what make the Cadence community thrive. Whether you have innovative ideas, insightful feedback, or just want to chat about Cadence, we encourage you to join our ",(0,i.jsx)(n.a,{href:"http://t.uber.com/cadence-slack",children:"Slack #community channel"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"We're committed to making this update as useful and informative as possible, so please share any feedback or suggestions you might have. Let\u2019s keep building a vibrant and collaborative Cadence community together!"}),"\n",(0,i.jsx)(n.p,{children:"Looking forward to sharing more exciting updates next month!"})]})}function h(e={}){const{wrapper:n}={...(0,o.R)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(d,{...e})}):d(e)}},8453:(e,n,t)=>{t.d(n,{R:()=>s,x:()=>r});var a=t(6540);const i={},o=a.createContext(i);function s(e){const n=a.useContext(o);return a.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function r(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:s(e.components),a.createElement(o.Provider,{value:n},e.children)}},2087:e=>{e.exports=JSON.parse('{"permalink":"/blog/2024/3/11/community-spotlight-update-march-2024","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2024-3-11-community-spotlight-update-march-2024.md","source":"@site/blog/2024-3-11-community-spotlight-update-march-2024.md","title":"Cadence Community Spotlight Update - March 2024","description":"Welcome back to the latest in our regular Cadence community spotlight updates where we aim to deliver you news from in and around the Cadence community!","date":"2023-03-11T00:00:00.000Z","tags":[{"inline":false,"label":"Community Spotlight","permalink":"/blog/tags/community-spotlights","description":"Community Spotlight tag description"}],"readingTime":2.91,"hasTruncateMarker":true,"authors":[{"name":"Kevin Corbett","title":"Open Source Community Manager | @instaclustr @NetApp","url":"https://github.com/kcorbett-netapp","page":{"permalink":"/blog/authors/kcorbett-netapp"},"socials":{"linkedin":"https://www.linkedin.com/in/kcorb95/","github":"https://github.com/kcorbett-netapp"},"imageURL":"https://github.com/kcorbett-netapp.png","key":"kcorbett-netapp"}],"frontMatter":{"title":"Cadence Community Spotlight Update - March 2024","date":"2023-03-11T00:00:00.000Z","authors":"kcorbett-netapp","tags":["community-spotlight"]},"unlisted":false,"prevItem":{"title":"Cadence Community Spotlight Update - March 2023","permalink":"/blog/2023/03/31/community-spotlight-march-2023"},"nextItem":{"title":"Cadence Community Spotlight Update - February 2023","permalink":"/blog/2023/02/28/community-spotlight-february"}}')}}]); \ No newline at end of file +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[5910],{7629:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>c,contentTitle:()=>r,default:()=>h,frontMatter:()=>s,metadata:()=>a,toc:()=>l});var a=t(2087),i=t(4848),o=t(8453);const s={title:"Cadence Community Spotlight Update - March 2024",date:new Date("2023-03-11T00:00:00.000Z"),authors:"kcorbett-netapp",tags:["community-spotlight"]},r=void 0,c={authorsImageUrls:[void 0]},l=[{value:"Proposal for Cadence Plugin System",id:"proposal-for-cadence-plugin-system",level:2},{value:"Admin API Permissions Rethinking",id:"admin-api-permissions-rethinking",level:2},{value:"New Java Samples for Cadence: Signal Workflow Interactions",id:"new-java-samples-for-cadence-signal-workflow-interactions",level:2},{value:"New GoLang client & Cadence Web Enhancements",id:"new-golang-client--cadence-web-enhancements",level:2},{value:"Release Updates: v1.2.6 & v1.2.7",id:"release-updates-v126--v127",level:2},{value:"Cadence in the News!",id:"cadence-in-the-news",level:2},{value:"Recent Events",id:"recent-events",level:2}];function d(e){const n={a:"a",br:"br",h2:"h2",li:"li",p:"p",ul:"ul",...(0,o.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsxs)(n.p,{children:["Welcome back to the latest in our regular Cadence community spotlight updates where we aim to deliver you news from in and around the Cadence community!\nIt\u2019s been a few months since our ",(0,i.jsx)(n.a,{href:"https://cadenceworkflow.io/blog/2023/11/30/community-spotlight-update-november-2023/",children:"last update"}),", so I have a bunch of exciting updates to share."]}),"\n",(0,i.jsx)(n.p,{children:"Let\u2019s get started!"}),"\n",(0,i.jsx)(n.h2,{id:"proposal-for-cadence-plugin-system",children:"Proposal for Cadence Plugin System"}),"\n",(0,i.jsxs)(n.p,{children:["Community member ",(0,i.jsx)(n.a,{href:"https://lt.linkedin.com/in/mantassidlauskas",children:"Mantas Sidlauskas"})," drafted a thorough proposal around putting together a plugin system in Cadence. Aimed at enhancing the flexibility of integrating various components like storage, document search, and archival, this system encourages the use of external plugins, promoting innovation and reducing dependency complications. Your insights and feedback are crucial; learn more and contribute your thoughts at the link below:"]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence/issues/5593",children:"Cadence Plugin System Proposal"})}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"A huge thank you to Mantas for initiating this work. This is an excellent example of how we can collaborate together to bring about new features that benefit us all."}),"\n",(0,i.jsx)(n.h2,{id:"admin-api-permissions-rethinking",children:"Admin API Permissions Rethinking"}),"\n",(0,i.jsxs)(n.p,{children:["The community is deliberating on the permission requirements for the Admin API DescribeCluster endpoint. This vital discussion aims to ensure Cadence web's accessibility across different user levels. We're exploring various solutions and your participation would greatly influence the decision-making process. Feel free to chime in ",(0,i.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence/issues/5683",children:"here"}),"!"]}),"\n",(0,i.jsx)(n.h2,{id:"new-java-samples-for-cadence-signal-workflow-interactions",children:"New Java Samples for Cadence: Signal Workflow Interactions"}),"\n",(0,i.jsxs)(n.p,{children:["In some exciting news for Java enthusiasts, a new sample has been added to the Cadence Java Samples repository, demonstrating how to initiate and interact with a signal workflow using the Cadence client. This practical example is a huge win for developers looking to deepen their understanding of workflow signaling in Java. Explore the new sample and expand your Cadence toolkit ",(0,i.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence-java-samples/pull/78",children:"here"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"new-golang-client--cadence-web-enhancements",children:"New GoLang client & Cadence Web Enhancements"}),"\n",(0,i.jsx)(n.p,{children:"Updates to the Cadence GoLang Client and Cadence Web have been rolled out, bringing new features and improvements that streamline user experiences. Highlights include upgraded Cassandra images, refined workflow interceptors, and more intuitive Cadence Web interfaces. Discover the full scope of updates on our GitHub repositories."}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence-go-client/releases",children:"GoLang Client Releases"})}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence-web/releases",children:"Cadence Web Releases"})}),"\n"]}),"\n",(0,i.jsx)(n.h2,{id:"release-updates-v126--v127",children:"Release Updates: v1.2.6 & v1.2.7"}),"\n",(0,i.jsxs)(n.p,{children:["Cadence recently saw the release of versions v1.2.6 and v1.2.7, featuring significant improvements and fixes that enhance the overall Cadence experience. These updates reflect a commitment to respond to the community's valuable feedback. Check out the detailed release notes on the ",(0,i.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence/releases",children:"GitHub releases page"}),"!"]}),"\n",(0,i.jsx)(n.h2,{id:"cadence-in-the-news",children:"Cadence in the News!"}),"\n",(0,i.jsx)(n.p,{children:"Below is a selection of Cadence related articles and blogs. Take a look and feel free to share your own with us via your own social media channels!"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"https://www.instaclustr.com/blog/how-to-avoid-domain-update-too-frequent-error-in-multi-region-cadence/",children:"How to Avoid \u201cDomain update too frequent\u201d Error in Multi-Region Cadence"})}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"https://levelup.gitconnected.com/build-a-digital-collectibles-portal-using-flow-and-cadence-part-1-2783f2902ef6",children:"Build a Digital Collectibles Portal Using Flow and Cadence (Part 1)"})}),"\n"]}),"\n",(0,i.jsx)(n.h2,{id:"recent-events",children:"Recent Events"}),"\n",(0,i.jsxs)(n.p,{children:['Check out this recent webinar, "Building with Cadence: Quantifiable Efficiency," available on-demand now. Discover the robust features of Cadence and how it can streamline the development of distributed applications through an engaging demonstration by ',(0,i.jsx)(n.a,{href:"https://au.linkedin.com/in/john-del-castillo-28b87b90?trk=people-guest_people_search-card",children:"John Del Castillo"}),"."]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"https://netapp.zoom.us/webinar/register/WN_jT5fxSldRhuzV0NSllBd7g#/registration",children:"On Demand: Building with Cadence: Quantifiable Efficiency"})}),"\n"]}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.br,{}),"\n",(0,i.jsx)(n.br,{}),"\n",(0,i.jsx)(n.br,{}),"\n","That\u2019s all for this month!"]}),"\n",(0,i.jsxs)(n.p,{children:["Your engagement and contributions are what make the Cadence community thrive. Whether you have innovative ideas, insightful feedback, or just want to chat about Cadence, we encourage you to join our ",(0,i.jsx)(n.a,{href:"http://t.uber.com/cadence-slack",children:"Slack #community channel"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"We're committed to making this update as useful and informative as possible, so please share any feedback or suggestions you might have. Let\u2019s keep building a vibrant and collaborative Cadence community together!"}),"\n",(0,i.jsx)(n.p,{children:"Looking forward to sharing more exciting updates next month!"})]})}function h(e={}){const{wrapper:n}={...(0,o.R)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(d,{...e})}):d(e)}},8453:(e,n,t)=>{t.d(n,{R:()=>s,x:()=>r});var a=t(6540);const i={},o=a.createContext(i);function s(e){const n=a.useContext(o);return a.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function r(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:s(e.components),a.createElement(o.Provider,{value:n},e.children)}},2087:e=>{e.exports=JSON.parse('{"permalink":"/Cadence-Docs/blog/2024/3/11/community-spotlight-update-march-2024","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2024-3-11-community-spotlight-update-march-2024.md","source":"@site/blog/2024-3-11-community-spotlight-update-march-2024.md","title":"Cadence Community Spotlight Update - March 2024","description":"Welcome back to the latest in our regular Cadence community spotlight updates where we aim to deliver you news from in and around the Cadence community!","date":"2023-03-11T00:00:00.000Z","tags":[{"inline":false,"label":"Community Spotlight","permalink":"/Cadence-Docs/blog/tags/community-spotlights","description":"Community Spotlight tag description"}],"readingTime":2.91,"hasTruncateMarker":true,"authors":[{"name":"Kevin Corbett","title":"Open Source Community Manager | @instaclustr @NetApp","url":"https://github.com/kcorbett-netapp","page":{"permalink":"/Cadence-Docs/blog/authors/kcorbett-netapp"},"socials":{"linkedin":"https://www.linkedin.com/in/kcorb95/","github":"https://github.com/kcorbett-netapp"},"imageURL":"https://github.com/kcorbett-netapp.png","key":"kcorbett-netapp"}],"frontMatter":{"title":"Cadence Community Spotlight Update - March 2024","date":"2023-03-11T00:00:00.000Z","authors":"kcorbett-netapp","tags":["community-spotlight"]},"unlisted":false,"prevItem":{"title":"Cadence Community Spotlight Update - March 2023","permalink":"/Cadence-Docs/blog/2023/03/31/community-spotlight-march-2023"},"nextItem":{"title":"Cadence Community Spotlight Update - February 2023","permalink":"/Cadence-Docs/blog/2023/02/28/community-spotlight-february"}}')}}]); \ No newline at end of file diff --git a/assets/js/90ce9713.c578cf3b.js b/assets/js/90ce9713.c578cf3b.js new file mode 100644 index 000000000..64a809925 --- /dev/null +++ b/assets/js/90ce9713.c578cf3b.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[8372],{9193:e=>{e.exports=JSON.parse('{"tag":{"label":"Community Spotlight","permalink":"/Cadence-Docs/blog/tags/community-spotlights","description":"Community Spotlight tag description","allTagsPath":"/Cadence-Docs/blog/tags","count":20,"unlisted":false},"listMetadata":{"permalink":"/Cadence-Docs/blog/tags/community-spotlights/page/2","page":2,"postsPerPage":10,"totalPages":2,"totalCount":20,"previousPage":"/Cadence-Docs/blog/tags/community-spotlights","blogDescription":"The latest news and updates from the Cadence team","blogTitle":"Cadence Blog"}}')}}]); \ No newline at end of file diff --git a/assets/js/90f276f1.b4874ef6.js b/assets/js/90f276f1.b4874ef6.js new file mode 100644 index 000000000..0ba4ee2c9 --- /dev/null +++ b/assets/js/90f276f1.b4874ef6.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[4960],{8926:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>l,contentTitle:()=>c,default:()=>u,frontMatter:()=>s,metadata:()=>o,toc:()=>a});const o=JSON.parse('{"id":"go-client/continue-as-new","title":"Continue as new","description":"Workflows: that need to rerun periodically could naively be implemented as a big for loop with","source":"@site/docs/05-go-client/09-continue-as-new.md","sourceDirName":"05-go-client","slug":"/go-client/continue-as-new","permalink":"/Cadence-Docs/docs/go-client/continue-as-new","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/05-go-client/09-continue-as-new.md","tags":[],"version":"current","sidebarPosition":9,"frontMatter":{"layout":"default","title":"Continue as new","permalink":"/docs/go-client/continue-as-new"},"sidebar":"docsSidebar","previous":{"title":"Signals","permalink":"/Cadence-Docs/docs/go-client/signals"},"next":{"title":"Side effect","permalink":"/Cadence-Docs/docs/go-client/side-effect"}}');var r=t(4848),i=t(8453);const s={layout:"default",title:"Continue as new",permalink:"/docs/go-client/continue-as-new"},c="Continue as new",l={},a=[];function d(e){const n={code:"code",h1:"h1",header:"header",p:"p",pre:"pre",strong:"strong",...(0,i.R)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(n.header,{children:(0,r.jsx)(n.h1,{id:"continue-as-new",children:"Continue as new"})}),"\n",(0,r.jsxs)(n.p,{children:["Workflows that need to rerun periodically could naively be implemented as a big ",(0,r.jsx)(n.strong,{children:"for"})," loop with\na sleep where the entire logic of the workflow is inside the body of the ",(0,r.jsx)(n.strong,{children:"for"})," loop. The problem\nwith this approach is that the history for that workflow will keep growing to a point where it\nreaches the maximum size enforced by the service."]}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.strong,{children:"ContinueAsNew"})," is the low level construct that enables implementing such workflows without the\nrisk of failures down the road. The operation atomically completes the current execution and starts\na new execution of the workflow with the same ",(0,r.jsx)(n.strong,{children:"workflow_ID"}),". The new execution will not carry\nover any history from the old execution. To trigger this behavior, the workflow function should\nterminate by returning the special ",(0,r.jsx)(n.strong,{children:"ContinueAsNewError"})," error:"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-go",children:"func SimpleWorkflow(workflow.Context ctx, value string) error {\n ...\n return workflow.NewContinueAsNewError(ctx, SimpleWorkflow, value)\n}\n"})})]})}function u(e={}){const{wrapper:n}={...(0,i.R)(),...e.components};return n?(0,r.jsx)(n,{...e,children:(0,r.jsx)(d,{...e})}):d(e)}},8453:(e,n,t)=>{t.d(n,{R:()=>s,x:()=>c});var o=t(6540);const r={},i=o.createContext(r);function s(e){const n=o.useContext(i);return o.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function c(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:s(e.components),o.createElement(i.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/90f276f1.c6c8d5d7.js b/assets/js/90f276f1.c6c8d5d7.js deleted file mode 100644 index 4fc7d8a3c..000000000 --- a/assets/js/90f276f1.c6c8d5d7.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[4960],{8926:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>l,contentTitle:()=>c,default:()=>u,frontMatter:()=>s,metadata:()=>o,toc:()=>a});const o=JSON.parse('{"id":"go-client/continue-as-new","title":"Continue as new","description":"Workflows: that need to rerun periodically could naively be implemented as a big for loop with","source":"@site/docs/05-go-client/09-continue-as-new.md","sourceDirName":"05-go-client","slug":"/go-client/continue-as-new","permalink":"/docs/go-client/continue-as-new","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/05-go-client/09-continue-as-new.md","tags":[],"version":"current","sidebarPosition":9,"frontMatter":{"layout":"default","title":"Continue as new","permalink":"/docs/go-client/continue-as-new"},"sidebar":"docsSidebar","previous":{"title":"Signals","permalink":"/docs/go-client/signals"},"next":{"title":"Side effect","permalink":"/docs/go-client/side-effect"}}');var r=t(4848),i=t(8453);const s={layout:"default",title:"Continue as new",permalink:"/docs/go-client/continue-as-new"},c="Continue as new",l={},a=[];function d(e){const n={code:"code",h1:"h1",header:"header",p:"p",pre:"pre",strong:"strong",...(0,i.R)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(n.header,{children:(0,r.jsx)(n.h1,{id:"continue-as-new",children:"Continue as new"})}),"\n",(0,r.jsxs)(n.p,{children:["Workflows that need to rerun periodically could naively be implemented as a big ",(0,r.jsx)(n.strong,{children:"for"})," loop with\na sleep where the entire logic of the workflow is inside the body of the ",(0,r.jsx)(n.strong,{children:"for"})," loop. The problem\nwith this approach is that the history for that workflow will keep growing to a point where it\nreaches the maximum size enforced by the service."]}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.strong,{children:"ContinueAsNew"})," is the low level construct that enables implementing such workflows without the\nrisk of failures down the road. The operation atomically completes the current execution and starts\na new execution of the workflow with the same ",(0,r.jsx)(n.strong,{children:"workflow_ID"}),". The new execution will not carry\nover any history from the old execution. To trigger this behavior, the workflow function should\nterminate by returning the special ",(0,r.jsx)(n.strong,{children:"ContinueAsNewError"})," error:"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-go",children:"func SimpleWorkflow(workflow.Context ctx, value string) error {\n ...\n return workflow.NewContinueAsNewError(ctx, SimpleWorkflow, value)\n}\n"})})]})}function u(e={}){const{wrapper:n}={...(0,i.R)(),...e.components};return n?(0,r.jsx)(n,{...e,children:(0,r.jsx)(d,{...e})}):d(e)}},8453:(e,n,t)=>{t.d(n,{R:()=>s,x:()=>c});var o=t(6540);const r={},i=o.createContext(r);function s(e){const n=o.useContext(i);return o.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function c(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:s(e.components),o.createElement(i.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/91c0087d.7488e4a4.js b/assets/js/91c0087d.7488e4a4.js new file mode 100644 index 000000000..871862c93 --- /dev/null +++ b/assets/js/91c0087d.7488e4a4.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[245],{3666:e=>{e.exports=JSON.parse('{"author":{"name":"Ender Demirkaya","title":"Senior Manager at Uber, Cadence. Author of the Software Engineering Handbook","url":"https://www.linkedin.com/in/enderdemirkaya/","page":{"permalink":"/Cadence-Docs/blog/authors/enderdemirkaya"},"socials":{"linkedin":"https://www.linkedin.com/in/enderdemirkaya/","github":"https://github.com/demirkayaender"},"imageURL":"https://github.com/demirkayaender.png","key":"enderdemirkaya","count":2},"listMetadata":{"permalink":"/Cadence-Docs/blog/authors/enderdemirkaya","page":1,"postsPerPage":10,"totalPages":1,"totalCount":2,"blogDescription":"The latest news and updates from the Cadence team","blogTitle":"Cadence Blog"}}')}}]); \ No newline at end of file diff --git a/assets/js/9250e00d.63ecac5c.js b/assets/js/9250e00d.63ecac5c.js deleted file mode 100644 index 40f8d87c4..000000000 --- a/assets/js/9250e00d.63ecac5c.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[3914],{121:e=>{e.exports=JSON.parse('{"author":{"name":"Chris Qin","title":"Applications Developer @ Uber","url":"https://www.linkedin.com/in/chrisqin0610/","page":{"permalink":"/blog/authors/chopincode"},"socials":{"linkedin":"https://www.linkedin.com/in/chrisqin0610/","github":"https://github.com/chopincode"},"imageURL":"https://github.com/chopincode.png","key":"chopincode","count":6},"listMetadata":{"permalink":"/blog/authors/chopincode","page":1,"postsPerPage":10,"totalPages":1,"totalCount":6,"blogDescription":"The latest news and updates from the Cadence team","blogTitle":"Cadence Blog"}}')}}]); \ No newline at end of file diff --git a/assets/js/92ce93dc.6cd896be.js b/assets/js/92ce93dc.6cd896be.js deleted file mode 100644 index d2a8a7d37..000000000 --- a/assets/js/92ce93dc.6cd896be.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[6941],{3273:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>c,contentTitle:()=>i,default:()=>h,frontMatter:()=>r,metadata:()=>s,toc:()=>d});var s=n(7896),a=n(4848),o=n(8453);const r={title:"2023 Cadence Community Survey Results",date:new Date("2023-06-08T00:00:00.000Z"),authors:"enderdemirkaya",tags:["announcement"]},i=void 0,c={authorsImageUrls:[void 0]},d=[];function l(e){const t={a:"a",img:"img",p:"p",...(0,o.R)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsxs)(t.p,{children:["We released a user survey earlier this year to learn about who our users are, how they use Cadence, and how we can help them. It was shared from our ",(0,a.jsx)(t.a,{href:"https://uber-cadence.slack.com/",children:"Slack workspace"}),", ",(0,a.jsx)(t.a,{href:"https://cadenceworkflow.io",children:"cadenceworkflow.io"})," Blog and ",(0,a.jsx)(t.a,{href:"https://www.linkedin.com/company/cadenceworkflow/",children:"LinkedIn"}),". After collecting the feedback, we wanted to share the results with our community. Thank you everyone for filling it out! Your feedback is invaluable and it helps us shape our roadmap for the future."]}),"\n",(0,a.jsx)(t.p,{children:"Here are some highlights in text and you can check out the visuals to get more details:"}),"\n",(0,a.jsx)(t.p,{children:(0,a.jsx)(t.img,{alt:"using.png",src:n(6232).A+"",width:"661",height:"351"})}),"\n",(0,a.jsx)(t.p,{children:(0,a.jsx)(t.img,{alt:"job_role.png",src:n(9574).A+"",width:"692",height:"351"})}),"\n",(0,a.jsx)(t.p,{children:"Most of the people who replied to our survey were engineers who were already using Cadence, actively evaluating, or migrating from a similar technology. This was exciting to hear! Some of you have contacted us to learn more about benchmarks, scale, and ideal use cases. We will share more guidelines about this but until then, feel free to contact us over our Slack workspace for guidance."}),"\n",(0,a.jsx)(t.p,{children:(0,a.jsx)(t.img,{alt:"scale.png",src:n(6550).A+"",width:"861",height:"382"})}),"\n",(0,a.jsx)(t.p,{children:"The scale our users operating Cadence varies from thousands to billions of workflows per month. It was exciting to see it being used in both small and large scale companies."}),"\n",(0,a.jsx)(t.p,{children:(0,a.jsx)(t.img,{alt:"time_zone.png",src:n(7360).A+"",width:"723",height:"390"})}),"\n",(0,a.jsx)(t.p,{children:"Most survey responders were from Europe compared to any other place. This is in-line with the Cadence team growing its presence in Europe. Users from different places also contacted us to contribute to Cadence as a follow up to the survey. We will start putting up-for-grabs and new-starter tasks on Github. Several of them wanted to meet with a Zoom call and to discuss their use cases and best practices. As the Cadence team has presence in both the EU and the US, we welcome all our users to contact us anytime. Slack is the fastest way to reach us."}),"\n",(0,a.jsx)(t.p,{children:(0,a.jsx)(t.img,{alt:"following.png",src:n(1657).A+"",width:"720",height:"344"})}),"\n",(0,a.jsx)(t.p,{children:(0,a.jsx)(t.img,{alt:"channels.png",src:n(374).A+"",width:"846",height:"361"})}),"\n",(0,a.jsxs)(t.p,{children:["Cadence is followed in ",(0,a.jsx)(t.a,{href:"https://uber-cadence.slack.com/",children:"Slack"})," the most, then ",(0,a.jsx)(t.a,{href:"https://github.com/cadence-workflow/cadence",children:"Github"})," and ",(0,a.jsx)(t.a,{href:"https://www.linkedin.com/company/cadenceworkflow/",children:"LinkedIn"}),". We are the most active in Slack and we plan to be more active in other mediums as well."]}),"\n",(0,a.jsxs)(t.p,{children:[(0,a.jsx)(t.img,{alt:"scenarios.png",src:n(7453).A+"",width:"709",height:"343"}),"\nAll of our main use cases were used across the board. While we mentioned the most common cases, several others were mentioned as a comment: enhanced timers, leader election etc."]}),"\n",(0,a.jsx)(t.p,{children:"We found out that Cadence has been used in several science communities. Some of them were using community built clients and were asking if we are going to support more languages. We are planning to take ownership of the Python and Javascript/Typescript clients and support them officially."}),"\n",(0,a.jsx)(t.p,{children:(0,a.jsx)(t.img,{alt:"improvement.png",src:n(8796).A+"",width:"864",height:"384"})}),"\n",(0,a.jsx)(t.p,{children:"Documentation is by far what our users wanted improvements on. We are revamping our documentation soon and there will be major changes on our website soon."}),"\n",(0,a.jsx)(t.p,{children:(0,a.jsx)(t.img,{alt:"help_stage.png",src:n(4456).A+"",width:"851",height:"382"})}),"\n",(0,a.jsx)(t.p,{children:"Other requests were about observability, debuggability, operability, and usability. These areas have been our main focus this year and we are planning to release updates and blogs about them."}),"\n",(0,a.jsx)(t.p,{children:(0,a.jsx)(t.img,{alt:"support.png",src:n(7565).A+"",width:"718",height:"448"})}),"\n",(0,a.jsx)(t.p,{children:"We noticed most of our users need help once a month or more. While we welcome questions and discussions over the mediums mentioned above, we plan to make more public posts about the common issues using our blog, StackOverflow, LinkedIn, or Twitter."}),"\n",(0,a.jsxs)(t.p,{children:["Many users wanted to hear more from Cadence about the roadmap and its growth. Our posts about these will be released soon. Expect more posts about upcoming features, investments, scale, and community updates. Follow us at ",(0,a.jsx)(t.a,{href:"https://www.linkedin.com/company/cadenceworkflow/",children:"LinkedIn"})," for such updates."]}),"\n",(0,a.jsx)(t.p,{children:"Our users are interested in learning more about guidelines, capacity expectations in on-prem and in managed solutions. While we have been providing feedback per user basis before, we plan to release more generic guidelines with our observability updates mentioned above."}),"\n",(0,a.jsx)(t.p,{children:"We also would like to thank our community for the increased interest and engagement with us! Cadence has been more active in different mediums (LinkedIn, Slack, blog, etc.) this year. In the first quarter, we observed that our user base and activities has almost doubled (+96% and +90% respectively) through both new and returning users. Based on such immediate positive reactions, we will keep increasing our community investments in different channels."})]})}function h(e={}){const{wrapper:t}={...(0,o.R)(),...e.components};return t?(0,a.jsx)(t,{...e,children:(0,a.jsx)(l,{...e})}):l(e)}},374:(e,t,n)=>{n.d(t,{A:()=>s});const s=n.p+"assets/images/channels-08aabebcf7c800d46a2f03ee63a8fa9f.png"},1657:(e,t,n)=>{n.d(t,{A:()=>s});const s=n.p+"assets/images/following-09f21d655f4971aa446ebe4752d68a8b.png"},4456:(e,t,n)=>{n.d(t,{A:()=>s});const s=n.p+"assets/images/help_stage-d8a5215377bf5d2fa1b3940d8fea1038.png"},8796:(e,t,n)=>{n.d(t,{A:()=>s});const s=n.p+"assets/images/improvement-7dfb8f11c50613774fd8fd1594b6608a.png"},9574:(e,t,n)=>{n.d(t,{A:()=>s});const s=n.p+"assets/images/job_role-fa7e2e7da9528b64de7e7be5ed191d10.png"},6550:(e,t,n)=>{n.d(t,{A:()=>s});const s=n.p+"assets/images/scale-3684b4e20edb7503ea54b785fcc9ec51.png"},7453:(e,t,n)=>{n.d(t,{A:()=>s});const s=n.p+"assets/images/scenarios-8b05e2f55e51a2be8aefa9b7e9aeb198.png"},7565:(e,t,n)=>{n.d(t,{A:()=>s});const s=n.p+"assets/images/support-43c799a1fdd201d7fb290c81212bfa64.png"},7360:(e,t,n)=>{n.d(t,{A:()=>s});const s=n.p+"assets/images/time_zone-9374252fe441af1fcb284417b2b8825e.png"},6232:(e,t,n)=>{n.d(t,{A:()=>s});const s=n.p+"assets/images/using-0b1f88906ffddbb98bebf54fb5967078.png"},8453:(e,t,n)=>{n.d(t,{R:()=>r,x:()=>i});var s=n(6540);const a={},o=s.createContext(a);function r(e){const t=s.useContext(o);return s.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function i(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:r(e.components),s.createElement(o.Provider,{value:t},e.children)}},7896:e=>{e.exports=JSON.parse('{"permalink":"/blog/2023/06/08/2023-06-08-survey-results/survey-results","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2023-06-08-survey-results/2023-06-08-survey-results.md","source":"@site/blog/2023-06-08-survey-results/2023-06-08-survey-results.md","title":"2023 Cadence Community Survey Results","description":"We released a user survey earlier this year to learn about who our users are, how they use Cadence, and how we can help them. It was shared from our Slack workspace, cadenceworkflow.io Blog and LinkedIn. After collecting the feedback, we wanted to share the results with our community. Thank you everyone for filling it out! Your feedback is invaluable and it helps us shape our roadmap for the future.","date":"2023-06-08T00:00:00.000Z","tags":[{"inline":false,"label":"Announcement","permalink":"/blog/tags/announcements","description":"Announcement tag description"}],"readingTime":3.255,"hasTruncateMarker":true,"authors":[{"name":"Ender Demirkaya","title":"Senior Manager at Uber, Cadence. Author of the Software Engineering Handbook","url":"https://www.linkedin.com/in/enderdemirkaya/","page":{"permalink":"/blog/authors/enderdemirkaya"},"socials":{"linkedin":"https://www.linkedin.com/in/enderdemirkaya/","github":"https://github.com/demirkayaender"},"imageURL":"https://github.com/demirkayaender.png","key":"enderdemirkaya"}],"frontMatter":{"title":"2023 Cadence Community Survey Results","date":"2023-06-08T00:00:00.000Z","authors":"enderdemirkaya","tags":["announcement"]},"unlisted":false,"prevItem":{"title":"Cadence Community Spotlight Update - June 2023","permalink":"/blog/2023/06/30/community-spotlight-june-2023"},"nextItem":{"title":"Cadence Community Spotlight Update - March 2023","permalink":"/blog/2023/03/31/community-spotlight-march-2023"}}')}}]); \ No newline at end of file diff --git a/assets/js/92ce93dc.ea84aa43.js b/assets/js/92ce93dc.ea84aa43.js new file mode 100644 index 000000000..466608409 --- /dev/null +++ b/assets/js/92ce93dc.ea84aa43.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[6941],{3273:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>c,contentTitle:()=>i,default:()=>h,frontMatter:()=>r,metadata:()=>s,toc:()=>d});var s=t(7896),a=t(4848),o=t(8453);const r={title:"2023 Cadence Community Survey Results",date:new Date("2023-06-08T00:00:00.000Z"),authors:"enderdemirkaya",tags:["announcement"]},i=void 0,c={authorsImageUrls:[void 0]},d=[];function l(e){const n={a:"a",img:"img",p:"p",...(0,o.R)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsxs)(n.p,{children:["We released a user survey earlier this year to learn about who our users are, how they use Cadence, and how we can help them. It was shared from our ",(0,a.jsx)(n.a,{href:"https://uber-cadence.slack.com/",children:"Slack workspace"}),", ",(0,a.jsx)(n.a,{href:"https://cadenceworkflow.io",children:"cadenceworkflow.io"})," Blog and ",(0,a.jsx)(n.a,{href:"https://www.linkedin.com/company/cadenceworkflow/",children:"LinkedIn"}),". After collecting the feedback, we wanted to share the results with our community. Thank you everyone for filling it out! Your feedback is invaluable and it helps us shape our roadmap for the future."]}),"\n",(0,a.jsx)(n.p,{children:"Here are some highlights in text and you can check out the visuals to get more details:"}),"\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.img,{alt:"using.png",src:t(6232).A+"",width:"661",height:"351"})}),"\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.img,{alt:"job_role.png",src:t(9574).A+"",width:"692",height:"351"})}),"\n",(0,a.jsx)(n.p,{children:"Most of the people who replied to our survey were engineers who were already using Cadence, actively evaluating, or migrating from a similar technology. This was exciting to hear! Some of you have contacted us to learn more about benchmarks, scale, and ideal use cases. We will share more guidelines about this but until then, feel free to contact us over our Slack workspace for guidance."}),"\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.img,{alt:"scale.png",src:t(6550).A+"",width:"861",height:"382"})}),"\n",(0,a.jsx)(n.p,{children:"The scale our users operating Cadence varies from thousands to billions of workflows per month. It was exciting to see it being used in both small and large scale companies."}),"\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.img,{alt:"time_zone.png",src:t(7360).A+"",width:"723",height:"390"})}),"\n",(0,a.jsx)(n.p,{children:"Most survey responders were from Europe compared to any other place. This is in-line with the Cadence team growing its presence in Europe. Users from different places also contacted us to contribute to Cadence as a follow up to the survey. We will start putting up-for-grabs and new-starter tasks on Github. Several of them wanted to meet with a Zoom call and to discuss their use cases and best practices. As the Cadence team has presence in both the EU and the US, we welcome all our users to contact us anytime. Slack is the fastest way to reach us."}),"\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.img,{alt:"following.png",src:t(1657).A+"",width:"720",height:"344"})}),"\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.img,{alt:"channels.png",src:t(374).A+"",width:"846",height:"361"})}),"\n",(0,a.jsxs)(n.p,{children:["Cadence is followed in ",(0,a.jsx)(n.a,{href:"https://uber-cadence.slack.com/",children:"Slack"})," the most, then ",(0,a.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence",children:"Github"})," and ",(0,a.jsx)(n.a,{href:"https://www.linkedin.com/company/cadenceworkflow/",children:"LinkedIn"}),". We are the most active in Slack and we plan to be more active in other mediums as well."]}),"\n",(0,a.jsxs)(n.p,{children:[(0,a.jsx)(n.img,{alt:"scenarios.png",src:t(7453).A+"",width:"709",height:"343"}),"\nAll of our main use cases were used across the board. While we mentioned the most common cases, several others were mentioned as a comment: enhanced timers, leader election etc."]}),"\n",(0,a.jsx)(n.p,{children:"We found out that Cadence has been used in several science communities. Some of them were using community built clients and were asking if we are going to support more languages. We are planning to take ownership of the Python and Javascript/Typescript clients and support them officially."}),"\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.img,{alt:"improvement.png",src:t(8796).A+"",width:"864",height:"384"})}),"\n",(0,a.jsx)(n.p,{children:"Documentation is by far what our users wanted improvements on. We are revamping our documentation soon and there will be major changes on our website soon."}),"\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.img,{alt:"help_stage.png",src:t(4456).A+"",width:"851",height:"382"})}),"\n",(0,a.jsx)(n.p,{children:"Other requests were about observability, debuggability, operability, and usability. These areas have been our main focus this year and we are planning to release updates and blogs about them."}),"\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.img,{alt:"support.png",src:t(7565).A+"",width:"718",height:"448"})}),"\n",(0,a.jsx)(n.p,{children:"We noticed most of our users need help once a month or more. While we welcome questions and discussions over the mediums mentioned above, we plan to make more public posts about the common issues using our blog, StackOverflow, LinkedIn, or Twitter."}),"\n",(0,a.jsxs)(n.p,{children:["Many users wanted to hear more from Cadence about the roadmap and its growth. Our posts about these will be released soon. Expect more posts about upcoming features, investments, scale, and community updates. Follow us at ",(0,a.jsx)(n.a,{href:"https://www.linkedin.com/company/cadenceworkflow/",children:"LinkedIn"})," for such updates."]}),"\n",(0,a.jsx)(n.p,{children:"Our users are interested in learning more about guidelines, capacity expectations in on-prem and in managed solutions. While we have been providing feedback per user basis before, we plan to release more generic guidelines with our observability updates mentioned above."}),"\n",(0,a.jsx)(n.p,{children:"We also would like to thank our community for the increased interest and engagement with us! Cadence has been more active in different mediums (LinkedIn, Slack, blog, etc.) this year. In the first quarter, we observed that our user base and activities has almost doubled (+96% and +90% respectively) through both new and returning users. Based on such immediate positive reactions, we will keep increasing our community investments in different channels."})]})}function h(e={}){const{wrapper:n}={...(0,o.R)(),...e.components};return n?(0,a.jsx)(n,{...e,children:(0,a.jsx)(l,{...e})}):l(e)}},374:(e,n,t)=>{t.d(n,{A:()=>s});const s=t.p+"assets/images/channels-08aabebcf7c800d46a2f03ee63a8fa9f.png"},1657:(e,n,t)=>{t.d(n,{A:()=>s});const s=t.p+"assets/images/following-09f21d655f4971aa446ebe4752d68a8b.png"},4456:(e,n,t)=>{t.d(n,{A:()=>s});const s=t.p+"assets/images/help_stage-d8a5215377bf5d2fa1b3940d8fea1038.png"},8796:(e,n,t)=>{t.d(n,{A:()=>s});const s=t.p+"assets/images/improvement-7dfb8f11c50613774fd8fd1594b6608a.png"},9574:(e,n,t)=>{t.d(n,{A:()=>s});const s=t.p+"assets/images/job_role-fa7e2e7da9528b64de7e7be5ed191d10.png"},6550:(e,n,t)=>{t.d(n,{A:()=>s});const s=t.p+"assets/images/scale-3684b4e20edb7503ea54b785fcc9ec51.png"},7453:(e,n,t)=>{t.d(n,{A:()=>s});const s=t.p+"assets/images/scenarios-8b05e2f55e51a2be8aefa9b7e9aeb198.png"},7565:(e,n,t)=>{t.d(n,{A:()=>s});const s=t.p+"assets/images/support-43c799a1fdd201d7fb290c81212bfa64.png"},7360:(e,n,t)=>{t.d(n,{A:()=>s});const s=t.p+"assets/images/time_zone-9374252fe441af1fcb284417b2b8825e.png"},6232:(e,n,t)=>{t.d(n,{A:()=>s});const s=t.p+"assets/images/using-0b1f88906ffddbb98bebf54fb5967078.png"},8453:(e,n,t)=>{t.d(n,{R:()=>r,x:()=>i});var s=t(6540);const a={},o=s.createContext(a);function r(e){const n=s.useContext(o);return s.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function i(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:r(e.components),s.createElement(o.Provider,{value:n},e.children)}},7896:e=>{e.exports=JSON.parse('{"permalink":"/Cadence-Docs/blog/2023/06/08/2023-06-08-survey-results/survey-results","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2023-06-08-survey-results/2023-06-08-survey-results.md","source":"@site/blog/2023-06-08-survey-results/2023-06-08-survey-results.md","title":"2023 Cadence Community Survey Results","description":"We released a user survey earlier this year to learn about who our users are, how they use Cadence, and how we can help them. It was shared from our Slack workspace, cadenceworkflow.io Blog and LinkedIn. After collecting the feedback, we wanted to share the results with our community. Thank you everyone for filling it out! Your feedback is invaluable and it helps us shape our roadmap for the future.","date":"2023-06-08T00:00:00.000Z","tags":[{"inline":false,"label":"Announcement","permalink":"/Cadence-Docs/blog/tags/announcements","description":"Announcement tag description"}],"readingTime":3.255,"hasTruncateMarker":true,"authors":[{"name":"Ender Demirkaya","title":"Senior Manager at Uber, Cadence. Author of the Software Engineering Handbook","url":"https://www.linkedin.com/in/enderdemirkaya/","page":{"permalink":"/Cadence-Docs/blog/authors/enderdemirkaya"},"socials":{"linkedin":"https://www.linkedin.com/in/enderdemirkaya/","github":"https://github.com/demirkayaender"},"imageURL":"https://github.com/demirkayaender.png","key":"enderdemirkaya"}],"frontMatter":{"title":"2023 Cadence Community Survey Results","date":"2023-06-08T00:00:00.000Z","authors":"enderdemirkaya","tags":["announcement"]},"unlisted":false,"prevItem":{"title":"Cadence Community Spotlight Update - June 2023","permalink":"/Cadence-Docs/blog/2023/06/30/community-spotlight-june-2023"},"nextItem":{"title":"Cadence Community Spotlight Update - March 2023","permalink":"/Cadence-Docs/blog/2023/03/31/community-spotlight-march-2023"}}')}}]); \ No newline at end of file diff --git a/assets/js/92fb1dcd.e1ea9f65.js b/assets/js/92fb1dcd.e1ea9f65.js deleted file mode 100644 index 49cdbdfe7..000000000 --- a/assets/js/92fb1dcd.e1ea9f65.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[9552],{6129:a=>{a.exports=JSON.parse('{"tag":{"label":"Roadmap","permalink":"/blog/tags/roadmap","description":"Roadmap tag description","allTagsPath":"/blog/tags","count":3,"unlisted":false},"listMetadata":{"permalink":"/blog/tags/roadmap","page":1,"postsPerPage":10,"totalPages":1,"totalCount":3,"blogDescription":"The latest news and updates from the Cadence team","blogTitle":"Cadence Blog"}}')}}]); \ No newline at end of file diff --git a/assets/js/9366521c.8dd92d41.js b/assets/js/9366521c.bbdf5568.js similarity index 77% rename from assets/js/9366521c.8dd92d41.js rename to assets/js/9366521c.bbdf5568.js index 666e83724..7fc35347a 100644 --- a/assets/js/9366521c.8dd92d41.js +++ b/assets/js/9366521c.bbdf5568.js @@ -1 +1 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[5086],{5365:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>c,contentTitle:()=>s,default:()=>d,frontMatter:()=>r,metadata:()=>a,toc:()=>l});var a=n(1900),i=n(4848),o=n(8453);const r={title:"Cadence Community Spotlight Update - March 2023",date:new Date("2023-03-31T00:00:00.000Z"),authors:"sharanf",tags:["community-spotlight"]},s=void 0,c={authorsImageUrls:[void 0]},l=[{value:"Cadence at Open Source Summit, North America",id:"cadence-at-open-source-summit-north-america",level:2},{value:"Community Activity",id:"community-activity",level:2},{value:"Cadence Developer Advocate",id:"cadence-developer-advocate",level:2},{value:"Cadence in the News!",id:"cadence-in-the-news",level:2},{value:"Upcoming Events",id:"upcoming-events",level:2}];function h(e){const t={a:"a",h2:"h2",li:"li",p:"p",ul:"ul",...(0,o.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(t.p,{children:"Welcome to the latest of our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!"}),"\n",(0,i.jsx)(t.p,{children:"Please see below for a roundup of the highlights:"}),"\n",(0,i.jsx)(t.h2,{id:"cadence-at-open-source-summit-north-america",children:"Cadence at Open Source Summit, North America"}),"\n",(0,i.jsxs)(t.p,{children:["We are very pleased to let you know that a talk on Cadence has been accepted for the Linux Foundation's ",(0,i.jsx)(t.a,{href:"https://events.linuxfoundation.org/open-source-summit-north-america/",children:"Open Source Summit, North America"})," in Vancouver on 10th - 12th May 2023."]}),"\n",(0,i.jsxs)(t.p,{children:["The talk called ",(0,i.jsx)(t.a,{href:"https://ossna2023.sched.com/event/1K5B1",children:"Cadence: The New Open Source Project for Building Complex Distributed Applications"})," will be given by ",(0,i.jsx)(t.a,{href:"https://www.linkedin.com/in/enderdemirkaya/",children:"Ender Demirkaya"})," and ",(0,i.jsx)(t.a,{href:"https://www.linkedin.com/in/emrahseker/",children:"Emrah Seker"})," If you are planning to attend the Open Source Summit then please don't forget to attend the talk and take time catch up with Ender and Emrah!"]}),"\n",(0,i.jsx)(t.h2,{id:"community-activity",children:"Community Activity"}),"\n",(0,i.jsx)(t.p,{children:"Our Slack #support channel has been very active over the last few months as we continue to get an continual stream of questions. Here are the stats:"}),"\n",(0,i.jsxs)(t.ul,{children:["\n",(0,i.jsx)(t.li,{children:"February 2023 : 16 questions asked"}),"\n",(0,i.jsx)(t.li,{children:"March 2023 : 12 questions asked"}),"\n"]}),"\n",(0,i.jsx)(t.p,{children:"All of these questions are being answered collaboratively by the community. Thanks everyone for sharing your knowledge and we are looking forward to receiving more of your questions!"}),"\n",(0,i.jsx)(t.h2,{id:"cadence-developer-advocate",children:"Cadence Developer Advocate"}),"\n",(0,i.jsx)(t.p,{children:"Please welcome Yizhe Qin - the new Cadence Developer Advocate from Uber team that will be working to help support the community."}),"\n",(0,i.jsx)(t.p,{children:"Yizhe's role will involve responding to support questions, organising documentation and anything else that will help keep the community running smoothly."}),"\n",(0,i.jsx)(t.p,{children:"Please feel free to say Hi to Yizhe on the Slack channel!"}),"\n",(0,i.jsx)(t.h2,{id:"cadence-in-the-news",children:"Cadence in the News!"}),"\n",(0,i.jsx)(t.p,{children:"Below are a selection of Cadence related articles, blogs and whitepapers. Please take a look and feel free to share via your own social media channels."}),"\n",(0,i.jsxs)(t.ul,{children:["\n",(0,i.jsxs)(t.li,{children:["\n",(0,i.jsx)(t.p,{children:(0,i.jsx)(t.a,{href:"https://www.instaclustr.com/blog/instaclustr-cadence-workflow-developer/",children:"Instaclustr Cadence Developer Offering - General Availability"})}),"\n"]}),"\n",(0,i.jsxs)(t.li,{children:["\n",(0,i.jsx)(t.p,{children:(0,i.jsx)(t.a,{href:"https://www.instaclustr.com/blog/improving-the-reliability-of-cadence-search-queries/",children:"Improving Reliability of Cadence Search Queries That Use OpenSearch/Elasticsearch"})}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(t.h2,{id:"upcoming-events",children:"Upcoming Events"}),"\n",(0,i.jsxs)(t.ul,{children:["\n",(0,i.jsx)(t.li,{children:(0,i.jsx)(t.a,{href:"https://netapp.zoom.us/webinar/register/WN__5fuwxmNQuWeZ6DiI5wUqg",children:"Webinar: Microservices - A Modern Orchestration Approach with Cadence"})}),"\n"]}),"\n",(0,i.jsxs)(t.p,{children:["If you have any news or topics you'd like us to include in our next update then please join our ",(0,i.jsx)(t.a,{href:"http://t.uber.com/cadence-slack",children:"Slack"}),"#community channel."]}),"\n",(0,i.jsxs)(t.p,{children:["Please remember that this update is for you - so if you have any comments or feedback that could help us improve it then please share it with us in the #community ",(0,i.jsx)(t.a,{href:"http://t.uber.com/cadence-slack",children:"Slack"})," channel."]})]})}function d(e={}){const{wrapper:t}={...(0,o.R)(),...e.components};return t?(0,i.jsx)(t,{...e,children:(0,i.jsx)(h,{...e})}):h(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>r,x:()=>s});var a=n(6540);const i={},o=a.createContext(i);function r(e){const t=a.useContext(o);return a.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function s(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:r(e.components),a.createElement(o.Provider,{value:t},e.children)}},1900:e=>{e.exports=JSON.parse('{"permalink":"/blog/2023/03/31/community-spotlight-march-2023","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2023-03-31-community-spotlight-march-2023.md","source":"@site/blog/2023-03-31-community-spotlight-march-2023.md","title":"Cadence Community Spotlight Update - March 2023","description":"Welcome to the latest of our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!","date":"2023-03-31T00:00:00.000Z","tags":[{"inline":false,"label":"Community Spotlight","permalink":"/blog/tags/community-spotlights","description":"Community Spotlight tag description"}],"readingTime":1.885,"hasTruncateMarker":true,"authors":[{"name":"Sharan Foga","title":"Director of Operations & Customer Success @ Encube Technologies","url":"https://www.linkedin.com/in/sfoga/","page":{"permalink":"/blog/authors/sharanf"},"socials":{"linkedin":"https://www.linkedin.com/in/sfoga/","github":"https://github.com/sharanf"},"imageURL":"https://github.com/sharanf.png","key":"sharanf"}],"frontMatter":{"title":"Cadence Community Spotlight Update - March 2023","date":"2023-03-31T00:00:00.000Z","authors":"sharanf","tags":["community-spotlight"]},"unlisted":false,"prevItem":{"title":"2023 Cadence Community Survey Results","permalink":"/blog/2023/06/08/2023-06-08-survey-results/survey-results"},"nextItem":{"title":"Cadence Community Spotlight Update - March 2024","permalink":"/blog/2024/3/11/community-spotlight-update-march-2024"}}')}}]); \ No newline at end of file +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[5086],{5365:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>c,contentTitle:()=>s,default:()=>d,frontMatter:()=>r,metadata:()=>a,toc:()=>l});var a=n(1900),i=n(4848),o=n(8453);const r={title:"Cadence Community Spotlight Update - March 2023",date:new Date("2023-03-31T00:00:00.000Z"),authors:"sharanf",tags:["community-spotlight"]},s=void 0,c={authorsImageUrls:[void 0]},l=[{value:"Cadence at Open Source Summit, North America",id:"cadence-at-open-source-summit-north-america",level:2},{value:"Community Activity",id:"community-activity",level:2},{value:"Cadence Developer Advocate",id:"cadence-developer-advocate",level:2},{value:"Cadence in the News!",id:"cadence-in-the-news",level:2},{value:"Upcoming Events",id:"upcoming-events",level:2}];function h(e){const t={a:"a",h2:"h2",li:"li",p:"p",ul:"ul",...(0,o.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(t.p,{children:"Welcome to the latest of our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!"}),"\n",(0,i.jsx)(t.p,{children:"Please see below for a roundup of the highlights:"}),"\n",(0,i.jsx)(t.h2,{id:"cadence-at-open-source-summit-north-america",children:"Cadence at Open Source Summit, North America"}),"\n",(0,i.jsxs)(t.p,{children:["We are very pleased to let you know that a talk on Cadence has been accepted for the Linux Foundation's ",(0,i.jsx)(t.a,{href:"https://events.linuxfoundation.org/open-source-summit-north-america/",children:"Open Source Summit, North America"})," in Vancouver on 10th - 12th May 2023."]}),"\n",(0,i.jsxs)(t.p,{children:["The talk called ",(0,i.jsx)(t.a,{href:"https://ossna2023.sched.com/event/1K5B1",children:"Cadence: The New Open Source Project for Building Complex Distributed Applications"})," will be given by ",(0,i.jsx)(t.a,{href:"https://www.linkedin.com/in/enderdemirkaya/",children:"Ender Demirkaya"})," and ",(0,i.jsx)(t.a,{href:"https://www.linkedin.com/in/emrahseker/",children:"Emrah Seker"})," If you are planning to attend the Open Source Summit then please don't forget to attend the talk and take time catch up with Ender and Emrah!"]}),"\n",(0,i.jsx)(t.h2,{id:"community-activity",children:"Community Activity"}),"\n",(0,i.jsx)(t.p,{children:"Our Slack #support channel has been very active over the last few months as we continue to get an continual stream of questions. Here are the stats:"}),"\n",(0,i.jsxs)(t.ul,{children:["\n",(0,i.jsx)(t.li,{children:"February 2023 : 16 questions asked"}),"\n",(0,i.jsx)(t.li,{children:"March 2023 : 12 questions asked"}),"\n"]}),"\n",(0,i.jsx)(t.p,{children:"All of these questions are being answered collaboratively by the community. Thanks everyone for sharing your knowledge and we are looking forward to receiving more of your questions!"}),"\n",(0,i.jsx)(t.h2,{id:"cadence-developer-advocate",children:"Cadence Developer Advocate"}),"\n",(0,i.jsx)(t.p,{children:"Please welcome Yizhe Qin - the new Cadence Developer Advocate from Uber team that will be working to help support the community."}),"\n",(0,i.jsx)(t.p,{children:"Yizhe's role will involve responding to support questions, organising documentation and anything else that will help keep the community running smoothly."}),"\n",(0,i.jsx)(t.p,{children:"Please feel free to say Hi to Yizhe on the Slack channel!"}),"\n",(0,i.jsx)(t.h2,{id:"cadence-in-the-news",children:"Cadence in the News!"}),"\n",(0,i.jsx)(t.p,{children:"Below are a selection of Cadence related articles, blogs and whitepapers. Please take a look and feel free to share via your own social media channels."}),"\n",(0,i.jsxs)(t.ul,{children:["\n",(0,i.jsxs)(t.li,{children:["\n",(0,i.jsx)(t.p,{children:(0,i.jsx)(t.a,{href:"https://www.instaclustr.com/blog/instaclustr-cadence-workflow-developer/",children:"Instaclustr Cadence Developer Offering - General Availability"})}),"\n"]}),"\n",(0,i.jsxs)(t.li,{children:["\n",(0,i.jsx)(t.p,{children:(0,i.jsx)(t.a,{href:"https://www.instaclustr.com/blog/improving-the-reliability-of-cadence-search-queries/",children:"Improving Reliability of Cadence Search Queries That Use OpenSearch/Elasticsearch"})}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(t.h2,{id:"upcoming-events",children:"Upcoming Events"}),"\n",(0,i.jsxs)(t.ul,{children:["\n",(0,i.jsx)(t.li,{children:(0,i.jsx)(t.a,{href:"https://netapp.zoom.us/webinar/register/WN__5fuwxmNQuWeZ6DiI5wUqg",children:"Webinar: Microservices - A Modern Orchestration Approach with Cadence"})}),"\n"]}),"\n",(0,i.jsxs)(t.p,{children:["If you have any news or topics you'd like us to include in our next update then please join our ",(0,i.jsx)(t.a,{href:"http://t.uber.com/cadence-slack",children:"Slack"}),"#community channel."]}),"\n",(0,i.jsxs)(t.p,{children:["Please remember that this update is for you - so if you have any comments or feedback that could help us improve it then please share it with us in the #community ",(0,i.jsx)(t.a,{href:"http://t.uber.com/cadence-slack",children:"Slack"})," channel."]})]})}function d(e={}){const{wrapper:t}={...(0,o.R)(),...e.components};return t?(0,i.jsx)(t,{...e,children:(0,i.jsx)(h,{...e})}):h(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>r,x:()=>s});var a=n(6540);const i={},o=a.createContext(i);function r(e){const t=a.useContext(o);return a.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function s(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:r(e.components),a.createElement(o.Provider,{value:t},e.children)}},1900:e=>{e.exports=JSON.parse('{"permalink":"/Cadence-Docs/blog/2023/03/31/community-spotlight-march-2023","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2023-03-31-community-spotlight-march-2023.md","source":"@site/blog/2023-03-31-community-spotlight-march-2023.md","title":"Cadence Community Spotlight Update - March 2023","description":"Welcome to the latest of our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!","date":"2023-03-31T00:00:00.000Z","tags":[{"inline":false,"label":"Community Spotlight","permalink":"/Cadence-Docs/blog/tags/community-spotlights","description":"Community Spotlight tag description"}],"readingTime":1.885,"hasTruncateMarker":true,"authors":[{"name":"Sharan Foga","title":"Director of Operations & Customer Success @ Encube Technologies","url":"https://www.linkedin.com/in/sfoga/","page":{"permalink":"/Cadence-Docs/blog/authors/sharanf"},"socials":{"linkedin":"https://www.linkedin.com/in/sfoga/","github":"https://github.com/sharanf"},"imageURL":"https://github.com/sharanf.png","key":"sharanf"}],"frontMatter":{"title":"Cadence Community Spotlight Update - March 2023","date":"2023-03-31T00:00:00.000Z","authors":"sharanf","tags":["community-spotlight"]},"unlisted":false,"prevItem":{"title":"2023 Cadence Community Survey Results","permalink":"/Cadence-Docs/blog/2023/06/08/2023-06-08-survey-results/survey-results"},"nextItem":{"title":"Cadence Community Spotlight Update - March 2024","permalink":"/Cadence-Docs/blog/2024/3/11/community-spotlight-update-march-2024"}}')}}]); \ No newline at end of file diff --git a/assets/js/93e7684d.7f67dd89.js b/assets/js/93e7684d.7f67dd89.js deleted file mode 100644 index 122c2a8b1..000000000 --- a/assets/js/93e7684d.7f67dd89.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[2761],{9001:e=>{e.exports=JSON.parse('{"tag":{"label":"Cadence Operations","permalink":"/blog/tags/cadence-operations","description":"Cadence Operations tag description","allTagsPath":"/blog/tags","count":2,"unlisted":false},"listMetadata":{"permalink":"/blog/tags/cadence-operations","page":1,"postsPerPage":10,"totalPages":1,"totalCount":2,"blogDescription":"The latest news and updates from the Cadence team","blogTitle":"Cadence Blog"}}')}}]); \ No newline at end of file diff --git a/assets/js/959827cd.19116a70.js b/assets/js/959827cd.19116a70.js deleted file mode 100644 index 43b5efe66..000000000 --- a/assets/js/959827cd.19116a70.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[150],{6392:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>c,contentTitle:()=>i,default:()=>m,frontMatter:()=>s,metadata:()=>o,toc:()=>l});var o=n(7799),a=n(4848),r=n(8453);const s={title:"Cadence Community Spotlight Update - September 2022",date:new Date("2022-10-11T00:00:00.000Z"),authors:"sharanf",tags:["community-spotlight"]},i="Cadence at Developer Week",c={authorsImageUrls:[void 0]},l=[];function h(e){const t={a:"a",h1:"h1",p:"p",...(0,r.R)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(t.p,{children:"Here\u2019s the latest in our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!"}),"\n",(0,a.jsx)(t.p,{children:"Please see below for a roundup of the highlights:"}),"\n",(0,a.jsxs)(t.p,{children:["A Cadence talk by ",(0,a.jsx)(t.a,{href:"https://www.linkedin.com/in/enderdemirkaya/",children:"Ender Demirkaya"})," and ",(0,a.jsx)(t.a,{href:"https://www.linkedin.com/in/ben-slater-2720562/",children:"Ben Slater"})," has been accepted for ",(0,a.jsx)(t.a,{href:"https://www.developerweek.com/global/conference/enterprise/",children:"Developer Week Enterprise"}),"."]}),"\n",(0,a.jsx)(t.p,{children:"The talk is scheduled to for 16th November so please make a note in your calendars."}),"\n",(0,a.jsx)(t.h1,{id:"sharing-knowledge",children:"Sharing Knowledge"}),"\n",(0,a.jsxs)(t.p,{children:["Over the last few months we have had a continual stream of Cadence questions in our ",(0,a.jsx)(t.a,{href:"http://t.uber.com/cadence-slack",children:"Slack"})," #support channel or on ",(0,a.jsx)(t.a,{href:"https://stackoverflow.com/questions/tagged/cadence-workflow",children:"StackOverflow"}),". As a result of the increased interest some members from the Cadence core team have decided to spend some time each day responding to your questions."]}),"\n",(0,a.jsx)(t.p,{children:"Remember that if you have received a response that has solved your problem especially on StackOverflow then please don't forget to accept answer!"})]})}function m(e={}){const{wrapper:t}={...(0,r.R)(),...e.components};return t?(0,a.jsx)(t,{...e,children:(0,a.jsx)(h,{...e})}):h(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>s,x:()=>i});var o=n(6540);const a={},r=o.createContext(a);function s(e){const t=o.useContext(r);return o.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function i(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:s(e.components),o.createElement(r.Provider,{value:t},e.children)}},7799:e=>{e.exports=JSON.parse('{"permalink":"/blog/2022/09/30/community-spotlight-september-2022","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2022-09-30-community-spotlight-september-2022.md","source":"@site/blog/2022-09-30-community-spotlight-september-2022.md","title":"Cadence Community Spotlight Update - September 2022","description":"Here\u2019s the latest in our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!","date":"2022-10-11T00:00:00.000Z","tags":[{"inline":false,"label":"Community Spotlight","permalink":"/blog/tags/community-spotlights","description":"Community Spotlight tag description"}],"readingTime":1.585,"hasTruncateMarker":true,"authors":[{"name":"Sharan Foga","title":"Director of Operations & Customer Success @ Encube Technologies","url":"https://www.linkedin.com/in/sfoga/","page":{"permalink":"/blog/authors/sharanf"},"socials":{"linkedin":"https://www.linkedin.com/in/sfoga/","github":"https://github.com/sharanf"},"imageURL":"https://github.com/sharanf.png","key":"sharanf"}],"frontMatter":{"title":"Cadence Community Spotlight Update - September 2022","date":"2022-10-11T00:00:00.000Z","authors":"sharanf","tags":["community-spotlight"]},"unlisted":false,"prevItem":{"title":"Cadence Community Spotlight Update - October 2022","permalink":"/blog/2022/10/31/community-spotlight-october-2022"},"nextItem":{"title":"Cadence Community Spotlight Update - August 2022","permalink":"/blog/2022/08/31/community-spotlight-august-2022"}}')}}]); \ No newline at end of file diff --git a/assets/js/959827cd.e0792857.js b/assets/js/959827cd.e0792857.js new file mode 100644 index 000000000..acc16ac4f --- /dev/null +++ b/assets/js/959827cd.e0792857.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[150],{6392:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>c,contentTitle:()=>i,default:()=>m,frontMatter:()=>r,metadata:()=>o,toc:()=>l});var o=n(7799),a=n(4848),s=n(8453);const r={title:"Cadence Community Spotlight Update - September 2022",date:new Date("2022-10-11T00:00:00.000Z"),authors:"sharanf",tags:["community-spotlight"]},i="Cadence at Developer Week",c={authorsImageUrls:[void 0]},l=[];function h(e){const t={a:"a",h1:"h1",p:"p",...(0,s.R)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(t.p,{children:"Here\u2019s the latest in our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!"}),"\n",(0,a.jsx)(t.p,{children:"Please see below for a roundup of the highlights:"}),"\n",(0,a.jsxs)(t.p,{children:["A Cadence talk by ",(0,a.jsx)(t.a,{href:"https://www.linkedin.com/in/enderdemirkaya/",children:"Ender Demirkaya"})," and ",(0,a.jsx)(t.a,{href:"https://www.linkedin.com/in/ben-slater-2720562/",children:"Ben Slater"})," has been accepted for ",(0,a.jsx)(t.a,{href:"https://www.developerweek.com/global/conference/enterprise/",children:"Developer Week Enterprise"}),"."]}),"\n",(0,a.jsx)(t.p,{children:"The talk is scheduled to for 16th November so please make a note in your calendars."}),"\n",(0,a.jsx)(t.h1,{id:"sharing-knowledge",children:"Sharing Knowledge"}),"\n",(0,a.jsxs)(t.p,{children:["Over the last few months we have had a continual stream of Cadence questions in our ",(0,a.jsx)(t.a,{href:"http://t.uber.com/cadence-slack",children:"Slack"})," #support channel or on ",(0,a.jsx)(t.a,{href:"https://stackoverflow.com/questions/tagged/cadence-workflow",children:"StackOverflow"}),". As a result of the increased interest some members from the Cadence core team have decided to spend some time each day responding to your questions."]}),"\n",(0,a.jsx)(t.p,{children:"Remember that if you have received a response that has solved your problem especially on StackOverflow then please don't forget to accept answer!"})]})}function m(e={}){const{wrapper:t}={...(0,s.R)(),...e.components};return t?(0,a.jsx)(t,{...e,children:(0,a.jsx)(h,{...e})}):h(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>r,x:()=>i});var o=n(6540);const a={},s=o.createContext(a);function r(e){const t=o.useContext(s);return o.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function i(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:r(e.components),o.createElement(s.Provider,{value:t},e.children)}},7799:e=>{e.exports=JSON.parse('{"permalink":"/Cadence-Docs/blog/2022/09/30/community-spotlight-september-2022","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2022-09-30-community-spotlight-september-2022.md","source":"@site/blog/2022-09-30-community-spotlight-september-2022.md","title":"Cadence Community Spotlight Update - September 2022","description":"Here\u2019s the latest in our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!","date":"2022-10-11T00:00:00.000Z","tags":[{"inline":false,"label":"Community Spotlight","permalink":"/Cadence-Docs/blog/tags/community-spotlights","description":"Community Spotlight tag description"}],"readingTime":1.585,"hasTruncateMarker":true,"authors":[{"name":"Sharan Foga","title":"Director of Operations & Customer Success @ Encube Technologies","url":"https://www.linkedin.com/in/sfoga/","page":{"permalink":"/Cadence-Docs/blog/authors/sharanf"},"socials":{"linkedin":"https://www.linkedin.com/in/sfoga/","github":"https://github.com/sharanf"},"imageURL":"https://github.com/sharanf.png","key":"sharanf"}],"frontMatter":{"title":"Cadence Community Spotlight Update - September 2022","date":"2022-10-11T00:00:00.000Z","authors":"sharanf","tags":["community-spotlight"]},"unlisted":false,"prevItem":{"title":"Cadence Community Spotlight Update - October 2022","permalink":"/Cadence-Docs/blog/2022/10/31/community-spotlight-october-2022"},"nextItem":{"title":"Cadence Community Spotlight Update - August 2022","permalink":"/Cadence-Docs/blog/2022/08/31/community-spotlight-august-2022"}}')}}]); \ No newline at end of file diff --git a/assets/js/95cc356a.1d9d46a3.js b/assets/js/95cc356a.1d9d46a3.js new file mode 100644 index 000000000..84239c6cb --- /dev/null +++ b/assets/js/95cc356a.1d9d46a3.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[4324],{7669:(e,o,r)=>{r.r(o),r.d(o,{assets:()=>s,contentTitle:()=>a,default:()=>h,frontMatter:()=>l,metadata:()=>n,toc:()=>d});const n=JSON.parse('{"id":"go-client/workflow-replay-shadowing","title":"Workflow Replay and Shadowing","description":"In the Versioning section, we mentioned that incompatible changes to workflow definition code could cause non-deterministic issues when processing workflow tasks if versioning is not done correctly. However, it may be hard for you to tell if a particular change is incompatible or not and whether versioning logic is needed. To help you identify incompatible changes and catch them before production traffic is impacted, we implemented Workflow Replayer and Workflow Shadower.","source":"@site/docs/05-go-client/18-workflow-replay-shadowing.md","sourceDirName":"05-go-client","slug":"/go-client/workflow-replay-shadowing","permalink":"/Cadence-Docs/docs/go-client/workflow-replay-shadowing","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/05-go-client/18-workflow-replay-shadowing.md","tags":[],"version":"current","sidebarPosition":18,"frontMatter":{"layout":"default","title":"Workflow Replay and Shadowing","permalink":"/docs/go-client/workflow-replay-shadowing"},"sidebar":"docsSidebar","previous":{"title":"Tracing and context propagation","permalink":"/Cadence-Docs/docs/go-client/tracing"},"next":{"title":"Introduction","permalink":"/Cadence-Docs/docs/cli/"}}');var t=r(4848),i=r(8453);const l={layout:"default",title:"Workflow Replay and Shadowing",permalink:"/docs/go-client/workflow-replay-shadowing"},a="Workflow Replay and Shadowing",s={},d=[{value:"Workflow Replayer",id:"workflow-replayer",level:2},{value:"Write a Replay Test",id:"write-a-replay-test",level:3},{value:"Step 1: Create workflow replayer",id:"step-1-create-workflow-replayer",level:4},{value:"Step 2: Register workflow definition",id:"step-2-register-workflow-definition",level:4},{value:"Step 3: Prepare workflow histories",id:"step-3-prepare-workflow-histories",level:4},{value:"Step 4: Call the replay method",id:"step-4-call-the-replay-method",level:4},{value:"Step 5: Check returned error",id:"step-5-check-returned-error",level:4},{value:"Sample Replay Test",id:"sample-replay-test",level:3},{value:"Workflow Shadower",id:"workflow-shadower",level:2},{value:"Shadow Options",id:"shadow-options",level:3},{value:"Scan Filters",id:"scan-filters",level:4},{value:"Shadow Exit Condition",id:"shadow-exit-condition",level:4},{value:"Shadow Mode",id:"shadow-mode",level:4},{value:"Shadow Concurrency",id:"shadow-concurrency",level:4},{value:"Local Shadowing Test",id:"local-shadowing-test",level:3},{value:"Shadowing Worker",id:"shadowing-worker",level:3}];function c(e){const o={a:"a",code:"code",h1:"h1",h2:"h2",h3:"h3",h4:"h4",header:"header",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,i.R)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(o.header,{children:(0,t.jsx)(o.h1,{id:"workflow-replay-and-shadowing",children:"Workflow Replay and Shadowing"})}),"\n",(0,t.jsx)(o.p,{children:"In the Versioning section, we mentioned that incompatible changes to workflow definition code could cause non-deterministic issues when processing workflow tasks if versioning is not done correctly. However, it may be hard for you to tell if a particular change is incompatible or not and whether versioning logic is needed. To help you identify incompatible changes and catch them before production traffic is impacted, we implemented Workflow Replayer and Workflow Shadower."}),"\n",(0,t.jsx)(o.h2,{id:"workflow-replayer",children:"Workflow Replayer"}),"\n",(0,t.jsx)(o.p,{children:"Workflow Replayer is a testing component for replaying existing workflow histories against a workflow definition. The replaying logic is the same as the one used for processing workflow tasks, so if there's any incompatible changes in the workflow definition, the replay test will fail."}),"\n",(0,t.jsx)(o.h3,{id:"write-a-replay-test",children:"Write a Replay Test"}),"\n",(0,t.jsx)(o.h4,{id:"step-1-create-workflow-replayer",children:"Step 1: Create workflow replayer"}),"\n",(0,t.jsx)(o.p,{children:"Create a workflow Replayer by:"}),"\n",(0,t.jsx)(o.pre,{children:(0,t.jsx)(o.code,{className:"language-go",children:"replayer := worker.NewWorkflowReplayer()\n"})}),"\n",(0,t.jsx)(o.p,{children:"or if custom data converter, context propagator, interceptor, etc. is used in your workflow:"}),"\n",(0,t.jsx)(o.pre,{children:(0,t.jsx)(o.code,{className:"language-go",children:"options := worker.ReplayOptions{\n DataConverter: myDataConverter,\n ContextPropagators: []workflow.ContextPropagator{\n myContextPropagator,\n },\n WorkflowInterceptorChainFactories: []interceptors.WorkflowInterceptorFactory{\n myInterceptorFactory,\n },\n Tracer: myTracer,\n}\nreplayer := worker.NewWorkflowReplayWithOptions(options)\n"})}),"\n",(0,t.jsx)(o.h4,{id:"step-2-register-workflow-definition",children:"Step 2: Register workflow definition"}),"\n",(0,t.jsx)(o.p,{children:"Next, register your workflow definitions as you normally do. Make sure workflows are registered the same way as they were when running and generating histories; otherwise the replay will not be able to find the corresponding definition."}),"\n",(0,t.jsx)(o.pre,{children:(0,t.jsx)(o.code,{className:"language-go",children:"replayer.RegisterWorkflow(myWorkflowFunc1)\nreplayer.RegisterWorkflow(myWorkflowFunc2, workflow.RegisterOptions{\n\tName: workflowName,\n})\n"})}),"\n",(0,t.jsx)(o.h4,{id:"step-3-prepare-workflow-histories",children:"Step 3: Prepare workflow histories"}),"\n",(0,t.jsx)(o.p,{children:"Replayer can read workflow history from a local json file or fetch it directly from the Cadence server. If you would like to use the first method, you can use the following CLI command, otherwise you can skip to the next step."}),"\n",(0,t.jsx)(o.pre,{children:(0,t.jsx)(o.code,{className:"language-bash",children:"cadence --do <domain> workflow show --wid <workflowID> --rid <runID> --of <output file name>\n"})}),"\n",(0,t.jsx)(o.p,{children:"The dumped workflow history will be stored in the file at the path you specified in json format."}),"\n",(0,t.jsx)(o.h4,{id:"step-4-call-the-replay-method",children:"Step 4: Call the replay method"}),"\n",(0,t.jsx)(o.p,{children:"Once you have the workflow history or have the connection to Cadence server for fetching history, call one of the four replay methods to start the replay test."}),"\n",(0,t.jsx)(o.pre,{children:(0,t.jsx)(o.code,{className:"language-go",children:"// if workflow history has been loaded into memory\nerr := replayer.ReplayWorkflowHistory(logger, history)\n\n// if workflow history is stored in a json file\nerr = replayer.ReplayWorkflowHistoryFromJSONFile(logger, jsonFileName)\n\n// if workflow history is stored in a json file and you only want to replay part of it\n// NOTE: lastEventID can't be set arbitrarily. It must be the end of of a history events batch\n// when in doubt, set to the eventID of decisionTaskStarted events.\nerr = replayer.ReplayPartialWorkflowHistoryFromJSONFile(logger, jsonFileName, lastEventID)\n\n// if you want to fetch workflow history directly from cadence server\n// please check the Worker Service page for how to create a cadence service client\nerr = replayer.ReplayWorkflowExecution(ctx, cadenceServiceClient, logger, domain, execution)\n"})}),"\n",(0,t.jsx)(o.h4,{id:"step-5-check-returned-error",children:"Step 5: Check returned error"}),"\n",(0,t.jsx)(o.p,{children:"If an error is returned from the replay method, it means there's a incompatible change in the workflow definition and the error message will contain more information regarding where the non-deterministic error happens."}),"\n",(0,t.jsx)(o.p,{children:"Note: currently an error will be returned if there are less than 3 events in the history. It is because the first 3 events in the history has nothing to do with the workflow code, so Replayer can't tell if there's a incompatible change or not."}),"\n",(0,t.jsx)(o.h3,{id:"sample-replay-test",children:"Sample Replay Test"}),"\n",(0,t.jsxs)(o.p,{children:["This sample is also available in our samples repo at ",(0,t.jsx)(o.a,{href:"https://github.com/cadence-workflow/cadence-samples/blob/master/cmd/samples/recipes/helloworld/replay_test.go#L39",children:"here"}),"."]}),"\n",(0,t.jsx)(o.pre,{children:(0,t.jsx)(o.code,{className:"language-go",children:'func TestReplayWorkflowHistoryFromFile(t *testing.T) {\n\treplayer := worker.NewWorkflowReplayer()\n\treplayer.RegisterWorkflow(helloWorldWorkflow)\n\terr := replayer.ReplayWorkflowHistoryFromJSONFile(zaptest.NewLogger(t), "helloworld.json")\n\trequire.NoError(t, err)\n}\n'})}),"\n",(0,t.jsx)(o.h2,{id:"workflow-shadower",children:"Workflow Shadower"}),"\n",(0,t.jsx)(o.p,{children:"Workflow Replayer works well when verifying the compatibility against a small number of workflow histories. If there are lots of workflows in production need to be verified, dumping all histories manually clearly won't work. Directly fetching histories from cadence server might be a solution, but the time to replay all workflow histories might be too long for a test."}),"\n",(0,t.jsx)(o.p,{children:"Workflow Shadower is built on top of Workflow Replayer to address this problem. The basic idea of shadowing is: scan workflows based on the filters you defined, fetch history for each of workflow in the scan result from Cadence server and run the replay test. It can be run either as a test to serve local development purpose or as a workflow in your worker to continuously replay production workflows."}),"\n",(0,t.jsx)(o.h3,{id:"shadow-options",children:"Shadow Options"}),"\n",(0,t.jsxs)(o.p,{children:["Complete documentation on shadow options which includes default values, accepted values, etc. can be found ",(0,t.jsx)(o.a,{href:"https://github.com/cadence-workflow/cadence-go-client/blob/master/internal/workflow_shadower.go#L53",children:"here"}),". The following sections are just a brief description of each option."]}),"\n",(0,t.jsx)(o.h4,{id:"scan-filters",children:"Scan Filters"}),"\n",(0,t.jsxs)(o.ul,{children:["\n",(0,t.jsx)(o.li,{children:"WorkflowQuery: If you are familiar with our advanced visibility query syntax, you can specify a query directly. If specified, all other scan filters must be left empty."}),"\n",(0,t.jsx)(o.li,{children:"WorkflowTypes: A list of workflow Type names."}),"\n",(0,t.jsx)(o.li,{children:"WorkflowStatus: A list of workflow status."}),"\n",(0,t.jsx)(o.li,{children:"WorkflowStartTimeFilter: Min and max timestamp for workflow start time."}),"\n",(0,t.jsx)(o.li,{children:"SamplingRate: Sampling workflows from the scan result before executing the replay test."}),"\n"]}),"\n",(0,t.jsx)(o.h4,{id:"shadow-exit-condition",children:"Shadow Exit Condition"}),"\n",(0,t.jsxs)(o.ul,{children:["\n",(0,t.jsx)(o.li,{children:"ExpirationInterval: Shadowing will exit when the specified interval has passed."}),"\n",(0,t.jsx)(o.li,{children:"ShadowCount: Shadowing will exit after this number of workflow has been replayed. Note: replay maybe skipped due to errors like can't fetch history, history too short, etc. Skipped workflows won't be taken account into ShadowCount."}),"\n"]}),"\n",(0,t.jsx)(o.h4,{id:"shadow-mode",children:"Shadow Mode"}),"\n",(0,t.jsxs)(o.ul,{children:["\n",(0,t.jsx)(o.li,{children:"Normal: Shadowing will complete after all workflows matches WorkflowQuery (after sampling) have been replayed or when exit condition is met."}),"\n",(0,t.jsx)(o.li,{children:"Continuous: A new round of shadowing will be started after all workflows matches WorkflowQuery have been replayed. There will be a 5 min wait period between each round, and currently this wait period is not configurable. Shadowing will complete only when ExitCondition is met. ExitCondition must be specified when using this mode."}),"\n"]}),"\n",(0,t.jsx)(o.h4,{id:"shadow-concurrency",children:"Shadow Concurrency"}),"\n",(0,t.jsxs)(o.ul,{children:["\n",(0,t.jsx)(o.li,{children:"Concurrency: workflow replay concurrency. If not specified, will be default to 1. For local shadowing, an error will be returned if a value higher than 1 is specified."}),"\n"]}),"\n",(0,t.jsx)(o.h3,{id:"local-shadowing-test",children:"Local Shadowing Test"}),"\n",(0,t.jsxs)(o.p,{children:["Local shadowing test is similar to the replay test. First create a workflow shadower with optional shadow and replay options, then register the workflow that need to be shadowed. Finally, call the ",(0,t.jsx)(o.code,{children:"Run"})," method to start the shadowing. The method will return if shadowing has finished or any non-deterministic error is found."]}),"\n",(0,t.jsxs)(o.p,{children:["Here's a simple example. The example is also available ",(0,t.jsx)(o.a,{href:"https://github.com/cadence-workflow/cadence-samples/blob/master/cmd/samples/recipes/helloworld/shadow_test.go",children:"here"}),"."]}),"\n",(0,t.jsx)(o.pre,{children:(0,t.jsx)(o.code,{className:"language-go",children:'func TestShadowWorkflow(t *testing.T) {\n\toptions := worker.ShadowOptions{\n\t\tWorkflowStartTimeFilter: worker.TimeFilter{\n\t\t\tMinTimestamp: time.Now().Add(-time.Hour),\n\t\t},\n\t\tExitCondition: worker.ShadowExitCondition{\n\t\t\tShadowCount: 10,\n\t\t},\n\t}\n\n // please check the Worker Service page for how to create a cadence service client\n\tservice := buildCadenceClient()\n\tshadower, err := worker.NewWorkflowShadower(service, "samples-domain", options, worker.ReplayOptions{}, zaptest.NewLogger(t))\n\tassert.NoError(t, err)\n\n\tshadower.RegisterWorkflowWithOptions(helloWorldWorkflow, workflow.RegisterOptions{Name: "helloWorld"})\n\tassert.NoError(t, shadower.Run())\n}\n'})}),"\n",(0,t.jsx)(o.h3,{id:"shadowing-worker",children:"Shadowing Worker"}),"\n",(0,t.jsx)(o.p,{children:"NOTE:"}),"\n",(0,t.jsxs)(o.ul,{children:["\n",(0,t.jsx)(o.li,{children:(0,t.jsx)(o.strong,{children:"All shadow workflows are running in one Cadence system domain, and right now, every user domain can only have one shadow workflow at a time."})}),"\n",(0,t.jsxs)(o.li,{children:[(0,t.jsx)(o.strong,{children:"The Cadence server used for scanning and getting workflow history will also be the Cadence server for running your shadow workflow."})," Currently, there's no way to specify different Cadence servers for hosting the shadowing workflow and scanning/fetching workflow."]}),"\n"]}),"\n",(0,t.jsx)(o.p,{children:"Your worker can also be configured to run in shadow mode to run shadow tests as a workflow. This is useful if there's a number of workflows need to be replayed. Using a workflow can make sure the shadowing won't accidentally fail in the middle and the replay load can be distributed by deploying more shadow mode workers. It can also be incorporated into your deployment process to make sure there's no failed replay checks before deploying your change to production workers."}),"\n",(0,t.jsx)(o.p,{children:"When running in shadow mode, the normal decision, activity and session worker will be disabled so that it won't update any production workflows. A special shadow activity worker will be started to execute activities for scanning and replaying workflows. The actual shadow workflow logic is controlled by Cadence server and your worker is only responsible for scanning and replaying workflows."}),"\n",(0,t.jsxs)(o.p,{children:[(0,t.jsx)(o.a,{href:"https://github.com/cadence-workflow/cadence-go-client/blob/master/internal/common/metrics/constants.go#L105",children:"Replay succeed, skipped and failed metrics"})," will be emitted by your worker when executing the shadow workflow and you can monitor those metrics to see if there's any incompatible changes."]}),"\n",(0,t.jsxs)(o.p,{children:["To enable the shadow mode, the only change needed is setting the ",(0,t.jsx)(o.code,{children:"EnableShadowWorker"})," field in ",(0,t.jsx)(o.code,{children:"worker.Options"})," to ",(0,t.jsx)(o.code,{children:"true"}),", and then specify the ",(0,t.jsx)(o.code,{children:"ShadowOptions"}),"."]}),"\n",(0,t.jsxs)(o.p,{children:["Registered workflows will be forwarded to the underlying WorkflowReplayer. DataConverter, WorkflowInterceptorChainFactories, ContextPropagators, and Tracer specified in the ",(0,t.jsx)(o.code,{children:"worker.Options"})," will also be used as ReplayOptions. Since all shadow workflows are running in one system domain, to avoid conflict, ",(0,t.jsxs)(o.strong,{children:["the actual task list name used will be ",(0,t.jsx)(o.code,{children:"domain-tasklist"}),"."]})]}),"\n",(0,t.jsxs)(o.p,{children:["A sample setup can be found ",(0,t.jsx)(o.a,{href:"https://github.com/cadence-workflow/cadence-samples/blob/master/cmd/samples/recipes/helloworld/main.go#L24",children:"here"}),"."]})]})}function h(e={}){const{wrapper:o}={...(0,i.R)(),...e.components};return o?(0,t.jsx)(o,{...e,children:(0,t.jsx)(c,{...e})}):c(e)}},8453:(e,o,r)=>{r.d(o,{R:()=>l,x:()=>a});var n=r(6540);const t={},i=n.createContext(t);function l(e){const o=n.useContext(i);return n.useMemo((function(){return"function"==typeof e?e(o):{...o,...e}}),[o,e])}function a(e){let o;return o=e.disableParentContext?"function"==typeof e.components?e.components(t):e.components||t:l(e.components),n.createElement(i.Provider,{value:o},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/95cc356a.e8082267.js b/assets/js/95cc356a.e8082267.js deleted file mode 100644 index bbe10c753..000000000 --- a/assets/js/95cc356a.e8082267.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[4324],{7669:(e,o,r)=>{r.r(o),r.d(o,{assets:()=>s,contentTitle:()=>a,default:()=>h,frontMatter:()=>l,metadata:()=>n,toc:()=>d});const n=JSON.parse('{"id":"go-client/workflow-replay-shadowing","title":"Workflow Replay and Shadowing","description":"In the Versioning section, we mentioned that incompatible changes to workflow definition code could cause non-deterministic issues when processing workflow tasks if versioning is not done correctly. However, it may be hard for you to tell if a particular change is incompatible or not and whether versioning logic is needed. To help you identify incompatible changes and catch them before production traffic is impacted, we implemented Workflow Replayer and Workflow Shadower.","source":"@site/docs/05-go-client/18-workflow-replay-shadowing.md","sourceDirName":"05-go-client","slug":"/go-client/workflow-replay-shadowing","permalink":"/docs/go-client/workflow-replay-shadowing","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/05-go-client/18-workflow-replay-shadowing.md","tags":[],"version":"current","sidebarPosition":18,"frontMatter":{"layout":"default","title":"Workflow Replay and Shadowing","permalink":"/docs/go-client/workflow-replay-shadowing"},"sidebar":"docsSidebar","previous":{"title":"Tracing and context propagation","permalink":"/docs/go-client/tracing"},"next":{"title":"Introduction","permalink":"/docs/cli/"}}');var t=r(4848),i=r(8453);const l={layout:"default",title:"Workflow Replay and Shadowing",permalink:"/docs/go-client/workflow-replay-shadowing"},a="Workflow Replay and Shadowing",s={},d=[{value:"Workflow Replayer",id:"workflow-replayer",level:2},{value:"Write a Replay Test",id:"write-a-replay-test",level:3},{value:"Step 1: Create workflow replayer",id:"step-1-create-workflow-replayer",level:4},{value:"Step 2: Register workflow definition",id:"step-2-register-workflow-definition",level:4},{value:"Step 3: Prepare workflow histories",id:"step-3-prepare-workflow-histories",level:4},{value:"Step 4: Call the replay method",id:"step-4-call-the-replay-method",level:4},{value:"Step 5: Check returned error",id:"step-5-check-returned-error",level:4},{value:"Sample Replay Test",id:"sample-replay-test",level:3},{value:"Workflow Shadower",id:"workflow-shadower",level:2},{value:"Shadow Options",id:"shadow-options",level:3},{value:"Scan Filters",id:"scan-filters",level:4},{value:"Shadow Exit Condition",id:"shadow-exit-condition",level:4},{value:"Shadow Mode",id:"shadow-mode",level:4},{value:"Shadow Concurrency",id:"shadow-concurrency",level:4},{value:"Local Shadowing Test",id:"local-shadowing-test",level:3},{value:"Shadowing Worker",id:"shadowing-worker",level:3}];function c(e){const o={a:"a",code:"code",h1:"h1",h2:"h2",h3:"h3",h4:"h4",header:"header",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,i.R)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(o.header,{children:(0,t.jsx)(o.h1,{id:"workflow-replay-and-shadowing",children:"Workflow Replay and Shadowing"})}),"\n",(0,t.jsx)(o.p,{children:"In the Versioning section, we mentioned that incompatible changes to workflow definition code could cause non-deterministic issues when processing workflow tasks if versioning is not done correctly. However, it may be hard for you to tell if a particular change is incompatible or not and whether versioning logic is needed. To help you identify incompatible changes and catch them before production traffic is impacted, we implemented Workflow Replayer and Workflow Shadower."}),"\n",(0,t.jsx)(o.h2,{id:"workflow-replayer",children:"Workflow Replayer"}),"\n",(0,t.jsx)(o.p,{children:"Workflow Replayer is a testing component for replaying existing workflow histories against a workflow definition. The replaying logic is the same as the one used for processing workflow tasks, so if there's any incompatible changes in the workflow definition, the replay test will fail."}),"\n",(0,t.jsx)(o.h3,{id:"write-a-replay-test",children:"Write a Replay Test"}),"\n",(0,t.jsx)(o.h4,{id:"step-1-create-workflow-replayer",children:"Step 1: Create workflow replayer"}),"\n",(0,t.jsx)(o.p,{children:"Create a workflow Replayer by:"}),"\n",(0,t.jsx)(o.pre,{children:(0,t.jsx)(o.code,{className:"language-go",children:"replayer := worker.NewWorkflowReplayer()\n"})}),"\n",(0,t.jsx)(o.p,{children:"or if custom data converter, context propagator, interceptor, etc. is used in your workflow:"}),"\n",(0,t.jsx)(o.pre,{children:(0,t.jsx)(o.code,{className:"language-go",children:"options := worker.ReplayOptions{\n DataConverter: myDataConverter,\n ContextPropagators: []workflow.ContextPropagator{\n myContextPropagator,\n },\n WorkflowInterceptorChainFactories: []interceptors.WorkflowInterceptorFactory{\n myInterceptorFactory,\n },\n Tracer: myTracer,\n}\nreplayer := worker.NewWorkflowReplayWithOptions(options)\n"})}),"\n",(0,t.jsx)(o.h4,{id:"step-2-register-workflow-definition",children:"Step 2: Register workflow definition"}),"\n",(0,t.jsx)(o.p,{children:"Next, register your workflow definitions as you normally do. Make sure workflows are registered the same way as they were when running and generating histories; otherwise the replay will not be able to find the corresponding definition."}),"\n",(0,t.jsx)(o.pre,{children:(0,t.jsx)(o.code,{className:"language-go",children:"replayer.RegisterWorkflow(myWorkflowFunc1)\nreplayer.RegisterWorkflow(myWorkflowFunc2, workflow.RegisterOptions{\n\tName: workflowName,\n})\n"})}),"\n",(0,t.jsx)(o.h4,{id:"step-3-prepare-workflow-histories",children:"Step 3: Prepare workflow histories"}),"\n",(0,t.jsx)(o.p,{children:"Replayer can read workflow history from a local json file or fetch it directly from the Cadence server. If you would like to use the first method, you can use the following CLI command, otherwise you can skip to the next step."}),"\n",(0,t.jsx)(o.pre,{children:(0,t.jsx)(o.code,{className:"language-bash",children:"cadence --do <domain> workflow show --wid <workflowID> --rid <runID> --of <output file name>\n"})}),"\n",(0,t.jsx)(o.p,{children:"The dumped workflow history will be stored in the file at the path you specified in json format."}),"\n",(0,t.jsx)(o.h4,{id:"step-4-call-the-replay-method",children:"Step 4: Call the replay method"}),"\n",(0,t.jsx)(o.p,{children:"Once you have the workflow history or have the connection to Cadence server for fetching history, call one of the four replay methods to start the replay test."}),"\n",(0,t.jsx)(o.pre,{children:(0,t.jsx)(o.code,{className:"language-go",children:"// if workflow history has been loaded into memory\nerr := replayer.ReplayWorkflowHistory(logger, history)\n\n// if workflow history is stored in a json file\nerr = replayer.ReplayWorkflowHistoryFromJSONFile(logger, jsonFileName)\n\n// if workflow history is stored in a json file and you only want to replay part of it\n// NOTE: lastEventID can't be set arbitrarily. It must be the end of of a history events batch\n// when in doubt, set to the eventID of decisionTaskStarted events.\nerr = replayer.ReplayPartialWorkflowHistoryFromJSONFile(logger, jsonFileName, lastEventID)\n\n// if you want to fetch workflow history directly from cadence server\n// please check the Worker Service page for how to create a cadence service client\nerr = replayer.ReplayWorkflowExecution(ctx, cadenceServiceClient, logger, domain, execution)\n"})}),"\n",(0,t.jsx)(o.h4,{id:"step-5-check-returned-error",children:"Step 5: Check returned error"}),"\n",(0,t.jsx)(o.p,{children:"If an error is returned from the replay method, it means there's a incompatible change in the workflow definition and the error message will contain more information regarding where the non-deterministic error happens."}),"\n",(0,t.jsx)(o.p,{children:"Note: currently an error will be returned if there are less than 3 events in the history. It is because the first 3 events in the history has nothing to do with the workflow code, so Replayer can't tell if there's a incompatible change or not."}),"\n",(0,t.jsx)(o.h3,{id:"sample-replay-test",children:"Sample Replay Test"}),"\n",(0,t.jsxs)(o.p,{children:["This sample is also available in our samples repo at ",(0,t.jsx)(o.a,{href:"https://github.com/cadence-workflow/cadence-samples/blob/master/cmd/samples/recipes/helloworld/replay_test.go#L39",children:"here"}),"."]}),"\n",(0,t.jsx)(o.pre,{children:(0,t.jsx)(o.code,{className:"language-go",children:'func TestReplayWorkflowHistoryFromFile(t *testing.T) {\n\treplayer := worker.NewWorkflowReplayer()\n\treplayer.RegisterWorkflow(helloWorldWorkflow)\n\terr := replayer.ReplayWorkflowHistoryFromJSONFile(zaptest.NewLogger(t), "helloworld.json")\n\trequire.NoError(t, err)\n}\n'})}),"\n",(0,t.jsx)(o.h2,{id:"workflow-shadower",children:"Workflow Shadower"}),"\n",(0,t.jsx)(o.p,{children:"Workflow Replayer works well when verifying the compatibility against a small number of workflow histories. If there are lots of workflows in production need to be verified, dumping all histories manually clearly won't work. Directly fetching histories from cadence server might be a solution, but the time to replay all workflow histories might be too long for a test."}),"\n",(0,t.jsx)(o.p,{children:"Workflow Shadower is built on top of Workflow Replayer to address this problem. The basic idea of shadowing is: scan workflows based on the filters you defined, fetch history for each of workflow in the scan result from Cadence server and run the replay test. It can be run either as a test to serve local development purpose or as a workflow in your worker to continuously replay production workflows."}),"\n",(0,t.jsx)(o.h3,{id:"shadow-options",children:"Shadow Options"}),"\n",(0,t.jsxs)(o.p,{children:["Complete documentation on shadow options which includes default values, accepted values, etc. can be found ",(0,t.jsx)(o.a,{href:"https://github.com/cadence-workflow/cadence-go-client/blob/master/internal/workflow_shadower.go#L53",children:"here"}),". The following sections are just a brief description of each option."]}),"\n",(0,t.jsx)(o.h4,{id:"scan-filters",children:"Scan Filters"}),"\n",(0,t.jsxs)(o.ul,{children:["\n",(0,t.jsx)(o.li,{children:"WorkflowQuery: If you are familiar with our advanced visibility query syntax, you can specify a query directly. If specified, all other scan filters must be left empty."}),"\n",(0,t.jsx)(o.li,{children:"WorkflowTypes: A list of workflow Type names."}),"\n",(0,t.jsx)(o.li,{children:"WorkflowStatus: A list of workflow status."}),"\n",(0,t.jsx)(o.li,{children:"WorkflowStartTimeFilter: Min and max timestamp for workflow start time."}),"\n",(0,t.jsx)(o.li,{children:"SamplingRate: Sampling workflows from the scan result before executing the replay test."}),"\n"]}),"\n",(0,t.jsx)(o.h4,{id:"shadow-exit-condition",children:"Shadow Exit Condition"}),"\n",(0,t.jsxs)(o.ul,{children:["\n",(0,t.jsx)(o.li,{children:"ExpirationInterval: Shadowing will exit when the specified interval has passed."}),"\n",(0,t.jsx)(o.li,{children:"ShadowCount: Shadowing will exit after this number of workflow has been replayed. Note: replay maybe skipped due to errors like can't fetch history, history too short, etc. Skipped workflows won't be taken account into ShadowCount."}),"\n"]}),"\n",(0,t.jsx)(o.h4,{id:"shadow-mode",children:"Shadow Mode"}),"\n",(0,t.jsxs)(o.ul,{children:["\n",(0,t.jsx)(o.li,{children:"Normal: Shadowing will complete after all workflows matches WorkflowQuery (after sampling) have been replayed or when exit condition is met."}),"\n",(0,t.jsx)(o.li,{children:"Continuous: A new round of shadowing will be started after all workflows matches WorkflowQuery have been replayed. There will be a 5 min wait period between each round, and currently this wait period is not configurable. Shadowing will complete only when ExitCondition is met. ExitCondition must be specified when using this mode."}),"\n"]}),"\n",(0,t.jsx)(o.h4,{id:"shadow-concurrency",children:"Shadow Concurrency"}),"\n",(0,t.jsxs)(o.ul,{children:["\n",(0,t.jsx)(o.li,{children:"Concurrency: workflow replay concurrency. If not specified, will be default to 1. For local shadowing, an error will be returned if a value higher than 1 is specified."}),"\n"]}),"\n",(0,t.jsx)(o.h3,{id:"local-shadowing-test",children:"Local Shadowing Test"}),"\n",(0,t.jsxs)(o.p,{children:["Local shadowing test is similar to the replay test. First create a workflow shadower with optional shadow and replay options, then register the workflow that need to be shadowed. Finally, call the ",(0,t.jsx)(o.code,{children:"Run"})," method to start the shadowing. The method will return if shadowing has finished or any non-deterministic error is found."]}),"\n",(0,t.jsxs)(o.p,{children:["Here's a simple example. The example is also available ",(0,t.jsx)(o.a,{href:"https://github.com/cadence-workflow/cadence-samples/blob/master/cmd/samples/recipes/helloworld/shadow_test.go",children:"here"}),"."]}),"\n",(0,t.jsx)(o.pre,{children:(0,t.jsx)(o.code,{className:"language-go",children:'func TestShadowWorkflow(t *testing.T) {\n\toptions := worker.ShadowOptions{\n\t\tWorkflowStartTimeFilter: worker.TimeFilter{\n\t\t\tMinTimestamp: time.Now().Add(-time.Hour),\n\t\t},\n\t\tExitCondition: worker.ShadowExitCondition{\n\t\t\tShadowCount: 10,\n\t\t},\n\t}\n\n // please check the Worker Service page for how to create a cadence service client\n\tservice := buildCadenceClient()\n\tshadower, err := worker.NewWorkflowShadower(service, "samples-domain", options, worker.ReplayOptions{}, zaptest.NewLogger(t))\n\tassert.NoError(t, err)\n\n\tshadower.RegisterWorkflowWithOptions(helloWorldWorkflow, workflow.RegisterOptions{Name: "helloWorld"})\n\tassert.NoError(t, shadower.Run())\n}\n'})}),"\n",(0,t.jsx)(o.h3,{id:"shadowing-worker",children:"Shadowing Worker"}),"\n",(0,t.jsx)(o.p,{children:"NOTE:"}),"\n",(0,t.jsxs)(o.ul,{children:["\n",(0,t.jsx)(o.li,{children:(0,t.jsx)(o.strong,{children:"All shadow workflows are running in one Cadence system domain, and right now, every user domain can only have one shadow workflow at a time."})}),"\n",(0,t.jsxs)(o.li,{children:[(0,t.jsx)(o.strong,{children:"The Cadence server used for scanning and getting workflow history will also be the Cadence server for running your shadow workflow."})," Currently, there's no way to specify different Cadence servers for hosting the shadowing workflow and scanning/fetching workflow."]}),"\n"]}),"\n",(0,t.jsx)(o.p,{children:"Your worker can also be configured to run in shadow mode to run shadow tests as a workflow. This is useful if there's a number of workflows need to be replayed. Using a workflow can make sure the shadowing won't accidentally fail in the middle and the replay load can be distributed by deploying more shadow mode workers. It can also be incorporated into your deployment process to make sure there's no failed replay checks before deploying your change to production workers."}),"\n",(0,t.jsx)(o.p,{children:"When running in shadow mode, the normal decision, activity and session worker will be disabled so that it won't update any production workflows. A special shadow activity worker will be started to execute activities for scanning and replaying workflows. The actual shadow workflow logic is controlled by Cadence server and your worker is only responsible for scanning and replaying workflows."}),"\n",(0,t.jsxs)(o.p,{children:[(0,t.jsx)(o.a,{href:"https://github.com/cadence-workflow/cadence-go-client/blob/master/internal/common/metrics/constants.go#L105",children:"Replay succeed, skipped and failed metrics"})," will be emitted by your worker when executing the shadow workflow and you can monitor those metrics to see if there's any incompatible changes."]}),"\n",(0,t.jsxs)(o.p,{children:["To enable the shadow mode, the only change needed is setting the ",(0,t.jsx)(o.code,{children:"EnableShadowWorker"})," field in ",(0,t.jsx)(o.code,{children:"worker.Options"})," to ",(0,t.jsx)(o.code,{children:"true"}),", and then specify the ",(0,t.jsx)(o.code,{children:"ShadowOptions"}),"."]}),"\n",(0,t.jsxs)(o.p,{children:["Registered workflows will be forwarded to the underlying WorkflowReplayer. DataConverter, WorkflowInterceptorChainFactories, ContextPropagators, and Tracer specified in the ",(0,t.jsx)(o.code,{children:"worker.Options"})," will also be used as ReplayOptions. Since all shadow workflows are running in one system domain, to avoid conflict, ",(0,t.jsxs)(o.strong,{children:["the actual task list name used will be ",(0,t.jsx)(o.code,{children:"domain-tasklist"}),"."]})]}),"\n",(0,t.jsxs)(o.p,{children:["A sample setup can be found ",(0,t.jsx)(o.a,{href:"https://github.com/cadence-workflow/cadence-samples/blob/master/cmd/samples/recipes/helloworld/main.go#L24",children:"here"}),"."]})]})}function h(e={}){const{wrapper:o}={...(0,i.R)(),...e.components};return o?(0,t.jsx)(o,{...e,children:(0,t.jsx)(c,{...e})}):c(e)}},8453:(e,o,r)=>{r.d(o,{R:()=>l,x:()=>a});var n=r(6540);const t={},i=n.createContext(t);function l(e){const o=n.useContext(i);return n.useMemo((function(){return"function"==typeof e?e(o):{...o,...e}}),[o,e])}function a(e){let o;return o=e.disableParentContext?"function"==typeof e.components?e.components(t):e.components||t:l(e.components),n.createElement(i.Provider,{value:o},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/95d054c5.9d8d05cd.js b/assets/js/95d054c5.9d8d05cd.js deleted file mode 100644 index 8ff440800..000000000 --- a/assets/js/95d054c5.9d8d05cd.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[9586],{7969:(e,o,n)=>{n.r(o),n.d(o,{assets:()=>s,contentTitle:()=>l,default:()=>h,frontMatter:()=>a,metadata:()=>r,toc:()=>d});const r=JSON.parse('{"id":"java-client/workflow-replay-shadowing","title":"Workflow Replay and Shadowing","description":"In the Versioning section, we mentioned that incompatible changes to workflow definition code could cause non-deterministic issues when processing workflow tasks if versioning is not done correctly. However, it may be hard for you to tell if a particular change is incompatible or not and whether versioning logic is needed. To help you identify incompatible changes and catch them before production traffic is impacted, we implemented Workflow Replayer and Workflow Shadower.","source":"@site/docs/04-java-client/18-workflow-replay-shadowing.md","sourceDirName":"04-java-client","slug":"/java-client/workflow-replay-shadowing","permalink":"/docs/java-client/workflow-replay-shadowing","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/04-java-client/18-workflow-replay-shadowing.md","tags":[],"version":"current","sidebarPosition":18,"frontMatter":{"layout":"default","title":"Workflow Replay and Shadowing","permalink":"/docs/java-client/workflow-replay-shadowing"},"sidebar":"docsSidebar","previous":{"title":"Testing","permalink":"/docs/java-client/testing"},"next":{"title":"Introduction","permalink":"/docs/go-client/"}}');var i=n(4848),t=n(8453);const a={layout:"default",title:"Workflow Replay and Shadowing",permalink:"/docs/java-client/workflow-replay-shadowing"},l="Workflow Replay and Shadowing",s={},d=[{value:"Workflow Replayer",id:"workflow-replayer",level:2},{value:"Write a Replay Test",id:"write-a-replay-test",level:3},{value:"Step 1: Prepare workflow histories",id:"step-1-prepare-workflow-histories",level:4},{value:"Step 2: Call the replay method",id:"step-2-call-the-replay-method",level:4},{value:"Step 3: Catch returned exception",id:"step-3-catch-returned-exception",level:4},{value:"Sample Replay Test",id:"sample-replay-test",level:3},{value:"Workflow Shadower",id:"workflow-shadower",level:2},{value:"Shadow Options",id:"shadow-options",level:3},{value:"Scan Filters",id:"scan-filters",level:4},{value:"Shadow Exit Condition",id:"shadow-exit-condition",level:4},{value:"Shadow Mode",id:"shadow-mode",level:4},{value:"Shadow Concurrency",id:"shadow-concurrency",level:4},{value:"Local Shadowing Test",id:"local-shadowing-test",level:3},{value:"Shadowing Worker",id:"shadowing-worker",level:3}];function c(e){const o={a:"a",code:"code",h1:"h1",h2:"h2",h3:"h3",h4:"h4",header:"header",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,t.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(o.header,{children:(0,i.jsx)(o.h1,{id:"workflow-replay-and-shadowing",children:"Workflow Replay and Shadowing"})}),"\n",(0,i.jsx)(o.p,{children:"In the Versioning section, we mentioned that incompatible changes to workflow definition code could cause non-deterministic issues when processing workflow tasks if versioning is not done correctly. However, it may be hard for you to tell if a particular change is incompatible or not and whether versioning logic is needed. To help you identify incompatible changes and catch them before production traffic is impacted, we implemented Workflow Replayer and Workflow Shadower."}),"\n",(0,i.jsx)(o.h2,{id:"workflow-replayer",children:"Workflow Replayer"}),"\n",(0,i.jsx)(o.p,{children:"Workflow Replayer is a testing component for replaying existing workflow histories against a workflow definition. The replaying logic is the same as the one used for processing workflow tasks, so if there's any incompatible changes in the workflow definition, the replay test will fail."}),"\n",(0,i.jsx)(o.h3,{id:"write-a-replay-test",children:"Write a Replay Test"}),"\n",(0,i.jsx)(o.h4,{id:"step-1-prepare-workflow-histories",children:"Step 1: Prepare workflow histories"}),"\n",(0,i.jsx)(o.p,{children:"Replayer can read workflow history from a local json file or fetch it directly from the Cadence server. If you would like to use the first method, you can use the following CLI command, otherwise you can skip to the next step."}),"\n",(0,i.jsx)(o.pre,{children:(0,i.jsx)(o.code,{children:"cadence --do <domain> workflow show --wid <workflowID> --rid <runID> --of <output file name>\n"})}),"\n",(0,i.jsx)(o.p,{children:"The dumped workflow history will be stored in the file at the path you specified in json format."}),"\n",(0,i.jsx)(o.h4,{id:"step-2-call-the-replay-method",children:"Step 2: Call the replay method"}),"\n",(0,i.jsx)(o.p,{children:"Once you have the workflow history or have the connection to Cadence server for fetching history, call one of the four replay methods to start the replay test."}),"\n",(0,i.jsx)(o.pre,{children:(0,i.jsx)(o.code,{className:"language-java",children:'// if workflow history has been loaded into memory\nWorkflowReplayer.replayWorkflowExecution(history, MyWorkflowImpl.class);\n\n// if workflow history is stored in a json file\nWorkflowReplayer.replayWorkflowExecutionFromResource("workflowHistory.json", MyWorkflowImpl.class);\n\n// if workflow history is read from a File\nWorkflowReplayer.replayWorkflowExecution(historyFileObject, MyWorkflowImpl.class);\n'})}),"\n",(0,i.jsx)(o.h4,{id:"step-3-catch-returned-exception",children:"Step 3: Catch returned exception"}),"\n",(0,i.jsx)(o.p,{children:"If an exception is returned from the replay method, it means there's a incompatible change in the workflow definition and the error message will contain more information regarding where the non-deterministic error happens."}),"\n",(0,i.jsx)(o.h3,{id:"sample-replay-test",children:"Sample Replay Test"}),"\n",(0,i.jsxs)(o.p,{children:["This sample is also available in our samples repo at ",(0,i.jsx)(o.a,{href:"https://github.com/cadence-workflow/cadence-java-samples/blob/master/src/test/java/com/uber/cadence/samples/hello/HelloActivityReplayTest.java",children:"here"}),"."]}),"\n",(0,i.jsx)(o.pre,{children:(0,i.jsx)(o.code,{className:"language-java",children:'public class HelloActivityReplayTest {\n @Test\n public void testReplay() throws Exception {\n WorkflowReplayer.replayWorkflowExecutionFromResource(\n "HelloActivity.json", HelloActivity.GreetingWorkflowImpl.class);\n }\n}\n'})}),"\n",(0,i.jsx)(o.h2,{id:"workflow-shadower",children:"Workflow Shadower"}),"\n",(0,i.jsx)(o.p,{children:"Workflow Replayer works well when verifying the compatibility against a small number of workflows histories. If there are lots of workflows in production that need to be verified, dumping all histories manually clearly won't work. Directly fetching histories from cadence server might be a solution, but the time to replay all workflow histories might be too long for a test."}),"\n",(0,i.jsx)(o.p,{children:"Workflow Shadower is built on top of Workflow Replayer to address this problem. The basic idea of shadowing is: scan workflows based on the filters you defined, fetch history for each workflow in the scan result from Cadence server and run the replay test. It can be run either as a test to serve local development purpose or as a workflow in your worker to continuously replay production workflows."}),"\n",(0,i.jsx)(o.h3,{id:"shadow-options",children:"Shadow Options"}),"\n",(0,i.jsxs)(o.p,{children:["Complete documentation on shadow options which includes default values, accepted values, etc. can be found ",(0,i.jsx)(o.a,{href:"https://github.com/cadence-workflow/cadence-java-client/blob/master/src/main/java/com/uber/cadence/worker/ShadowingOptions.java",children:"here"}),". The following sections are just a brief description of each option."]}),"\n",(0,i.jsx)(o.h4,{id:"scan-filters",children:"Scan Filters"}),"\n",(0,i.jsxs)(o.ul,{children:["\n",(0,i.jsx)(o.li,{children:"WorkflowQuery: If you are familiar with our advanced visibility query syntax, you can specify a query directly. If specified, all other scan filters must be left empty."}),"\n",(0,i.jsx)(o.li,{children:"WorkflowTypes: A list of workflow Type names."}),"\n",(0,i.jsx)(o.li,{children:"WorkflowStatuses: A list of workflow status."}),"\n",(0,i.jsx)(o.li,{children:"WorkflowStartTimeFilter: Min and max timestamp for workflow start time."}),"\n",(0,i.jsx)(o.li,{children:"WorkflowSamplingRate: Sampling workflows from the scan result before executing the replay test."}),"\n"]}),"\n",(0,i.jsx)(o.h4,{id:"shadow-exit-condition",children:"Shadow Exit Condition"}),"\n",(0,i.jsxs)(o.ul,{children:["\n",(0,i.jsx)(o.li,{children:"ExpirationInterval: Shadowing will exit when the specified interval has passed."}),"\n",(0,i.jsx)(o.li,{children:"ShadowCount: Shadowing will exit after this number of workflow has been replayed. Note: replay maybe skipped due to errors like can't fetch history, history too short, etc. Skipped workflows won't be taken into account for ShadowCount."}),"\n"]}),"\n",(0,i.jsx)(o.h4,{id:"shadow-mode",children:"Shadow Mode"}),"\n",(0,i.jsxs)(o.ul,{children:["\n",(0,i.jsx)(o.li,{children:"Normal: Shadowing will complete after all workflows matches WorkflowQuery (after sampling) have been replayed or when exit condition is met."}),"\n",(0,i.jsx)(o.li,{children:"Continuous: A new round of shadowing will be started after all workflows matches WorkflowQuery have been replayed. There will be a 5 min wait period between each round, and currently this wait period is not configurable. Shadowing will complete only when ExitCondition is met. ExitCondition must be specified when using this mode."}),"\n"]}),"\n",(0,i.jsx)(o.h4,{id:"shadow-concurrency",children:"Shadow Concurrency"}),"\n",(0,i.jsxs)(o.ul,{children:["\n",(0,i.jsx)(o.li,{children:"Concurrency: workflow replay concurrency. If not specified, it will default to 1. For local shadowing, an error will be returned if a value higher than 1 is specified."}),"\n"]}),"\n",(0,i.jsx)(o.h3,{id:"local-shadowing-test",children:"Local Shadowing Test"}),"\n",(0,i.jsxs)(o.p,{children:["Local shadowing test is similar to the replay test. First create a workflow shadower with optional shadow and replay options, then register the workflow that needs to be shadowed. Finally, call the ",(0,i.jsx)(o.code,{children:"Run"})," method to start the shadowing. The method will return if shadowing has finished or any non-deterministic error is found."]}),"\n",(0,i.jsxs)(o.p,{children:["Here's a simple example. The example is also available ",(0,i.jsx)(o.a,{href:"https://github.com/cadence-workflow/cadence-java-samples/blob/master/src/test/java/com/uber/cadence/samples/hello/HelloWorkflowShadowingTest.java",children:"here"}),"."]}),"\n",(0,i.jsx)(o.pre,{children:(0,i.jsx)(o.code,{className:"language-java",children:'public void testShadowing() throws Throwable {\n IWorkflowService service = new WorkflowServiceTChannel(ClientOptions.defaultInstance());\n\n ShadowingOptions options = ShadowingOptions\n .newBuilder()\n .setDomain(DOMAIN)\n .setShadowMode(Mode.Normal)\n .setWorkflowTypes(Lists.newArrayList("GreetingWorkflow::getGreeting"))\n .setWorkflowStatuses(Lists.newArrayList(WorkflowStatus.OPEN, WorkflowStatus.CLOSED))\n .setExitCondition(new ExitCondition().setExpirationIntervalInSeconds(60))\n .build();\n WorkflowShadower shadower = new WorkflowShadower(service, options, TASK_LIST);\n shadower.registerWorkflowImplementationTypes(HelloActivity.GreetingWorkflowImpl.class);\n\n shadower.run();\n}\n'})}),"\n",(0,i.jsx)(o.h3,{id:"shadowing-worker",children:"Shadowing Worker"}),"\n",(0,i.jsx)(o.p,{children:"NOTE:"}),"\n",(0,i.jsxs)(o.ul,{children:["\n",(0,i.jsx)(o.li,{children:(0,i.jsx)(o.strong,{children:"All shadow workflows are running in one Cadence system domain, and right now, every user domain can only have one shadow workflow at a time."})}),"\n",(0,i.jsxs)(o.li,{children:[(0,i.jsx)(o.strong,{children:"The Cadence server used for scanning and getting workflow history will also be the Cadence server for running your shadow workflow."})," Currently, there's no way to specify different Cadence servers for hosting the shadowing workflow and scanning/fetching workflow."]}),"\n"]}),"\n",(0,i.jsx)(o.p,{children:"Your worker can also be configured to run in shadow mode to run shadow tests as a workflow. This is useful if there's a number of workflows that need to be replayed. Using a workflow can make sure the shadowing won't accidentally fail in the middle and the replay load can be distributed by deploying more shadow mode workers. It can also be incorporated into your deployment process to make sure there's no failed replay checks before deploying your change to production workers."}),"\n",(0,i.jsx)(o.p,{children:"When running in shadow mode, the normal decision worker will be disabled so that it won't update any production workflows. A special shadow activity worker will be started to execute activities for scanning and replaying workflows. The actual shadow workflow logic is controlled by Cadence server and your worker is only responsible for scanning and replaying workflows."}),"\n",(0,i.jsxs)(o.p,{children:[(0,i.jsx)(o.a,{href:"https://github.com/cadence-workflow/cadence-java-client/blob/master/src/main/java/com/uber/cadence/internal/metrics/MetricsType.java#L169-L172",children:"Replay succeed, skipped and failed metrics"})," will be emitted by your worker when executing the shadow workflow and you can monitor those metrics to see if there's any incompatible changes."]}),"\n",(0,i.jsx)(o.p,{children:"To enable the shadow mode, you can initialize a shadowing worker and pass in the shadowing options."}),"\n",(0,i.jsxs)(o.p,{children:["To enable the shadowing worker, here is a example. The example is also available ",(0,i.jsx)(o.a,{href:"https://github.com/cadence-workflow/cadence-java-samples/blob/master/src/main/java/com/uber/cadence/samples/shadowing/ShadowTraffic.java",children:"here"}),":"]}),"\n",(0,i.jsx)(o.pre,{children:(0,i.jsx)(o.code,{className:"language-java",children:'WorkflowClient workflowClient =\n WorkflowClient.newInstance(\n new WorkflowServiceTChannel(ClientOptions.defaultInstance()),\n WorkflowClientOptions.newBuilder().setDomain(DOMAIN).build());\n ShadowingOptions options = ShadowingOptions\n .newBuilder()\n .setDomain(DOMAIN)\n .setShadowMode(Mode.Normal)\n .setWorkflowTypes(Lists.newArrayList("GreetingWorkflow::getGreeting"))\n .setWorkflowStatuses(Lists.newArrayList(WorkflowStatus.OPEN, WorkflowStatus.CLOSED))\n .setExitCondition(new ExitCondition().setExpirationIntervalInSeconds(60))\n .build();\n\n ShadowingWorker shadowingWorker = new ShadowingWorker(\n workflowClient,\n "HelloActivity",\n WorkerOptions.defaultInstance(),\n options);\n shadowingWorker.registerWorkflowImplementationTypes(HelloActivity.GreetingWorkflowImpl.class);\n\tshadowingWorker.start();\n'})}),"\n",(0,i.jsxs)(o.p,{children:["Registered workflows will be forwarded to the underlying WorkflowReplayer. DataConverter, WorkflowInterceptorChainFactories, ContextPropagators, and Tracer specified in the ",(0,i.jsx)(o.code,{children:"worker.Options"})," will also be used as ReplayOptions. Since all shadow workflows are running in one system domain, to avoid conflict, ",(0,i.jsxs)(o.strong,{children:["the actual task list name used will be ",(0,i.jsx)(o.code,{children:"domain-tasklist"}),"."]})]})]})}function h(e={}){const{wrapper:o}={...(0,t.R)(),...e.components};return o?(0,i.jsx)(o,{...e,children:(0,i.jsx)(c,{...e})}):c(e)}},8453:(e,o,n)=>{n.d(o,{R:()=>a,x:()=>l});var r=n(6540);const i={},t=r.createContext(i);function a(e){const o=r.useContext(t);return r.useMemo((function(){return"function"==typeof e?e(o):{...o,...e}}),[o,e])}function l(e){let o;return o=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:a(e.components),r.createElement(t.Provider,{value:o},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/95d054c5.bf0bd990.js b/assets/js/95d054c5.bf0bd990.js new file mode 100644 index 000000000..8b20c945a --- /dev/null +++ b/assets/js/95d054c5.bf0bd990.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[9586],{7969:(e,o,n)=>{n.r(o),n.d(o,{assets:()=>s,contentTitle:()=>l,default:()=>h,frontMatter:()=>a,metadata:()=>r,toc:()=>d});const r=JSON.parse('{"id":"java-client/workflow-replay-shadowing","title":"Workflow Replay and Shadowing","description":"In the Versioning section, we mentioned that incompatible changes to workflow definition code could cause non-deterministic issues when processing workflow tasks if versioning is not done correctly. However, it may be hard for you to tell if a particular change is incompatible or not and whether versioning logic is needed. To help you identify incompatible changes and catch them before production traffic is impacted, we implemented Workflow Replayer and Workflow Shadower.","source":"@site/docs/04-java-client/18-workflow-replay-shadowing.md","sourceDirName":"04-java-client","slug":"/java-client/workflow-replay-shadowing","permalink":"/Cadence-Docs/docs/java-client/workflow-replay-shadowing","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/04-java-client/18-workflow-replay-shadowing.md","tags":[],"version":"current","sidebarPosition":18,"frontMatter":{"layout":"default","title":"Workflow Replay and Shadowing","permalink":"/docs/java-client/workflow-replay-shadowing"},"sidebar":"docsSidebar","previous":{"title":"Testing","permalink":"/Cadence-Docs/docs/java-client/testing"},"next":{"title":"Introduction","permalink":"/Cadence-Docs/docs/go-client/"}}');var i=n(4848),t=n(8453);const a={layout:"default",title:"Workflow Replay and Shadowing",permalink:"/docs/java-client/workflow-replay-shadowing"},l="Workflow Replay and Shadowing",s={},d=[{value:"Workflow Replayer",id:"workflow-replayer",level:2},{value:"Write a Replay Test",id:"write-a-replay-test",level:3},{value:"Step 1: Prepare workflow histories",id:"step-1-prepare-workflow-histories",level:4},{value:"Step 2: Call the replay method",id:"step-2-call-the-replay-method",level:4},{value:"Step 3: Catch returned exception",id:"step-3-catch-returned-exception",level:4},{value:"Sample Replay Test",id:"sample-replay-test",level:3},{value:"Workflow Shadower",id:"workflow-shadower",level:2},{value:"Shadow Options",id:"shadow-options",level:3},{value:"Scan Filters",id:"scan-filters",level:4},{value:"Shadow Exit Condition",id:"shadow-exit-condition",level:4},{value:"Shadow Mode",id:"shadow-mode",level:4},{value:"Shadow Concurrency",id:"shadow-concurrency",level:4},{value:"Local Shadowing Test",id:"local-shadowing-test",level:3},{value:"Shadowing Worker",id:"shadowing-worker",level:3}];function c(e){const o={a:"a",code:"code",h1:"h1",h2:"h2",h3:"h3",h4:"h4",header:"header",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,t.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(o.header,{children:(0,i.jsx)(o.h1,{id:"workflow-replay-and-shadowing",children:"Workflow Replay and Shadowing"})}),"\n",(0,i.jsx)(o.p,{children:"In the Versioning section, we mentioned that incompatible changes to workflow definition code could cause non-deterministic issues when processing workflow tasks if versioning is not done correctly. However, it may be hard for you to tell if a particular change is incompatible or not and whether versioning logic is needed. To help you identify incompatible changes and catch them before production traffic is impacted, we implemented Workflow Replayer and Workflow Shadower."}),"\n",(0,i.jsx)(o.h2,{id:"workflow-replayer",children:"Workflow Replayer"}),"\n",(0,i.jsx)(o.p,{children:"Workflow Replayer is a testing component for replaying existing workflow histories against a workflow definition. The replaying logic is the same as the one used for processing workflow tasks, so if there's any incompatible changes in the workflow definition, the replay test will fail."}),"\n",(0,i.jsx)(o.h3,{id:"write-a-replay-test",children:"Write a Replay Test"}),"\n",(0,i.jsx)(o.h4,{id:"step-1-prepare-workflow-histories",children:"Step 1: Prepare workflow histories"}),"\n",(0,i.jsx)(o.p,{children:"Replayer can read workflow history from a local json file or fetch it directly from the Cadence server. If you would like to use the first method, you can use the following CLI command, otherwise you can skip to the next step."}),"\n",(0,i.jsx)(o.pre,{children:(0,i.jsx)(o.code,{children:"cadence --do <domain> workflow show --wid <workflowID> --rid <runID> --of <output file name>\n"})}),"\n",(0,i.jsx)(o.p,{children:"The dumped workflow history will be stored in the file at the path you specified in json format."}),"\n",(0,i.jsx)(o.h4,{id:"step-2-call-the-replay-method",children:"Step 2: Call the replay method"}),"\n",(0,i.jsx)(o.p,{children:"Once you have the workflow history or have the connection to Cadence server for fetching history, call one of the four replay methods to start the replay test."}),"\n",(0,i.jsx)(o.pre,{children:(0,i.jsx)(o.code,{className:"language-java",children:'// if workflow history has been loaded into memory\nWorkflowReplayer.replayWorkflowExecution(history, MyWorkflowImpl.class);\n\n// if workflow history is stored in a json file\nWorkflowReplayer.replayWorkflowExecutionFromResource("workflowHistory.json", MyWorkflowImpl.class);\n\n// if workflow history is read from a File\nWorkflowReplayer.replayWorkflowExecution(historyFileObject, MyWorkflowImpl.class);\n'})}),"\n",(0,i.jsx)(o.h4,{id:"step-3-catch-returned-exception",children:"Step 3: Catch returned exception"}),"\n",(0,i.jsx)(o.p,{children:"If an exception is returned from the replay method, it means there's a incompatible change in the workflow definition and the error message will contain more information regarding where the non-deterministic error happens."}),"\n",(0,i.jsx)(o.h3,{id:"sample-replay-test",children:"Sample Replay Test"}),"\n",(0,i.jsxs)(o.p,{children:["This sample is also available in our samples repo at ",(0,i.jsx)(o.a,{href:"https://github.com/cadence-workflow/cadence-java-samples/blob/master/src/test/java/com/uber/cadence/samples/hello/HelloActivityReplayTest.java",children:"here"}),"."]}),"\n",(0,i.jsx)(o.pre,{children:(0,i.jsx)(o.code,{className:"language-java",children:'public class HelloActivityReplayTest {\n @Test\n public void testReplay() throws Exception {\n WorkflowReplayer.replayWorkflowExecutionFromResource(\n "HelloActivity.json", HelloActivity.GreetingWorkflowImpl.class);\n }\n}\n'})}),"\n",(0,i.jsx)(o.h2,{id:"workflow-shadower",children:"Workflow Shadower"}),"\n",(0,i.jsx)(o.p,{children:"Workflow Replayer works well when verifying the compatibility against a small number of workflows histories. If there are lots of workflows in production that need to be verified, dumping all histories manually clearly won't work. Directly fetching histories from cadence server might be a solution, but the time to replay all workflow histories might be too long for a test."}),"\n",(0,i.jsx)(o.p,{children:"Workflow Shadower is built on top of Workflow Replayer to address this problem. The basic idea of shadowing is: scan workflows based on the filters you defined, fetch history for each workflow in the scan result from Cadence server and run the replay test. It can be run either as a test to serve local development purpose or as a workflow in your worker to continuously replay production workflows."}),"\n",(0,i.jsx)(o.h3,{id:"shadow-options",children:"Shadow Options"}),"\n",(0,i.jsxs)(o.p,{children:["Complete documentation on shadow options which includes default values, accepted values, etc. can be found ",(0,i.jsx)(o.a,{href:"https://github.com/cadence-workflow/cadence-java-client/blob/master/src/main/java/com/uber/cadence/worker/ShadowingOptions.java",children:"here"}),". The following sections are just a brief description of each option."]}),"\n",(0,i.jsx)(o.h4,{id:"scan-filters",children:"Scan Filters"}),"\n",(0,i.jsxs)(o.ul,{children:["\n",(0,i.jsx)(o.li,{children:"WorkflowQuery: If you are familiar with our advanced visibility query syntax, you can specify a query directly. If specified, all other scan filters must be left empty."}),"\n",(0,i.jsx)(o.li,{children:"WorkflowTypes: A list of workflow Type names."}),"\n",(0,i.jsx)(o.li,{children:"WorkflowStatuses: A list of workflow status."}),"\n",(0,i.jsx)(o.li,{children:"WorkflowStartTimeFilter: Min and max timestamp for workflow start time."}),"\n",(0,i.jsx)(o.li,{children:"WorkflowSamplingRate: Sampling workflows from the scan result before executing the replay test."}),"\n"]}),"\n",(0,i.jsx)(o.h4,{id:"shadow-exit-condition",children:"Shadow Exit Condition"}),"\n",(0,i.jsxs)(o.ul,{children:["\n",(0,i.jsx)(o.li,{children:"ExpirationInterval: Shadowing will exit when the specified interval has passed."}),"\n",(0,i.jsx)(o.li,{children:"ShadowCount: Shadowing will exit after this number of workflow has been replayed. Note: replay maybe skipped due to errors like can't fetch history, history too short, etc. Skipped workflows won't be taken into account for ShadowCount."}),"\n"]}),"\n",(0,i.jsx)(o.h4,{id:"shadow-mode",children:"Shadow Mode"}),"\n",(0,i.jsxs)(o.ul,{children:["\n",(0,i.jsx)(o.li,{children:"Normal: Shadowing will complete after all workflows matches WorkflowQuery (after sampling) have been replayed or when exit condition is met."}),"\n",(0,i.jsx)(o.li,{children:"Continuous: A new round of shadowing will be started after all workflows matches WorkflowQuery have been replayed. There will be a 5 min wait period between each round, and currently this wait period is not configurable. Shadowing will complete only when ExitCondition is met. ExitCondition must be specified when using this mode."}),"\n"]}),"\n",(0,i.jsx)(o.h4,{id:"shadow-concurrency",children:"Shadow Concurrency"}),"\n",(0,i.jsxs)(o.ul,{children:["\n",(0,i.jsx)(o.li,{children:"Concurrency: workflow replay concurrency. If not specified, it will default to 1. For local shadowing, an error will be returned if a value higher than 1 is specified."}),"\n"]}),"\n",(0,i.jsx)(o.h3,{id:"local-shadowing-test",children:"Local Shadowing Test"}),"\n",(0,i.jsxs)(o.p,{children:["Local shadowing test is similar to the replay test. First create a workflow shadower with optional shadow and replay options, then register the workflow that needs to be shadowed. Finally, call the ",(0,i.jsx)(o.code,{children:"Run"})," method to start the shadowing. The method will return if shadowing has finished or any non-deterministic error is found."]}),"\n",(0,i.jsxs)(o.p,{children:["Here's a simple example. The example is also available ",(0,i.jsx)(o.a,{href:"https://github.com/cadence-workflow/cadence-java-samples/blob/master/src/test/java/com/uber/cadence/samples/hello/HelloWorkflowShadowingTest.java",children:"here"}),"."]}),"\n",(0,i.jsx)(o.pre,{children:(0,i.jsx)(o.code,{className:"language-java",children:'public void testShadowing() throws Throwable {\n IWorkflowService service = new WorkflowServiceTChannel(ClientOptions.defaultInstance());\n\n ShadowingOptions options = ShadowingOptions\n .newBuilder()\n .setDomain(DOMAIN)\n .setShadowMode(Mode.Normal)\n .setWorkflowTypes(Lists.newArrayList("GreetingWorkflow::getGreeting"))\n .setWorkflowStatuses(Lists.newArrayList(WorkflowStatus.OPEN, WorkflowStatus.CLOSED))\n .setExitCondition(new ExitCondition().setExpirationIntervalInSeconds(60))\n .build();\n WorkflowShadower shadower = new WorkflowShadower(service, options, TASK_LIST);\n shadower.registerWorkflowImplementationTypes(HelloActivity.GreetingWorkflowImpl.class);\n\n shadower.run();\n}\n'})}),"\n",(0,i.jsx)(o.h3,{id:"shadowing-worker",children:"Shadowing Worker"}),"\n",(0,i.jsx)(o.p,{children:"NOTE:"}),"\n",(0,i.jsxs)(o.ul,{children:["\n",(0,i.jsx)(o.li,{children:(0,i.jsx)(o.strong,{children:"All shadow workflows are running in one Cadence system domain, and right now, every user domain can only have one shadow workflow at a time."})}),"\n",(0,i.jsxs)(o.li,{children:[(0,i.jsx)(o.strong,{children:"The Cadence server used for scanning and getting workflow history will also be the Cadence server for running your shadow workflow."})," Currently, there's no way to specify different Cadence servers for hosting the shadowing workflow and scanning/fetching workflow."]}),"\n"]}),"\n",(0,i.jsx)(o.p,{children:"Your worker can also be configured to run in shadow mode to run shadow tests as a workflow. This is useful if there's a number of workflows that need to be replayed. Using a workflow can make sure the shadowing won't accidentally fail in the middle and the replay load can be distributed by deploying more shadow mode workers. It can also be incorporated into your deployment process to make sure there's no failed replay checks before deploying your change to production workers."}),"\n",(0,i.jsx)(o.p,{children:"When running in shadow mode, the normal decision worker will be disabled so that it won't update any production workflows. A special shadow activity worker will be started to execute activities for scanning and replaying workflows. The actual shadow workflow logic is controlled by Cadence server and your worker is only responsible for scanning and replaying workflows."}),"\n",(0,i.jsxs)(o.p,{children:[(0,i.jsx)(o.a,{href:"https://github.com/cadence-workflow/cadence-java-client/blob/master/src/main/java/com/uber/cadence/internal/metrics/MetricsType.java#L169-L172",children:"Replay succeed, skipped and failed metrics"})," will be emitted by your worker when executing the shadow workflow and you can monitor those metrics to see if there's any incompatible changes."]}),"\n",(0,i.jsx)(o.p,{children:"To enable the shadow mode, you can initialize a shadowing worker and pass in the shadowing options."}),"\n",(0,i.jsxs)(o.p,{children:["To enable the shadowing worker, here is a example. The example is also available ",(0,i.jsx)(o.a,{href:"https://github.com/cadence-workflow/cadence-java-samples/blob/master/src/main/java/com/uber/cadence/samples/shadowing/ShadowTraffic.java",children:"here"}),":"]}),"\n",(0,i.jsx)(o.pre,{children:(0,i.jsx)(o.code,{className:"language-java",children:'WorkflowClient workflowClient =\n WorkflowClient.newInstance(\n new WorkflowServiceTChannel(ClientOptions.defaultInstance()),\n WorkflowClientOptions.newBuilder().setDomain(DOMAIN).build());\n ShadowingOptions options = ShadowingOptions\n .newBuilder()\n .setDomain(DOMAIN)\n .setShadowMode(Mode.Normal)\n .setWorkflowTypes(Lists.newArrayList("GreetingWorkflow::getGreeting"))\n .setWorkflowStatuses(Lists.newArrayList(WorkflowStatus.OPEN, WorkflowStatus.CLOSED))\n .setExitCondition(new ExitCondition().setExpirationIntervalInSeconds(60))\n .build();\n\n ShadowingWorker shadowingWorker = new ShadowingWorker(\n workflowClient,\n "HelloActivity",\n WorkerOptions.defaultInstance(),\n options);\n shadowingWorker.registerWorkflowImplementationTypes(HelloActivity.GreetingWorkflowImpl.class);\n\tshadowingWorker.start();\n'})}),"\n",(0,i.jsxs)(o.p,{children:["Registered workflows will be forwarded to the underlying WorkflowReplayer. DataConverter, WorkflowInterceptorChainFactories, ContextPropagators, and Tracer specified in the ",(0,i.jsx)(o.code,{children:"worker.Options"})," will also be used as ReplayOptions. Since all shadow workflows are running in one system domain, to avoid conflict, ",(0,i.jsxs)(o.strong,{children:["the actual task list name used will be ",(0,i.jsx)(o.code,{children:"domain-tasklist"}),"."]})]})]})}function h(e={}){const{wrapper:o}={...(0,t.R)(),...e.components};return o?(0,i.jsx)(o,{...e,children:(0,i.jsx)(c,{...e})}):c(e)}},8453:(e,o,n)=>{n.d(o,{R:()=>a,x:()=>l});var r=n(6540);const i={},t=r.createContext(i);function a(e){const o=r.useContext(t);return r.useMemo((function(){return"function"==typeof e?e(o):{...o,...e}}),[o,e])}function l(e){let o;return o=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:a(e.components),r.createElement(t.Provider,{value:o},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/965c09ae.812cb177.js b/assets/js/965c09ae.812cb177.js new file mode 100644 index 000000000..1fc0dd9aa --- /dev/null +++ b/assets/js/965c09ae.812cb177.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[2469],{9382:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>c,contentTitle:()=>r,default:()=>d,frontMatter:()=>s,metadata:()=>o,toc:()=>l});var o=n(5550),a=n(4848),i=n(8453);const s={title:"Cadence Community Spotlight Update - August 2023",date:new Date("2023-08-31T00:00:00.000Z"),authors:"sharanf",tags:["introduction-to-cadence","community-spotlight"]},r=void 0,c={authorsImageUrls:[void 0]},l=[{value:"More Cadence How To's",id:"more-cadence-how-tos",level:2}];function h(e){const t={a:"a",h2:"h2",li:"li",p:"p",ul:"ul",...(0,i.R)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(t.p,{children:"Welcome to the latest of our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!"}),"\n",(0,a.jsx)(t.p,{children:"Please see below for a roundup of the highlights:"}),"\n",(0,a.jsx)(t.h2,{id:"more-cadence-how-tos",children:"More Cadence How To's"}),"\n",(0,a.jsxs)(t.p,{children:["You might have noticed that we have had a few more contributions to our blog from ",(0,a.jsx)(t.a,{href:"https://www.linkedin.com/in/chrisqin0610",children:"Chris Qin"}),". Chris has been busy sharing insights, and tips on a few important Cadence topics. The objective is to help the community with any potential problems."]}),"\n",(0,a.jsx)(t.p,{children:"Here are the latest topics:"}),"\n",(0,a.jsxs)(t.ul,{children:["\n",(0,a.jsxs)(t.li,{children:["\n",(0,a.jsx)(t.p,{children:(0,a.jsx)(t.a,{href:"https://cadenceworkflow.io/blog/2023/07/10/cadence-bad-practices-part-1/",children:"Bad Practices and Anti-Patterns with Cadence - Part 1"})}),"\n"]}),"\n",(0,a.jsxs)(t.li,{children:["\n",(0,a.jsx)(t.p,{children:(0,a.jsx)(t.a,{href:"https://cadenceworkflow.io/blog/2023/08/27/nondeterministic-errors-replayers-shadowers/",children:"Non-Determistic Errors, Replayers and Shadowers"})}),"\n"]}),"\n"]}),"\n",(0,a.jsx)(t.p,{children:"Even if you have not encountered these use cases - it is good to be prepared and have a solution ready.Please take a look and let us have your feedback."}),"\n",(0,a.jsxs)(t.p,{children:["Chris is also going to take a look at the ",(0,a.jsx)(t.a,{href:"https://cadenceworkflow.io/docs/java-client/client-overview/#samples",children:"Cadence Samples"})," to make sure they are all working and if not - he's going to re-write them so that they do!"]}),"\n",(0,a.jsx)(t.p,{children:"Thanks very much Chris for all the work you are doing to help improve the project!"})]})}function d(e={}){const{wrapper:t}={...(0,i.R)(),...e.components};return t?(0,a.jsx)(t,{...e,children:(0,a.jsx)(h,{...e})}):h(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>s,x:()=>r});var o=n(6540);const a={},i=o.createContext(a);function s(e){const t=o.useContext(i);return o.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function r(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:s(e.components),o.createElement(i.Provider,{value:t},e.children)}},5550:e=>{e.exports=JSON.parse('{"permalink":"/Cadence-Docs/blog/2023/08/31/community-spotlight-august-2023","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2023-08-31-community-spotlight-august-2023.md","source":"@site/blog/2023-08-31-community-spotlight-august-2023.md","title":"Cadence Community Spotlight Update - August 2023","description":"Welcome to the latest of our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!","date":"2023-08-31T00:00:00.000Z","tags":[{"inline":false,"label":"Introduction to Cadence","permalink":"/Cadence-Docs/blog/tags/introduction-to-cadence","description":"Introduction to Cadence tag description"},{"inline":false,"label":"Community Spotlight","permalink":"/Cadence-Docs/blog/tags/community-spotlights","description":"Community Spotlight tag description"}],"readingTime":2.955,"hasTruncateMarker":true,"authors":[{"name":"Sharan Foga","title":"Director of Operations & Customer Success @ Encube Technologies","url":"https://www.linkedin.com/in/sfoga/","page":{"permalink":"/Cadence-Docs/blog/authors/sharanf"},"socials":{"linkedin":"https://www.linkedin.com/in/sfoga/","github":"https://github.com/sharanf"},"imageURL":"https://github.com/sharanf.png","key":"sharanf"}],"frontMatter":{"title":"Cadence Community Spotlight Update - August 2023","date":"2023-08-31T00:00:00.000Z","authors":"sharanf","tags":["introduction-to-cadence","community-spotlight"]},"unlisted":false,"prevItem":{"title":"Cadence Community Spotlight Update - November 2023","permalink":"/Cadence-Docs/blog/2023/11/30/community-spotlight-update-november-2023"},"nextItem":{"title":"Non-deterministic errors, replayers and shadowers","permalink":"/Cadence-Docs/blog/2023/08/28/nondeterministic-errors-replayers-shadowers"}}')}}]); \ No newline at end of file diff --git a/assets/js/965c09ae.fcd4d823.js b/assets/js/965c09ae.fcd4d823.js deleted file mode 100644 index fce25d365..000000000 --- a/assets/js/965c09ae.fcd4d823.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[2469],{9382:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>c,contentTitle:()=>r,default:()=>d,frontMatter:()=>s,metadata:()=>o,toc:()=>l});var o=n(5550),i=n(4848),a=n(8453);const s={title:"Cadence Community Spotlight Update - August 2023",date:new Date("2023-08-31T00:00:00.000Z"),authors:"sharanf",tags:["introduction-to-cadence","community-spotlight"]},r=void 0,c={authorsImageUrls:[void 0]},l=[{value:"More Cadence How To's",id:"more-cadence-how-tos",level:2}];function h(e){const t={a:"a",h2:"h2",li:"li",p:"p",ul:"ul",...(0,a.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(t.p,{children:"Welcome to the latest of our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!"}),"\n",(0,i.jsx)(t.p,{children:"Please see below for a roundup of the highlights:"}),"\n",(0,i.jsx)(t.h2,{id:"more-cadence-how-tos",children:"More Cadence How To's"}),"\n",(0,i.jsxs)(t.p,{children:["You might have noticed that we have had a few more contributions to our blog from ",(0,i.jsx)(t.a,{href:"https://www.linkedin.com/in/chrisqin0610",children:"Chris Qin"}),". Chris has been busy sharing insights, and tips on a few important Cadence topics. The objective is to help the community with any potential problems."]}),"\n",(0,i.jsx)(t.p,{children:"Here are the latest topics:"}),"\n",(0,i.jsxs)(t.ul,{children:["\n",(0,i.jsxs)(t.li,{children:["\n",(0,i.jsx)(t.p,{children:(0,i.jsx)(t.a,{href:"https://cadenceworkflow.io/blog/2023/07/10/cadence-bad-practices-part-1/",children:"Bad Practices and Anti-Patterns with Cadence - Part 1"})}),"\n"]}),"\n",(0,i.jsxs)(t.li,{children:["\n",(0,i.jsx)(t.p,{children:(0,i.jsx)(t.a,{href:"https://cadenceworkflow.io/blog/2023/08/27/nondeterministic-errors-replayers-shadowers/",children:"Non-Determistic Errors, Replayers and Shadowers"})}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(t.p,{children:"Even if you have not encountered these use cases - it is good to be prepared and have a solution ready.Please take a look and let us have your feedback."}),"\n",(0,i.jsxs)(t.p,{children:["Chris is also going to take a look at the ",(0,i.jsx)(t.a,{href:"https://cadenceworkflow.io/docs/java-client/client-overview/#samples",children:"Cadence Samples"})," to make sure they are all working and if not - he's going to re-write them so that they do!"]}),"\n",(0,i.jsx)(t.p,{children:"Thanks very much Chris for all the work you are doing to help improve the project!"})]})}function d(e={}){const{wrapper:t}={...(0,a.R)(),...e.components};return t?(0,i.jsx)(t,{...e,children:(0,i.jsx)(h,{...e})}):h(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>s,x:()=>r});var o=n(6540);const i={},a=o.createContext(i);function s(e){const t=o.useContext(a);return o.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function r(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:s(e.components),o.createElement(a.Provider,{value:t},e.children)}},5550:e=>{e.exports=JSON.parse('{"permalink":"/blog/2023/08/31/community-spotlight-august-2023","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2023-08-31-community-spotlight-august-2023.md","source":"@site/blog/2023-08-31-community-spotlight-august-2023.md","title":"Cadence Community Spotlight Update - August 2023","description":"Welcome to the latest of our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!","date":"2023-08-31T00:00:00.000Z","tags":[{"inline":false,"label":"Introduction to Cadence","permalink":"/blog/tags/introduction-to-cadence","description":"Introduction to Cadence tag description"},{"inline":false,"label":"Community Spotlight","permalink":"/blog/tags/community-spotlights","description":"Community Spotlight tag description"}],"readingTime":2.955,"hasTruncateMarker":true,"authors":[{"name":"Sharan Foga","title":"Director of Operations & Customer Success @ Encube Technologies","url":"https://www.linkedin.com/in/sfoga/","page":{"permalink":"/blog/authors/sharanf"},"socials":{"linkedin":"https://www.linkedin.com/in/sfoga/","github":"https://github.com/sharanf"},"imageURL":"https://github.com/sharanf.png","key":"sharanf"}],"frontMatter":{"title":"Cadence Community Spotlight Update - August 2023","date":"2023-08-31T00:00:00.000Z","authors":"sharanf","tags":["introduction-to-cadence","community-spotlight"]},"unlisted":false,"prevItem":{"title":"Cadence Community Spotlight Update - November 2023","permalink":"/blog/2023/11/30/community-spotlight-update-november-2023"},"nextItem":{"title":"Non-deterministic errors, replayers and shadowers","permalink":"/blog/2023/08/28/nondeterministic-errors-replayers-shadowers"}}')}}]); \ No newline at end of file diff --git a/assets/js/9674d0ef.3364f8cb.js b/assets/js/9674d0ef.3364f8cb.js new file mode 100644 index 000000000..a755edf9d --- /dev/null +++ b/assets/js/9674d0ef.3364f8cb.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[1010],{6705:(e,n,o)=>{o.r(n),o.d(n,{assets:()=>l,contentTitle:()=>s,default:()=>u,frontMatter:()=>t,metadata:()=>a,toc:()=>c});const a=JSON.parse('{"id":"concepts/cross-dc-replication","title":"Cross DC replication","description":"The Cadence GlobalDomainworkflow_execution: from another","source":"@site/docs/03-concepts/08-cross-dc-replication.md","sourceDirName":"03-concepts","slug":"/concepts/cross-dc-replication","permalink":"/Cadence-Docs/docs/concepts/cross-dc-replication","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/03-concepts/08-cross-dc-replication.md","tags":[],"version":"current","sidebarPosition":8,"frontMatter":{"layout":"default","title":"Cross DC replication","permalink":"/docs/concepts/cross-dc-replication"},"sidebar":"docsSidebar","previous":{"title":"Archival","permalink":"/Cadence-Docs/docs/concepts/archival"},"next":{"title":"Search workflows(Advanced visibility)","permalink":"/Cadence-Docs/docs/concepts/search-workflows"}}');var i=o(4848),r=o(8453);const t={layout:"default",title:"Cross DC replication",permalink:"/docs/concepts/cross-dc-replication"},s="Cross-DC replication",l={},c=[{value:"Global Domains Architecture",id:"global-domains-architecture",level:2},{value:"Conflict Resolution",id:"conflict-resolution",level:3},{value:"Global Domain Concepts, Configuration and Operation",id:"global-domain-concepts-configuration-and-operation",level:2},{value:"Concepts",id:"concepts",level:3},{value:"IsGlobal",id:"isglobal",level:4},{value:"Clusters",id:"clusters",level:4},{value:"Active Cluster Name",id:"active-cluster-name",level:4},{value:"Failover Version",id:"failover-version",level:4},{value:"Operate by CLI",id:"operate-by-cli",level:3},{value:"Describe Global Domain",id:"describe-global-domain",level:4},{value:"Failover Global Domain using domain update command(being deprecated in favor of managed graceful failover)",id:"failover-global-domain-using-domain-update-commandbeing-deprecated-in-favor-of-managed-graceful-failover",level:4},{value:"Failover Global Domain using Managed Graceful Failover",id:"failover-global-domain-using-managed-graceful-failover",level:4},{value:"Running Locally",id:"running-locally",level:2},{value:"Running in Production",id:"running-in-production",level:2}];function d(e){const n={a:"a",code:"code",em:"em",h1:"h1",h2:"h2",h3:"h3",h4:"h4",header:"header",li:"li",ol:"ol",p:"p",pre:"pre",...(0,r.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.header,{children:(0,i.jsx)(n.h1,{id:"cross-dc-replication",children:"Cross-DC replication"})}),"\n",(0,i.jsx)(n.p,{children:"The Cadence Global Domain feature provides clients with the capability to continue their workflow_execution from another\ncluster in the event of a datacenter failover. Although you can configure a Global Domain to be replicated to any number of\nclusters, it is only considered active in a single cluster."}),"\n",(0,i.jsx)(n.h2,{id:"global-domains-architecture",children:"Global Domains Architecture"}),"\n",(0,i.jsxs)(n.p,{children:["Cadence has introduced a new top level entity, Global Domains, which provides support for replication of workflow\nexecution across clusters. A global domain can be configured with more than one clusters, but can only be ",(0,i.jsx)(n.code,{children:"active"})," in one of the clusters at any point of time.\nWe call it ",(0,i.jsx)(n.code,{children:"passive"})," or ",(0,i.jsx)(n.code,{children:"standby"})," when not active in other clusters."]}),"\n",(0,i.jsx)(n.p,{children:"The number of standby clusters can be zero, if a global domain only configured to one cluster. This is preferred/recommended."}),"\n",(0,i.jsxs)(n.p,{children:["Any workflow of a global domain can only make make progress in its ",(0,i.jsx)(n.code,{children:"active"})," cluster. And the workflow progress is replicated to other ",(0,i.jsx)(n.code,{children:"standby"})," clusters. For example,\nstarting workflow by calling ",(0,i.jsx)(n.code,{children:"StartWorkflow"}),", or starting activity(by ",(0,i.jsx)(n.code,{children:"PollForActivityTask"})," API), can only be processed in its active cluster. After active cluster made progress,\nstandby clusters (if any) will poll the history from active to replicate the workflow states."]}),"\n",(0,i.jsxs)(n.p,{children:["However, standby clusters can also receive the requests, e.g. for starting workflows or starting activities. They know which cluster the domain is active at.\nSo the requests can be routed to the active clusters. This is called ",(0,i.jsx)(n.code,{children:"api-forwarding"})," in Cadence. ",(0,i.jsx)(n.code,{children:"api-forwarding"})," makes it possible to have no downtime during failover.\nThere are two ",(0,i.jsx)(n.code,{children:"api-forwarding"})," policy: ",(0,i.jsx)(n.code,{children:"selected-api-forwarding"})," and ",(0,i.jsx)(n.code,{children:"all-domain-api-forwarding"})," policy."]}),"\n",(0,i.jsxs)(n.p,{children:["When using ",(0,i.jsx)(n.code,{children:"selected-api-forwarding"}),", applications need to run different set of activity & workflow workers polling on every cluster.\nCadence will only dispatch tasks on the current active cluster; workers on the standby cluster will sit idle\nuntil the Global Domain is failed over. This is recommended if XDC is being used in multiple clusters running in very remote data centers(regions), which forwarding is expensive to do."]}),"\n",(0,i.jsxs)(n.p,{children:["When using ",(0,i.jsx)(n.code,{children:"all-domain-api-forwarding"}),", applications only need to run activity & workflow workers polling on one cluster. This makes it easier for the application setup. This is recommended\nwhen clusters are all in local or nearby datacenters. See more details in ",(0,i.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence/discussions/4530",children:"discussion"}),"."]}),"\n",(0,i.jsx)(n.h3,{id:"conflict-resolution",children:"Conflict Resolution"}),"\n",(0,i.jsx)(n.p,{children:"Unlike local domains which provide at-most-once semantics for activity execution, Global Domains can only support at-least-once\nsemantics. Cadence global domain relies on asynchronous replication of events across clusters, so in the event of a failover\nit is possible that activity gets dispatched again on the new active cluster due to a replication task lag. This also\nmeans that whenever workflow_execution is updated after a failover by the new cluster, any previous replication tasks\nfor that execution cannot be applied. This results in loss of some progress made by the workflow_execution in the\nprevious active cluster. During such conflict resolution, Cadence re-injects any external events like Signals to the\nnew history before discarding replication tasks. Even though some progress could rollback during failovers, Cadence\nprovides the guarantee that workflows won\u2019t get stuck and will continue to make forward progress."}),"\n",(0,i.jsx)(n.h2,{id:"global-domain-concepts-configuration-and-operation",children:"Global Domain Concepts, Configuration and Operation"}),"\n",(0,i.jsx)(n.h3,{id:"concepts",children:"Concepts"}),"\n",(0,i.jsx)(n.h4,{id:"isglobal",children:"IsGlobal"}),"\n",(0,i.jsx)(n.p,{children:"This config is used to distinguish domains local to the cluster from the global domain. It controls the creation of\nreplication tasks on updates allowing the state to be replicated across clusters. This is a read-only setting that can\nonly be set when the domain is provisioned."}),"\n",(0,i.jsx)(n.h4,{id:"clusters",children:"Clusters"}),"\n",(0,i.jsx)(n.p,{children:"A list of clusters where the domain can fail over to, including the current active cluster.\nThis is also a read-only setting that can only be set when the domain is provisioned. A re-replication feature on the\nroadmap will allow updating this config to add/remove clusters in the future."}),"\n",(0,i.jsx)(n.h4,{id:"active-cluster-name",children:"Active Cluster Name"}),"\n",(0,i.jsx)(n.p,{children:"Name of the current active cluster for the Global Domain. This config is updated each time the Global Domain is failed over to\nanother cluster."}),"\n",(0,i.jsx)(n.h4,{id:"failover-version",children:"Failover Version"}),"\n",(0,i.jsx)(n.p,{children:"Unique failover version which also represents the current active cluster for Global Domain. Cadence allows failover to\nbe triggered from any cluster, so failover version is designed in a way to not allow conflicts if failover is mistakenly\ntriggered simultaneously on two clusters."}),"\n",(0,i.jsx)(n.h3,{id:"operate-by-cli",children:"Operate by CLI"}),"\n",(0,i.jsx)(n.p,{children:"The Cadence CLI can also be used to query the domain config or perform failovers. Here are some useful commands."}),"\n",(0,i.jsx)(n.h4,{id:"describe-global-domain",children:"Describe Global Domain"}),"\n",(0,i.jsx)(n.p,{children:"The following command can be used to describe Global Domain metadata:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"$ cadence --do cadence-canary-xdc d desc\nName: cadence-canary-xdc\nDescription: cadence canary cross dc testing domain\nOwnerEmail: cadence-dev@cadenceworkflow.io\nDomainData:\nStatus: REGISTERED\nRetentionInDays: 7\nEmitMetrics: true\nActiveClusterName: dc1\nClusters: dc1, dc2\n"})}),"\n",(0,i.jsx)(n.h4,{id:"failover-global-domain-using-domain-update-commandbeing-deprecated-in-favor-of-managed-graceful-failover",children:"Failover Global Domain using domain update command(being deprecated in favor of managed graceful failover)"}),"\n",(0,i.jsxs)(n.p,{children:["The following command can be used to failover Global Domain ",(0,i.jsx)(n.em,{children:"my-domain-global"})," to the ",(0,i.jsx)(n.em,{children:"dc2"})," cluster:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"$ cadence --do my-domain-global d up --ac dc2\n"})}),"\n",(0,i.jsx)(n.h4,{id:"failover-global-domain-using-managed-graceful-failover",children:"Failover Global Domain using Managed Graceful Failover"}),"\n",(0,i.jsx)(n.p,{children:"First of all, update the domain to enable this feature for the domain"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"$ cadence --do test-global-domain-0 d update --domain_data IsManagedByCadence:true\n$ cadence --do test-global-domain-1 d update --domain_data IsManagedByCadence:true\n$ cadence --do test-global-domain-2 d update --domain_data IsManagedByCadence:true\n...\n"})}),"\n",(0,i.jsx)(n.p,{children:"Then you can start failover the those global domains using managed failover:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"cadence admin cluster failover start --source_cluster dc1 --target_cluster dc2\n"})}),"\n",(0,i.jsxs)(n.p,{children:["This will failover all the domains with ",(0,i.jsx)(n.code,{children:"IsManagedByCadence:true"})," from dc1 to dc2."]}),"\n",(0,i.jsxs)(n.p,{children:["You can provide more detailed options when using the command, and also watch the progress of the failover.\nFeel free to explore the ",(0,i.jsx)(n.code,{children:"cadence admin cluster failover"})," tab."]}),"\n",(0,i.jsx)(n.h2,{id:"running-locally",children:"Running Locally"}),"\n",(0,i.jsxs)(n.p,{children:["The best way is to use Cadence ",(0,i.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence/tree/master/docker",children:"docker-compose"}),":\n",(0,i.jsx)(n.code,{children:"docker-compose -f docker-compose-multiclusters.yml up"})]}),"\n",(0,i.jsx)(n.h2,{id:"running-in-production",children:"Running in Production"}),"\n",(0,i.jsxs)(n.p,{children:["Enable global domain feature needs to be enabled in ",(0,i.jsx)(n.a,{href:"/docs/operation-guide/setup/#static-configuration",children:"static config"}),"."]}),"\n",(0,i.jsx)(n.p,{children:'Here we use clusterDCA and clusterDCB as an example. We pick clusterDCA as the primary(used to called "master") cluster.\nThe only difference of being a primary cluster is that it is responsible for domain registration. Primary can be changed later but it needs to be the same across all clusters.'}),"\n",(0,i.jsx)(n.p,{children:"The ClusterMeta config of clusterDCA should be"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-yaml",children:'dcRedirectionPolicy:\n policy: "selected-apis-forwarding"\n\nclusterMetadata:\n enableGlobalDomain: true\n failoverVersionIncrement: 10\n masterClusterName: "clusterDCA"\n currentClusterName: "clusterDCA"\n clusterInformation:\n clusterDCA:\n enabled: true\n initialFailoverVersion: 1\n rpcName: "cadence-frontend"\n rpcAddress: "<>:<>"\n clusterDCB:\n enabled: true\n initialFailoverVersion: 0\n rpcName: "cadence-frontend"\n rpcAddress: "<>:<>"\n'})}),"\n",(0,i.jsx)(n.p,{children:"And ClusterMeta config of clusterDCB should be"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-yaml",children:'dcRedirectionPolicy:\n policy: "selected-apis-forwarding"\n\nclusterMetadata:\n enableGlobalDomain: true\n failoverVersionIncrement: 10\n masterClusterName: "clusterDCA"\n currentClusterName: "clusterDCB"\n clusterInformation:\n clusterDCA:\n enabled: true\n initialFailoverVersion: 1\n rpcName: "cadence-frontend"\n rpcAddress: "<>:<>"\n clusterDCB:\n enabled: true\n initialFailoverVersion: 0\n\n rpcName: "cadence-frontend"\n rpcAddress: "<>:<>"\n'})}),"\n",(0,i.jsx)(n.p,{children:"After the configuration is deployed:"}),"\n",(0,i.jsxs)(n.ol,{children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:["Register a global domain\n",(0,i.jsx)(n.code,{children:"cadence --do <domain_name> domain register --global_domain true --clusters clusterDCA clusterDCB --active_cluster clusterDCA"})]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:["Run some workflow and failover domain from one to another\n",(0,i.jsx)(n.code,{children:"cadence --do <domain_name> domain update --active_cluster clusterDCB"})]}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Then the domain should be failed over to clusterDCB. Now worklfows are read-only in clusterDCA. So your workers polling tasks from clusterDCA will become idle."}),"\n",(0,i.jsx)(n.p,{children:"Note 1: that even though clusterDCA is standy/read-only for this domain, it can be active for another domain. So being active/standy is per domain basis not per clusters. In other words, for example if you use XDC in case of DC failure of clusterDCA, you need to failover all domains from clusterDCA to clusterDCB."}),"\n",(0,i.jsx)(n.p,{children:"Note 2: even though a domain is standy/read-only in a cluster, say clusterDCA, sending write requests(startWF, signalWF, etc) could still work because there is a forwarding component in the Frontend service. It will try to re-route the requests to an active cluster for the domain."})]})}function u(e={}){const{wrapper:n}={...(0,r.R)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(d,{...e})}):d(e)}},8453:(e,n,o)=>{o.d(n,{R:()=>t,x:()=>s});var a=o(6540);const i={},r=a.createContext(i);function t(e){const n=a.useContext(r);return a.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function s(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:t(e.components),a.createElement(r.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/9674d0ef.b89b74bb.js b/assets/js/9674d0ef.b89b74bb.js deleted file mode 100644 index e23a29e06..000000000 --- a/assets/js/9674d0ef.b89b74bb.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[1010],{6705:(e,n,o)=>{o.r(n),o.d(n,{assets:()=>l,contentTitle:()=>s,default:()=>u,frontMatter:()=>t,metadata:()=>a,toc:()=>c});const a=JSON.parse('{"id":"concepts/cross-dc-replication","title":"Cross DC replication","description":"The Cadence GlobalDomainworkflow_execution: from another","source":"@site/docs/03-concepts/08-cross-dc-replication.md","sourceDirName":"03-concepts","slug":"/concepts/cross-dc-replication","permalink":"/docs/concepts/cross-dc-replication","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/03-concepts/08-cross-dc-replication.md","tags":[],"version":"current","sidebarPosition":8,"frontMatter":{"layout":"default","title":"Cross DC replication","permalink":"/docs/concepts/cross-dc-replication"},"sidebar":"docsSidebar","previous":{"title":"Archival","permalink":"/docs/concepts/archival"},"next":{"title":"Search workflows(Advanced visibility)","permalink":"/docs/concepts/search-workflows"}}');var i=o(4848),r=o(8453);const t={layout:"default",title:"Cross DC replication",permalink:"/docs/concepts/cross-dc-replication"},s="Cross-DC replication",l={},c=[{value:"Global Domains Architecture",id:"global-domains-architecture",level:2},{value:"Conflict Resolution",id:"conflict-resolution",level:3},{value:"Global Domain Concepts, Configuration and Operation",id:"global-domain-concepts-configuration-and-operation",level:2},{value:"Concepts",id:"concepts",level:3},{value:"IsGlobal",id:"isglobal",level:4},{value:"Clusters",id:"clusters",level:4},{value:"Active Cluster Name",id:"active-cluster-name",level:4},{value:"Failover Version",id:"failover-version",level:4},{value:"Operate by CLI",id:"operate-by-cli",level:3},{value:"Describe Global Domain",id:"describe-global-domain",level:4},{value:"Failover Global Domain using domain update command(being deprecated in favor of managed graceful failover)",id:"failover-global-domain-using-domain-update-commandbeing-deprecated-in-favor-of-managed-graceful-failover",level:4},{value:"Failover Global Domain using Managed Graceful Failover",id:"failover-global-domain-using-managed-graceful-failover",level:4},{value:"Running Locally",id:"running-locally",level:2},{value:"Running in Production",id:"running-in-production",level:2}];function d(e){const n={a:"a",code:"code",em:"em",h1:"h1",h2:"h2",h3:"h3",h4:"h4",header:"header",li:"li",ol:"ol",p:"p",pre:"pre",...(0,r.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.header,{children:(0,i.jsx)(n.h1,{id:"cross-dc-replication",children:"Cross-DC replication"})}),"\n",(0,i.jsx)(n.p,{children:"The Cadence Global Domain feature provides clients with the capability to continue their workflow_execution from another\ncluster in the event of a datacenter failover. Although you can configure a Global Domain to be replicated to any number of\nclusters, it is only considered active in a single cluster."}),"\n",(0,i.jsx)(n.h2,{id:"global-domains-architecture",children:"Global Domains Architecture"}),"\n",(0,i.jsxs)(n.p,{children:["Cadence has introduced a new top level entity, Global Domains, which provides support for replication of workflow\nexecution across clusters. A global domain can be configured with more than one clusters, but can only be ",(0,i.jsx)(n.code,{children:"active"})," in one of the clusters at any point of time.\nWe call it ",(0,i.jsx)(n.code,{children:"passive"})," or ",(0,i.jsx)(n.code,{children:"standby"})," when not active in other clusters."]}),"\n",(0,i.jsx)(n.p,{children:"The number of standby clusters can be zero, if a global domain only configured to one cluster. This is preferred/recommended."}),"\n",(0,i.jsxs)(n.p,{children:["Any workflow of a global domain can only make make progress in its ",(0,i.jsx)(n.code,{children:"active"})," cluster. And the workflow progress is replicated to other ",(0,i.jsx)(n.code,{children:"standby"})," clusters. For example,\nstarting workflow by calling ",(0,i.jsx)(n.code,{children:"StartWorkflow"}),", or starting activity(by ",(0,i.jsx)(n.code,{children:"PollForActivityTask"})," API), can only be processed in its active cluster. After active cluster made progress,\nstandby clusters (if any) will poll the history from active to replicate the workflow states."]}),"\n",(0,i.jsxs)(n.p,{children:["However, standby clusters can also receive the requests, e.g. for starting workflows or starting activities. They know which cluster the domain is active at.\nSo the requests can be routed to the active clusters. This is called ",(0,i.jsx)(n.code,{children:"api-forwarding"})," in Cadence. ",(0,i.jsx)(n.code,{children:"api-forwarding"})," makes it possible to have no downtime during failover.\nThere are two ",(0,i.jsx)(n.code,{children:"api-forwarding"})," policy: ",(0,i.jsx)(n.code,{children:"selected-api-forwarding"})," and ",(0,i.jsx)(n.code,{children:"all-domain-api-forwarding"})," policy."]}),"\n",(0,i.jsxs)(n.p,{children:["When using ",(0,i.jsx)(n.code,{children:"selected-api-forwarding"}),", applications need to run different set of activity & workflow workers polling on every cluster.\nCadence will only dispatch tasks on the current active cluster; workers on the standby cluster will sit idle\nuntil the Global Domain is failed over. This is recommended if XDC is being used in multiple clusters running in very remote data centers(regions), which forwarding is expensive to do."]}),"\n",(0,i.jsxs)(n.p,{children:["When using ",(0,i.jsx)(n.code,{children:"all-domain-api-forwarding"}),", applications only need to run activity & workflow workers polling on one cluster. This makes it easier for the application setup. This is recommended\nwhen clusters are all in local or nearby datacenters. See more details in ",(0,i.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence/discussions/4530",children:"discussion"}),"."]}),"\n",(0,i.jsx)(n.h3,{id:"conflict-resolution",children:"Conflict Resolution"}),"\n",(0,i.jsx)(n.p,{children:"Unlike local domains which provide at-most-once semantics for activity execution, Global Domains can only support at-least-once\nsemantics. Cadence global domain relies on asynchronous replication of events across clusters, so in the event of a failover\nit is possible that activity gets dispatched again on the new active cluster due to a replication task lag. This also\nmeans that whenever workflow_execution is updated after a failover by the new cluster, any previous replication tasks\nfor that execution cannot be applied. This results in loss of some progress made by the workflow_execution in the\nprevious active cluster. During such conflict resolution, Cadence re-injects any external events like Signals to the\nnew history before discarding replication tasks. Even though some progress could rollback during failovers, Cadence\nprovides the guarantee that workflows won\u2019t get stuck and will continue to make forward progress."}),"\n",(0,i.jsx)(n.h2,{id:"global-domain-concepts-configuration-and-operation",children:"Global Domain Concepts, Configuration and Operation"}),"\n",(0,i.jsx)(n.h3,{id:"concepts",children:"Concepts"}),"\n",(0,i.jsx)(n.h4,{id:"isglobal",children:"IsGlobal"}),"\n",(0,i.jsx)(n.p,{children:"This config is used to distinguish domains local to the cluster from the global domain. It controls the creation of\nreplication tasks on updates allowing the state to be replicated across clusters. This is a read-only setting that can\nonly be set when the domain is provisioned."}),"\n",(0,i.jsx)(n.h4,{id:"clusters",children:"Clusters"}),"\n",(0,i.jsx)(n.p,{children:"A list of clusters where the domain can fail over to, including the current active cluster.\nThis is also a read-only setting that can only be set when the domain is provisioned. A re-replication feature on the\nroadmap will allow updating this config to add/remove clusters in the future."}),"\n",(0,i.jsx)(n.h4,{id:"active-cluster-name",children:"Active Cluster Name"}),"\n",(0,i.jsx)(n.p,{children:"Name of the current active cluster for the Global Domain. This config is updated each time the Global Domain is failed over to\nanother cluster."}),"\n",(0,i.jsx)(n.h4,{id:"failover-version",children:"Failover Version"}),"\n",(0,i.jsx)(n.p,{children:"Unique failover version which also represents the current active cluster for Global Domain. Cadence allows failover to\nbe triggered from any cluster, so failover version is designed in a way to not allow conflicts if failover is mistakenly\ntriggered simultaneously on two clusters."}),"\n",(0,i.jsx)(n.h3,{id:"operate-by-cli",children:"Operate by CLI"}),"\n",(0,i.jsx)(n.p,{children:"The Cadence CLI can also be used to query the domain config or perform failovers. Here are some useful commands."}),"\n",(0,i.jsx)(n.h4,{id:"describe-global-domain",children:"Describe Global Domain"}),"\n",(0,i.jsx)(n.p,{children:"The following command can be used to describe Global Domain metadata:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"$ cadence --do cadence-canary-xdc d desc\nName: cadence-canary-xdc\nDescription: cadence canary cross dc testing domain\nOwnerEmail: cadence-dev@cadenceworkflow.io\nDomainData:\nStatus: REGISTERED\nRetentionInDays: 7\nEmitMetrics: true\nActiveClusterName: dc1\nClusters: dc1, dc2\n"})}),"\n",(0,i.jsx)(n.h4,{id:"failover-global-domain-using-domain-update-commandbeing-deprecated-in-favor-of-managed-graceful-failover",children:"Failover Global Domain using domain update command(being deprecated in favor of managed graceful failover)"}),"\n",(0,i.jsxs)(n.p,{children:["The following command can be used to failover Global Domain ",(0,i.jsx)(n.em,{children:"my-domain-global"})," to the ",(0,i.jsx)(n.em,{children:"dc2"})," cluster:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"$ cadence --do my-domain-global d up --ac dc2\n"})}),"\n",(0,i.jsx)(n.h4,{id:"failover-global-domain-using-managed-graceful-failover",children:"Failover Global Domain using Managed Graceful Failover"}),"\n",(0,i.jsx)(n.p,{children:"First of all, update the domain to enable this feature for the domain"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"$ cadence --do test-global-domain-0 d update --domain_data IsManagedByCadence:true\n$ cadence --do test-global-domain-1 d update --domain_data IsManagedByCadence:true\n$ cadence --do test-global-domain-2 d update --domain_data IsManagedByCadence:true\n...\n"})}),"\n",(0,i.jsx)(n.p,{children:"Then you can start failover the those global domains using managed failover:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"cadence admin cluster failover start --source_cluster dc1 --target_cluster dc2\n"})}),"\n",(0,i.jsxs)(n.p,{children:["This will failover all the domains with ",(0,i.jsx)(n.code,{children:"IsManagedByCadence:true"})," from dc1 to dc2."]}),"\n",(0,i.jsxs)(n.p,{children:["You can provide more detailed options when using the command, and also watch the progress of the failover.\nFeel free to explore the ",(0,i.jsx)(n.code,{children:"cadence admin cluster failover"})," tab."]}),"\n",(0,i.jsx)(n.h2,{id:"running-locally",children:"Running Locally"}),"\n",(0,i.jsxs)(n.p,{children:["The best way is to use Cadence ",(0,i.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence/tree/master/docker",children:"docker-compose"}),":\n",(0,i.jsx)(n.code,{children:"docker-compose -f docker-compose-multiclusters.yml up"})]}),"\n",(0,i.jsx)(n.h2,{id:"running-in-production",children:"Running in Production"}),"\n",(0,i.jsxs)(n.p,{children:["Enable global domain feature needs to be enabled in ",(0,i.jsx)(n.a,{href:"/docs/operation-guide/setup/#static-configuration",children:"static config"}),"."]}),"\n",(0,i.jsx)(n.p,{children:'Here we use clusterDCA and clusterDCB as an example. We pick clusterDCA as the primary(used to called "master") cluster.\nThe only difference of being a primary cluster is that it is responsible for domain registration. Primary can be changed later but it needs to be the same across all clusters.'}),"\n",(0,i.jsx)(n.p,{children:"The ClusterMeta config of clusterDCA should be"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-yaml",children:'dcRedirectionPolicy:\n policy: "selected-apis-forwarding"\n\nclusterMetadata:\n enableGlobalDomain: true\n failoverVersionIncrement: 10\n masterClusterName: "clusterDCA"\n currentClusterName: "clusterDCA"\n clusterInformation:\n clusterDCA:\n enabled: true\n initialFailoverVersion: 1\n rpcName: "cadence-frontend"\n rpcAddress: "<>:<>"\n clusterDCB:\n enabled: true\n initialFailoverVersion: 0\n rpcName: "cadence-frontend"\n rpcAddress: "<>:<>"\n'})}),"\n",(0,i.jsx)(n.p,{children:"And ClusterMeta config of clusterDCB should be"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-yaml",children:'dcRedirectionPolicy:\n policy: "selected-apis-forwarding"\n\nclusterMetadata:\n enableGlobalDomain: true\n failoverVersionIncrement: 10\n masterClusterName: "clusterDCA"\n currentClusterName: "clusterDCB"\n clusterInformation:\n clusterDCA:\n enabled: true\n initialFailoverVersion: 1\n rpcName: "cadence-frontend"\n rpcAddress: "<>:<>"\n clusterDCB:\n enabled: true\n initialFailoverVersion: 0\n\n rpcName: "cadence-frontend"\n rpcAddress: "<>:<>"\n'})}),"\n",(0,i.jsx)(n.p,{children:"After the configuration is deployed:"}),"\n",(0,i.jsxs)(n.ol,{children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:["Register a global domain\n",(0,i.jsx)(n.code,{children:"cadence --do <domain_name> domain register --global_domain true --clusters clusterDCA clusterDCB --active_cluster clusterDCA"})]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:["Run some workflow and failover domain from one to another\n",(0,i.jsx)(n.code,{children:"cadence --do <domain_name> domain update --active_cluster clusterDCB"})]}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Then the domain should be failed over to clusterDCB. Now worklfows are read-only in clusterDCA. So your workers polling tasks from clusterDCA will become idle."}),"\n",(0,i.jsx)(n.p,{children:"Note 1: that even though clusterDCA is standy/read-only for this domain, it can be active for another domain. So being active/standy is per domain basis not per clusters. In other words, for example if you use XDC in case of DC failure of clusterDCA, you need to failover all domains from clusterDCA to clusterDCB."}),"\n",(0,i.jsx)(n.p,{children:"Note 2: even though a domain is standy/read-only in a cluster, say clusterDCA, sending write requests(startWF, signalWF, etc) could still work because there is a forwarding component in the Frontend service. It will try to re-route the requests to an active cluster for the domain."})]})}function u(e={}){const{wrapper:n}={...(0,r.R)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(d,{...e})}):d(e)}},8453:(e,n,o)=>{o.d(n,{R:()=>t,x:()=>s});var a=o(6540);const i={},r=a.createContext(i);function t(e){const n=a.useContext(r);return a.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function s(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:t(e.components),a.createElement(r.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/97fa9516.32206c7c.js b/assets/js/97fa9516.32206c7c.js deleted file mode 100644 index 082c9f080..000000000 --- a/assets/js/97fa9516.32206c7c.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[3355],{771:e=>{e.exports=JSON.parse('{"tag":{"label":"Releases","permalink":"/blog/tags/releases","description":"Releases tag description","allTagsPath":"/blog/tags","count":2,"unlisted":false},"listMetadata":{"permalink":"/blog/tags/releases","page":1,"postsPerPage":10,"totalPages":1,"totalCount":2,"blogDescription":"The latest news and updates from the Cadence team","blogTitle":"Cadence Blog"}}')}}]); \ No newline at end of file diff --git a/assets/js/981d14b8.43550098.js b/assets/js/981d14b8.43550098.js new file mode 100644 index 000000000..0395226bf --- /dev/null +++ b/assets/js/981d14b8.43550098.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[7970],{2724:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>r,contentTitle:()=>c,default:()=>l,frontMatter:()=>i,metadata:()=>o,toc:()=>m});var o=n(586),a=n(4848),s=n(8453);const i={title:"Cadence Community Spotlight Update - November 2023",date:new Date("2023-11-30T00:00:00.000Z"),authors:"sharanf",tags:["community-spotlight","announcement"]},c=void 0,r={authorsImageUrls:[void 0]},m=[];function u(e){const t={p:"p",...(0,s.R)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(t.p,{children:"Welcome to the latest of our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!"}),"\n",(0,a.jsx)(t.p,{children:"It's been a couple of months since our last update so we have a lot of updates to share with you."}),"\n",(0,a.jsx)(t.p,{children:"Please see below for a roundup of the highlights:"})]})}function l(e={}){const{wrapper:t}={...(0,s.R)(),...e.components};return t?(0,a.jsx)(t,{...e,children:(0,a.jsx)(u,{...e})}):u(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>i,x:()=>c});var o=n(6540);const a={},s=o.createContext(a);function i(e){const t=o.useContext(s);return o.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function c(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:i(e.components),o.createElement(s.Provider,{value:t},e.children)}},586:e=>{e.exports=JSON.parse('{"permalink":"/Cadence-Docs/blog/2023/11/30/community-spotlight-update-november-2023","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2023-11-30-community-spotlight-update-november-2023.md","source":"@site/blog/2023-11-30-community-spotlight-update-november-2023.md","title":"Cadence Community Spotlight Update - November 2023","description":"Welcome to the latest of our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!","date":"2023-11-30T00:00:00.000Z","tags":[{"inline":false,"label":"Community Spotlight","permalink":"/Cadence-Docs/blog/tags/community-spotlights","description":"Community Spotlight tag description"},{"inline":false,"label":"Announcement","permalink":"/Cadence-Docs/blog/tags/announcements","description":"Announcement tag description"}],"readingTime":3.46,"hasTruncateMarker":true,"authors":[{"name":"Sharan Foga","title":"Director of Operations & Customer Success @ Encube Technologies","url":"https://www.linkedin.com/in/sfoga/","page":{"permalink":"/Cadence-Docs/blog/authors/sharanf"},"socials":{"linkedin":"https://www.linkedin.com/in/sfoga/","github":"https://github.com/sharanf"},"imageURL":"https://github.com/sharanf.png","key":"sharanf"}],"frontMatter":{"title":"Cadence Community Spotlight Update - November 2023","date":"2023-11-30T00:00:00.000Z","authors":"sharanf","tags":["community-spotlight","announcement"]},"unlisted":false,"prevItem":{"title":"Cadence non-derministic errors common question Q&A (part 1)","permalink":"/Cadence-Docs/blog/2024/02/15/cadence-non-deterministic-common-qa"},"nextItem":{"title":"Cadence Community Spotlight Update - August 2023","permalink":"/Cadence-Docs/blog/2023/08/31/community-spotlight-august-2023"}}')}}]); \ No newline at end of file diff --git a/assets/js/981d14b8.592b7d62.js b/assets/js/981d14b8.592b7d62.js deleted file mode 100644 index 3f6b653e5..000000000 --- a/assets/js/981d14b8.592b7d62.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[7970],{2724:(t,e,n)=>{n.r(e),n.d(e,{assets:()=>m,contentTitle:()=>r,default:()=>l,frontMatter:()=>s,metadata:()=>o,toc:()=>c});var o=n(586),a=n(4848),i=n(8453);const s={title:"Cadence Community Spotlight Update - November 2023",date:new Date("2023-11-30T00:00:00.000Z"),authors:"sharanf",tags:["community-spotlight","announcement"]},r=void 0,m={authorsImageUrls:[void 0]},c=[];function u(t){const e={p:"p",...(0,i.R)(),...t.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(e.p,{children:"Welcome to the latest of our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!"}),"\n",(0,a.jsx)(e.p,{children:"It's been a couple of months since our last update so we have a lot of updates to share with you."}),"\n",(0,a.jsx)(e.p,{children:"Please see below for a roundup of the highlights:"})]})}function l(t={}){const{wrapper:e}={...(0,i.R)(),...t.components};return e?(0,a.jsx)(e,{...t,children:(0,a.jsx)(u,{...t})}):u(t)}},8453:(t,e,n)=>{n.d(e,{R:()=>s,x:()=>r});var o=n(6540);const a={},i=o.createContext(a);function s(t){const e=o.useContext(i);return o.useMemo((function(){return"function"==typeof t?t(e):{...e,...t}}),[e,t])}function r(t){let e;return e=t.disableParentContext?"function"==typeof t.components?t.components(a):t.components||a:s(t.components),o.createElement(i.Provider,{value:e},t.children)}},586:t=>{t.exports=JSON.parse('{"permalink":"/blog/2023/11/30/community-spotlight-update-november-2023","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2023-11-30-community-spotlight-update-november-2023.md","source":"@site/blog/2023-11-30-community-spotlight-update-november-2023.md","title":"Cadence Community Spotlight Update - November 2023","description":"Welcome to the latest of our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!","date":"2023-11-30T00:00:00.000Z","tags":[{"inline":false,"label":"Community Spotlight","permalink":"/blog/tags/community-spotlights","description":"Community Spotlight tag description"},{"inline":false,"label":"Announcement","permalink":"/blog/tags/announcements","description":"Announcement tag description"}],"readingTime":3.46,"hasTruncateMarker":true,"authors":[{"name":"Sharan Foga","title":"Director of Operations & Customer Success @ Encube Technologies","url":"https://www.linkedin.com/in/sfoga/","page":{"permalink":"/blog/authors/sharanf"},"socials":{"linkedin":"https://www.linkedin.com/in/sfoga/","github":"https://github.com/sharanf"},"imageURL":"https://github.com/sharanf.png","key":"sharanf"}],"frontMatter":{"title":"Cadence Community Spotlight Update - November 2023","date":"2023-11-30T00:00:00.000Z","authors":"sharanf","tags":["community-spotlight","announcement"]},"unlisted":false,"prevItem":{"title":"Cadence non-derministic errors common question Q&A (part 1)","permalink":"/blog/2024/02/15/cadence-non-deterministic-common-qa"},"nextItem":{"title":"Cadence Community Spotlight Update - August 2023","permalink":"/blog/2023/08/31/community-spotlight-august-2023"}}')}}]); \ No newline at end of file diff --git a/assets/js/98f5ac88.916513ba.js b/assets/js/98f5ac88.11a58769.js similarity index 82% rename from assets/js/98f5ac88.916513ba.js rename to assets/js/98f5ac88.11a58769.js index dddd70668..2adec65a7 100644 --- a/assets/js/98f5ac88.916513ba.js +++ b/assets/js/98f5ac88.11a58769.js @@ -1 +1 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[2235],{6724:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>l,contentTitle:()=>r,default:()=>d,frontMatter:()=>s,metadata:()=>o,toc:()=>c});var o=t(6398),i=t(4848),a=t(8453);const s={title:"Cadence Community Spotlight Update - June 2023",date:new Date("2023-06-30T00:00:00.000Z"),authors:"sharanf",tags:["community-spotlight","release"]},r=void 0,l={authorsImageUrls:[void 0]},c=[{value:"Cadence Release 1.0",id:"cadence-release-10",level:2},{value:"Community Survey Results",id:"community-survey-results",level:2},{value:"Cadence Video Open Source Summit, North America",id:"cadence-video-open-source-summit-north-america",level:2},{value:"Overcoming Potential Workflow Versioning Maintenance Challenges",id:"overcoming-potential-workflow-versioning-maintenance-challenges",level:2},{value:"Cadence in the News!",id:"cadence-in-the-news",level:2},{value:"Upcoming Events",id:"upcoming-events",level:2}];function h(e){const n={a:"a",h2:"h2",li:"li",p:"p",ul:"ul",...(0,a.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.p,{children:"We've had a short break but now we are back. Welcome to the latest of our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!"}),"\n",(0,i.jsx)(n.p,{children:"Please see below for a roundup of the highlights:"}),"\n",(0,i.jsx)(n.h2,{id:"cadence-release-10",children:"Cadence Release 1.0"}),"\n",(0,i.jsxs)(n.p,{children:["Just in case you missed it - at the end of April ",(0,i.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence/releases/tag/v1.0.0",children:"Cadence v1.0"})," was officially released. This release is a significant milestone for the project and the community. It indicates that we are confident in the stability of the code that we can recommend it and promote it widely to more users. Kudos to everyone that worked together to make this release happen."]}),"\n",(0,i.jsxs)(n.p,{children:["And the Uber team also gave Cadence a writeup on the ",(0,i.jsx)(n.a,{href:"https://www.uber.com/en-SE/blog/announcing-cadence/",children:"Uber Engineering Blog"})," so please take a look."]}),"\n",(0,i.jsx)(n.h2,{id:"community-survey-results",children:"Community Survey Results"}),"\n",(0,i.jsxs)(n.p,{children:["The results of our Community Survey have been published and you can find ",(0,i.jsx)(n.a,{href:"https://cadenceworkflow.io/blog/2023/06/08/survey-results/",children:"the details right here on our blog"}),". From the results we can see that:"]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"our community is a good mix of people using, evaluating, testing or thinking about migrating to Cadence"}),"\n",(0,i.jsx)(n.li,{children:"Software Engineers featured highly as a community user profile"}),"\n",(0,i.jsx)(n.li,{children:"Europe seems to be the most common community timezone"}),"\n",(0,i.jsx)(n.li,{children:"People prefer using our Slack channel for questions"}),"\n",(0,i.jsx)(n.li,{children:"Debugging is what most people need help with"}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Thank you to Ender for compiling the data and to everyone who participated."}),"\n",(0,i.jsx)(n.h2,{id:"cadence-video-open-source-summit-north-america",children:"Cadence Video Open Source Summit, North America"}),"\n",(0,i.jsxs)(n.p,{children:["In May ",(0,i.jsx)(n.a,{href:"https://www.linkedin.com/in/enderdemirkaya/",children:"Ender Demirkaya"})," gave a talk called on Cadence at the Linux Foundation's ",(0,i.jsx)(n.a,{href:"https://events.linuxfoundation.org/open-source-summit-north-america/",children:"Open Source Summit, North America"})," in Vancouver. The presentation attracted a sizeable audience and was very well received. There was also a lot of questions from the audience which is a sign that Cadence sounded potentially useful to them."]}),"\n",(0,i.jsxs)(n.p,{children:["A recording of the talk ",(0,i.jsx)(n.a,{href:"https://www.youtube.com/watch?v=vFPJlE6d4xs",children:"Cadence: The New Open Source Project for Building Complex Distributed Applications"})," is now available."]}),"\n",(0,i.jsx)(n.h2,{id:"overcoming-potential-workflow-versioning-maintenance-challenges",children:"Overcoming Potential Workflow Versioning Maintenance Challenges"}),"\n",(0,i.jsxs)(n.p,{children:["Community member ",(0,i.jsx)(n.a,{href:"https://www.linkedin.com/in/prclqz/",children:"Quanzheng Long"})," has written a ",(0,i.jsx)(n.a,{href:"https://medium.com/@qlong/how-to-overcome-some-maintenance-challenges-of-temporal-cadence-workflow-versioning-f893815dd18d",children:"detailed article on Medium"})," about some of the potential maintenance challenges of workflow versioning. It's a short read and has some good examples that explains the potential problems and identifies some approaches for dealing with them."]}),"\n",(0,i.jsx)(n.p,{children:"Thanks Long for sharing this knowledge with the community!"}),"\n",(0,i.jsx)(n.h2,{id:"cadence-in-the-news",children:"Cadence in the News!"}),"\n",(0,i.jsx)(n.p,{children:"Below are a selection of Cadence related articles, blogs and whitepapers. Please take a look and feel free to share via your own social media channels."}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://www.uber.com/en-SE/blog/announcing-cadence/",children:"Announcing Cadence 1.0: The Powerful Workflow Platform Built for Scale and Reliability"})}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://www.instaclustr.com/blog/cadence-1-0-released-on-the-instaclustr-managed-platform/",children:"Cadence 1.0 Released on the Instaclustr Managed Platform"})}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://medium.com/@qlong/how-to-overcome-some-maintenance-challenges-of-temporal-cadence-workflow-versioning-f893815dd18d",children:"How to Overcome Some Maintenance Challenges of Temporal/Cadence Workflow Versioning"})}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://www.youtube.com/watch?v=vFPJlE6d4xs",children:"Video: Cadence - The New Open Source Project for Building Complex Distributed Applications"})}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://www.instaclustr.com/blog/instaclustr-releases-multi-region-cadence-workflow-2/",children:"Instaclustr Releases Multi-Region Cadence Workflow"})}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://cadenceworkflow.io/blog/2023/07/01/components-of-cadence-application-setup/",children:"Understanding Components of Cadence Application"})}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://www.instaclustr.com/blog/improving-the-reliability-of-cadence-search-queries/",children:"Improving the Reliability of Cadence Search Queries That Use OpenSearch/Elasticsearch"})}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://www.instaclustr.com/blog/instaclustr-cadence-workflow-developer/",children:"Instaclustr Cadence Workflow Developer Offering Hits General Availability"})}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.h2,{id:"upcoming-events",children:"Upcoming Events"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"None"}),"\n"]}),"\n",(0,i.jsxs)(n.p,{children:["If you have any news or topics you'd like us to include in our next update then please join our ",(0,i.jsx)(n.a,{href:"http://t.uber.com/cadence-slack",children:"Slack"}),"#community channel."]}),"\n",(0,i.jsxs)(n.p,{children:["Please remember that this update is for you - so if you have any comments or feedback that could help us improve it then please share it with us in the #community ",(0,i.jsx)(n.a,{href:"http://t.uber.com/cadence-slack",children:"Slack"})," channel."]})]})}function d(e={}){const{wrapper:n}={...(0,a.R)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(h,{...e})}):h(e)}},8453:(e,n,t)=>{t.d(n,{R:()=>s,x:()=>r});var o=t(6540);const i={},a=o.createContext(i);function s(e){const n=o.useContext(a);return o.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function r(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:s(e.components),o.createElement(a.Provider,{value:n},e.children)}},6398:e=>{e.exports=JSON.parse('{"permalink":"/blog/2023/06/30/community-spotlight-june-2023","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2023-06-30-community-spotlight-june-2023.md","source":"@site/blog/2023-06-30-community-spotlight-june-2023.md","title":"Cadence Community Spotlight Update - June 2023","description":"We\'ve had a short break but now we are back. Welcome to the latest of our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!","date":"2023-06-30T00:00:00.000Z","tags":[{"inline":false,"label":"Community Spotlight","permalink":"/blog/tags/community-spotlights","description":"Community Spotlight tag description"},{"inline":false,"label":"Releases","permalink":"/blog/tags/releases","description":"Releases tag description"}],"readingTime":2.725,"hasTruncateMarker":true,"authors":[{"name":"Sharan Foga","title":"Director of Operations & Customer Success @ Encube Technologies","url":"https://www.linkedin.com/in/sfoga/","page":{"permalink":"/blog/authors/sharanf"},"socials":{"linkedin":"https://www.linkedin.com/in/sfoga/","github":"https://github.com/sharanf"},"imageURL":"https://github.com/sharanf.png","key":"sharanf"}],"frontMatter":{"title":"Cadence Community Spotlight Update - June 2023","date":"2023-06-30T00:00:00.000Z","authors":"sharanf","tags":["community-spotlight","release"]},"unlisted":false,"prevItem":{"title":"Understanding components of Cadence application","permalink":"/blog/2023/06/28/components-of-cadence-application-setup"},"nextItem":{"title":"2023 Cadence Community Survey Results","permalink":"/blog/2023/06/08/2023-06-08-survey-results/survey-results"}}')}}]); \ No newline at end of file +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[2235],{6724:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>l,contentTitle:()=>r,default:()=>d,frontMatter:()=>s,metadata:()=>o,toc:()=>c});var o=t(6398),i=t(4848),a=t(8453);const s={title:"Cadence Community Spotlight Update - June 2023",date:new Date("2023-06-30T00:00:00.000Z"),authors:"sharanf",tags:["community-spotlight","release"]},r=void 0,l={authorsImageUrls:[void 0]},c=[{value:"Cadence Release 1.0",id:"cadence-release-10",level:2},{value:"Community Survey Results",id:"community-survey-results",level:2},{value:"Cadence Video Open Source Summit, North America",id:"cadence-video-open-source-summit-north-america",level:2},{value:"Overcoming Potential Workflow Versioning Maintenance Challenges",id:"overcoming-potential-workflow-versioning-maintenance-challenges",level:2},{value:"Cadence in the News!",id:"cadence-in-the-news",level:2},{value:"Upcoming Events",id:"upcoming-events",level:2}];function h(e){const n={a:"a",h2:"h2",li:"li",p:"p",ul:"ul",...(0,a.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.p,{children:"We've had a short break but now we are back. Welcome to the latest of our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!"}),"\n",(0,i.jsx)(n.p,{children:"Please see below for a roundup of the highlights:"}),"\n",(0,i.jsx)(n.h2,{id:"cadence-release-10",children:"Cadence Release 1.0"}),"\n",(0,i.jsxs)(n.p,{children:["Just in case you missed it - at the end of April ",(0,i.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence/releases/tag/v1.0.0",children:"Cadence v1.0"})," was officially released. This release is a significant milestone for the project and the community. It indicates that we are confident in the stability of the code that we can recommend it and promote it widely to more users. Kudos to everyone that worked together to make this release happen."]}),"\n",(0,i.jsxs)(n.p,{children:["And the Uber team also gave Cadence a writeup on the ",(0,i.jsx)(n.a,{href:"https://www.uber.com/en-SE/blog/announcing-cadence/",children:"Uber Engineering Blog"})," so please take a look."]}),"\n",(0,i.jsx)(n.h2,{id:"community-survey-results",children:"Community Survey Results"}),"\n",(0,i.jsxs)(n.p,{children:["The results of our Community Survey have been published and you can find ",(0,i.jsx)(n.a,{href:"https://cadenceworkflow.io/blog/2023/06/08/survey-results/",children:"the details right here on our blog"}),". From the results we can see that:"]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"our community is a good mix of people using, evaluating, testing or thinking about migrating to Cadence"}),"\n",(0,i.jsx)(n.li,{children:"Software Engineers featured highly as a community user profile"}),"\n",(0,i.jsx)(n.li,{children:"Europe seems to be the most common community timezone"}),"\n",(0,i.jsx)(n.li,{children:"People prefer using our Slack channel for questions"}),"\n",(0,i.jsx)(n.li,{children:"Debugging is what most people need help with"}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Thank you to Ender for compiling the data and to everyone who participated."}),"\n",(0,i.jsx)(n.h2,{id:"cadence-video-open-source-summit-north-america",children:"Cadence Video Open Source Summit, North America"}),"\n",(0,i.jsxs)(n.p,{children:["In May ",(0,i.jsx)(n.a,{href:"https://www.linkedin.com/in/enderdemirkaya/",children:"Ender Demirkaya"})," gave a talk called on Cadence at the Linux Foundation's ",(0,i.jsx)(n.a,{href:"https://events.linuxfoundation.org/open-source-summit-north-america/",children:"Open Source Summit, North America"})," in Vancouver. The presentation attracted a sizeable audience and was very well received. There was also a lot of questions from the audience which is a sign that Cadence sounded potentially useful to them."]}),"\n",(0,i.jsxs)(n.p,{children:["A recording of the talk ",(0,i.jsx)(n.a,{href:"https://www.youtube.com/watch?v=vFPJlE6d4xs",children:"Cadence: The New Open Source Project for Building Complex Distributed Applications"})," is now available."]}),"\n",(0,i.jsx)(n.h2,{id:"overcoming-potential-workflow-versioning-maintenance-challenges",children:"Overcoming Potential Workflow Versioning Maintenance Challenges"}),"\n",(0,i.jsxs)(n.p,{children:["Community member ",(0,i.jsx)(n.a,{href:"https://www.linkedin.com/in/prclqz/",children:"Quanzheng Long"})," has written a ",(0,i.jsx)(n.a,{href:"https://medium.com/@qlong/how-to-overcome-some-maintenance-challenges-of-temporal-cadence-workflow-versioning-f893815dd18d",children:"detailed article on Medium"})," about some of the potential maintenance challenges of workflow versioning. It's a short read and has some good examples that explains the potential problems and identifies some approaches for dealing with them."]}),"\n",(0,i.jsx)(n.p,{children:"Thanks Long for sharing this knowledge with the community!"}),"\n",(0,i.jsx)(n.h2,{id:"cadence-in-the-news",children:"Cadence in the News!"}),"\n",(0,i.jsx)(n.p,{children:"Below are a selection of Cadence related articles, blogs and whitepapers. Please take a look and feel free to share via your own social media channels."}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://www.uber.com/en-SE/blog/announcing-cadence/",children:"Announcing Cadence 1.0: The Powerful Workflow Platform Built for Scale and Reliability"})}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://www.instaclustr.com/blog/cadence-1-0-released-on-the-instaclustr-managed-platform/",children:"Cadence 1.0 Released on the Instaclustr Managed Platform"})}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://medium.com/@qlong/how-to-overcome-some-maintenance-challenges-of-temporal-cadence-workflow-versioning-f893815dd18d",children:"How to Overcome Some Maintenance Challenges of Temporal/Cadence Workflow Versioning"})}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://www.youtube.com/watch?v=vFPJlE6d4xs",children:"Video: Cadence - The New Open Source Project for Building Complex Distributed Applications"})}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://www.instaclustr.com/blog/instaclustr-releases-multi-region-cadence-workflow-2/",children:"Instaclustr Releases Multi-Region Cadence Workflow"})}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://cadenceworkflow.io/blog/2023/07/01/components-of-cadence-application-setup/",children:"Understanding Components of Cadence Application"})}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://www.instaclustr.com/blog/improving-the-reliability-of-cadence-search-queries/",children:"Improving the Reliability of Cadence Search Queries That Use OpenSearch/Elasticsearch"})}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://www.instaclustr.com/blog/instaclustr-cadence-workflow-developer/",children:"Instaclustr Cadence Workflow Developer Offering Hits General Availability"})}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.h2,{id:"upcoming-events",children:"Upcoming Events"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"None"}),"\n"]}),"\n",(0,i.jsxs)(n.p,{children:["If you have any news or topics you'd like us to include in our next update then please join our ",(0,i.jsx)(n.a,{href:"http://t.uber.com/cadence-slack",children:"Slack"}),"#community channel."]}),"\n",(0,i.jsxs)(n.p,{children:["Please remember that this update is for you - so if you have any comments or feedback that could help us improve it then please share it with us in the #community ",(0,i.jsx)(n.a,{href:"http://t.uber.com/cadence-slack",children:"Slack"})," channel."]})]})}function d(e={}){const{wrapper:n}={...(0,a.R)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(h,{...e})}):h(e)}},8453:(e,n,t)=>{t.d(n,{R:()=>s,x:()=>r});var o=t(6540);const i={},a=o.createContext(i);function s(e){const n=o.useContext(a);return o.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function r(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:s(e.components),o.createElement(a.Provider,{value:n},e.children)}},6398:e=>{e.exports=JSON.parse('{"permalink":"/Cadence-Docs/blog/2023/06/30/community-spotlight-june-2023","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2023-06-30-community-spotlight-june-2023.md","source":"@site/blog/2023-06-30-community-spotlight-june-2023.md","title":"Cadence Community Spotlight Update - June 2023","description":"We\'ve had a short break but now we are back. Welcome to the latest of our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!","date":"2023-06-30T00:00:00.000Z","tags":[{"inline":false,"label":"Community Spotlight","permalink":"/Cadence-Docs/blog/tags/community-spotlights","description":"Community Spotlight tag description"},{"inline":false,"label":"Releases","permalink":"/Cadence-Docs/blog/tags/releases","description":"Releases tag description"}],"readingTime":2.725,"hasTruncateMarker":true,"authors":[{"name":"Sharan Foga","title":"Director of Operations & Customer Success @ Encube Technologies","url":"https://www.linkedin.com/in/sfoga/","page":{"permalink":"/Cadence-Docs/blog/authors/sharanf"},"socials":{"linkedin":"https://www.linkedin.com/in/sfoga/","github":"https://github.com/sharanf"},"imageURL":"https://github.com/sharanf.png","key":"sharanf"}],"frontMatter":{"title":"Cadence Community Spotlight Update - June 2023","date":"2023-06-30T00:00:00.000Z","authors":"sharanf","tags":["community-spotlight","release"]},"unlisted":false,"prevItem":{"title":"Understanding components of Cadence application","permalink":"/Cadence-Docs/blog/2023/06/28/components-of-cadence-application-setup"},"nextItem":{"title":"2023 Cadence Community Survey Results","permalink":"/Cadence-Docs/blog/2023/06/08/2023-06-08-survey-results/survey-results"}}')}}]); \ No newline at end of file diff --git a/assets/js/98f77afb.432f310b.js b/assets/js/98f77afb.432f310b.js new file mode 100644 index 000000000..9278547d2 --- /dev/null +++ b/assets/js/98f77afb.432f310b.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[1193],{1786:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>r,contentTitle:()=>c,default:()=>m,frontMatter:()=>s,metadata:()=>o,toc:()=>l});var o=n(7683),i=n(4848),a=n(8453);const s={title:"Cadence Community Spotlight Update - April 2022",date:new Date("2022-04-30T00:00:00.000Z"),authors:"sharanf",tags:["community-spotlight"]},c=void 0,r={authorsImageUrls:[void 0]},l=[{value:"SD Times Names Cadence Open Source Project of the Week",id:"sd-times-names-cadence-open-source-project-of-the-week",level:2},{value:"Follow Us on LinkedIn and Twitter!",id:"follow-us-on-linkedin-and-twitter",level:2}];function d(e){const t={a:"a",em:"em",h2:"h2",p:"p",...(0,a.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(t.p,{children:"Welcome to our Cadence Community Spotlight update!"}),"\n",(0,i.jsx)(t.p,{children:"This is our monthly blog post series focused on news from in and around the Cadence community."}),"\n",(0,i.jsx)(t.p,{children:"Please see below for a short activity roundup of what has happened recently in the community."}),"\n",(0,i.jsx)(t.h2,{id:"sd-times-names-cadence-open-source-project-of-the-week",children:"SD Times Names Cadence Open Source Project of the Week"}),"\n",(0,i.jsxs)(t.p,{children:["In April Cadence was named as open source project of the week by the SD Times. Being named gives the project some great publicity and means the project is getting noticed. You can find a link to the article in the ",(0,i.jsx)(t.em,{children:"Cadence in the News"})," section below."]}),"\n",(0,i.jsx)(t.h2,{id:"follow-us-on-linkedin-and-twitter",children:"Follow Us on LinkedIn and Twitter!"}),"\n",(0,i.jsxs)(t.p,{children:["We have now set up Cadence accounts on ",(0,i.jsx)(t.a,{href:"https://www.linkedin.com/company/cadenceworkflow/",children:"LinkedIn"})," and ",(0,i.jsx)(t.a,{href:"https://twitter.com/cadenceworkflow",children:"Twitter"})," where you can keep up to date with what is happening in the community. We will be using these social media accounts to share news, articles, stories and links related to Cadence - so please follow us!"]}),"\n",(0,i.jsx)(t.p,{children:"And don\u2019t forget to share your news with us. We are looking forward to receiving your feedback and comments. The more we interact - the more we build our community!"})]})}function m(e={}){const{wrapper:t}={...(0,a.R)(),...e.components};return t?(0,i.jsx)(t,{...e,children:(0,i.jsx)(d,{...e})}):d(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>s,x:()=>c});var o=n(6540);const i={},a=o.createContext(i);function s(e){const t=o.useContext(a);return o.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function c(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:s(e.components),o.createElement(a.Provider,{value:t},e.children)}},7683:e=>{e.exports=JSON.parse('{"permalink":"/Cadence-Docs/blog/2022/04/30/community-spotlight-update-april-2022","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2022-04-30-community-spotlight-update-april-2022.md","source":"@site/blog/2022-04-30-community-spotlight-update-april-2022.md","title":"Cadence Community Spotlight Update - April 2022","description":"Welcome to our Cadence Community Spotlight update!","date":"2022-04-30T00:00:00.000Z","tags":[{"inline":false,"label":"Community Spotlight","permalink":"/Cadence-Docs/blog/tags/community-spotlights","description":"Community Spotlight tag description"}],"readingTime":2.955,"hasTruncateMarker":true,"authors":[{"name":"Sharan Foga","title":"Director of Operations & Customer Success @ Encube Technologies","url":"https://www.linkedin.com/in/sfoga/","page":{"permalink":"/Cadence-Docs/blog/authors/sharanf"},"socials":{"linkedin":"https://www.linkedin.com/in/sfoga/","github":"https://github.com/sharanf"},"imageURL":"https://github.com/sharanf.png","key":"sharanf"}],"frontMatter":{"title":"Cadence Community Spotlight Update - April 2022","date":"2022-04-30T00:00:00.000Z","authors":"sharanf","tags":["community-spotlight"]},"unlisted":false,"prevItem":{"title":"Cadence Community Spotlight Update - May 2022","permalink":"/Cadence-Docs/blog/2022/05/31/community-spotlight-update-may-2022"},"nextItem":{"title":"Cadence Community Spotlight Update - March 2022","permalink":"/Cadence-Docs/blog/2022/03/31/community-spotlight-update-march-2022"}}')}}]); \ No newline at end of file diff --git a/assets/js/98f77afb.c48f878c.js b/assets/js/98f77afb.c48f878c.js deleted file mode 100644 index 963401d10..000000000 --- a/assets/js/98f77afb.c48f878c.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[1193],{1786:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>c,contentTitle:()=>r,default:()=>m,frontMatter:()=>s,metadata:()=>o,toc:()=>l});var o=n(64),i=n(4848),a=n(8453);const s={title:"Cadence Community Spotlight Update - April 2022",date:new Date("2022-04-30T00:00:00.000Z"),authors:"sharanf",tags:["community-spotlight"]},r=void 0,c={authorsImageUrls:[void 0]},l=[{value:"SD Times Names Cadence Open Source Project of the Week",id:"sd-times-names-cadence-open-source-project-of-the-week",level:2},{value:"Follow Us on LinkedIn and Twitter!",id:"follow-us-on-linkedin-and-twitter",level:2}];function d(e){const t={a:"a",em:"em",h2:"h2",p:"p",...(0,a.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(t.p,{children:"Welcome to our Cadence Community Spotlight update!"}),"\n",(0,i.jsx)(t.p,{children:"This is our monthly blog post series focused on news from in and around the Cadence community."}),"\n",(0,i.jsx)(t.p,{children:"Please see below for a short activity roundup of what has happened recently in the community."}),"\n",(0,i.jsx)(t.h2,{id:"sd-times-names-cadence-open-source-project-of-the-week",children:"SD Times Names Cadence Open Source Project of the Week"}),"\n",(0,i.jsxs)(t.p,{children:["In April Cadence was named as open source project of the week by the SD Times. Being named gives the project some great publicity and means the project is getting noticed. You can find a link to the article in the ",(0,i.jsx)(t.em,{children:"Cadence in the News"})," section below."]}),"\n",(0,i.jsx)(t.h2,{id:"follow-us-on-linkedin-and-twitter",children:"Follow Us on LinkedIn and Twitter!"}),"\n",(0,i.jsxs)(t.p,{children:["We have now set up Cadence accounts on ",(0,i.jsx)(t.a,{href:"https://www.linkedin.com/company/cadenceworkflow/",children:"LinkedIn"})," and ",(0,i.jsx)(t.a,{href:"https://twitter.com/cadenceworkflow",children:"Twitter"})," where you can keep up to date with what is happening in the community. We will be using these social media accounts to share news, articles, stories and links related to Cadence - so please follow us!"]}),"\n",(0,i.jsx)(t.p,{children:"And don\u2019t forget to share your news with us. We are looking forward to receiving your feedback and comments. The more we interact - the more we build our community!"})]})}function m(e={}){const{wrapper:t}={...(0,a.R)(),...e.components};return t?(0,i.jsx)(t,{...e,children:(0,i.jsx)(d,{...e})}):d(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>s,x:()=>r});var o=n(6540);const i={},a=o.createContext(i);function s(e){const t=o.useContext(a);return o.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function r(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:s(e.components),o.createElement(a.Provider,{value:t},e.children)}},64:e=>{e.exports=JSON.parse('{"permalink":"/blog/2022/04/30/community-spotlight-update-april-2022","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2022-04-30-community-spotlight-update-april-2022.md","source":"@site/blog/2022-04-30-community-spotlight-update-april-2022.md","title":"Cadence Community Spotlight Update - April 2022","description":"Welcome to our Cadence Community Spotlight update!","date":"2022-04-30T00:00:00.000Z","tags":[{"inline":false,"label":"Community Spotlight","permalink":"/blog/tags/community-spotlights","description":"Community Spotlight tag description"}],"readingTime":2.955,"hasTruncateMarker":true,"authors":[{"name":"Sharan Foga","title":"Director of Operations & Customer Success @ Encube Technologies","url":"https://www.linkedin.com/in/sfoga/","page":{"permalink":"/blog/authors/sharanf"},"socials":{"linkedin":"https://www.linkedin.com/in/sfoga/","github":"https://github.com/sharanf"},"imageURL":"https://github.com/sharanf.png","key":"sharanf"}],"frontMatter":{"title":"Cadence Community Spotlight Update - April 2022","date":"2022-04-30T00:00:00.000Z","authors":"sharanf","tags":["community-spotlight"]},"unlisted":false,"prevItem":{"title":"Cadence Community Spotlight Update - May 2022","permalink":"/blog/2022/05/31/community-spotlight-update-may-2022"},"nextItem":{"title":"Cadence Community Spotlight Update - March 2022","permalink":"/blog/2022/03/31/community-spotlight-update-march-2022"}}')}}]); \ No newline at end of file diff --git a/assets/js/99c90dae.2490f04f.js b/assets/js/99c90dae.2490f04f.js new file mode 100644 index 000000000..ff5fb21a3 --- /dev/null +++ b/assets/js/99c90dae.2490f04f.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[9203],{2771:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>a,contentTitle:()=>i,default:()=>p,frontMatter:()=>r,metadata:()=>c,toc:()=>d});const c=JSON.parse('{"id":"concepts/index","title":"Introduction","description":"Cadence is a new developer friendly way to develop distributed applications.","source":"@site/docs/03-concepts/index.md","sourceDirName":"03-concepts","slug":"/concepts/","permalink":"/Cadence-Docs/docs/concepts/","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/03-concepts/index.md","tags":[],"version":"current","frontMatter":{"layout":"default","title":"Introduction","permalink":"/docs/concepts"},"sidebar":"docsSidebar","previous":{"title":"Big data and ML","permalink":"/Cadence-Docs/docs/use-cases/big-ml"},"next":{"title":"Activities","permalink":"/Cadence-Docs/docs/concepts/activities"}}');var o=n(4848),s=n(8453);const r={layout:"default",title:"Introduction",permalink:"/docs/concepts"},i="Concepts",a={},d=[];function l(e){const t={a:"a",h1:"h1",header:"header",p:"p",...(0,s.R)(),...e.components};return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsx)(t.header,{children:(0,o.jsx)(t.h1,{id:"concepts",children:"Concepts"})}),"\n",(0,o.jsx)(t.p,{children:"Cadence is a new developer friendly way to develop distributed applications."}),"\n",(0,o.jsxs)(t.p,{children:["It borrows the core terminology from the workflow-automation space. So its concepts include ",(0,o.jsx)(t.a,{href:"/docs/concepts/workflows",children:"workflows"})," and ",(0,o.jsx)(t.a,{href:"/docs/concepts/activities",children:"activities"}),". Workflows can react to ",(0,o.jsx)(t.a,{href:"/docs/concepts/events",children:"events"})," and return internal state through ",(0,o.jsx)(t.a,{href:"/docs/concepts/queries",children:"queries"}),"."]}),"\n",(0,o.jsxs)(t.p,{children:["The ",(0,o.jsx)(t.a,{href:"/docs/concepts/topology",children:"deployment topology"})," explains how all these concepts are mapped to deployable software components."]}),"\n",(0,o.jsxs)(t.p,{children:["The ",(0,o.jsx)(t.a,{href:"/docs/concepts/http-api",children:"HTTP API reference"})," describes how to use HTTP API to interact with Cadence server."]})]})}function p(e={}){const{wrapper:t}={...(0,s.R)(),...e.components};return t?(0,o.jsx)(t,{...e,children:(0,o.jsx)(l,{...e})}):l(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>r,x:()=>i});var c=n(6540);const o={},s=c.createContext(o);function r(e){const t=c.useContext(s);return c.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function i(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:r(e.components),c.createElement(s.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/99c90dae.e8bf1305.js b/assets/js/99c90dae.e8bf1305.js deleted file mode 100644 index a8d58565f..000000000 --- a/assets/js/99c90dae.e8bf1305.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[9203],{2771:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>a,contentTitle:()=>i,default:()=>p,frontMatter:()=>r,metadata:()=>o,toc:()=>d});const o=JSON.parse('{"id":"concepts/index","title":"Introduction","description":"Cadence is a new developer friendly way to develop distributed applications.","source":"@site/docs/03-concepts/index.md","sourceDirName":"03-concepts","slug":"/concepts/","permalink":"/docs/concepts/","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/03-concepts/index.md","tags":[],"version":"current","frontMatter":{"layout":"default","title":"Introduction","permalink":"/docs/concepts"},"sidebar":"docsSidebar","previous":{"title":"Big data and ML","permalink":"/docs/use-cases/big-ml"},"next":{"title":"Activities","permalink":"/docs/concepts/activities"}}');var c=n(4848),s=n(8453);const r={layout:"default",title:"Introduction",permalink:"/docs/concepts"},i="Concepts",a={},d=[];function l(e){const t={a:"a",h1:"h1",header:"header",p:"p",...(0,s.R)(),...e.components};return(0,c.jsxs)(c.Fragment,{children:[(0,c.jsx)(t.header,{children:(0,c.jsx)(t.h1,{id:"concepts",children:"Concepts"})}),"\n",(0,c.jsx)(t.p,{children:"Cadence is a new developer friendly way to develop distributed applications."}),"\n",(0,c.jsxs)(t.p,{children:["It borrows the core terminology from the workflow-automation space. So its concepts include ",(0,c.jsx)(t.a,{href:"/docs/concepts/workflows",children:"workflows"})," and ",(0,c.jsx)(t.a,{href:"/docs/concepts/activities",children:"activities"}),". Workflows can react to ",(0,c.jsx)(t.a,{href:"/docs/concepts/events",children:"events"})," and return internal state through ",(0,c.jsx)(t.a,{href:"/docs/concepts/queries",children:"queries"}),"."]}),"\n",(0,c.jsxs)(t.p,{children:["The ",(0,c.jsx)(t.a,{href:"/docs/concepts/topology",children:"deployment topology"})," explains how all these concepts are mapped to deployable software components."]}),"\n",(0,c.jsxs)(t.p,{children:["The ",(0,c.jsx)(t.a,{href:"/docs/concepts/http-api",children:"HTTP API reference"})," describes how to use HTTP API to interact with Cadence server."]})]})}function p(e={}){const{wrapper:t}={...(0,s.R)(),...e.components};return t?(0,c.jsx)(t,{...e,children:(0,c.jsx)(l,{...e})}):l(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>r,x:()=>i});var o=n(6540);const c={},s=o.createContext(c);function r(e){const t=o.useContext(s);return o.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function i(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(c):e.components||c:r(e.components),o.createElement(s.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/9e9bbe09.0d260b5d.js b/assets/js/9e9bbe09.e35cf0d2.js similarity index 69% rename from assets/js/9e9bbe09.0d260b5d.js rename to assets/js/9e9bbe09.e35cf0d2.js index ea2065666..08bbd9f04 100644 --- a/assets/js/9e9bbe09.0d260b5d.js +++ b/assets/js/9e9bbe09.e35cf0d2.js @@ -1 +1 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[3718],{9118:(e,i,n)=>{n.r(i),n.d(i,{assets:()=>s,contentTitle:()=>c,default:()=>h,frontMatter:()=>r,metadata:()=>t,toc:()=>l});var t=n(9426),o=n(4848),a=n(8453);const r={title:"Cadence non-derministic errors common question Q&A (part 1)",date:new Date("2024-03-10T00:00:00.000Z"),authors:"chopincode",tags:["deep-dive"]},c=void 0,s={authorsImageUrls:[void 0]},l=[{value:"If I change code logic inside an Cadence activity (for example, my activity is calling database A but now I want it to call database B), will it trigger an non-deterministic error?",id:"if-i-change-code-logic-inside-an-cadence-activity-for-example-my-activity-is-calling-database-a-but-now-i-want-it-to-call-database-b--will-it-trigger-an-non-deterministic-error",level:3},{value:"Does changing the workflow definition trigger non-determinstic errors?",id:"does-changing-the-workflow-definition-trigger-non-determinstic-errors",level:3}];function d(e){const i={h3:"h3",li:"li",p:"p",ul:"ul",...(0,a.R)(),...e.components};return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsx)(i.h3,{id:"if-i-change-code-logic-inside-an-cadence-activity-for-example-my-activity-is-calling-database-a-but-now-i-want-it-to-call-database-b--will-it-trigger-an-non-deterministic-error",children:"If I change code logic inside an Cadence activity (for example, my activity is calling database A but now I want it to call database B), will it trigger an non-deterministic error?"}),"\n",(0,o.jsxs)(i.p,{children:[(0,o.jsx)("b",{children:"NO"}),". This change will not trigger non-deterministic error."]}),"\n",(0,o.jsx)(i.p,{children:"An Activity is the smallest unit of execution for Cadence and what happens inside activities are not recorded as historical events and therefore will not be replayed. In short, this change is deterministic and it is fine to modify logic inside activities."}),"\n",(0,o.jsx)(i.h3,{id:"does-changing-the-workflow-definition-trigger-non-determinstic-errors",children:"Does changing the workflow definition trigger non-determinstic errors?"}),"\n",(0,o.jsxs)(i.p,{children:[(0,o.jsx)("b",{children:"YES"}),". This is a very typical non-deterministic error."]}),"\n",(0,o.jsx)(i.p,{children:"When a new workflow code change is deployed, Cadence will find if it is compatible with\nCadence history. Changes to workflow definition will fail the replay process of Cadence\nas it finds the new workflow definition imcompatible with previous historical events."}),"\n",(0,o.jsx)(i.p,{children:"Here is a list of common workflow definition changes."}),"\n",(0,o.jsxs)(i.ul,{children:["\n",(0,o.jsx)(i.li,{children:"Changing workflow parameter counts"}),"\n",(0,o.jsx)(i.li,{children:"Changing workflow parameter types"}),"\n",(0,o.jsx)(i.li,{children:"Changing workflow return types"}),"\n"]}),"\n",(0,o.jsx)(i.p,{children:"The following changes are not categorized as definition changes and therefore will not\ntrigger non-deterministic errors."}),"\n",(0,o.jsxs)(i.ul,{children:["\n",(0,o.jsx)(i.li,{children:"Changes of workflow return values"}),"\n",(0,o.jsx)(i.li,{children:"Changing workflow parameter names as they are just positional"}),"\n"]})]})}function h(e={}){const{wrapper:i}={...(0,a.R)(),...e.components};return i?(0,o.jsx)(i,{...e,children:(0,o.jsx)(d,{...e})}):d(e)}},8453:(e,i,n)=>{n.d(i,{R:()=>r,x:()=>c});var t=n(6540);const o={},a=t.createContext(o);function r(e){const i=t.useContext(a);return t.useMemo((function(){return"function"==typeof e?e(i):{...i,...e}}),[i,e])}function c(e){let i;return i=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:r(e.components),t.createElement(a.Provider,{value:i},e.children)}},9426:e=>{e.exports=JSON.parse('{"permalink":"/blog/2024/02/15/cadence-non-deterministic-common-qa","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2024-02-15-cadence-non-deterministic-common-qa.md","source":"@site/blog/2024-02-15-cadence-non-deterministic-common-qa.md","title":"Cadence non-derministic errors common question Q&A (part 1)","description":"If I change code logic inside an Cadence activity (for example, my activity is calling database A but now I want it to call database B), will it trigger an non-deterministic error?","date":"2024-03-10T00:00:00.000Z","tags":[{"inline":false,"label":"Deep Dives","permalink":"/blog/tags/deep-dives","description":"Deep Dives tag description"}],"readingTime":2.625,"hasTruncateMarker":true,"authors":[{"name":"Chris Qin","title":"Applications Developer @ Uber","url":"https://www.linkedin.com/in/chrisqin0610/","page":{"permalink":"/blog/authors/chopincode"},"socials":{"linkedin":"https://www.linkedin.com/in/chrisqin0610/","github":"https://github.com/chopincode"},"imageURL":"https://github.com/chopincode.png","key":"chopincode"}],"frontMatter":{"title":"Cadence non-derministic errors common question Q&A (part 1)","date":"2024-03-10T00:00:00.000Z","authors":"chopincode","tags":["deep-dive"]},"unlisted":false,"prevItem":{"title":"2024 Cadence Yearly Roadmap Update","permalink":"/blog/2024/07/11/2024-07-11-yearly-roadmap-update/yearly-roadmap-update"},"nextItem":{"title":"Cadence Community Spotlight Update - November 2023","permalink":"/blog/2023/11/30/community-spotlight-update-november-2023"}}')}}]); \ No newline at end of file +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[3718],{9118:(e,i,n)=>{n.r(i),n.d(i,{assets:()=>s,contentTitle:()=>c,default:()=>h,frontMatter:()=>r,metadata:()=>t,toc:()=>l});var t=n(9426),o=n(4848),a=n(8453);const r={title:"Cadence non-derministic errors common question Q&A (part 1)",date:new Date("2024-03-10T00:00:00.000Z"),authors:"chopincode",tags:["deep-dive"]},c=void 0,s={authorsImageUrls:[void 0]},l=[{value:"If I change code logic inside an Cadence activity (for example, my activity is calling database A but now I want it to call database B), will it trigger an non-deterministic error?",id:"if-i-change-code-logic-inside-an-cadence-activity-for-example-my-activity-is-calling-database-a-but-now-i-want-it-to-call-database-b--will-it-trigger-an-non-deterministic-error",level:3},{value:"Does changing the workflow definition trigger non-determinstic errors?",id:"does-changing-the-workflow-definition-trigger-non-determinstic-errors",level:3}];function d(e){const i={h3:"h3",li:"li",p:"p",ul:"ul",...(0,a.R)(),...e.components};return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsx)(i.h3,{id:"if-i-change-code-logic-inside-an-cadence-activity-for-example-my-activity-is-calling-database-a-but-now-i-want-it-to-call-database-b--will-it-trigger-an-non-deterministic-error",children:"If I change code logic inside an Cadence activity (for example, my activity is calling database A but now I want it to call database B), will it trigger an non-deterministic error?"}),"\n",(0,o.jsxs)(i.p,{children:[(0,o.jsx)("b",{children:"NO"}),". This change will not trigger non-deterministic error."]}),"\n",(0,o.jsx)(i.p,{children:"An Activity is the smallest unit of execution for Cadence and what happens inside activities are not recorded as historical events and therefore will not be replayed. In short, this change is deterministic and it is fine to modify logic inside activities."}),"\n",(0,o.jsx)(i.h3,{id:"does-changing-the-workflow-definition-trigger-non-determinstic-errors",children:"Does changing the workflow definition trigger non-determinstic errors?"}),"\n",(0,o.jsxs)(i.p,{children:[(0,o.jsx)("b",{children:"YES"}),". This is a very typical non-deterministic error."]}),"\n",(0,o.jsx)(i.p,{children:"When a new workflow code change is deployed, Cadence will find if it is compatible with\nCadence history. Changes to workflow definition will fail the replay process of Cadence\nas it finds the new workflow definition imcompatible with previous historical events."}),"\n",(0,o.jsx)(i.p,{children:"Here is a list of common workflow definition changes."}),"\n",(0,o.jsxs)(i.ul,{children:["\n",(0,o.jsx)(i.li,{children:"Changing workflow parameter counts"}),"\n",(0,o.jsx)(i.li,{children:"Changing workflow parameter types"}),"\n",(0,o.jsx)(i.li,{children:"Changing workflow return types"}),"\n"]}),"\n",(0,o.jsx)(i.p,{children:"The following changes are not categorized as definition changes and therefore will not\ntrigger non-deterministic errors."}),"\n",(0,o.jsxs)(i.ul,{children:["\n",(0,o.jsx)(i.li,{children:"Changes of workflow return values"}),"\n",(0,o.jsx)(i.li,{children:"Changing workflow parameter names as they are just positional"}),"\n"]})]})}function h(e={}){const{wrapper:i}={...(0,a.R)(),...e.components};return i?(0,o.jsx)(i,{...e,children:(0,o.jsx)(d,{...e})}):d(e)}},8453:(e,i,n)=>{n.d(i,{R:()=>r,x:()=>c});var t=n(6540);const o={},a=t.createContext(o);function r(e){const i=t.useContext(a);return t.useMemo((function(){return"function"==typeof e?e(i):{...i,...e}}),[i,e])}function c(e){let i;return i=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:r(e.components),t.createElement(a.Provider,{value:i},e.children)}},9426:e=>{e.exports=JSON.parse('{"permalink":"/Cadence-Docs/blog/2024/02/15/cadence-non-deterministic-common-qa","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2024-02-15-cadence-non-deterministic-common-qa.md","source":"@site/blog/2024-02-15-cadence-non-deterministic-common-qa.md","title":"Cadence non-derministic errors common question Q&A (part 1)","description":"If I change code logic inside an Cadence activity (for example, my activity is calling database A but now I want it to call database B), will it trigger an non-deterministic error?","date":"2024-03-10T00:00:00.000Z","tags":[{"inline":false,"label":"Deep Dives","permalink":"/Cadence-Docs/blog/tags/deep-dives","description":"Deep Dives tag description"}],"readingTime":2.625,"hasTruncateMarker":true,"authors":[{"name":"Chris Qin","title":"Applications Developer @ Uber","url":"https://www.linkedin.com/in/chrisqin0610/","page":{"permalink":"/Cadence-Docs/blog/authors/chopincode"},"socials":{"linkedin":"https://www.linkedin.com/in/chrisqin0610/","github":"https://github.com/chopincode"},"imageURL":"https://github.com/chopincode.png","key":"chopincode"}],"frontMatter":{"title":"Cadence non-derministic errors common question Q&A (part 1)","date":"2024-03-10T00:00:00.000Z","authors":"chopincode","tags":["deep-dive"]},"unlisted":false,"prevItem":{"title":"2024 Cadence Yearly Roadmap Update","permalink":"/Cadence-Docs/blog/2024/07/11/2024-07-11-yearly-roadmap-update/yearly-roadmap-update"},"nextItem":{"title":"Cadence Community Spotlight Update - November 2023","permalink":"/Cadence-Docs/blog/2023/11/30/community-spotlight-update-november-2023"}}')}}]); \ No newline at end of file diff --git a/assets/js/a17e1a1b.5089a5b2.js b/assets/js/a17e1a1b.5089a5b2.js new file mode 100644 index 000000000..68313f9e2 --- /dev/null +++ b/assets/js/a17e1a1b.5089a5b2.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[9090],{2622:e=>{e.exports=JSON.parse('{"tags":[{"label":"Announcement","permalink":"/Cadence-Docs/blog/tags/announcements","description":"Announcement tag description","count":7},{"label":"Deep Dives","permalink":"/Cadence-Docs/blog/tags/deep-dives","description":"Deep Dives tag description","count":10},{"label":"Cadence Operations","permalink":"/Cadence-Docs/blog/tags/cadence-operations","description":"Cadence Operations tag description","count":2},{"label":"Roadmap","permalink":"/Cadence-Docs/blog/tags/roadmap","description":"Roadmap tag description","count":3},{"label":"Community Spotlight","permalink":"/Cadence-Docs/blog/tags/community-spotlights","description":"Community Spotlight tag description","count":20},{"label":"Introduction to Cadence","permalink":"/Cadence-Docs/blog/tags/introduction-to-cadence","description":"Introduction to Cadence tag description","count":5},{"label":"Testing","permalink":"/Cadence-Docs/blog/tags/testing","description":"Testing tag description","count":1},{"label":"Releases","permalink":"/Cadence-Docs/blog/tags/releases","description":"Releases tag description","count":2}]}')}}]); \ No newline at end of file diff --git a/assets/js/a197b989.5019c634.js b/assets/js/a197b989.86ac0e2d.js similarity index 74% rename from assets/js/a197b989.5019c634.js rename to assets/js/a197b989.86ac0e2d.js index 441854f77..cd9bb9af3 100644 --- a/assets/js/a197b989.5019c634.js +++ b/assets/js/a197b989.86ac0e2d.js @@ -1 +1 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[6975],{5905:(e,t,o)=>{o.r(t),o.d(t,{assets:()=>s,contentTitle:()=>c,default:()=>h,frontMatter:()=>a,metadata:()=>r,toc:()=>l});var r=o(5105),n=o(4848),i=o(8453);const a={title:"Write your first workflow with Cadence",date:new Date("2023-07-16T00:00:00.000Z"),authors:"chopincode",tags:["deep-dive","introduction-to-cadence"]},c=void 0,s={authorsImageUrls:[void 0]},l=[];function d(e){const t={a:"a",code:"code",img:"img",p:"p",pre:"pre",...(0,i.R)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsxs)(t.p,{children:["We have covered ",(0,n.jsx)(t.a,{href:"/blog/2023/06/28/components-of-cadence-application-setup",children:"basic components of Cadence"})," and ",(0,n.jsx)(t.a,{href:"/blog/2023/07/05/implement-cadence-worker-from-scratch",children:"how to implement a Cadence worker on local environment"})," in previous blogs. In this blog, let's write your very first HelloWorld workflow with Cadence. I've started the Cadence backend server in background and registered a domain named ",(0,n.jsx)(t.code,{children:"test-domain"}),". You may use the code snippet for the worker service in ",(0,n.jsx)(t.a,{href:"/blog/2023/07/05/implement-cadence-worker-from-scratch",children:"this blog"})," Let's first write a activity, which takes a single string argument and print a log in the console."]}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{className:"language-go",children:'func helloWorldActivity(ctx context.Context, name string) (string, error) {\n\tlogger := activity.GetLogger(ctx)\n\tlogger.Info("helloworld activity started")\n\treturn "Hello " + name + "!", nil\n}\n'})}),"\n",(0,n.jsx)(t.p,{children:"Then let's write a workflow that invokes this activity"}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{className:"language-go",children:'func helloWorldWorkflow(ctx workflow.Context, name string) error {\n\tao := workflow.ActivityOptions{\n\t\tScheduleToStartTimeout: time.Minute,\n\t\tStartToCloseTimeout: time.Minute,\n\t\tHeartbeatTimeout: time.Second * 20,\n\t}\n\tctx = workflow.WithActivityOptions(ctx, ao)\n\n\tlogger := workflow.GetLogger(ctx)\n\tlogger.Info("helloworld workflow started")\n\tvar helloworldResult string\n\terr := workflow.ExecuteActivity(ctx, helloWorldActivity, name).Get(ctx, &helloworldResult)\n\tif err != nil {\n\t\tlogger.Error("Activity failed.", zap.Error(err))\n\t\treturn err\n\t}\n\n\tlogger.Info("Workflow completed.", zap.String("Result", helloworldResult))\n\n\treturn nil\n}\n'})}),"\n",(0,n.jsxs)(t.p,{children:["Don't forget to register your workflow and activity to your worker in the ",(0,n.jsx)(t.code,{children:"init"})," function."]}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{className:"language-go",children:"func init() {\n workflow.Register(helloWorldWorkflow)\n activity.Register(helloWorldActivity)\n}\n"})}),"\n",(0,n.jsx)(t.p,{children:"Now restart your worker and you will only see logs like"}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{className:"language-bash",children:'2023-07-16T12:07:33.165-0700 INFO internal/internal_worker.go:834 Started Workflow Worker {"Domain": "test-domain", "TaskList": "test-worker", "WorkerID": "13585@uber-C02F18EQMD6R@test-worker@42f8a76f-cc42-4a0d-a001-7f7959d5d623"}\n2023-07-16T12:07:33.175-0700 INFO internal/internal_worker.go:859 Started Activity Worker {"Domain": "test-domain", "TaskList": "test-worker", "WorkerID": "13585@uber-C02F18EQMD6R@test-worker@42f8a76f-cc42-4a0d-a001-7f7959d5d623"}\n2023-07-16T12:07:33.175-0700 INFO cadence-worker/code.go:84 Started Worker. {"worker": "test-worker"}\n'})}),"\n",(0,n.jsx)(t.p,{children:"Let's try to run a Cadence workflow using Cadence CLI."}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{className:"language-bash",children:"cadence --env development --domain test-domain workflow start --et 60 --tl test-worker --workflow_type main.helloWorldWorkflow --input '\"World\"'\n"})}),"\n",(0,n.jsx)(t.p,{children:"You should see the Hello World log such like"}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{className:"language-bash",children:'2023-07-16T12:09:11.858-0700 INFO cadence-worker/code.go:104 Workflow completed. {"Domain": "test-domain", "TaskList": "test-worker", "WorkerID": "13585@uber-C02F18EQMD6R@test-worker@42f8a76f-cc42-4a0d-a001-7f7959d5d623", "WorkflowType": "main.helloWorldWorkflow", "WorkflowID": "8cb7fb2a-243b-43f8-82d9-48d758c9d62f", "RunID": "3c070007-89c3-4e00-a039-19a86b2f9224", "Result": "Hello World!"}\n'})}),"\n",(0,n.jsx)(t.p,{children:"Congratulations, you have successfully run your very first Cadence workflow."}),"\n",(0,n.jsxs)(t.p,{children:["For a bonus point, the Cadence team has also developed a demonstrative web dashboard to visualize the history of all workflows you have run when you start the Cadence server. Check ",(0,n.jsx)(t.a,{href:"http://localhost:8088",children:"http://localhost:8088"})," to see the dashboard like this."]}),"\n",(0,n.jsx)(t.p,{children:(0,n.jsx)(t.img,{alt:"cadencde-ui",src:o(6472).A+"",width:"3790",height:"674"})}),"\n",(0,n.jsxs)(t.p,{children:["This web portal persists all historical workflow you have run recently. Search for the domain you used for this tutorial. In our case, type ",(0,n.jsx)(t.code,{children:"test-domain"})," and hit enter. You may see a list of workflows with detailed information. Feel free to explore the web UI and raise your suggestions to our ",(0,n.jsx)(t.a,{href:"https://github.com/cadence-workflow/cadence-web",children:"Github repo"}),"."]}),"\n",(0,n.jsx)(t.p,{children:(0,n.jsx)(t.img,{alt:"cadence-ui-detailed",src:o(7277).A+"",width:"3790",height:"764"})}),"\n",(0,n.jsx)(t.p,{children:"For the incoming blogs, we will cover more advanced topics and use cases with Cadence."})]})}function h(e={}){const{wrapper:t}={...(0,i.R)(),...e.components};return t?(0,n.jsx)(t,{...e,children:(0,n.jsx)(d,{...e})}):d(e)}},6472:(e,t,o)=>{o.d(t,{A:()=>r});const r=o.p+"assets/images/cadence_ui-7a1200a6a9f9d11aa28452f0cd539b71.png"},7277:(e,t,o)=>{o.d(t,{A:()=>r});const r=o.p+"assets/images/cadence_ui_detailed-786dba0e7aa1f9048af4f0c1420c3ccf.png"},8453:(e,t,o)=>{o.d(t,{R:()=>a,x:()=>c});var r=o(6540);const n={},i=r.createContext(n);function a(e){const t=r.useContext(i);return r.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function c(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(n):e.components||n:a(e.components),r.createElement(i.Provider,{value:t},e.children)}},5105:e=>{e.exports=JSON.parse('{"permalink":"/blog/2023/07/16/2023-07-16-write-your-first-workflow-with-cadence/write-your-first-workflow-with-cadence","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2023-07-16-write-your-first-workflow-with-cadence/2023-07-16-write-your-first-workflow-with-cadence.md","source":"@site/blog/2023-07-16-write-your-first-workflow-with-cadence/2023-07-16-write-your-first-workflow-with-cadence.md","title":"Write your first workflow with Cadence","description":"We have covered basic components of Cadence and how to implement a Cadence worker on local environment in previous blogs. In this blog, let\'s write your very first HelloWorld workflow with Cadence. I\'ve started the Cadence backend server in background and registered a domain named test-domain. You may use the code snippet for the worker service in this blog Let\'s first write a activity, which takes a single string argument and print a log in the console.","date":"2023-07-16T00:00:00.000Z","tags":[{"inline":false,"label":"Deep Dives","permalink":"/blog/tags/deep-dives","description":"Deep Dives tag description"},{"inline":false,"label":"Introduction to Cadence","permalink":"/blog/tags/introduction-to-cadence","description":"Introduction to Cadence tag description"}],"readingTime":2.075,"hasTruncateMarker":true,"authors":[{"name":"Chris Qin","title":"Applications Developer @ Uber","url":"https://www.linkedin.com/in/chrisqin0610/","page":{"permalink":"/blog/authors/chopincode"},"socials":{"linkedin":"https://www.linkedin.com/in/chrisqin0610/","github":"https://github.com/chopincode"},"imageURL":"https://github.com/chopincode.png","key":"chopincode"}],"frontMatter":{"title":"Write your first workflow with Cadence","date":"2023-07-16T00:00:00.000Z","authors":"chopincode","tags":["deep-dive","introduction-to-cadence"]},"unlisted":false,"prevItem":{"title":"Cadence Community Spotlight Update - July 2023","permalink":"/blog/2023/07/31/community-spotlight-july-2023"},"nextItem":{"title":"Bad practices and Anti-patterns with Cadence (Part 1)","permalink":"/blog/2023/07/10/cadence-bad-practices-part-1"}}')}}]); \ No newline at end of file +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[6975],{5905:(e,t,o)=>{o.r(t),o.d(t,{assets:()=>s,contentTitle:()=>c,default:()=>h,frontMatter:()=>a,metadata:()=>r,toc:()=>l});var r=o(5105),n=o(4848),i=o(8453);const a={title:"Write your first workflow with Cadence",date:new Date("2023-07-16T00:00:00.000Z"),authors:"chopincode",tags:["deep-dive","introduction-to-cadence"]},c=void 0,s={authorsImageUrls:[void 0]},l=[];function d(e){const t={a:"a",code:"code",img:"img",p:"p",pre:"pre",...(0,i.R)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsxs)(t.p,{children:["We have covered ",(0,n.jsx)(t.a,{href:"/blog/2023/06/28/components-of-cadence-application-setup",children:"basic components of Cadence"})," and ",(0,n.jsx)(t.a,{href:"/blog/2023/07/05/implement-cadence-worker-from-scratch",children:"how to implement a Cadence worker on local environment"})," in previous blogs. In this blog, let's write your very first HelloWorld workflow with Cadence. I've started the Cadence backend server in background and registered a domain named ",(0,n.jsx)(t.code,{children:"test-domain"}),". You may use the code snippet for the worker service in ",(0,n.jsx)(t.a,{href:"/blog/2023/07/05/implement-cadence-worker-from-scratch",children:"this blog"})," Let's first write a activity, which takes a single string argument and print a log in the console."]}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{className:"language-go",children:'func helloWorldActivity(ctx context.Context, name string) (string, error) {\n\tlogger := activity.GetLogger(ctx)\n\tlogger.Info("helloworld activity started")\n\treturn "Hello " + name + "!", nil\n}\n'})}),"\n",(0,n.jsx)(t.p,{children:"Then let's write a workflow that invokes this activity"}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{className:"language-go",children:'func helloWorldWorkflow(ctx workflow.Context, name string) error {\n\tao := workflow.ActivityOptions{\n\t\tScheduleToStartTimeout: time.Minute,\n\t\tStartToCloseTimeout: time.Minute,\n\t\tHeartbeatTimeout: time.Second * 20,\n\t}\n\tctx = workflow.WithActivityOptions(ctx, ao)\n\n\tlogger := workflow.GetLogger(ctx)\n\tlogger.Info("helloworld workflow started")\n\tvar helloworldResult string\n\terr := workflow.ExecuteActivity(ctx, helloWorldActivity, name).Get(ctx, &helloworldResult)\n\tif err != nil {\n\t\tlogger.Error("Activity failed.", zap.Error(err))\n\t\treturn err\n\t}\n\n\tlogger.Info("Workflow completed.", zap.String("Result", helloworldResult))\n\n\treturn nil\n}\n'})}),"\n",(0,n.jsxs)(t.p,{children:["Don't forget to register your workflow and activity to your worker in the ",(0,n.jsx)(t.code,{children:"init"})," function."]}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{className:"language-go",children:"func init() {\n workflow.Register(helloWorldWorkflow)\n activity.Register(helloWorldActivity)\n}\n"})}),"\n",(0,n.jsx)(t.p,{children:"Now restart your worker and you will only see logs like"}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{className:"language-bash",children:'2023-07-16T12:07:33.165-0700 INFO internal/internal_worker.go:834 Started Workflow Worker {"Domain": "test-domain", "TaskList": "test-worker", "WorkerID": "13585@uber-C02F18EQMD6R@test-worker@42f8a76f-cc42-4a0d-a001-7f7959d5d623"}\n2023-07-16T12:07:33.175-0700 INFO internal/internal_worker.go:859 Started Activity Worker {"Domain": "test-domain", "TaskList": "test-worker", "WorkerID": "13585@uber-C02F18EQMD6R@test-worker@42f8a76f-cc42-4a0d-a001-7f7959d5d623"}\n2023-07-16T12:07:33.175-0700 INFO cadence-worker/code.go:84 Started Worker. {"worker": "test-worker"}\n'})}),"\n",(0,n.jsx)(t.p,{children:"Let's try to run a Cadence workflow using Cadence CLI."}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{className:"language-bash",children:"cadence --env development --domain test-domain workflow start --et 60 --tl test-worker --workflow_type main.helloWorldWorkflow --input '\"World\"'\n"})}),"\n",(0,n.jsx)(t.p,{children:"You should see the Hello World log such like"}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{className:"language-bash",children:'2023-07-16T12:09:11.858-0700 INFO cadence-worker/code.go:104 Workflow completed. {"Domain": "test-domain", "TaskList": "test-worker", "WorkerID": "13585@uber-C02F18EQMD6R@test-worker@42f8a76f-cc42-4a0d-a001-7f7959d5d623", "WorkflowType": "main.helloWorldWorkflow", "WorkflowID": "8cb7fb2a-243b-43f8-82d9-48d758c9d62f", "RunID": "3c070007-89c3-4e00-a039-19a86b2f9224", "Result": "Hello World!"}\n'})}),"\n",(0,n.jsx)(t.p,{children:"Congratulations, you have successfully run your very first Cadence workflow."}),"\n",(0,n.jsxs)(t.p,{children:["For a bonus point, the Cadence team has also developed a demonstrative web dashboard to visualize the history of all workflows you have run when you start the Cadence server. Check ",(0,n.jsx)(t.a,{href:"http://localhost:8088",children:"http://localhost:8088"})," to see the dashboard like this."]}),"\n",(0,n.jsx)(t.p,{children:(0,n.jsx)(t.img,{alt:"cadencde-ui",src:o(6472).A+"",width:"3790",height:"674"})}),"\n",(0,n.jsxs)(t.p,{children:["This web portal persists all historical workflow you have run recently. Search for the domain you used for this tutorial. In our case, type ",(0,n.jsx)(t.code,{children:"test-domain"})," and hit enter. You may see a list of workflows with detailed information. Feel free to explore the web UI and raise your suggestions to our ",(0,n.jsx)(t.a,{href:"https://github.com/cadence-workflow/cadence-web",children:"Github repo"}),"."]}),"\n",(0,n.jsx)(t.p,{children:(0,n.jsx)(t.img,{alt:"cadence-ui-detailed",src:o(7277).A+"",width:"3790",height:"764"})}),"\n",(0,n.jsx)(t.p,{children:"For the incoming blogs, we will cover more advanced topics and use cases with Cadence."})]})}function h(e={}){const{wrapper:t}={...(0,i.R)(),...e.components};return t?(0,n.jsx)(t,{...e,children:(0,n.jsx)(d,{...e})}):d(e)}},6472:(e,t,o)=>{o.d(t,{A:()=>r});const r=o.p+"assets/images/cadence_ui-7a1200a6a9f9d11aa28452f0cd539b71.png"},7277:(e,t,o)=>{o.d(t,{A:()=>r});const r=o.p+"assets/images/cadence_ui_detailed-786dba0e7aa1f9048af4f0c1420c3ccf.png"},8453:(e,t,o)=>{o.d(t,{R:()=>a,x:()=>c});var r=o(6540);const n={},i=r.createContext(n);function a(e){const t=r.useContext(i);return r.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function c(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(n):e.components||n:a(e.components),r.createElement(i.Provider,{value:t},e.children)}},5105:e=>{e.exports=JSON.parse('{"permalink":"/Cadence-Docs/blog/2023/07/16/2023-07-16-write-your-first-workflow-with-cadence/write-your-first-workflow-with-cadence","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2023-07-16-write-your-first-workflow-with-cadence/2023-07-16-write-your-first-workflow-with-cadence.md","source":"@site/blog/2023-07-16-write-your-first-workflow-with-cadence/2023-07-16-write-your-first-workflow-with-cadence.md","title":"Write your first workflow with Cadence","description":"We have covered basic components of Cadence and how to implement a Cadence worker on local environment in previous blogs. In this blog, let\'s write your very first HelloWorld workflow with Cadence. I\'ve started the Cadence backend server in background and registered a domain named test-domain. You may use the code snippet for the worker service in this blog Let\'s first write a activity, which takes a single string argument and print a log in the console.","date":"2023-07-16T00:00:00.000Z","tags":[{"inline":false,"label":"Deep Dives","permalink":"/Cadence-Docs/blog/tags/deep-dives","description":"Deep Dives tag description"},{"inline":false,"label":"Introduction to Cadence","permalink":"/Cadence-Docs/blog/tags/introduction-to-cadence","description":"Introduction to Cadence tag description"}],"readingTime":2.075,"hasTruncateMarker":true,"authors":[{"name":"Chris Qin","title":"Applications Developer @ Uber","url":"https://www.linkedin.com/in/chrisqin0610/","page":{"permalink":"/Cadence-Docs/blog/authors/chopincode"},"socials":{"linkedin":"https://www.linkedin.com/in/chrisqin0610/","github":"https://github.com/chopincode"},"imageURL":"https://github.com/chopincode.png","key":"chopincode"}],"frontMatter":{"title":"Write your first workflow with Cadence","date":"2023-07-16T00:00:00.000Z","authors":"chopincode","tags":["deep-dive","introduction-to-cadence"]},"unlisted":false,"prevItem":{"title":"Cadence Community Spotlight Update - July 2023","permalink":"/Cadence-Docs/blog/2023/07/31/community-spotlight-july-2023"},"nextItem":{"title":"Bad practices and Anti-patterns with Cadence (Part 1)","permalink":"/Cadence-Docs/blog/2023/07/10/cadence-bad-practices-part-1"}}')}}]); \ No newline at end of file diff --git a/assets/js/a3886376.0badbb19.js b/assets/js/a3886376.0badbb19.js deleted file mode 100644 index 222563aff..000000000 --- a/assets/js/a3886376.0badbb19.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[5349],{7159:e=>{e.exports=JSON.parse('{"author":{"name":"Ender Demirkaya","title":"Senior Manager at Uber, Cadence. Author of the Software Engineering Handbook","url":"https://www.linkedin.com/in/enderdemirkaya/","page":{"permalink":"/blog/authors/enderdemirkaya"},"socials":{"linkedin":"https://www.linkedin.com/in/enderdemirkaya/","github":"https://github.com/demirkayaender"},"imageURL":"https://github.com/demirkayaender.png","key":"enderdemirkaya","count":2},"listMetadata":{"permalink":"/blog/authors/enderdemirkaya","page":1,"postsPerPage":10,"totalPages":1,"totalCount":2,"blogDescription":"The latest news and updates from the Cadence team","blogTitle":"Cadence Blog"}}')}}]); \ No newline at end of file diff --git a/assets/js/a3dd65a2.584bd5fb.js b/assets/js/a3dd65a2.dbc5d255.js similarity index 82% rename from assets/js/a3dd65a2.584bd5fb.js rename to assets/js/a3dd65a2.dbc5d255.js index 76eda6c17..633120c30 100644 --- a/assets/js/a3dd65a2.584bd5fb.js +++ b/assets/js/a3dd65a2.dbc5d255.js @@ -1 +1 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[1485],{9983:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>r,contentTitle:()=>c,default:()=>d,frontMatter:()=>s,metadata:()=>a,toc:()=>l});var a=t(7186),o=t(4848),i=t(8453);const s={title:"Cadence Community Spotlight Update - February 2022",date:new Date("2022-02-28T00:00:00.000Z"),authors:"sharanf",tags:["community-spotlight"]},c=void 0,r={authorsImageUrls:[void 0]},l=[{value:"Announcements",id:"announcements",level:2},{value:"Community Supporting the Community",id:"community-supporting-the-community",level:2},{value:"Please Subscribe to our Youtube Channel",id:"please-subscribe-to-our-youtube-channel",level:2},{value:"Help us to Make Cadence even better",id:"help-us-to-make-cadence-even-better",level:2},{value:"Cadence Calendar",id:"cadence-calendar",level:2},{value:"Cadence Technical Office Hours",id:"cadence-technical-office-hours",level:2},{value:"Cadence in the News!",id:"cadence-in-the-news",level:2},{value:"Upcoming Events",id:"upcoming-events",level:2}];function h(e){const n={a:"a",h2:"h2",li:"li",p:"p",ul:"ul",...(0,i.R)(),...e.components};return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsx)(n.p,{children:"Welcome to the Cadence Community Spotlight update!"}),"\n",(0,o.jsx)(n.p,{children:"This is the second in our series of monthly updates focused on the Cadence community and news about what you have been doing with Cadence. We hope that you enjoyed last month's update and are keen to find out what has been happening."}),"\n",(0,o.jsx)(n.p,{children:"Please see below for a short activity roundup of what has happened recently in the community."}),"\n",(0,o.jsx)(n.h2,{id:"announcements",children:"Announcements"}),"\n",(0,o.jsxs)(n.p,{children:["Just in case you missed it the alpha version of the Cadence notification service has been released. Details can be found at the following link:\n",(0,o.jsx)(n.a,{href:"https://github.com/cadence-oss/cadence-notification/releases/tag/v0.0.1",children:"Cadence Notification Service"})]}),"\n",(0,o.jsx)(n.p,{children:"Thanks very much to everyone that worked on this!"}),"\n",(0,o.jsx)(n.h2,{id:"community-supporting-the-community",children:"Community Supporting the Community"}),"\n",(0,o.jsxs)(n.p,{children:["During February 16 questions were posted in the Cadence #support ",(0,o.jsx)(n.a,{href:"http://t.uber.com/cadence-slack",children:"Slack"})," channel from new Cadence users and existing community members looking for help and guidance. A very big thank you to the following community members who took the time to help others: Ali, David, Tamas Weisz, Liang Mei, Quanzheng Long, peaceChoi, Emrah Seker, Ben Slater and Sathyaraju Sekaran."]}),"\n",(0,o.jsx)(n.p,{children:"It\u2019s great to see that we are supporting each other - and that is exactly what communities do!"}),"\n",(0,o.jsx)(n.h2,{id:"please-subscribe-to-our-youtube-channel",children:"Please Subscribe to our Youtube Channel"}),"\n",(0,o.jsxs)(n.p,{children:["Did you know that we have a Youtube channel where you can find Cadence related videos and even the recording of our last meetup? Well we do and you can find it here:\n",(0,o.jsx)(n.a,{href:"https://www.youtube.com/channel/UC6H9Jsq4ZQ74g8coDgJu9ZA/videos",children:"Cadence Youtube"}),"\nPlease subscribe and let us know what other videos you\u2019d like to see there."]}),"\n",(0,o.jsx)(n.h2,{id:"help-us-to-make-cadence-even-better",children:"Help us to Make Cadence even better"}),"\n",(0,o.jsxs)(n.p,{children:["Are you interested in helping us improve Cadence? We are always looking for contributors to help share the workload. If you\u2019d like to help then you can start by taking a look at our list of ",(0,o.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence/issues",children:"open issues"})," on Github. We currently have 320 of them that need to be worked on so if you want to learn more about Cadence and solve some of the reported issues then please take a look and volunteer to fix it."]}),"\n",(0,o.jsx)(n.p,{children:"If you are new to Cadence or you\u2019d like to try something simple then we have some issues labelled as \u2018good first issue\u2019. These are a great place to start to get more Cadence experience."}),"\n",(0,o.jsx)(n.h2,{id:"cadence-calendar",children:"Cadence Calendar"}),"\n",(0,o.jsxs)(n.p,{children:["We have created a ",(0,o.jsx)(n.a,{href:"https://calendar.google.com/calendar/embed?src=e6r40gp3c2r01054id7e99dlac%40group.calendar.google.com&ctz=America%2FLos_Angeles",children:"Cadence public calendar"})," where we can highlight events, meetings, webinars etc that are planned around Cadence. The calendar will soon be available on the ",(0,o.jsx)(n.a,{href:"https://cadenceworkflow.io/",children:"Cadence website"})," so please make sure that you check it regularly.\nThis means that you can easily find out if there are any Cadence events planned that you would like to attend."]}),"\n",(0,o.jsx)(n.h2,{id:"cadence-technical-office-hours",children:"Cadence Technical Office Hours"}),"\n",(0,o.jsx)(n.p,{children:"Our second Technical Office Hours event took place on February 28th, Monday at 9AM PST. The main objective was provide Cadence support, respond to any questions about and to share any knowledge that you have learned. We always encourage community members to come along - and thanks very much to everyone who participated."}),"\n",(0,o.jsx)(n.h2,{id:"cadence-in-the-news",children:"Cadence in the News!"}),"\n",(0,o.jsx)(n.p,{children:"Below are a selection of Cadence related articles, blogs and whitepapers. Please take a look and feel free to share via your own social media channels."}),"\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsx)(n.li,{children:(0,o.jsx)(n.a,{href:"https://www.instaclustr.com/blog/spinning-apache-kafka-microservices-with-cadence-workflows/",children:"Spinning Apache Kafka\xae Microservices With Cadence Workflows"})}),"\n"]}),"\n",(0,o.jsx)(n.h2,{id:"upcoming-events",children:"Upcoming Events"}),"\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsx)(n.li,{children:(0,o.jsx)(n.a,{href:"https://info.instaclustr.com/webinar-apac-what-is-cadence.html",children:"Webinar : What is Cadence? And is it right for you? (APAC)"})}),"\n"]}),"\n",(0,o.jsxs)(n.p,{children:["If you have any news or topics you'd like us to include in our next update then please join our ",(0,o.jsx)(n.a,{href:"http://t.uber.com/cadence-slack",children:"Slack"}),"#community channel."]}),"\n",(0,o.jsxs)(n.p,{children:["Please remember that this update is for you - so if you have any comments or feedback that could help us improve it then please share it with us in the #community ",(0,o.jsx)(n.a,{href:"http://t.uber.com/cadence-slack",children:"Slack"})," channel."]})]})}function d(e={}){const{wrapper:n}={...(0,i.R)(),...e.components};return n?(0,o.jsx)(n,{...e,children:(0,o.jsx)(h,{...e})}):h(e)}},8453:(e,n,t)=>{t.d(n,{R:()=>s,x:()=>c});var a=t(6540);const o={},i=a.createContext(o);function s(e){const n=a.useContext(i);return a.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function c(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:s(e.components),a.createElement(i.Provider,{value:n},e.children)}},7186:e=>{e.exports=JSON.parse('{"permalink":"/blog/2022/02/28/community-spotlight-february-2022","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2022-02-28-community-spotlight-february-2022.md","source":"@site/blog/2022-02-28-community-spotlight-february-2022.md","title":"Cadence Community Spotlight Update - February 2022","description":"Welcome to the Cadence Community Spotlight update!","date":"2022-02-28T00:00:00.000Z","tags":[{"inline":false,"label":"Community Spotlight","permalink":"/blog/tags/community-spotlights","description":"Community Spotlight tag description"}],"readingTime":2.99,"hasTruncateMarker":true,"authors":[{"name":"Sharan Foga","title":"Director of Operations & Customer Success @ Encube Technologies","url":"https://www.linkedin.com/in/sfoga/","page":{"permalink":"/blog/authors/sharanf"},"socials":{"linkedin":"https://www.linkedin.com/in/sfoga/","github":"https://github.com/sharanf"},"imageURL":"https://github.com/sharanf.png","key":"sharanf"}],"frontMatter":{"title":"Cadence Community Spotlight Update - February 2022","date":"2022-02-28T00:00:00.000Z","authors":"sharanf","tags":["community-spotlight"]},"unlisted":false,"prevItem":{"title":"Cadence Community Spotlight Update - March 2022","permalink":"/blog/2022/03/31/community-spotlight-update-march-2022"},"nextItem":{"title":"Cadence Community Spotlight Update - January 2022","permalink":"/blog/2022/01/31/community-spotlight-january-2022"}}')}}]); \ No newline at end of file +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[1485],{9983:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>r,contentTitle:()=>c,default:()=>d,frontMatter:()=>s,metadata:()=>a,toc:()=>l});var a=t(7186),o=t(4848),i=t(8453);const s={title:"Cadence Community Spotlight Update - February 2022",date:new Date("2022-02-28T00:00:00.000Z"),authors:"sharanf",tags:["community-spotlight"]},c=void 0,r={authorsImageUrls:[void 0]},l=[{value:"Announcements",id:"announcements",level:2},{value:"Community Supporting the Community",id:"community-supporting-the-community",level:2},{value:"Please Subscribe to our Youtube Channel",id:"please-subscribe-to-our-youtube-channel",level:2},{value:"Help us to Make Cadence even better",id:"help-us-to-make-cadence-even-better",level:2},{value:"Cadence Calendar",id:"cadence-calendar",level:2},{value:"Cadence Technical Office Hours",id:"cadence-technical-office-hours",level:2},{value:"Cadence in the News!",id:"cadence-in-the-news",level:2},{value:"Upcoming Events",id:"upcoming-events",level:2}];function h(e){const n={a:"a",h2:"h2",li:"li",p:"p",ul:"ul",...(0,i.R)(),...e.components};return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsx)(n.p,{children:"Welcome to the Cadence Community Spotlight update!"}),"\n",(0,o.jsx)(n.p,{children:"This is the second in our series of monthly updates focused on the Cadence community and news about what you have been doing with Cadence. We hope that you enjoyed last month's update and are keen to find out what has been happening."}),"\n",(0,o.jsx)(n.p,{children:"Please see below for a short activity roundup of what has happened recently in the community."}),"\n",(0,o.jsx)(n.h2,{id:"announcements",children:"Announcements"}),"\n",(0,o.jsxs)(n.p,{children:["Just in case you missed it the alpha version of the Cadence notification service has been released. Details can be found at the following link:\n",(0,o.jsx)(n.a,{href:"https://github.com/cadence-oss/cadence-notification/releases/tag/v0.0.1",children:"Cadence Notification Service"})]}),"\n",(0,o.jsx)(n.p,{children:"Thanks very much to everyone that worked on this!"}),"\n",(0,o.jsx)(n.h2,{id:"community-supporting-the-community",children:"Community Supporting the Community"}),"\n",(0,o.jsxs)(n.p,{children:["During February 16 questions were posted in the Cadence #support ",(0,o.jsx)(n.a,{href:"http://t.uber.com/cadence-slack",children:"Slack"})," channel from new Cadence users and existing community members looking for help and guidance. A very big thank you to the following community members who took the time to help others: Ali, David, Tamas Weisz, Liang Mei, Quanzheng Long, peaceChoi, Emrah Seker, Ben Slater and Sathyaraju Sekaran."]}),"\n",(0,o.jsx)(n.p,{children:"It\u2019s great to see that we are supporting each other - and that is exactly what communities do!"}),"\n",(0,o.jsx)(n.h2,{id:"please-subscribe-to-our-youtube-channel",children:"Please Subscribe to our Youtube Channel"}),"\n",(0,o.jsxs)(n.p,{children:["Did you know that we have a Youtube channel where you can find Cadence related videos and even the recording of our last meetup? Well we do and you can find it here:\n",(0,o.jsx)(n.a,{href:"https://www.youtube.com/channel/UC6H9Jsq4ZQ74g8coDgJu9ZA/videos",children:"Cadence Youtube"}),"\nPlease subscribe and let us know what other videos you\u2019d like to see there."]}),"\n",(0,o.jsx)(n.h2,{id:"help-us-to-make-cadence-even-better",children:"Help us to Make Cadence even better"}),"\n",(0,o.jsxs)(n.p,{children:["Are you interested in helping us improve Cadence? We are always looking for contributors to help share the workload. If you\u2019d like to help then you can start by taking a look at our list of ",(0,o.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence/issues",children:"open issues"})," on Github. We currently have 320 of them that need to be worked on so if you want to learn more about Cadence and solve some of the reported issues then please take a look and volunteer to fix it."]}),"\n",(0,o.jsx)(n.p,{children:"If you are new to Cadence or you\u2019d like to try something simple then we have some issues labelled as \u2018good first issue\u2019. These are a great place to start to get more Cadence experience."}),"\n",(0,o.jsx)(n.h2,{id:"cadence-calendar",children:"Cadence Calendar"}),"\n",(0,o.jsxs)(n.p,{children:["We have created a ",(0,o.jsx)(n.a,{href:"https://calendar.google.com/calendar/embed?src=e6r40gp3c2r01054id7e99dlac%40group.calendar.google.com&ctz=America%2FLos_Angeles",children:"Cadence public calendar"})," where we can highlight events, meetings, webinars etc that are planned around Cadence. The calendar will soon be available on the ",(0,o.jsx)(n.a,{href:"https://cadenceworkflow.io/",children:"Cadence website"})," so please make sure that you check it regularly.\nThis means that you can easily find out if there are any Cadence events planned that you would like to attend."]}),"\n",(0,o.jsx)(n.h2,{id:"cadence-technical-office-hours",children:"Cadence Technical Office Hours"}),"\n",(0,o.jsx)(n.p,{children:"Our second Technical Office Hours event took place on February 28th, Monday at 9AM PST. The main objective was provide Cadence support, respond to any questions about and to share any knowledge that you have learned. We always encourage community members to come along - and thanks very much to everyone who participated."}),"\n",(0,o.jsx)(n.h2,{id:"cadence-in-the-news",children:"Cadence in the News!"}),"\n",(0,o.jsx)(n.p,{children:"Below are a selection of Cadence related articles, blogs and whitepapers. Please take a look and feel free to share via your own social media channels."}),"\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsx)(n.li,{children:(0,o.jsx)(n.a,{href:"https://www.instaclustr.com/blog/spinning-apache-kafka-microservices-with-cadence-workflows/",children:"Spinning Apache Kafka\xae Microservices With Cadence Workflows"})}),"\n"]}),"\n",(0,o.jsx)(n.h2,{id:"upcoming-events",children:"Upcoming Events"}),"\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsx)(n.li,{children:(0,o.jsx)(n.a,{href:"https://info.instaclustr.com/webinar-apac-what-is-cadence.html",children:"Webinar : What is Cadence? And is it right for you? (APAC)"})}),"\n"]}),"\n",(0,o.jsxs)(n.p,{children:["If you have any news or topics you'd like us to include in our next update then please join our ",(0,o.jsx)(n.a,{href:"http://t.uber.com/cadence-slack",children:"Slack"}),"#community channel."]}),"\n",(0,o.jsxs)(n.p,{children:["Please remember that this update is for you - so if you have any comments or feedback that could help us improve it then please share it with us in the #community ",(0,o.jsx)(n.a,{href:"http://t.uber.com/cadence-slack",children:"Slack"})," channel."]})]})}function d(e={}){const{wrapper:n}={...(0,i.R)(),...e.components};return n?(0,o.jsx)(n,{...e,children:(0,o.jsx)(h,{...e})}):h(e)}},8453:(e,n,t)=>{t.d(n,{R:()=>s,x:()=>c});var a=t(6540);const o={},i=a.createContext(o);function s(e){const n=a.useContext(i);return a.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function c(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:s(e.components),a.createElement(i.Provider,{value:n},e.children)}},7186:e=>{e.exports=JSON.parse('{"permalink":"/Cadence-Docs/blog/2022/02/28/community-spotlight-february-2022","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2022-02-28-community-spotlight-february-2022.md","source":"@site/blog/2022-02-28-community-spotlight-february-2022.md","title":"Cadence Community Spotlight Update - February 2022","description":"Welcome to the Cadence Community Spotlight update!","date":"2022-02-28T00:00:00.000Z","tags":[{"inline":false,"label":"Community Spotlight","permalink":"/Cadence-Docs/blog/tags/community-spotlights","description":"Community Spotlight tag description"}],"readingTime":2.99,"hasTruncateMarker":true,"authors":[{"name":"Sharan Foga","title":"Director of Operations & Customer Success @ Encube Technologies","url":"https://www.linkedin.com/in/sfoga/","page":{"permalink":"/Cadence-Docs/blog/authors/sharanf"},"socials":{"linkedin":"https://www.linkedin.com/in/sfoga/","github":"https://github.com/sharanf"},"imageURL":"https://github.com/sharanf.png","key":"sharanf"}],"frontMatter":{"title":"Cadence Community Spotlight Update - February 2022","date":"2022-02-28T00:00:00.000Z","authors":"sharanf","tags":["community-spotlight"]},"unlisted":false,"prevItem":{"title":"Cadence Community Spotlight Update - March 2022","permalink":"/Cadence-Docs/blog/2022/03/31/community-spotlight-update-march-2022"},"nextItem":{"title":"Cadence Community Spotlight Update - January 2022","permalink":"/Cadence-Docs/blog/2022/01/31/community-spotlight-january-2022"}}')}}]); \ No newline at end of file diff --git a/assets/js/a48fa53f.c7dd8c5d.js b/assets/js/a48fa53f.c7dd8c5d.js deleted file mode 100644 index e519586d8..000000000 --- a/assets/js/a48fa53f.c7dd8c5d.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[9387],{552:a=>{a.exports=JSON.parse('{"author":{"name":"Sharan Foga","title":"Director of Operations & Customer Success @ Encube Technologies","url":"https://www.linkedin.com/in/sfoga/","page":{"permalink":"/blog/authors/sharanf"},"socials":{"linkedin":"https://www.linkedin.com/in/sfoga/","github":"https://github.com/sharanf"},"imageURL":"https://github.com/sharanf.png","key":"sharanf","count":19},"listMetadata":{"permalink":"/blog/authors/sharanf/authors/2","page":2,"postsPerPage":10,"totalPages":2,"totalCount":19,"previousPage":"/blog/authors/sharanf","blogDescription":"The latest news and updates from the Cadence team","blogTitle":"Cadence Blog"}}')}}]); \ No newline at end of file diff --git a/assets/js/a4f1f4dd.7cf1027b.js b/assets/js/a4f1f4dd.7cf1027b.js new file mode 100644 index 000000000..6d74f4ca5 --- /dev/null +++ b/assets/js/a4f1f4dd.7cf1027b.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[9961],{2496:(e,i,t)=>{t.r(i),t.d(i,{assets:()=>d,contentTitle:()=>c,default:()=>h,frontMatter:()=>o,metadata:()=>n,toc:()=>l});const n=JSON.parse('{"id":"go-client/workflow-non-deterministic-error","title":"Workflow Non-deterministic errors","description":"Root cause of non-deterministic errors","source":"@site/docs/05-go-client/19-workflow-non-deterministic-error.md","sourceDirName":"05-go-client","slug":"/go-client/workflow-non-deterministic-error","permalink":"/Cadence-Docs/docs/go-client/workflow-non-deterministic-error","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/05-go-client/19-workflow-non-deterministic-error.md","tags":[],"version":"current","sidebarPosition":19,"frontMatter":{"layout":"default","title":"Workflow Non-deterministic errors","permalink":"/docs/go-client/workflow-non-deterministic-errors"}}');var r=t(4848),s=t(8453);const o={layout:"default",title:"Workflow Non-deterministic errors",permalink:"/docs/go-client/workflow-non-deterministic-errors"},c="Workflow Non-deterministic errors",d={},l=[{value:"Root cause of non-deterministic errors",id:"root-cause-of-non-deterministic-errors",level:2},{value:"Decision tasks of workflow",id:"decision-tasks-of-workflow",level:2},{value:"Categories of non-deterministic errors",id:"categories-of-non-deterministic-errors",level:2},{value:"1. Missing decisions",id:"1-missing-decisions",level:3},{value:"2. Extra decisions",id:"2-extra-decisions",level:3},{value:"3. Mismatched decisions",id:"3-mismatched-decisions",level:3},{value:"4. Decision state machine panic",id:"4-decision-state-machine-panic",level:3},{value:"Common Q&A",id:"common-qa",level:2},{value:"I want to change my workflow implementation. What code changes may produce non-deterministic errors?",id:"i-want-to-change-my-workflow-implementation-what-code-changes-may-produce-non-deterministic-errors",level:3},{value:"What are some changes that will NOT trigger non-deterministic errors?",id:"what-are-some-changes-that-will-not-trigger-non-deterministic-errors",level:3},{value:"I want to check if my code change will produce non-deterministic errors, how can I debug?",id:"i-want-to-check-if-my-code-change-will-produce-non-deterministic-errors-how-can-i-debug",level:3}];function a(e){const i={a:"a",code:"code",h1:"h1",h2:"h2",h3:"h3",header:"header",img:"img",li:"li",ol:"ol",p:"p",pre:"pre",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",...(0,s.R)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(i.header,{children:(0,r.jsx)(i.h1,{id:"workflow-non-deterministic-errors",children:"Workflow Non-deterministic errors"})}),"\n",(0,r.jsx)(i.h2,{id:"root-cause-of-non-deterministic-errors",children:"Root cause of non-deterministic errors"}),"\n",(0,r.jsx)(i.p,{children:"Cadence workflows are designed as long-running operations, and therefore the workflow code you write must be deterministic so that no matter how many time it is executed it always produce the same results."}),"\n",(0,r.jsx)(i.p,{children:"In production environment, your workflow code will run on a distributed system orchestrated by clusters of machines. However, machine failures are inevitable and can happen anytime to your workflow host. If you have a workflow running for long period of time, maybe months even years, and it fails due to loss of a host, it will be resumed on another machine and continue the rest of its execution."}),"\n",(0,r.jsxs)(i.p,{children:["Consider the following diagram where ",(0,r.jsx)(i.code,{children:"Workflow A"})," is running on ",(0,r.jsx)(i.code,{children:"Host A"})," but suddenly it crashes."]}),"\n",(0,r.jsx)(i.p,{children:(0,r.jsx)(i.img,{alt:"change-workflow-ownership",src:t(1742).A+"",width:"716",height:"822"})}),"\n",(0,r.jsxs)(i.p,{children:["Workflow A then will be picked up by Host B and continues its execution. This process is called ",(0,r.jsx)("b",{children:"change of workflow ownership"}),". However, after Host B gains ownership of the Workflow A, it does not have any information about its historical executions. For example, Workflow A may have executed many activities and it fails. Host B needs to redo all its history until the moment of failure. The process of reconstructing history of a workflow is called ",(0,r.jsx)("b",{children:"history replay"}),"."]}),"\n",(0,r.jsxs)(i.p,{children:["In general, any errors occurs during the replay process are called ",(0,r.jsx)("b",{children:"non-deterministic errors"}),". We will explore different types of non-deterministic errors in sections below but first let's try to understand how Cadence is able to perform the replay of workflow in case of failure."]}),"\n",(0,r.jsx)(i.h2,{id:"decision-tasks-of-workflow",children:"Decision tasks of workflow"}),"\n",(0,r.jsx)(i.p,{children:"In the previous section, we learned that Cadence is able to replay workflow histories in case of failure. We will learn exactly how Cadence keeps track of histories and how they get replayed when necessary."}),"\n",(0,r.jsxs)(i.p,{children:["Workflow histories are built based on event-sourcing, and each history event are persisted in Cadence storage. In Cadence, we call these history events ",(0,r.jsx)("b",{children:"decision tasks"}),", the foundation of history replay. Most decision tasks have three status - ",(0,r.jsx)("b",{children:"Scheduled"}),", ",(0,r.jsx)("b",{children:"Started"}),", ",(0,r.jsx)("b",{children:"Completed"})," and we will go over decision tasks produced by each Cadence operation in section below."]}),"\n",(0,r.jsx)(i.p,{children:"When changing a workflow ownership of host and replaying a workflow, the decision tasks are downloaded from database and persisted in memory. Then during the workflow replaying process, if Cadence finds a decision task already exists for a particular step, it will immediately return the value of a decision task instead of rerunning the whole workflow logic. Let's take a look at the following simple workflow implementation and explicitly list all decision tasks produced by this workflow."}),"\n",(0,r.jsx)(i.pre,{children:(0,r.jsx)(i.code,{className:"language-go",children:"func SimpleWorkflow(ctx workflow.Context) error {\n\tao := workflow.ActivityOptions{\n\t\t...\n\t}\n\tctx = workflow.WithActivityOptions(ctx, ao)\n\n\tvar a int\n\terr := workflow.ExecuteActivity(ctx, ActivityA).Get(ctx, &a)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tworkflow.Sleep(time.Minute)\n\n\terr = workflow.ExecuteActivity(ctx, ActivityB, a).Get(ctx, nil)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tworkflow.Sleep(time.Hour)\n\treturn nil\n}\n"})}),"\n",(0,r.jsx)(i.p,{children:"In this workflow, when it starts, it first execute ActivityA and then assign the result to an integer. It sleeps for one minute and then use the integer as an input argument to execute ActivityB. Finally it sleeps for one hour and completes."}),"\n",(0,r.jsx)(i.p,{children:"The following table lists the decision tasks stack produced by this workflow. It may look overwhelming first but if you associate each decision task with its corresponding Cadence operation, it becomes self-explanatory."}),"\n",(0,r.jsxs)(i.table,{children:[(0,r.jsx)(i.thead,{children:(0,r.jsxs)(i.tr,{children:[(0,r.jsx)(i.th,{children:"ID"}),(0,r.jsx)(i.th,{children:"Decision Task Type"}),(0,r.jsx)(i.th,{children:"Explanation"})]})}),(0,r.jsxs)(i.tbody,{children:[(0,r.jsxs)(i.tr,{children:[(0,r.jsx)(i.td,{children:"1"}),(0,r.jsx)(i.td,{children:"WorkflowStarted"}),(0,r.jsx)(i.td,{children:"the recorded StartWorkflow call's data, which usually schedules a new decision task immediately"})]}),(0,r.jsxs)(i.tr,{children:[(0,r.jsx)(i.td,{children:"2"}),(0,r.jsx)(i.td,{children:"DecisionTaskScheduled"}),(0,r.jsx)(i.td,{children:"workflow worker polling for work"})]}),(0,r.jsxs)(i.tr,{children:[(0,r.jsx)(i.td,{children:"3"}),(0,r.jsx)(i.td,{children:"DecisionTaskStarted"}),(0,r.jsxs)(i.td,{children:["worker gets the type ",(0,r.jsx)(i.code,{children:"SimpleWorkflow"}),", lookup registred funcs, deserialize input, call it"]})]}),(0,r.jsxs)(i.tr,{children:[(0,r.jsx)(i.td,{children:"4"}),(0,r.jsx)(i.td,{children:"DecisionTaskCompleted"}),(0,r.jsx)(i.td,{children:"worker finishes"})]}),(0,r.jsxs)(i.tr,{children:[(0,r.jsx)(i.td,{children:"5"}),(0,r.jsx)(i.td,{children:"ActivityTaskScheduled"}),(0,r.jsx)(i.td,{children:"activity available for a worker"})]}),(0,r.jsxs)(i.tr,{children:[(0,r.jsx)(i.td,{children:"6"}),(0,r.jsx)(i.td,{children:"ActivityTaskStarted"}),(0,r.jsxs)(i.td,{children:["activity worker polls and gets type ",(0,r.jsx)(i.code,{children:"ActivityA"})," and do the job"]})]}),(0,r.jsxs)(i.tr,{children:[(0,r.jsx)(i.td,{children:"7"}),(0,r.jsx)(i.td,{children:"ActivityTaskCompleted"}),(0,r.jsx)(i.td,{children:"activity work completed with result of var a"})]}),(0,r.jsxs)(i.tr,{children:[(0,r.jsx)(i.td,{children:"8"}),(0,r.jsx)(i.td,{children:"DecisionTaskScheduled"}),(0,r.jsx)(i.td,{children:"triggered by ActivityCompleted. server schedule next task"})]}),(0,r.jsxs)(i.tr,{children:[(0,r.jsx)(i.td,{children:"9"}),(0,r.jsx)(i.td,{children:"DecisionTaskStarted"}),(0,r.jsx)(i.td,{})]}),(0,r.jsxs)(i.tr,{children:[(0,r.jsx)(i.td,{children:"10"}),(0,r.jsx)(i.td,{children:"DecisionTaskCompleted"}),(0,r.jsx)(i.td,{})]}),(0,r.jsxs)(i.tr,{children:[(0,r.jsx)(i.td,{children:"11"}),(0,r.jsx)(i.td,{children:"TimerStarted"}),(0,r.jsx)(i.td,{children:"decision scheduled a timer for 1 minute"})]}),(0,r.jsxs)(i.tr,{children:[(0,r.jsx)(i.td,{children:"12"}),(0,r.jsx)(i.td,{children:"TimerFired"}),(0,r.jsx)(i.td,{children:"fired after 1 minute"})]}),(0,r.jsxs)(i.tr,{children:[(0,r.jsx)(i.td,{children:"13"}),(0,r.jsx)(i.td,{children:"DecisionTaskScheduled"}),(0,r.jsx)(i.td,{children:"triggered by TimerFired"})]}),(0,r.jsxs)(i.tr,{children:[(0,r.jsx)(i.td,{children:"14"}),(0,r.jsx)(i.td,{children:"DecisionTaskStarted"}),(0,r.jsx)(i.td,{})]}),(0,r.jsxs)(i.tr,{children:[(0,r.jsx)(i.td,{children:"15"}),(0,r.jsx)(i.td,{children:"DecisionTaskCompleted"}),(0,r.jsx)(i.td,{})]}),(0,r.jsxs)(i.tr,{children:[(0,r.jsx)(i.td,{children:"16"}),(0,r.jsx)(i.td,{children:"ActivityTaskScheduled"}),(0,r.jsxs)(i.td,{children:[(0,r.jsx)(i.code,{children:"ActivityB"})," scheduled by decision with param a"]})]}),(0,r.jsxs)(i.tr,{children:[(0,r.jsx)(i.td,{children:"17"}),(0,r.jsx)(i.td,{children:"ActivityTaskStarted"}),(0,r.jsx)(i.td,{children:"started by worker"})]}),(0,r.jsxs)(i.tr,{children:[(0,r.jsx)(i.td,{children:"18"}),(0,r.jsx)(i.td,{children:"ActivityTaskCompleted"}),(0,r.jsx)(i.td,{children:"completed with nil"})]}),(0,r.jsxs)(i.tr,{children:[(0,r.jsx)(i.td,{children:"19"}),(0,r.jsx)(i.td,{children:"DecisionTaskScheduled"}),(0,r.jsx)(i.td,{children:"triggered by ActivityCompleted"})]}),(0,r.jsxs)(i.tr,{children:[(0,r.jsx)(i.td,{children:"20"}),(0,r.jsx)(i.td,{children:"DecisionTaskStarted"}),(0,r.jsx)(i.td,{})]}),(0,r.jsxs)(i.tr,{children:[(0,r.jsx)(i.td,{children:"21"}),(0,r.jsx)(i.td,{children:"DecisionTaskCompleted"}),(0,r.jsx)(i.td,{})]}),(0,r.jsxs)(i.tr,{children:[(0,r.jsx)(i.td,{children:"22"}),(0,r.jsx)(i.td,{children:"TimerStarted"}),(0,r.jsx)(i.td,{children:"decision scheduled a timer for 1 hour"})]}),(0,r.jsxs)(i.tr,{children:[(0,r.jsx)(i.td,{children:"23"}),(0,r.jsx)(i.td,{children:"TimerFired"}),(0,r.jsx)(i.td,{children:"fired after 1 hour"})]}),(0,r.jsxs)(i.tr,{children:[(0,r.jsx)(i.td,{children:"24"}),(0,r.jsx)(i.td,{children:"DecisionTaskScheduled"}),(0,r.jsx)(i.td,{children:"triggered by TimerFired"})]}),(0,r.jsxs)(i.tr,{children:[(0,r.jsx)(i.td,{children:"25"}),(0,r.jsx)(i.td,{children:"DecisionTaskStarted"}),(0,r.jsx)(i.td,{})]}),(0,r.jsxs)(i.tr,{children:[(0,r.jsx)(i.td,{children:"26"}),(0,r.jsx)(i.td,{children:"DecisionTaskCompleted"}),(0,r.jsx)(i.td,{})]}),(0,r.jsxs)(i.tr,{children:[(0,r.jsx)(i.td,{children:"27"}),(0,r.jsx)(i.td,{children:"WorkflowCompleted"}),(0,r.jsx)(i.td,{children:"completed by decision (the function call returned)"})]})]})]}),"\n",(0,r.jsx)(i.p,{children:"As you may observe that this stack has strict orders. The whole point of the table above is that if the code you write involves some orchestration by Cadence, either your worker or Cadence server, they produce decision tasks. When your workflow gets replayed, it will strive to reconstruct this stack. Therefore, code changes to your workflow needs to make sure that they do not mess up with these decision tasks, which trigger non-deterministic errors. Then let's explore different types of non-deterministic errors and their root causes."}),"\n",(0,r.jsx)(i.h2,{id:"categories-of-non-deterministic-errors",children:"Categories of non-deterministic errors"}),"\n",(0,r.jsx)(i.p,{children:"Programmatically, Cadence surfaces 4 categories of non-deterministic errors. With understanding of decision tasks in the previous section and combining the error messages, you should be able to pinpoint what code changes may yield to non-deterministic errors."}),"\n",(0,r.jsx)(i.h3,{id:"1-missing-decisions",children:"1. Missing decisions"}),"\n",(0,r.jsx)(i.pre,{children:(0,r.jsx)(i.code,{className:"language-go",children:'fmt.Errorf("nondeterministic workflow: missing replay decision for %s", util.HistoryEventToString(e))\n'})}),"\n",(0,r.jsxs)(i.p,{children:["For source code click ",(0,r.jsx)(i.a,{href:"https://github.com/cadence-workflow/cadence-go-client/blob/e5081b085b0333bac23f198e57959681e0aee987/internal/internal_task_handlers.go#L1206",children:"here"})]}),"\n",(0,r.jsx)(i.p,{children:"This means after replay code, the decision is scheduled less than history events. Using the previous history as an example, when the workflow is waiting at the one hour timer(event ID 22), if we delete the line of :"}),"\n",(0,r.jsx)(i.pre,{children:(0,r.jsx)(i.code,{className:"language-go",children:"workflow.Sleep(time.Hour)\n"})}),"\n",(0,r.jsx)(i.p,{children:"and restart worker, then it will run into this error. Because in the history, the workflow has a timer event that is supposed to fire in one hour. However, during replay, there is no logic to schedule that timer."}),"\n",(0,r.jsx)(i.h3,{id:"2-extra-decisions",children:"2. Extra decisions"}),"\n",(0,r.jsx)(i.pre,{children:(0,r.jsx)(i.code,{className:"language-go",children:'fmt.Errorf("nondeterministic workflow: extra replay decision for %s", util.DecisionToString(d))\n'})}),"\n",(0,r.jsxs)(i.p,{children:["For source code click ",(0,r.jsx)(i.a,{href:"https://github.com/cadence-workflow/cadence-go-client/blob/e5081b085b0333bac23f198e57959681e0aee987/internal/internal_task_handlers.go#L1210",children:"here"})]}),"\n",(0,r.jsx)(i.p,{children:"This is basically the opposite of the previous case, which means that during replay, Cadence generates more decisions than those in history events. Using the previous history as an example, when the workflow is waiting at the one hour timer(event ID 22), if we change the line of:"}),"\n",(0,r.jsx)(i.pre,{children:(0,r.jsx)(i.code,{className:"language-go",children:"err = workflow.ExecuteActivity(ctx, activityB, a).Get(ctx, nil)\n"})}),"\n",(0,r.jsx)(i.p,{children:"to"}),"\n",(0,r.jsx)(i.pre,{children:(0,r.jsx)(i.code,{className:"language-go",children:"fb := workflow.ExecuteActivity(ctx, activityB, a)\nfc := workflow.ExecuteActivity(ctx, activityC, a)\nerr = fb.Get(ctx,nil)\nif err != nil {\n\treturn err\n}\nerr = fc.Get(ctx,nil)\nif err != nil {\n\treturn err\n}\n"})}),"\n",(0,r.jsx)(i.p,{children:"And restart worker, then it will run into this error. Because in the history, the workflow has scheduled only activityB after the one minute timer, however, during replay, there are two activities scheduled in a decision (in parallel)."}),"\n",(0,r.jsx)(i.h3,{id:"3-mismatched-decisions",children:"3. Mismatched decisions"}),"\n",(0,r.jsx)(i.pre,{children:(0,r.jsx)(i.code,{className:"language-go",children:'fmt.Errorf("nondeterministic workflow: history event is %s, replay decision is %s",util.HistoryEventToString(e), util.DecisionToString(d))\n'})}),"\n",(0,r.jsxs)(i.p,{children:["For source code click ",(0,r.jsx)(i.a,{href:"https://github.com/cadence-workflow/cadence-go-client/blob/e5081b085b0333bac23f198e57959681e0aee987/internal/internal_task_handlers.go#L1214",children:"here"})]}),"\n",(0,r.jsx)(i.p,{children:"This means after replay code, the decision scheduled is different than the one in history. Using the previous history as an example, when the workflow is waiting at the one hour timer(event ID 22),\nif we change the line of :"}),"\n",(0,r.jsx)(i.pre,{children:(0,r.jsx)(i.code,{className:"language-go",children:"err = workflow.ExecuteActivity(ctx, ActivityB, a).Get(ctx, nil)\n"})}),"\n",(0,r.jsx)(i.p,{children:"to"}),"\n",(0,r.jsx)(i.pre,{children:(0,r.jsx)(i.code,{className:"language-go",children:"err = workflow.ExecuteActivity(ctx, ActivityC, a).Get(ctx, nil)\n"})}),"\n",(0,r.jsx)(i.p,{children:"And restart worker, then it will run into this error. Because in the history, the workflow has scheduled ActivityB with input a, but during replay, it schedules ActivityC."}),"\n",(0,r.jsx)(i.h3,{id:"4-decision-state-machine-panic",children:"4. Decision state machine panic"}),"\n",(0,r.jsx)(i.pre,{children:(0,r.jsx)(i.code,{className:"language-go",children:'fmt.Sprintf("unknown decision %v, possible causes are nondeterministic workflow definition code"+" or incompatible change in the workflow definition", id)\n'})}),"\n",(0,r.jsxs)(i.p,{children:["For source code click ",(0,r.jsx)(i.a,{href:"https://github.com/cadence-workflow/cadence-go-client/blob/e5081b085b0333bac23f198e57959681e0aee987/internal/internal_decision_state_machine.go#L693",children:"here"})]}),"\n",(0,r.jsx)(i.p,{children:"This usually means workflow history is corrupted due to some bug. For example, the same activity can be scheduled and differentiated by activityID. So ActivityIDs for different activities are supposed to be unique in workflow history. If however we have an ActivityID collision, replay will run into this error."}),"\n",(0,r.jsx)(i.h2,{id:"common-qa",children:"Common Q&A"}),"\n",(0,r.jsx)(i.h3,{id:"i-want-to-change-my-workflow-implementation-what-code-changes-may-produce-non-deterministic-errors",children:"I want to change my workflow implementation. What code changes may produce non-deterministic errors?"}),"\n",(0,r.jsx)(i.p,{children:"As we discussed in previous sections, if your changes change decision tasks, then they will probably lead to non-deterministic errors.\nThese are some common changes that can be categorized by these previous 4 types mentioned above."}),"\n",(0,r.jsxs)(i.ol,{children:["\n",(0,r.jsx)(i.li,{children:"Changing the order of executing Cadence defined operations, such as activities, timer, child workflows, signals, cancelRequest."}),"\n",(0,r.jsx)(i.li,{children:"Change the duration of a timer"}),"\n",(0,r.jsxs)(i.li,{children:["Use build-in goroutine of golang instead of using ",(0,r.jsx)(i.code,{children:"workflow.Go"})]}),"\n",(0,r.jsxs)(i.li,{children:["Use build-in channel of golang instead of using ",(0,r.jsx)(i.code,{children:"workflow.Channel"})]}),"\n",(0,r.jsxs)(i.li,{children:["Use build-in sleep function instead of using ",(0,r.jsx)(i.code,{children:"workflow.Sleep"})]}),"\n"]}),"\n",(0,r.jsx)(i.h3,{id:"what-are-some-changes-that-will-not-trigger-non-deterministic-errors",children:"What are some changes that will NOT trigger non-deterministic errors?"}),"\n",(0,r.jsx)(i.p,{children:"Code changes that are free of non-deterministic erorrs normally do not involve decision tasks in Cadence."}),"\n",(0,r.jsxs)(i.ol,{children:["\n",(0,r.jsxs)(i.li,{children:["Activity input and output changes do not directly cause non-deterministic errors because the contents are not checked. However, changes may produce serialization errors based on your data converter implementation (type or number-of-arg changes are particularly prone to problems, so we recommend you always use a single struct). Cadence uses ",(0,r.jsx)(i.code,{children:"json.Marshal"})," and ",(0,r.jsx)(i.code,{children:"json.Unmarshal"})," (with ",(0,r.jsx)(i.code,{children:"Decoder.UseNumber()"}),") by default."]}),"\n",(0,r.jsx)(i.li,{children:"Code changes that does not modify history events are safe to be checked in. For example, logging or metrics implementations."}),"\n",(0,r.jsx)(i.li,{children:"Change of retry policies, as these are not compared. Adding or removing retry policies is also safe. Changes will only take effect on new calls however, not ones that have already been scheduled."}),"\n"]}),"\n",(0,r.jsx)(i.h3,{id:"i-want-to-check-if-my-code-change-will-produce-non-deterministic-errors-how-can-i-debug",children:"I want to check if my code change will produce non-deterministic errors, how can I debug?"}),"\n",(0,r.jsxs)(i.p,{children:["Cadence provides replayer test, which functions as an unit test on your local machine to replay your workflow history comparing to your potential code change. If you introduce a non-deterministic change and your history triggers it, the test should fail. Check out ",(0,r.jsx)(i.a,{href:"/docs/go-client/workflow-replay-shadowing",children:"this page"})," for more details."]})]})}function h(e={}){const{wrapper:i}={...(0,s.R)(),...e.components};return i?(0,r.jsx)(i,{...e,children:(0,r.jsx)(a,{...e})}):a(e)}},1742:(e,i,t)=>{t.d(i,{A:()=>n});const n=t.p+"assets/images/change-workflow-ownership-22c8e7b0ae2dd75d6e1a81978fcb87f6.png"},8453:(e,i,t)=>{t.d(i,{R:()=>o,x:()=>c});var n=t(6540);const r={},s=n.createContext(r);function o(e){const i=n.useContext(s);return n.useMemo((function(){return"function"==typeof e?e(i):{...i,...e}}),[i,e])}function c(e){let i;return i=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:o(e.components),n.createElement(s.Provider,{value:i},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/a4f1f4dd.c8373370.js b/assets/js/a4f1f4dd.c8373370.js deleted file mode 100644 index e2cd89d28..000000000 --- a/assets/js/a4f1f4dd.c8373370.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[9961],{2496:(e,i,t)=>{t.r(i),t.d(i,{assets:()=>d,contentTitle:()=>c,default:()=>h,frontMatter:()=>o,metadata:()=>n,toc:()=>l});const n=JSON.parse('{"id":"go-client/workflow-non-deterministic-error","title":"Workflow Non-deterministic errors","description":"Root cause of non-deterministic errors","source":"@site/docs/05-go-client/19-workflow-non-deterministic-error.md","sourceDirName":"05-go-client","slug":"/go-client/workflow-non-deterministic-error","permalink":"/docs/go-client/workflow-non-deterministic-error","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/05-go-client/19-workflow-non-deterministic-error.md","tags":[],"version":"current","sidebarPosition":19,"frontMatter":{"layout":"default","title":"Workflow Non-deterministic errors","permalink":"/docs/go-client/workflow-non-deterministic-errors"}}');var r=t(4848),s=t(8453);const o={layout:"default",title:"Workflow Non-deterministic errors",permalink:"/docs/go-client/workflow-non-deterministic-errors"},c="Workflow Non-deterministic errors",d={},l=[{value:"Root cause of non-deterministic errors",id:"root-cause-of-non-deterministic-errors",level:2},{value:"Decision tasks of workflow",id:"decision-tasks-of-workflow",level:2},{value:"Categories of non-deterministic errors",id:"categories-of-non-deterministic-errors",level:2},{value:"1. Missing decisions",id:"1-missing-decisions",level:3},{value:"2. Extra decisions",id:"2-extra-decisions",level:3},{value:"3. Mismatched decisions",id:"3-mismatched-decisions",level:3},{value:"4. Decision state machine panic",id:"4-decision-state-machine-panic",level:3},{value:"Common Q&A",id:"common-qa",level:2},{value:"I want to change my workflow implementation. What code changes may produce non-deterministic errors?",id:"i-want-to-change-my-workflow-implementation-what-code-changes-may-produce-non-deterministic-errors",level:3},{value:"What are some changes that will NOT trigger non-deterministic errors?",id:"what-are-some-changes-that-will-not-trigger-non-deterministic-errors",level:3},{value:"I want to check if my code change will produce non-deterministic errors, how can I debug?",id:"i-want-to-check-if-my-code-change-will-produce-non-deterministic-errors-how-can-i-debug",level:3}];function a(e){const i={a:"a",code:"code",h1:"h1",h2:"h2",h3:"h3",header:"header",img:"img",li:"li",ol:"ol",p:"p",pre:"pre",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",...(0,s.R)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(i.header,{children:(0,r.jsx)(i.h1,{id:"workflow-non-deterministic-errors",children:"Workflow Non-deterministic errors"})}),"\n",(0,r.jsx)(i.h2,{id:"root-cause-of-non-deterministic-errors",children:"Root cause of non-deterministic errors"}),"\n",(0,r.jsx)(i.p,{children:"Cadence workflows are designed as long-running operations, and therefore the workflow code you write must be deterministic so that no matter how many time it is executed it always produce the same results."}),"\n",(0,r.jsx)(i.p,{children:"In production environment, your workflow code will run on a distributed system orchestrated by clusters of machines. However, machine failures are inevitable and can happen anytime to your workflow host. If you have a workflow running for long period of time, maybe months even years, and it fails due to loss of a host, it will be resumed on another machine and continue the rest of its execution."}),"\n",(0,r.jsxs)(i.p,{children:["Consider the following diagram where ",(0,r.jsx)(i.code,{children:"Workflow A"})," is running on ",(0,r.jsx)(i.code,{children:"Host A"})," but suddenly it crashes."]}),"\n",(0,r.jsx)(i.p,{children:(0,r.jsx)(i.img,{alt:"change-workflow-ownership",src:t(1742).A+"",width:"716",height:"822"})}),"\n",(0,r.jsxs)(i.p,{children:["Workflow A then will be picked up by Host B and continues its execution. This process is called ",(0,r.jsx)("b",{children:"change of workflow ownership"}),". However, after Host B gains ownership of the Workflow A, it does not have any information about its historical executions. For example, Workflow A may have executed many activities and it fails. Host B needs to redo all its history until the moment of failure. The process of reconstructing history of a workflow is called ",(0,r.jsx)("b",{children:"history replay"}),"."]}),"\n",(0,r.jsxs)(i.p,{children:["In general, any errors occurs during the replay process are called ",(0,r.jsx)("b",{children:"non-deterministic errors"}),". We will explore different types of non-deterministic errors in sections below but first let's try to understand how Cadence is able to perform the replay of workflow in case of failure."]}),"\n",(0,r.jsx)(i.h2,{id:"decision-tasks-of-workflow",children:"Decision tasks of workflow"}),"\n",(0,r.jsx)(i.p,{children:"In the previous section, we learned that Cadence is able to replay workflow histories in case of failure. We will learn exactly how Cadence keeps track of histories and how they get replayed when necessary."}),"\n",(0,r.jsxs)(i.p,{children:["Workflow histories are built based on event-sourcing, and each history event are persisted in Cadence storage. In Cadence, we call these history events ",(0,r.jsx)("b",{children:"decision tasks"}),", the foundation of history replay. Most decision tasks have three status - ",(0,r.jsx)("b",{children:"Scheduled"}),", ",(0,r.jsx)("b",{children:"Started"}),", ",(0,r.jsx)("b",{children:"Completed"})," and we will go over decision tasks produced by each Cadence operation in section below."]}),"\n",(0,r.jsx)(i.p,{children:"When changing a workflow ownership of host and replaying a workflow, the decision tasks are downloaded from database and persisted in memory. Then during the workflow replaying process, if Cadence finds a decision task already exists for a particular step, it will immediately return the value of a decision task instead of rerunning the whole workflow logic. Let's take a look at the following simple workflow implementation and explicitly list all decision tasks produced by this workflow."}),"\n",(0,r.jsx)(i.pre,{children:(0,r.jsx)(i.code,{className:"language-go",children:"func SimpleWorkflow(ctx workflow.Context) error {\n\tao := workflow.ActivityOptions{\n\t\t...\n\t}\n\tctx = workflow.WithActivityOptions(ctx, ao)\n\n\tvar a int\n\terr := workflow.ExecuteActivity(ctx, ActivityA).Get(ctx, &a)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tworkflow.Sleep(time.Minute)\n\n\terr = workflow.ExecuteActivity(ctx, ActivityB, a).Get(ctx, nil)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tworkflow.Sleep(time.Hour)\n\treturn nil\n}\n"})}),"\n",(0,r.jsx)(i.p,{children:"In this workflow, when it starts, it first execute ActivityA and then assign the result to an integer. It sleeps for one minute and then use the integer as an input argument to execute ActivityB. Finally it sleeps for one hour and completes."}),"\n",(0,r.jsx)(i.p,{children:"The following table lists the decision tasks stack produced by this workflow. It may look overwhelming first but if you associate each decision task with its corresponding Cadence operation, it becomes self-explanatory."}),"\n",(0,r.jsxs)(i.table,{children:[(0,r.jsx)(i.thead,{children:(0,r.jsxs)(i.tr,{children:[(0,r.jsx)(i.th,{children:"ID"}),(0,r.jsx)(i.th,{children:"Decision Task Type"}),(0,r.jsx)(i.th,{children:"Explanation"})]})}),(0,r.jsxs)(i.tbody,{children:[(0,r.jsxs)(i.tr,{children:[(0,r.jsx)(i.td,{children:"1"}),(0,r.jsx)(i.td,{children:"WorkflowStarted"}),(0,r.jsx)(i.td,{children:"the recorded StartWorkflow call's data, which usually schedules a new decision task immediately"})]}),(0,r.jsxs)(i.tr,{children:[(0,r.jsx)(i.td,{children:"2"}),(0,r.jsx)(i.td,{children:"DecisionTaskScheduled"}),(0,r.jsx)(i.td,{children:"workflow worker polling for work"})]}),(0,r.jsxs)(i.tr,{children:[(0,r.jsx)(i.td,{children:"3"}),(0,r.jsx)(i.td,{children:"DecisionTaskStarted"}),(0,r.jsxs)(i.td,{children:["worker gets the type ",(0,r.jsx)(i.code,{children:"SimpleWorkflow"}),", lookup registred funcs, deserialize input, call it"]})]}),(0,r.jsxs)(i.tr,{children:[(0,r.jsx)(i.td,{children:"4"}),(0,r.jsx)(i.td,{children:"DecisionTaskCompleted"}),(0,r.jsx)(i.td,{children:"worker finishes"})]}),(0,r.jsxs)(i.tr,{children:[(0,r.jsx)(i.td,{children:"5"}),(0,r.jsx)(i.td,{children:"ActivityTaskScheduled"}),(0,r.jsx)(i.td,{children:"activity available for a worker"})]}),(0,r.jsxs)(i.tr,{children:[(0,r.jsx)(i.td,{children:"6"}),(0,r.jsx)(i.td,{children:"ActivityTaskStarted"}),(0,r.jsxs)(i.td,{children:["activity worker polls and gets type ",(0,r.jsx)(i.code,{children:"ActivityA"})," and do the job"]})]}),(0,r.jsxs)(i.tr,{children:[(0,r.jsx)(i.td,{children:"7"}),(0,r.jsx)(i.td,{children:"ActivityTaskCompleted"}),(0,r.jsx)(i.td,{children:"activity work completed with result of var a"})]}),(0,r.jsxs)(i.tr,{children:[(0,r.jsx)(i.td,{children:"8"}),(0,r.jsx)(i.td,{children:"DecisionTaskScheduled"}),(0,r.jsx)(i.td,{children:"triggered by ActivityCompleted. server schedule next task"})]}),(0,r.jsxs)(i.tr,{children:[(0,r.jsx)(i.td,{children:"9"}),(0,r.jsx)(i.td,{children:"DecisionTaskStarted"}),(0,r.jsx)(i.td,{})]}),(0,r.jsxs)(i.tr,{children:[(0,r.jsx)(i.td,{children:"10"}),(0,r.jsx)(i.td,{children:"DecisionTaskCompleted"}),(0,r.jsx)(i.td,{})]}),(0,r.jsxs)(i.tr,{children:[(0,r.jsx)(i.td,{children:"11"}),(0,r.jsx)(i.td,{children:"TimerStarted"}),(0,r.jsx)(i.td,{children:"decision scheduled a timer for 1 minute"})]}),(0,r.jsxs)(i.tr,{children:[(0,r.jsx)(i.td,{children:"12"}),(0,r.jsx)(i.td,{children:"TimerFired"}),(0,r.jsx)(i.td,{children:"fired after 1 minute"})]}),(0,r.jsxs)(i.tr,{children:[(0,r.jsx)(i.td,{children:"13"}),(0,r.jsx)(i.td,{children:"DecisionTaskScheduled"}),(0,r.jsx)(i.td,{children:"triggered by TimerFired"})]}),(0,r.jsxs)(i.tr,{children:[(0,r.jsx)(i.td,{children:"14"}),(0,r.jsx)(i.td,{children:"DecisionTaskStarted"}),(0,r.jsx)(i.td,{})]}),(0,r.jsxs)(i.tr,{children:[(0,r.jsx)(i.td,{children:"15"}),(0,r.jsx)(i.td,{children:"DecisionTaskCompleted"}),(0,r.jsx)(i.td,{})]}),(0,r.jsxs)(i.tr,{children:[(0,r.jsx)(i.td,{children:"16"}),(0,r.jsx)(i.td,{children:"ActivityTaskScheduled"}),(0,r.jsxs)(i.td,{children:[(0,r.jsx)(i.code,{children:"ActivityB"})," scheduled by decision with param a"]})]}),(0,r.jsxs)(i.tr,{children:[(0,r.jsx)(i.td,{children:"17"}),(0,r.jsx)(i.td,{children:"ActivityTaskStarted"}),(0,r.jsx)(i.td,{children:"started by worker"})]}),(0,r.jsxs)(i.tr,{children:[(0,r.jsx)(i.td,{children:"18"}),(0,r.jsx)(i.td,{children:"ActivityTaskCompleted"}),(0,r.jsx)(i.td,{children:"completed with nil"})]}),(0,r.jsxs)(i.tr,{children:[(0,r.jsx)(i.td,{children:"19"}),(0,r.jsx)(i.td,{children:"DecisionTaskScheduled"}),(0,r.jsx)(i.td,{children:"triggered by ActivityCompleted"})]}),(0,r.jsxs)(i.tr,{children:[(0,r.jsx)(i.td,{children:"20"}),(0,r.jsx)(i.td,{children:"DecisionTaskStarted"}),(0,r.jsx)(i.td,{})]}),(0,r.jsxs)(i.tr,{children:[(0,r.jsx)(i.td,{children:"21"}),(0,r.jsx)(i.td,{children:"DecisionTaskCompleted"}),(0,r.jsx)(i.td,{})]}),(0,r.jsxs)(i.tr,{children:[(0,r.jsx)(i.td,{children:"22"}),(0,r.jsx)(i.td,{children:"TimerStarted"}),(0,r.jsx)(i.td,{children:"decision scheduled a timer for 1 hour"})]}),(0,r.jsxs)(i.tr,{children:[(0,r.jsx)(i.td,{children:"23"}),(0,r.jsx)(i.td,{children:"TimerFired"}),(0,r.jsx)(i.td,{children:"fired after 1 hour"})]}),(0,r.jsxs)(i.tr,{children:[(0,r.jsx)(i.td,{children:"24"}),(0,r.jsx)(i.td,{children:"DecisionTaskScheduled"}),(0,r.jsx)(i.td,{children:"triggered by TimerFired"})]}),(0,r.jsxs)(i.tr,{children:[(0,r.jsx)(i.td,{children:"25"}),(0,r.jsx)(i.td,{children:"DecisionTaskStarted"}),(0,r.jsx)(i.td,{})]}),(0,r.jsxs)(i.tr,{children:[(0,r.jsx)(i.td,{children:"26"}),(0,r.jsx)(i.td,{children:"DecisionTaskCompleted"}),(0,r.jsx)(i.td,{})]}),(0,r.jsxs)(i.tr,{children:[(0,r.jsx)(i.td,{children:"27"}),(0,r.jsx)(i.td,{children:"WorkflowCompleted"}),(0,r.jsx)(i.td,{children:"completed by decision (the function call returned)"})]})]})]}),"\n",(0,r.jsx)(i.p,{children:"As you may observe that this stack has strict orders. The whole point of the table above is that if the code you write involves some orchestration by Cadence, either your worker or Cadence server, they produce decision tasks. When your workflow gets replayed, it will strive to reconstruct this stack. Therefore, code changes to your workflow needs to make sure that they do not mess up with these decision tasks, which trigger non-deterministic errors. Then let's explore different types of non-deterministic errors and their root causes."}),"\n",(0,r.jsx)(i.h2,{id:"categories-of-non-deterministic-errors",children:"Categories of non-deterministic errors"}),"\n",(0,r.jsx)(i.p,{children:"Programmatically, Cadence surfaces 4 categories of non-deterministic errors. With understanding of decision tasks in the previous section and combining the error messages, you should be able to pinpoint what code changes may yield to non-deterministic errors."}),"\n",(0,r.jsx)(i.h3,{id:"1-missing-decisions",children:"1. Missing decisions"}),"\n",(0,r.jsx)(i.pre,{children:(0,r.jsx)(i.code,{className:"language-go",children:'fmt.Errorf("nondeterministic workflow: missing replay decision for %s", util.HistoryEventToString(e))\n'})}),"\n",(0,r.jsxs)(i.p,{children:["For source code click ",(0,r.jsx)(i.a,{href:"https://github.com/cadence-workflow/cadence-go-client/blob/e5081b085b0333bac23f198e57959681e0aee987/internal/internal_task_handlers.go#L1206",children:"here"})]}),"\n",(0,r.jsx)(i.p,{children:"This means after replay code, the decision is scheduled less than history events. Using the previous history as an example, when the workflow is waiting at the one hour timer(event ID 22), if we delete the line of :"}),"\n",(0,r.jsx)(i.pre,{children:(0,r.jsx)(i.code,{className:"language-go",children:"workflow.Sleep(time.Hour)\n"})}),"\n",(0,r.jsx)(i.p,{children:"and restart worker, then it will run into this error. Because in the history, the workflow has a timer event that is supposed to fire in one hour. However, during replay, there is no logic to schedule that timer."}),"\n",(0,r.jsx)(i.h3,{id:"2-extra-decisions",children:"2. Extra decisions"}),"\n",(0,r.jsx)(i.pre,{children:(0,r.jsx)(i.code,{className:"language-go",children:'fmt.Errorf("nondeterministic workflow: extra replay decision for %s", util.DecisionToString(d))\n'})}),"\n",(0,r.jsxs)(i.p,{children:["For source code click ",(0,r.jsx)(i.a,{href:"https://github.com/cadence-workflow/cadence-go-client/blob/e5081b085b0333bac23f198e57959681e0aee987/internal/internal_task_handlers.go#L1210",children:"here"})]}),"\n",(0,r.jsx)(i.p,{children:"This is basically the opposite of the previous case, which means that during replay, Cadence generates more decisions than those in history events. Using the previous history as an example, when the workflow is waiting at the one hour timer(event ID 22), if we change the line of:"}),"\n",(0,r.jsx)(i.pre,{children:(0,r.jsx)(i.code,{className:"language-go",children:"err = workflow.ExecuteActivity(ctx, activityB, a).Get(ctx, nil)\n"})}),"\n",(0,r.jsx)(i.p,{children:"to"}),"\n",(0,r.jsx)(i.pre,{children:(0,r.jsx)(i.code,{className:"language-go",children:"fb := workflow.ExecuteActivity(ctx, activityB, a)\nfc := workflow.ExecuteActivity(ctx, activityC, a)\nerr = fb.Get(ctx,nil)\nif err != nil {\n\treturn err\n}\nerr = fc.Get(ctx,nil)\nif err != nil {\n\treturn err\n}\n"})}),"\n",(0,r.jsx)(i.p,{children:"And restart worker, then it will run into this error. Because in the history, the workflow has scheduled only activityB after the one minute timer, however, during replay, there are two activities scheduled in a decision (in parallel)."}),"\n",(0,r.jsx)(i.h3,{id:"3-mismatched-decisions",children:"3. Mismatched decisions"}),"\n",(0,r.jsx)(i.pre,{children:(0,r.jsx)(i.code,{className:"language-go",children:'fmt.Errorf("nondeterministic workflow: history event is %s, replay decision is %s",util.HistoryEventToString(e), util.DecisionToString(d))\n'})}),"\n",(0,r.jsxs)(i.p,{children:["For source code click ",(0,r.jsx)(i.a,{href:"https://github.com/cadence-workflow/cadence-go-client/blob/e5081b085b0333bac23f198e57959681e0aee987/internal/internal_task_handlers.go#L1214",children:"here"})]}),"\n",(0,r.jsx)(i.p,{children:"This means after replay code, the decision scheduled is different than the one in history. Using the previous history as an example, when the workflow is waiting at the one hour timer(event ID 22),\nif we change the line of :"}),"\n",(0,r.jsx)(i.pre,{children:(0,r.jsx)(i.code,{className:"language-go",children:"err = workflow.ExecuteActivity(ctx, ActivityB, a).Get(ctx, nil)\n"})}),"\n",(0,r.jsx)(i.p,{children:"to"}),"\n",(0,r.jsx)(i.pre,{children:(0,r.jsx)(i.code,{className:"language-go",children:"err = workflow.ExecuteActivity(ctx, ActivityC, a).Get(ctx, nil)\n"})}),"\n",(0,r.jsx)(i.p,{children:"And restart worker, then it will run into this error. Because in the history, the workflow has scheduled ActivityB with input a, but during replay, it schedules ActivityC."}),"\n",(0,r.jsx)(i.h3,{id:"4-decision-state-machine-panic",children:"4. Decision state machine panic"}),"\n",(0,r.jsx)(i.pre,{children:(0,r.jsx)(i.code,{className:"language-go",children:'fmt.Sprintf("unknown decision %v, possible causes are nondeterministic workflow definition code"+" or incompatible change in the workflow definition", id)\n'})}),"\n",(0,r.jsxs)(i.p,{children:["For source code click ",(0,r.jsx)(i.a,{href:"https://github.com/cadence-workflow/cadence-go-client/blob/e5081b085b0333bac23f198e57959681e0aee987/internal/internal_decision_state_machine.go#L693",children:"here"})]}),"\n",(0,r.jsx)(i.p,{children:"This usually means workflow history is corrupted due to some bug. For example, the same activity can be scheduled and differentiated by activityID. So ActivityIDs for different activities are supposed to be unique in workflow history. If however we have an ActivityID collision, replay will run into this error."}),"\n",(0,r.jsx)(i.h2,{id:"common-qa",children:"Common Q&A"}),"\n",(0,r.jsx)(i.h3,{id:"i-want-to-change-my-workflow-implementation-what-code-changes-may-produce-non-deterministic-errors",children:"I want to change my workflow implementation. What code changes may produce non-deterministic errors?"}),"\n",(0,r.jsx)(i.p,{children:"As we discussed in previous sections, if your changes change decision tasks, then they will probably lead to non-deterministic errors.\nThese are some common changes that can be categorized by these previous 4 types mentioned above."}),"\n",(0,r.jsxs)(i.ol,{children:["\n",(0,r.jsx)(i.li,{children:"Changing the order of executing Cadence defined operations, such as activities, timer, child workflows, signals, cancelRequest."}),"\n",(0,r.jsx)(i.li,{children:"Change the duration of a timer"}),"\n",(0,r.jsxs)(i.li,{children:["Use build-in goroutine of golang instead of using ",(0,r.jsx)(i.code,{children:"workflow.Go"})]}),"\n",(0,r.jsxs)(i.li,{children:["Use build-in channel of golang instead of using ",(0,r.jsx)(i.code,{children:"workflow.Channel"})]}),"\n",(0,r.jsxs)(i.li,{children:["Use build-in sleep function instead of using ",(0,r.jsx)(i.code,{children:"workflow.Sleep"})]}),"\n"]}),"\n",(0,r.jsx)(i.h3,{id:"what-are-some-changes-that-will-not-trigger-non-deterministic-errors",children:"What are some changes that will NOT trigger non-deterministic errors?"}),"\n",(0,r.jsx)(i.p,{children:"Code changes that are free of non-deterministic erorrs normally do not involve decision tasks in Cadence."}),"\n",(0,r.jsxs)(i.ol,{children:["\n",(0,r.jsxs)(i.li,{children:["Activity input and output changes do not directly cause non-deterministic errors because the contents are not checked. However, changes may produce serialization errors based on your data converter implementation (type or number-of-arg changes are particularly prone to problems, so we recommend you always use a single struct). Cadence uses ",(0,r.jsx)(i.code,{children:"json.Marshal"})," and ",(0,r.jsx)(i.code,{children:"json.Unmarshal"})," (with ",(0,r.jsx)(i.code,{children:"Decoder.UseNumber()"}),") by default."]}),"\n",(0,r.jsx)(i.li,{children:"Code changes that does not modify history events are safe to be checked in. For example, logging or metrics implementations."}),"\n",(0,r.jsx)(i.li,{children:"Change of retry policies, as these are not compared. Adding or removing retry policies is also safe. Changes will only take effect on new calls however, not ones that have already been scheduled."}),"\n"]}),"\n",(0,r.jsx)(i.h3,{id:"i-want-to-check-if-my-code-change-will-produce-non-deterministic-errors-how-can-i-debug",children:"I want to check if my code change will produce non-deterministic errors, how can I debug?"}),"\n",(0,r.jsxs)(i.p,{children:["Cadence provides replayer test, which functions as an unit test on your local machine to replay your workflow history comparing to your potential code change. If you introduce a non-deterministic change and your history triggers it, the test should fail. Check out ",(0,r.jsx)(i.a,{href:"/docs/go-client/workflow-replay-shadowing",children:"this page"})," for more details."]})]})}function h(e={}){const{wrapper:i}={...(0,s.R)(),...e.components};return i?(0,r.jsx)(i,{...e,children:(0,r.jsx)(a,{...e})}):a(e)}},1742:(e,i,t)=>{t.d(i,{A:()=>n});const n=t.p+"assets/images/change-workflow-ownership-22c8e7b0ae2dd75d6e1a81978fcb87f6.png"},8453:(e,i,t)=>{t.d(i,{R:()=>o,x:()=>c});var n=t(6540);const r={},s=n.createContext(r);function o(e){const i=n.useContext(s);return n.useMemo((function(){return"function"==typeof e?e(i):{...i,...e}}),[i,e])}function c(e){let i;return i=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:o(e.components),n.createElement(s.Provider,{value:i},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/a7552915.21801cc4.js b/assets/js/a7552915.21801cc4.js new file mode 100644 index 000000000..0edae015f --- /dev/null +++ b/assets/js/a7552915.21801cc4.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[9520],{1735:(e,t,i)=>{i.r(t),i.d(t,{assets:()=>r,contentTitle:()=>l,default:()=>m,frontMatter:()=>c,metadata:()=>n,toc:()=>s});const n=JSON.parse('{"id":"java-client/implementing-activities","title":"Implementing activities","description":"Activityactivityactivity implementation","source":"@site/docs/04-java-client/06-implementing-activities.md","sourceDirName":"04-java-client","slug":"/java-client/implementing-activities","permalink":"/Cadence-Docs/docs/java-client/implementing-activities","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/04-java-client/06-implementing-activities.md","tags":[],"version":"current","sidebarPosition":6,"frontMatter":{"layout":"default","title":"Implementing activities","permalink":"/docs/java-client/implementing-activities"}}');var a=i(4848),o=i(8453);const c={layout:"default",title:"Implementing activities",permalink:"/docs/java-client/implementing-activities"},l="Implementing activities",r={},s=[{value:"Accessing Activity Info",id:"accessing-activity-info",level:2},{value:"Asynchronous Activity Completion",id:"asynchronous-activity-completion",level:2},{value:"Activity Heart Beating",id:"activity-heart-beating",level:2}];function d(e){const t={a:"a",code:"code",em:"em",h1:"h1",h2:"h2",header:"header",p:"p",pre:"pre",...(0,o.R)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(t.header,{children:(0,a.jsx)(t.h1,{id:"implementing-activities",children:"Implementing activities"})}),"\n",(0,a.jsxs)(t.p,{children:["Activity implementation is an implementation of an activity interface. A single instance of the activities implementation\nis shared across multiple simultaneous activity invocations. Therefore, the activity implementation code must be ",(0,a.jsx)(t.em,{children:"thread safe"}),"."]}),"\n",(0,a.jsx)(t.p,{children:"The values passed to activities through invocation parameters or returned through a result value are recorded in the execution history.\nThe entire execution history is transferred from the Cadence service to workflow_workers when a workflow state needs to recover.\nA large execution history can thus adversely impact the performance of your workflow. Therefore, be mindful of the amount of data you transfer via activity invocation parameters or return values. Otherwise, no additional limitations exist on activity implementations."}),"\n",(0,a.jsx)(t.pre,{children:(0,a.jsx)(t.code,{className:"language-java",children:"public class FileProcessingActivitiesImpl implements FileProcessingActivities {\n\n private final AmazonS3 s3Client;\n\n private final String localDirectory;\n\n void upload(String bucketName, String localName, String targetName) {\n File f = new File(localName);\n s3Client.putObject(bucket, remoteName, f);\n }\n\n String download(String bucketName, String remoteName, String localName) {\n // Implementation omitted for brevity.\n return downloadFileFromS3(bucketName, remoteName, localDirectory + localName);\n }\n\n String processFile(String localName) {\n // Implementation omitted for brevity.\n return compressFile(localName);\n }\n\n void deleteLocalFile(String fileName) {\n File f = new File(localDirectory + fileName);\n f.delete();\n }\n}\n"})}),"\n",(0,a.jsx)(t.h2,{id:"accessing-activity-info",children:"Accessing Activity Info"}),"\n",(0,a.jsxs)(t.p,{children:["The ",(0,a.jsx)(t.a,{href:"https://static.javadoc.io/com.uber.cadence/cadence-client/2.4.1/index.html?com/cadence-workflow/cadence/activity/Activity.html",children:"Activity"}),"\nclass provides static getters to access information about the workflow that invoked it. Note that this information is stored in a thread local variable. Therefore, calls to Activity accessors succeed only in the thread that invoked the activity function."]}),"\n",(0,a.jsx)(t.pre,{children:(0,a.jsx)(t.code,{className:"language-java",children:'public class FileProcessingActivitiesImpl implements FileProcessingActivities {\n\n @Override\n public String download(String bucketName, String remoteName, String localName) {\n log.info("domain=" + Activity.getDomain());\n WorkflowExecution execution = Activity.getWorkflowExecution();\n log.info("workflowId=" + execution.getWorkflowId());\n log.info("runId=" + execution.getRunId());\n ActivityTask activityTask = Activity.getTask();\n log.info("activityId=" + activityTask.getActivityId());\n log.info("activityTimeout=" + activityTask.getStartToCloseTimeoutSeconds());\n return downloadFileFromS3(bucketName, remoteName, localDirectory + localName);\n }\n ...\n}\n'})}),"\n",(0,a.jsx)(t.h2,{id:"asynchronous-activity-completion",children:"Asynchronous Activity Completion"}),"\n",(0,a.jsx)(t.p,{children:"Sometimes an activity lifecycle goes beyond a synchronous method invocation. For example, a request can be put in a queue\nand later a reply comes and is picked up by a different worker process. The whole request-reply interaction can be modeled\nas a single Cadence activity."}),"\n",(0,a.jsxs)(t.p,{children:["To indicate that an activity should not be completed upon its method return, call ",(0,a.jsx)(t.code,{children:"Activity.doNotCompleteOnReturn()"})," from the\noriginal activity thread. Then later, when replies come, complete the activity using ",(0,a.jsx)(t.a,{href:"https://static.javadoc.io/com.uber.cadence/cadence-client/2.4.1/index.html?com/cadence-workflow/cadence/client/ActivityCompletionClient.html",children:"ActivityCompletionClient"}),".\nTo correlate activity invocation with completion, use either ",(0,a.jsx)(t.code,{children:"TaskToken"})," or workflow and activity IDs."]}),"\n",(0,a.jsx)(t.pre,{children:(0,a.jsx)(t.code,{className:"language-java",children:'public class FileProcessingActivitiesImpl implements FileProcessingActivities {\n\n public String download(String bucketName, String remoteName, String localName) {\n byte[] taskToken = Activity.getTaskToken(); // Used to correlate reply.\n asyncDownloadFileFromS3(taskToken, bucketName, remoteName, localDirectory + localName);\n Activity.doNotCompleteOnReturn();\n return "ignored"; // Return value is ignored when doNotCompleteOnReturn was called.\n }\n ...\n}\n'})}),"\n",(0,a.jsx)(t.p,{children:"When the download is complete, the download service potentially calls back from a different process:"}),"\n",(0,a.jsx)(t.pre,{children:(0,a.jsx)(t.code,{className:"language-java",children:"public <R> void completeActivity(byte[] taskToken, R result) {\n completionClient.complete(taskToken, result);\n}\n\npublic void failActivity(byte[] taskToken, Exception failure) {\n completionClient.completeExceptionally(taskToken, failure);\n}\n"})}),"\n",(0,a.jsx)(t.h2,{id:"activity-heart-beating",children:"Activity Heart Beating"}),"\n",(0,a.jsxs)(t.p,{children:["Some activities are long running. To react to a crash quickly, use a heartbeat mechanism.\nThe ",(0,a.jsx)(t.code,{children:"Activity.heartbeat"})," function lets the Cadence service know that the activity is still alive. You can piggyback\n",(0,a.jsx)(t.code,{children:"details"})," on an activity heartbeat. If an activity times out, the last value of ",(0,a.jsx)(t.code,{children:"details"})," is included\nin the ",(0,a.jsx)(t.code,{children:"ActivityTimeoutException"})," delivered to a workflow. Then the workflow can pass the details to\nthe next activity invocation. This acts as a periodic checkpoint mechanism for the progress of an activity."]}),"\n",(0,a.jsx)(t.pre,{children:(0,a.jsx)(t.code,{className:"language-java",children:"public class FileProcessingActivitiesImpl implements FileProcessingActivities {\n\n @Override\n public String download(String bucketName, String remoteName, String localName) {\n InputStream inputStream = openInputStream(file);\n try {\n byte[] bytes = new byte[MAX_BUFFER_SIZE];\n while ((read = inputStream.read(bytes)) != -1) {\n totalRead += read;\n f.write(bytes, 0, read);\n /*\n * Let the service know about the download progress.\n */\n Activity.heartbeat(totalRead);\n }\n } finally {\n inputStream.close();\n }\n }\n ...\n}\n"})})]})}function m(e={}){const{wrapper:t}={...(0,o.R)(),...e.components};return t?(0,a.jsx)(t,{...e,children:(0,a.jsx)(d,{...e})}):d(e)}},8453:(e,t,i)=>{i.d(t,{R:()=>c,x:()=>l});var n=i(6540);const a={},o=n.createContext(a);function c(e){const t=n.useContext(o);return n.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function l(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:c(e.components),n.createElement(o.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/a7552915.b96a4321.js b/assets/js/a7552915.b96a4321.js deleted file mode 100644 index 5dad4b469..000000000 --- a/assets/js/a7552915.b96a4321.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[9520],{1735:(e,t,i)=>{i.r(t),i.d(t,{assets:()=>r,contentTitle:()=>l,default:()=>m,frontMatter:()=>c,metadata:()=>n,toc:()=>s});const n=JSON.parse('{"id":"java-client/implementing-activities","title":"Implementing activities","description":"Activityactivityactivity implementation","source":"@site/docs/04-java-client/06-implementing-activities.md","sourceDirName":"04-java-client","slug":"/java-client/implementing-activities","permalink":"/docs/java-client/implementing-activities","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/04-java-client/06-implementing-activities.md","tags":[],"version":"current","sidebarPosition":6,"frontMatter":{"layout":"default","title":"Implementing activities","permalink":"/docs/java-client/implementing-activities"}}');var a=i(4848),o=i(8453);const c={layout:"default",title:"Implementing activities",permalink:"/docs/java-client/implementing-activities"},l="Implementing activities",r={},s=[{value:"Accessing Activity Info",id:"accessing-activity-info",level:2},{value:"Asynchronous Activity Completion",id:"asynchronous-activity-completion",level:2},{value:"Activity Heart Beating",id:"activity-heart-beating",level:2}];function d(e){const t={a:"a",code:"code",em:"em",h1:"h1",h2:"h2",header:"header",p:"p",pre:"pre",...(0,o.R)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(t.header,{children:(0,a.jsx)(t.h1,{id:"implementing-activities",children:"Implementing activities"})}),"\n",(0,a.jsxs)(t.p,{children:["Activity implementation is an implementation of an activity interface. A single instance of the activities implementation\nis shared across multiple simultaneous activity invocations. Therefore, the activity implementation code must be ",(0,a.jsx)(t.em,{children:"thread safe"}),"."]}),"\n",(0,a.jsx)(t.p,{children:"The values passed to activities through invocation parameters or returned through a result value are recorded in the execution history.\nThe entire execution history is transferred from the Cadence service to workflow_workers when a workflow state needs to recover.\nA large execution history can thus adversely impact the performance of your workflow. Therefore, be mindful of the amount of data you transfer via activity invocation parameters or return values. Otherwise, no additional limitations exist on activity implementations."}),"\n",(0,a.jsx)(t.pre,{children:(0,a.jsx)(t.code,{className:"language-java",children:"public class FileProcessingActivitiesImpl implements FileProcessingActivities {\n\n private final AmazonS3 s3Client;\n\n private final String localDirectory;\n\n void upload(String bucketName, String localName, String targetName) {\n File f = new File(localName);\n s3Client.putObject(bucket, remoteName, f);\n }\n\n String download(String bucketName, String remoteName, String localName) {\n // Implementation omitted for brevity.\n return downloadFileFromS3(bucketName, remoteName, localDirectory + localName);\n }\n\n String processFile(String localName) {\n // Implementation omitted for brevity.\n return compressFile(localName);\n }\n\n void deleteLocalFile(String fileName) {\n File f = new File(localDirectory + fileName);\n f.delete();\n }\n}\n"})}),"\n",(0,a.jsx)(t.h2,{id:"accessing-activity-info",children:"Accessing Activity Info"}),"\n",(0,a.jsxs)(t.p,{children:["The ",(0,a.jsx)(t.a,{href:"https://static.javadoc.io/com.uber.cadence/cadence-client/2.4.1/index.html?com/cadence-workflow/cadence/activity/Activity.html",children:"Activity"}),"\nclass provides static getters to access information about the workflow that invoked it. Note that this information is stored in a thread local variable. Therefore, calls to Activity accessors succeed only in the thread that invoked the activity function."]}),"\n",(0,a.jsx)(t.pre,{children:(0,a.jsx)(t.code,{className:"language-java",children:'public class FileProcessingActivitiesImpl implements FileProcessingActivities {\n\n @Override\n public String download(String bucketName, String remoteName, String localName) {\n log.info("domain=" + Activity.getDomain());\n WorkflowExecution execution = Activity.getWorkflowExecution();\n log.info("workflowId=" + execution.getWorkflowId());\n log.info("runId=" + execution.getRunId());\n ActivityTask activityTask = Activity.getTask();\n log.info("activityId=" + activityTask.getActivityId());\n log.info("activityTimeout=" + activityTask.getStartToCloseTimeoutSeconds());\n return downloadFileFromS3(bucketName, remoteName, localDirectory + localName);\n }\n ...\n}\n'})}),"\n",(0,a.jsx)(t.h2,{id:"asynchronous-activity-completion",children:"Asynchronous Activity Completion"}),"\n",(0,a.jsx)(t.p,{children:"Sometimes an activity lifecycle goes beyond a synchronous method invocation. For example, a request can be put in a queue\nand later a reply comes and is picked up by a different worker process. The whole request-reply interaction can be modeled\nas a single Cadence activity."}),"\n",(0,a.jsxs)(t.p,{children:["To indicate that an activity should not be completed upon its method return, call ",(0,a.jsx)(t.code,{children:"Activity.doNotCompleteOnReturn()"})," from the\noriginal activity thread. Then later, when replies come, complete the activity using ",(0,a.jsx)(t.a,{href:"https://static.javadoc.io/com.uber.cadence/cadence-client/2.4.1/index.html?com/cadence-workflow/cadence/client/ActivityCompletionClient.html",children:"ActivityCompletionClient"}),".\nTo correlate activity invocation with completion, use either ",(0,a.jsx)(t.code,{children:"TaskToken"})," or workflow and activity IDs."]}),"\n",(0,a.jsx)(t.pre,{children:(0,a.jsx)(t.code,{className:"language-java",children:'public class FileProcessingActivitiesImpl implements FileProcessingActivities {\n\n public String download(String bucketName, String remoteName, String localName) {\n byte[] taskToken = Activity.getTaskToken(); // Used to correlate reply.\n asyncDownloadFileFromS3(taskToken, bucketName, remoteName, localDirectory + localName);\n Activity.doNotCompleteOnReturn();\n return "ignored"; // Return value is ignored when doNotCompleteOnReturn was called.\n }\n ...\n}\n'})}),"\n",(0,a.jsx)(t.p,{children:"When the download is complete, the download service potentially calls back from a different process:"}),"\n",(0,a.jsx)(t.pre,{children:(0,a.jsx)(t.code,{className:"language-java",children:"public <R> void completeActivity(byte[] taskToken, R result) {\n completionClient.complete(taskToken, result);\n}\n\npublic void failActivity(byte[] taskToken, Exception failure) {\n completionClient.completeExceptionally(taskToken, failure);\n}\n"})}),"\n",(0,a.jsx)(t.h2,{id:"activity-heart-beating",children:"Activity Heart Beating"}),"\n",(0,a.jsxs)(t.p,{children:["Some activities are long running. To react to a crash quickly, use a heartbeat mechanism.\nThe ",(0,a.jsx)(t.code,{children:"Activity.heartbeat"})," function lets the Cadence service know that the activity is still alive. You can piggyback\n",(0,a.jsx)(t.code,{children:"details"})," on an activity heartbeat. If an activity times out, the last value of ",(0,a.jsx)(t.code,{children:"details"})," is included\nin the ",(0,a.jsx)(t.code,{children:"ActivityTimeoutException"})," delivered to a workflow. Then the workflow can pass the details to\nthe next activity invocation. This acts as a periodic checkpoint mechanism for the progress of an activity."]}),"\n",(0,a.jsx)(t.pre,{children:(0,a.jsx)(t.code,{className:"language-java",children:"public class FileProcessingActivitiesImpl implements FileProcessingActivities {\n\n @Override\n public String download(String bucketName, String remoteName, String localName) {\n InputStream inputStream = openInputStream(file);\n try {\n byte[] bytes = new byte[MAX_BUFFER_SIZE];\n while ((read = inputStream.read(bytes)) != -1) {\n totalRead += read;\n f.write(bytes, 0, read);\n /*\n * Let the service know about the download progress.\n */\n Activity.heartbeat(totalRead);\n }\n } finally {\n inputStream.close();\n }\n }\n ...\n}\n"})})]})}function m(e={}){const{wrapper:t}={...(0,o.R)(),...e.components};return t?(0,a.jsx)(t,{...e,children:(0,a.jsx)(d,{...e})}):d(e)}},8453:(e,t,i)=>{i.d(t,{R:()=>c,x:()=>l});var n=i(6540);const a={},o=n.createContext(a);function c(e){const t=n.useContext(o);return n.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function l(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:c(e.components),n.createElement(o.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/a7de3fbd.67fdf090.js b/assets/js/a7de3fbd.67fdf090.js deleted file mode 100644 index 1f269f002..000000000 --- a/assets/js/a7de3fbd.67fdf090.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[783],{8515:(e,s,t)=>{t.r(s),t.d(s,{assets:()=>c,contentTitle:()=>r,default:()=>u,frontMatter:()=>o,metadata:()=>n,toc:()=>l});const n=JSON.parse('{"id":"use-cases/dsl","title":"DSL workflows","description":"Cadence supports implementing business logic directly in programming languages like Java and Go. But there are cases when","source":"@site/docs/02-use-cases/11-dsl.md","sourceDirName":"02-use-cases","slug":"/use-cases/dsl","permalink":"/docs/use-cases/dsl","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/02-use-cases/11-dsl.md","tags":[],"version":"current","sidebarPosition":11,"frontMatter":{"layout":"default","title":"DSL workflows","permalink":"/docs/use-cases/dsl"},"sidebar":"docsSidebar","previous":{"title":"Interactive application","permalink":"/docs/use-cases/interactive"},"next":{"title":"Big data and ML","permalink":"/docs/use-cases/big-ml"}}');var a=t(4848),i=t(8453);const o={layout:"default",title:"DSL workflows",permalink:"/docs/use-cases/dsl"},r="DSL workflows",c={},l=[];function d(e){const s={h1:"h1",header:"header",p:"p",...(0,i.R)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(s.header,{children:(0,a.jsx)(s.h1,{id:"dsl-workflows",children:"DSL workflows"})}),"\n",(0,a.jsx)(s.p,{children:"Cadence supports implementing business logic directly in programming languages like Java and Go. But there are cases when\nusing a domain-specific language is more appropriate. Or there might be a legacy system that uses some form of DSL for process definition but it is not operationally stable and scalable. This also applies to more recent systems like Apache Airflow, various BPMN engines and AWS Step Functions."}),"\n",(0,a.jsx)(s.p,{children:"An application that interprets the DSL definition can be written using the Cadence SDK. It automatically becomes highly fault tolerant, scalable, and durable when running on Cadence. Cadence has been used to deprecate several Uber internal DSL engines. The customers continue to use existing process definitions, but Cadence is used as an execution engine."}),"\n",(0,a.jsx)(s.p,{children:'There are multiple benefits of unifying all company workflow engines on top of Cadence. The most obvious one is that\nit is more efficient to support a single product instead of many. It is also difficult to beat the scalability and stability of\nCadence which each of the integrations it comes with. Additionally, the ability to share activities across "engines"\nmight be a huge benefit in some cases.'})]})}function u(e={}){const{wrapper:s}={...(0,i.R)(),...e.components};return s?(0,a.jsx)(s,{...e,children:(0,a.jsx)(d,{...e})}):d(e)}},8453:(e,s,t)=>{t.d(s,{R:()=>o,x:()=>r});var n=t(6540);const a={},i=n.createContext(a);function o(e){const s=n.useContext(i);return n.useMemo((function(){return"function"==typeof e?e(s):{...s,...e}}),[s,e])}function r(e){let s;return s=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:o(e.components),n.createElement(i.Provider,{value:s},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/a7de3fbd.93cd659d.js b/assets/js/a7de3fbd.93cd659d.js new file mode 100644 index 000000000..0b61df766 --- /dev/null +++ b/assets/js/a7de3fbd.93cd659d.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[783],{8515:(e,s,t)=>{t.r(s),t.d(s,{assets:()=>r,contentTitle:()=>c,default:()=>u,frontMatter:()=>o,metadata:()=>n,toc:()=>l});const n=JSON.parse('{"id":"use-cases/dsl","title":"DSL workflows","description":"Cadence supports implementing business logic directly in programming languages like Java and Go. But there are cases when","source":"@site/docs/02-use-cases/11-dsl.md","sourceDirName":"02-use-cases","slug":"/use-cases/dsl","permalink":"/Cadence-Docs/docs/use-cases/dsl","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/02-use-cases/11-dsl.md","tags":[],"version":"current","sidebarPosition":11,"frontMatter":{"layout":"default","title":"DSL workflows","permalink":"/docs/use-cases/dsl"},"sidebar":"docsSidebar","previous":{"title":"Interactive application","permalink":"/Cadence-Docs/docs/use-cases/interactive"},"next":{"title":"Big data and ML","permalink":"/Cadence-Docs/docs/use-cases/big-ml"}}');var a=t(4848),i=t(8453);const o={layout:"default",title:"DSL workflows",permalink:"/docs/use-cases/dsl"},c="DSL workflows",r={},l=[];function d(e){const s={h1:"h1",header:"header",p:"p",...(0,i.R)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(s.header,{children:(0,a.jsx)(s.h1,{id:"dsl-workflows",children:"DSL workflows"})}),"\n",(0,a.jsx)(s.p,{children:"Cadence supports implementing business logic directly in programming languages like Java and Go. But there are cases when\nusing a domain-specific language is more appropriate. Or there might be a legacy system that uses some form of DSL for process definition but it is not operationally stable and scalable. This also applies to more recent systems like Apache Airflow, various BPMN engines and AWS Step Functions."}),"\n",(0,a.jsx)(s.p,{children:"An application that interprets the DSL definition can be written using the Cadence SDK. It automatically becomes highly fault tolerant, scalable, and durable when running on Cadence. Cadence has been used to deprecate several Uber internal DSL engines. The customers continue to use existing process definitions, but Cadence is used as an execution engine."}),"\n",(0,a.jsx)(s.p,{children:'There are multiple benefits of unifying all company workflow engines on top of Cadence. The most obvious one is that\nit is more efficient to support a single product instead of many. It is also difficult to beat the scalability and stability of\nCadence which each of the integrations it comes with. Additionally, the ability to share activities across "engines"\nmight be a huge benefit in some cases.'})]})}function u(e={}){const{wrapper:s}={...(0,i.R)(),...e.components};return s?(0,a.jsx)(s,{...e,children:(0,a.jsx)(d,{...e})}):d(e)}},8453:(e,s,t)=>{t.d(s,{R:()=>o,x:()=>c});var n=t(6540);const a={},i=n.createContext(a);function o(e){const s=n.useContext(i);return n.useMemo((function(){return"function"==typeof e?e(s):{...s,...e}}),[s,e])}function c(e){let s;return s=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:o(e.components),n.createElement(i.Provider,{value:s},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/a82a64d4.31f567ec.js b/assets/js/a82a64d4.31f567ec.js new file mode 100644 index 000000000..a5be1e068 --- /dev/null +++ b/assets/js/a82a64d4.31f567ec.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[9433],{5758:e=>{e.exports=JSON.parse('{"tag":{"label":"Introduction to Cadence","permalink":"/Cadence-Docs/blog/tags/introduction-to-cadence","description":"Introduction to Cadence tag description","allTagsPath":"/Cadence-Docs/blog/tags","count":5,"unlisted":false},"listMetadata":{"permalink":"/Cadence-Docs/blog/tags/introduction-to-cadence","page":1,"postsPerPage":10,"totalPages":1,"totalCount":5,"blogDescription":"The latest news and updates from the Cadence team","blogTitle":"Cadence Blog"}}')}}]); \ No newline at end of file diff --git a/assets/js/a844cb54.d01bcae6.js b/assets/js/a844cb54.d01bcae6.js new file mode 100644 index 000000000..fbf967ca5 --- /dev/null +++ b/assets/js/a844cb54.d01bcae6.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[7940],{4002:i=>{i.exports=JSON.parse('{"authors":[{"name":"Chris Qin","title":"Applications Developer @ Uber","url":"https://www.linkedin.com/in/chrisqin0610/","page":{"permalink":"/Cadence-Docs/blog/authors/chopincode"},"socials":{"linkedin":"https://www.linkedin.com/in/chrisqin0610/","github":"https://github.com/chopincode"},"imageURL":"https://github.com/chopincode.png","key":"chopincode","count":6},{"name":"Ender Demirkaya","title":"Senior Manager at Uber, Cadence. Author of the Software Engineering Handbook","url":"https://www.linkedin.com/in/enderdemirkaya/","page":{"permalink":"/Cadence-Docs/blog/authors/enderdemirkaya"},"socials":{"linkedin":"https://www.linkedin.com/in/enderdemirkaya/","github":"https://github.com/demirkayaender"},"imageURL":"https://github.com/demirkayaender.png","key":"enderdemirkaya","count":2},{"name":"Jakob Haahr Taankvist","title":"Software Engineer II @ Uber","url":"https://www.linkedin.com/in/jakob-taankvist/","page":{"permalink":"/Cadence-Docs/blog/authors/jakobht"},"socials":{"linkedin":"https://www.linkedin.com/in/jakob-taankvist/","github":"https://github.com/jakobht"},"imageURL":"https://github.com/jakobht.png","key":"jakobht","count":1},{"name":"Josu\xe9 Alexander Ibarra","title":"Developer Advocate @ Uber","url":"https://github.com/ibarrajo/","page":{"permalink":"/Cadence-Docs/blog/authors/ibarrajo"},"socials":{"github":"https://github.com/ibarrajo","linkedin":"https://www.linkedin.com/in/elninja/"},"imageURL":"https://github.com/ibarrajo.png","key":"ibarrajo","count":1},{"name":"Kevin Corbett","title":"Open Source Community Manager | @instaclustr @NetApp","url":"https://github.com/kcorbett-netapp","page":{"permalink":"/Cadence-Docs/blog/authors/kcorbett-netapp"},"socials":{"linkedin":"https://www.linkedin.com/in/kcorb95/","github":"https://github.com/kcorbett-netapp"},"imageURL":"https://github.com/kcorbett-netapp.png","key":"kcorbett-netapp","count":1},{"name":"Liang Mei","title":"Engineering Manager @ Uber","url":"https://www.linkedin.com/in/meiliang86/","page":{"permalink":"/Cadence-Docs/blog/authors/meiliang-86"},"socials":{"linkedin":"https://www.linkedin.com/in/meiliang86/","github":"https://github.com/meiliang86"},"imageURL":"https://github.com/meiliang86.png","key":"meiliang86","count":2},{"name":"Sharan Foga","title":"Director of Operations & Customer Success @ Encube Technologies","url":"https://www.linkedin.com/in/sfoga/","page":{"permalink":"/Cadence-Docs/blog/authors/sharanf"},"socials":{"linkedin":"https://www.linkedin.com/in/sfoga/","github":"https://github.com/sharanf"},"imageURL":"https://github.com/sharanf.png","key":"sharanf","count":19},{"name":"Taylan Isikdemir","title":"Sr. Staff Software Engineer @ Uber","url":"https://www.linkedin.com/in/taylan-isikdemir","page":{"permalink":"/Cadence-Docs/blog/authors/taylanisikdemir"},"socials":{"linkedin":"https://www.linkedin.com/in/taylan-isikdemir","github":"https://github.com/taylanisikdemir"},"imageURL":"https://github.com/taylanisikdemir.png","key":"taylanisikdemir","count":1},{"name":"Vytautas Karpavicius","title":"Software Engineer @ Uber","url":"https://www.linkedin.com/in/vytautas-karpavicius","page":{"permalink":"/Cadence-Docs/blog/authors/vytautas-karpavicius"},"socials":{"linkedin":"https://www.linkedin.com/in/vytautas-karpavicius","github":"https://github.com/vytautas-karpavicius"},"imageURL":"https://github.com/vytautas-karpavicius.png","key":"vytautas-karpavicius","count":1},{"name":"Zijian Chen","title":"Software Engineer @ Uber","url":"https://www.linkedin.com/in/zijian-chen-5868938b/","page":{"permalink":"/Cadence-Docs/blog/authors/shaddoll"},"socials":{"linkedin":"https://www.linkedin.com/in/zijian-chen-5868938b/","github":"https://github.com/Shaddoll"},"imageURL":"https://github.com/Shaddoll.png","key":"shaddoll","count":1}]}')}}]); \ No newline at end of file diff --git a/assets/js/a94774ec.0bbe74fe.js b/assets/js/a94774ec.3c16e9e5.js similarity index 82% rename from assets/js/a94774ec.0bbe74fe.js rename to assets/js/a94774ec.3c16e9e5.js index 7cd0d77ac..ed88375d6 100644 --- a/assets/js/a94774ec.0bbe74fe.js +++ b/assets/js/a94774ec.3c16e9e5.js @@ -1 +1 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[2887],{2318:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>c,contentTitle:()=>r,default:()=>h,frontMatter:()=>s,metadata:()=>o,toc:()=>l});var o=n(8143),i=n(4848),a=n(8453);const s={title:"Cadence Community Spotlight Update - August 2022",date:new Date("2022-08-31T00:00:00.000Z"),authors:"sharanf",tags:["community-spotlight"]},r=void 0,c={authorsImageUrls:[void 0]},l=[{value:"Community Survey",id:"community-survey",level:2},{value:"Support Activity",id:"support-activity",level:2},{value:"GitHub Activity",id:"github-activity",level:2},{value:"Come Along to Our Next Cadence Meetup!",id:"come-along-to-our-next-cadence-meetup",level:2},{value:"Looking for a Cadence Role?",id:"looking-for-a-cadence-role",level:2},{value:"Cadence in the News!",id:"cadence-in-the-news",level:2},{value:"Upcoming Events",id:"upcoming-events",level:2}];function u(e){const t={a:"a",h2:"h2",li:"li",p:"p",ul:"ul",...(0,a.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(t.p,{children:"Here\u2019s the latest in our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!"}),"\n",(0,i.jsx)(t.p,{children:"Please see below for a roundup of the highlights:"}),"\n",(0,i.jsx)(t.h2,{id:"community-survey",children:"Community Survey"}),"\n",(0,i.jsx)(t.p,{children:"We are working on putting together our first community survey to find out a bit more about our community. We would like to get your feedback about on a few things such as:"}),"\n",(0,i.jsxs)(t.ul,{children:["\n",(0,i.jsx)(t.li,{children:"how you are using Cadence"}),"\n",(0,i.jsx)(t.li,{children:"any specific experiences you have had where you'd like to see new features"}),"\n",(0,i.jsx)(t.li,{children:"any special use cases not yet covered"}),"\n",(0,i.jsx)(t.li,{children:"and of course whatever other feedback you'd like to give us"}),"\n"]}),"\n",(0,i.jsx)(t.p,{children:"So please watch out for the survey which will be coming out to you via the Slack channel soon!"}),"\n",(0,i.jsx)(t.h2,{id:"support-activity",children:"Support Activity"}),"\n",(0,i.jsx)(t.p,{children:"We have noticed that community activity is increasing and that we are continuing to respond to questions in our Slack #support channel. Eight questions have been posted in the channel this month and another seven questions have been posted on StackOverflow. We encourage people to post their questions on StackOverflow so that the response can be shared. You can also post a link to the StackOverflow question in the support channel to be extra sure it gets seen by our community members."}),"\n",(0,i.jsx)(t.p,{children:"We are looking always forward to receiving more of your questions!"}),"\n",(0,i.jsx)(t.h2,{id:"github-activity",children:"GitHub Activity"}),"\n",(0,i.jsx)(t.p,{children:"Do you remember our GitHub Statistics from last month? Don't worry if you don't! In July we had 28 pull requests (PRs) merged into the code repository. This month we have had 43 PRs merged (nearly double!)- so you can see the level of activity is also increasing in terms of the project code."}),"\n",(0,i.jsxs)(t.p,{children:["If you are interested in contributing to Cadence then please take a look at our ",(0,i.jsx)(t.a,{href:"https://github.com/cadence-workflow/cadence/blob/86f645da952e15d7a7415cdf9fcd2726f28063a6/CONTRIBUTING.md",children:"Contribution Guidelines"})," and also our list of ",(0,i.jsx)(t.a,{href:"https://github.com/cadence-workflow/cadence/contribute",children:"good first issues"})," to work on."]}),"\n",(0,i.jsx)(t.h2,{id:"come-along-to-our-next-cadence-meetup",children:"Come Along to Our Next Cadence Meetup!"}),"\n",(0,i.jsx)(t.p,{children:"It's been a while since we had a Cadence meetup so we have decided to organise another one. This time we are planning to do an in-person meetup in the San Francisco Bay area in early November. We are looking for any companies using Cadence to come along and speak about how they are using it. We'd also like to hear about any interesting use cases that you have used Cadence for."}),"\n",(0,i.jsxs)(t.p,{children:["If you are interested in speaking at our next meetup then please contact ",(0,i.jsx)(t.a,{href:"https://www.linkedin.com/in/enderdemirkaya/",children:"Ender Demirkaya"})]}),"\n",(0,i.jsx)(t.h2,{id:"looking-for-a-cadence-role",children:"Looking for a Cadence Role?"}),"\n",(0,i.jsxs)(t.p,{children:["The Cadence teeam at Uber are recruiting for a Fullstack Engineer. If you are interested then please contact ",(0,i.jsx)(t.a,{href:"https://www.linkedin.com/in/enderdemirkaya/",children:"Ender Demirkaya"})," for more details."]}),"\n",(0,i.jsx)(t.h2,{id:"cadence-in-the-news",children:"Cadence in the News!"}),"\n",(0,i.jsx)(t.p,{children:"Below are a selection of Cadence related articles, blogs and whitepapers. Please take a look and feel free to share via your own social media channels."}),"\n",(0,i.jsxs)(t.ul,{children:["\n",(0,i.jsxs)(t.li,{children:["\n",(0,i.jsx)(t.p,{children:(0,i.jsx)(t.a,{href:"https://www.instaclustr.com/blog/cadence-advanced-visibility-enhance-your-workflows-with-searchability/",children:"Cadence Advanced Visibility: Enhance Your Workflows with Searchability"})}),"\n"]}),"\n",(0,i.jsxs)(t.li,{children:["\n",(0,i.jsx)(t.p,{children:(0,i.jsx)(t.a,{href:"https://www.instaclustr.com/blog/new-features-for-instaclustr-managed-cadence/",children:"New Features for Instaclustr Managed Cadence"})}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(t.h2,{id:"upcoming-events",children:"Upcoming Events"}),"\n",(0,i.jsxs)(t.ul,{children:["\n",(0,i.jsxs)(t.li,{children:["\n",(0,i.jsx)(t.p,{children:(0,i.jsx)(t.a,{href:"https://info.instaclustr.com/webinar-emea-building-cadence-workflow.html",children:"Webinar: Building Your First Cadence Workflow with Java and Go - 1st September 2022"})}),"\n"]}),"\n",(0,i.jsxs)(t.li,{children:["\n",(0,i.jsx)(t.p,{children:(0,i.jsx)(t.a,{href:"https://calendar.google.com/calendar/u/0/embed?src=e6r40gp3c2r01054id7e99dlac@group.calendar.google.com&ctz=America/Los_Angeles",children:"Cadence Technical Office Hours - 26th September 2022 @ 9am PT"})}),"\n"]}),"\n"]}),"\n",(0,i.jsxs)(t.p,{children:["If you have any news or topics you'd like us to include in our next update then please join our ",(0,i.jsx)(t.a,{href:"http://t.uber.com/cadence-slack",children:"Slack"}),"#community channel."]}),"\n",(0,i.jsxs)(t.p,{children:["Please remember that this update is for you - so if you have any comments or feedback that could help us improve it then please share it with us in the #community ",(0,i.jsx)(t.a,{href:"http://t.uber.com/cadence-slack",children:"Slack"})," channel."]})]})}function h(e={}){const{wrapper:t}={...(0,a.R)(),...e.components};return t?(0,i.jsx)(t,{...e,children:(0,i.jsx)(u,{...e})}):u(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>s,x:()=>r});var o=n(6540);const i={},a=o.createContext(i);function s(e){const t=o.useContext(a);return o.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function r(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:s(e.components),o.createElement(a.Provider,{value:t},e.children)}},8143:e=>{e.exports=JSON.parse('{"permalink":"/blog/2022/08/31/community-spotlight-august-2022","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2022-08-31-community-spotlight-august-2022.md","source":"@site/blog/2022-08-31-community-spotlight-august-2022.md","title":"Cadence Community Spotlight Update - August 2022","description":"Here\u2019s the latest in our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!","date":"2022-08-31T00:00:00.000Z","tags":[{"inline":false,"label":"Community Spotlight","permalink":"/blog/tags/community-spotlights","description":"Community Spotlight tag description"}],"readingTime":2.83,"hasTruncateMarker":true,"authors":[{"name":"Sharan Foga","title":"Director of Operations & Customer Success @ Encube Technologies","url":"https://www.linkedin.com/in/sfoga/","page":{"permalink":"/blog/authors/sharanf"},"socials":{"linkedin":"https://www.linkedin.com/in/sfoga/","github":"https://github.com/sharanf"},"imageURL":"https://github.com/sharanf.png","key":"sharanf"}],"frontMatter":{"title":"Cadence Community Spotlight Update - August 2022","date":"2022-08-31T00:00:00.000Z","authors":"sharanf","tags":["community-spotlight"]},"unlisted":false,"prevItem":{"title":"Cadence Community Spotlight Update - September 2022","permalink":"/blog/2022/09/30/community-spotlight-september-2022"},"nextItem":{"title":"Cadence Community Spotlight Update - July 2022","permalink":"/blog/2022/07/31/community-spotlight-update-july-2022"}}')}}]); \ No newline at end of file +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[2887],{2318:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>c,contentTitle:()=>r,default:()=>h,frontMatter:()=>s,metadata:()=>o,toc:()=>l});var o=n(8143),i=n(4848),a=n(8453);const s={title:"Cadence Community Spotlight Update - August 2022",date:new Date("2022-08-31T00:00:00.000Z"),authors:"sharanf",tags:["community-spotlight"]},r=void 0,c={authorsImageUrls:[void 0]},l=[{value:"Community Survey",id:"community-survey",level:2},{value:"Support Activity",id:"support-activity",level:2},{value:"GitHub Activity",id:"github-activity",level:2},{value:"Come Along to Our Next Cadence Meetup!",id:"come-along-to-our-next-cadence-meetup",level:2},{value:"Looking for a Cadence Role?",id:"looking-for-a-cadence-role",level:2},{value:"Cadence in the News!",id:"cadence-in-the-news",level:2},{value:"Upcoming Events",id:"upcoming-events",level:2}];function u(e){const t={a:"a",h2:"h2",li:"li",p:"p",ul:"ul",...(0,a.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(t.p,{children:"Here\u2019s the latest in our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!"}),"\n",(0,i.jsx)(t.p,{children:"Please see below for a roundup of the highlights:"}),"\n",(0,i.jsx)(t.h2,{id:"community-survey",children:"Community Survey"}),"\n",(0,i.jsx)(t.p,{children:"We are working on putting together our first community survey to find out a bit more about our community. We would like to get your feedback about on a few things such as:"}),"\n",(0,i.jsxs)(t.ul,{children:["\n",(0,i.jsx)(t.li,{children:"how you are using Cadence"}),"\n",(0,i.jsx)(t.li,{children:"any specific experiences you have had where you'd like to see new features"}),"\n",(0,i.jsx)(t.li,{children:"any special use cases not yet covered"}),"\n",(0,i.jsx)(t.li,{children:"and of course whatever other feedback you'd like to give us"}),"\n"]}),"\n",(0,i.jsx)(t.p,{children:"So please watch out for the survey which will be coming out to you via the Slack channel soon!"}),"\n",(0,i.jsx)(t.h2,{id:"support-activity",children:"Support Activity"}),"\n",(0,i.jsx)(t.p,{children:"We have noticed that community activity is increasing and that we are continuing to respond to questions in our Slack #support channel. Eight questions have been posted in the channel this month and another seven questions have been posted on StackOverflow. We encourage people to post their questions on StackOverflow so that the response can be shared. You can also post a link to the StackOverflow question in the support channel to be extra sure it gets seen by our community members."}),"\n",(0,i.jsx)(t.p,{children:"We are looking always forward to receiving more of your questions!"}),"\n",(0,i.jsx)(t.h2,{id:"github-activity",children:"GitHub Activity"}),"\n",(0,i.jsx)(t.p,{children:"Do you remember our GitHub Statistics from last month? Don't worry if you don't! In July we had 28 pull requests (PRs) merged into the code repository. This month we have had 43 PRs merged (nearly double!)- so you can see the level of activity is also increasing in terms of the project code."}),"\n",(0,i.jsxs)(t.p,{children:["If you are interested in contributing to Cadence then please take a look at our ",(0,i.jsx)(t.a,{href:"https://github.com/cadence-workflow/cadence/blob/86f645da952e15d7a7415cdf9fcd2726f28063a6/CONTRIBUTING.md",children:"Contribution Guidelines"})," and also our list of ",(0,i.jsx)(t.a,{href:"https://github.com/cadence-workflow/cadence/contribute",children:"good first issues"})," to work on."]}),"\n",(0,i.jsx)(t.h2,{id:"come-along-to-our-next-cadence-meetup",children:"Come Along to Our Next Cadence Meetup!"}),"\n",(0,i.jsx)(t.p,{children:"It's been a while since we had a Cadence meetup so we have decided to organise another one. This time we are planning to do an in-person meetup in the San Francisco Bay area in early November. We are looking for any companies using Cadence to come along and speak about how they are using it. We'd also like to hear about any interesting use cases that you have used Cadence for."}),"\n",(0,i.jsxs)(t.p,{children:["If you are interested in speaking at our next meetup then please contact ",(0,i.jsx)(t.a,{href:"https://www.linkedin.com/in/enderdemirkaya/",children:"Ender Demirkaya"})]}),"\n",(0,i.jsx)(t.h2,{id:"looking-for-a-cadence-role",children:"Looking for a Cadence Role?"}),"\n",(0,i.jsxs)(t.p,{children:["The Cadence teeam at Uber are recruiting for a Fullstack Engineer. If you are interested then please contact ",(0,i.jsx)(t.a,{href:"https://www.linkedin.com/in/enderdemirkaya/",children:"Ender Demirkaya"})," for more details."]}),"\n",(0,i.jsx)(t.h2,{id:"cadence-in-the-news",children:"Cadence in the News!"}),"\n",(0,i.jsx)(t.p,{children:"Below are a selection of Cadence related articles, blogs and whitepapers. Please take a look and feel free to share via your own social media channels."}),"\n",(0,i.jsxs)(t.ul,{children:["\n",(0,i.jsxs)(t.li,{children:["\n",(0,i.jsx)(t.p,{children:(0,i.jsx)(t.a,{href:"https://www.instaclustr.com/blog/cadence-advanced-visibility-enhance-your-workflows-with-searchability/",children:"Cadence Advanced Visibility: Enhance Your Workflows with Searchability"})}),"\n"]}),"\n",(0,i.jsxs)(t.li,{children:["\n",(0,i.jsx)(t.p,{children:(0,i.jsx)(t.a,{href:"https://www.instaclustr.com/blog/new-features-for-instaclustr-managed-cadence/",children:"New Features for Instaclustr Managed Cadence"})}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(t.h2,{id:"upcoming-events",children:"Upcoming Events"}),"\n",(0,i.jsxs)(t.ul,{children:["\n",(0,i.jsxs)(t.li,{children:["\n",(0,i.jsx)(t.p,{children:(0,i.jsx)(t.a,{href:"https://info.instaclustr.com/webinar-emea-building-cadence-workflow.html",children:"Webinar: Building Your First Cadence Workflow with Java and Go - 1st September 2022"})}),"\n"]}),"\n",(0,i.jsxs)(t.li,{children:["\n",(0,i.jsx)(t.p,{children:(0,i.jsx)(t.a,{href:"https://calendar.google.com/calendar/u/0/embed?src=e6r40gp3c2r01054id7e99dlac@group.calendar.google.com&ctz=America/Los_Angeles",children:"Cadence Technical Office Hours - 26th September 2022 @ 9am PT"})}),"\n"]}),"\n"]}),"\n",(0,i.jsxs)(t.p,{children:["If you have any news or topics you'd like us to include in our next update then please join our ",(0,i.jsx)(t.a,{href:"http://t.uber.com/cadence-slack",children:"Slack"}),"#community channel."]}),"\n",(0,i.jsxs)(t.p,{children:["Please remember that this update is for you - so if you have any comments or feedback that could help us improve it then please share it with us in the #community ",(0,i.jsx)(t.a,{href:"http://t.uber.com/cadence-slack",children:"Slack"})," channel."]})]})}function h(e={}){const{wrapper:t}={...(0,a.R)(),...e.components};return t?(0,i.jsx)(t,{...e,children:(0,i.jsx)(u,{...e})}):u(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>s,x:()=>r});var o=n(6540);const i={},a=o.createContext(i);function s(e){const t=o.useContext(a);return o.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function r(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:s(e.components),o.createElement(a.Provider,{value:t},e.children)}},8143:e=>{e.exports=JSON.parse('{"permalink":"/Cadence-Docs/blog/2022/08/31/community-spotlight-august-2022","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2022-08-31-community-spotlight-august-2022.md","source":"@site/blog/2022-08-31-community-spotlight-august-2022.md","title":"Cadence Community Spotlight Update - August 2022","description":"Here\u2019s the latest in our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!","date":"2022-08-31T00:00:00.000Z","tags":[{"inline":false,"label":"Community Spotlight","permalink":"/Cadence-Docs/blog/tags/community-spotlights","description":"Community Spotlight tag description"}],"readingTime":2.83,"hasTruncateMarker":true,"authors":[{"name":"Sharan Foga","title":"Director of Operations & Customer Success @ Encube Technologies","url":"https://www.linkedin.com/in/sfoga/","page":{"permalink":"/Cadence-Docs/blog/authors/sharanf"},"socials":{"linkedin":"https://www.linkedin.com/in/sfoga/","github":"https://github.com/sharanf"},"imageURL":"https://github.com/sharanf.png","key":"sharanf"}],"frontMatter":{"title":"Cadence Community Spotlight Update - August 2022","date":"2022-08-31T00:00:00.000Z","authors":"sharanf","tags":["community-spotlight"]},"unlisted":false,"prevItem":{"title":"Cadence Community Spotlight Update - September 2022","permalink":"/Cadence-Docs/blog/2022/09/30/community-spotlight-september-2022"},"nextItem":{"title":"Cadence Community Spotlight Update - July 2022","permalink":"/Cadence-Docs/blog/2022/07/31/community-spotlight-update-july-2022"}}')}}]); \ No newline at end of file diff --git a/assets/js/a9771bf1.9c404020.js b/assets/js/a9771bf1.9c404020.js new file mode 100644 index 000000000..bc41dc746 --- /dev/null +++ b/assets/js/a9771bf1.9c404020.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[7157],{2156:e=>{e.exports=JSON.parse('{"author":{"name":"Liang Mei","title":"Engineering Manager @ Uber","url":"https://www.linkedin.com/in/meiliang86/","page":{"permalink":"/Cadence-Docs/blog/authors/meiliang-86"},"socials":{"linkedin":"https://www.linkedin.com/in/meiliang86/","github":"https://github.com/meiliang86"},"imageURL":"https://github.com/meiliang86.png","key":"meiliang86","count":2},"listMetadata":{"permalink":"/Cadence-Docs/blog/authors/meiliang-86","page":1,"postsPerPage":10,"totalPages":1,"totalCount":2,"blogDescription":"The latest news and updates from the Cadence team","blogTitle":"Cadence Blog"}}')}}]); \ No newline at end of file diff --git a/assets/js/aa55d0af.34532fcb.js b/assets/js/aa55d0af.34532fcb.js deleted file mode 100644 index 08e0084cc..000000000 --- a/assets/js/aa55d0af.34532fcb.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[8330],{7867:t=>{t.exports=JSON.parse('{"author":{"name":"Jakob Haahr Taankvist","title":"Software Engineer II @ Uber","url":"https://www.linkedin.com/in/jakob-taankvist/","page":{"permalink":"/blog/authors/jakobht"},"socials":{"linkedin":"https://www.linkedin.com/in/jakob-taankvist/","github":"https://github.com/jakobht"},"imageURL":"https://github.com/jakobht.png","key":"jakobht","count":1},"listMetadata":{"permalink":"/blog/authors/jakobht","page":1,"postsPerPage":10,"totalPages":1,"totalCount":1,"blogDescription":"The latest news and updates from the Cadence team","blogTitle":"Cadence Blog"}}')}}]); \ No newline at end of file diff --git a/assets/js/aac593d4.d9eac105.js b/assets/js/aac593d4.40f077e5.js similarity index 65% rename from assets/js/aac593d4.d9eac105.js rename to assets/js/aac593d4.40f077e5.js index 7f595404a..8f498ae6f 100644 --- a/assets/js/aac593d4.d9eac105.js +++ b/assets/js/aac593d4.40f077e5.js @@ -1 +1 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[6269],{5492:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>c,contentTitle:()=>r,default:()=>h,frontMatter:()=>s,metadata:()=>o,toc:()=>u});var o=n(9476),i=n(4848),a=n(8453);const s={title:"Cadence Community Spotlight Update - June 2022",date:new Date("2022-06-30T00:00:00.000Z"),authors:"sharanf",tags:["community-spotlight"]},r=void 0,c={authorsImageUrls:[void 0]},u=[{value:"Knowledge Sharing and Support",id:"knowledge-sharing-and-support",level:2},{value:"Improving Technical Office Hours",id:"improving-technical-office-hours",level:2}];function l(e){const t={h2:"h2",p:"p",strong:"strong",...(0,a.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(t.p,{children:"It\u2019s time for our monthly Cadence Community Spotlight update with news from in and around the Cadence community!"}),"\n",(0,i.jsx)(t.p,{children:"Please see below for a roundup of the highlights:"}),"\n",(0,i.jsx)(t.h2,{id:"knowledge-sharing-and-support",children:"Knowledge Sharing and Support"}),"\n",(0,i.jsx)(t.p,{children:"Our Slack #support channel has been busy this month with 13 questions asked this month by 12 different community members. Six community members took time to respond to those questions which clearly shows our community is growing, collaborating and keen to share knowledge."}),"\n",(0,i.jsxs)(t.p,{children:["Please don\u2019t forget that we encourage everyone to post questions on StackOverflow using the ",(0,i.jsx)(t.strong,{children:"cadence-workflow"})," and ",(0,i.jsx)(t.strong,{children:"uber-cadence"})," tags so that others with similar questions or issues can easily search for and find an answer."]}),"\n",(0,i.jsx)(t.h2,{id:"improving-technical-office-hours",children:"Improving Technical Office Hours"}),"\n",(0,i.jsx)(t.p,{children:"Over the last few months we have been holding regular monthly Office Hours meetings but they have not attracted as many participants as we would like. We would like to understand if there is something preventing people from attending (e.g perhaps the timing or dates are not convenient) so we are planning to send out a short community survey."}),"\n",(0,i.jsx)(t.p,{children:"If you have any ideas or comments about how we can improve our community office hours sessions then please include this in your feedback or contact us in the #community Slack channel."})]})}function h(e={}){const{wrapper:t}={...(0,a.R)(),...e.components};return t?(0,i.jsx)(t,{...e,children:(0,i.jsx)(l,{...e})}):l(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>s,x:()=>r});var o=n(6540);const i={},a=o.createContext(i);function s(e){const t=o.useContext(a);return o.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function r(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:s(e.components),o.createElement(a.Provider,{value:t},e.children)}},9476:e=>{e.exports=JSON.parse('{"permalink":"/blog/2022/06/30/community-spotlight-update-june-2022","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2022-06-30-community-spotlight-update-june-2022.md","source":"@site/blog/2022-06-30-community-spotlight-update-june-2022.md","title":"Cadence Community Spotlight Update - June 2022","description":"It\u2019s time for our monthly Cadence Community Spotlight update with news from in and around the Cadence community!","date":"2022-06-30T00:00:00.000Z","tags":[{"inline":false,"label":"Community Spotlight","permalink":"/blog/tags/community-spotlights","description":"Community Spotlight tag description"}],"readingTime":2.285,"hasTruncateMarker":true,"authors":[{"name":"Sharan Foga","title":"Director of Operations & Customer Success @ Encube Technologies","url":"https://www.linkedin.com/in/sfoga/","page":{"permalink":"/blog/authors/sharanf"},"socials":{"linkedin":"https://www.linkedin.com/in/sfoga/","github":"https://github.com/sharanf"},"imageURL":"https://github.com/sharanf.png","key":"sharanf"}],"frontMatter":{"title":"Cadence Community Spotlight Update - June 2022","date":"2022-06-30T00:00:00.000Z","authors":"sharanf","tags":["community-spotlight"]},"unlisted":false,"prevItem":{"title":"Cadence Community Spotlight Update - July 2022","permalink":"/blog/2022/07/31/community-spotlight-update-july-2022"},"nextItem":{"title":"Cadence Community Spotlight Update - May 2022","permalink":"/blog/2022/05/31/community-spotlight-update-may-2022"}}')}}]); \ No newline at end of file +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[6269],{5492:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>c,contentTitle:()=>r,default:()=>h,frontMatter:()=>s,metadata:()=>o,toc:()=>u});var o=n(9476),i=n(4848),a=n(8453);const s={title:"Cadence Community Spotlight Update - June 2022",date:new Date("2022-06-30T00:00:00.000Z"),authors:"sharanf",tags:["community-spotlight"]},r=void 0,c={authorsImageUrls:[void 0]},u=[{value:"Knowledge Sharing and Support",id:"knowledge-sharing-and-support",level:2},{value:"Improving Technical Office Hours",id:"improving-technical-office-hours",level:2}];function l(e){const t={h2:"h2",p:"p",strong:"strong",...(0,a.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(t.p,{children:"It\u2019s time for our monthly Cadence Community Spotlight update with news from in and around the Cadence community!"}),"\n",(0,i.jsx)(t.p,{children:"Please see below for a roundup of the highlights:"}),"\n",(0,i.jsx)(t.h2,{id:"knowledge-sharing-and-support",children:"Knowledge Sharing and Support"}),"\n",(0,i.jsx)(t.p,{children:"Our Slack #support channel has been busy this month with 13 questions asked this month by 12 different community members. Six community members took time to respond to those questions which clearly shows our community is growing, collaborating and keen to share knowledge."}),"\n",(0,i.jsxs)(t.p,{children:["Please don\u2019t forget that we encourage everyone to post questions on StackOverflow using the ",(0,i.jsx)(t.strong,{children:"cadence-workflow"})," and ",(0,i.jsx)(t.strong,{children:"uber-cadence"})," tags so that others with similar questions or issues can easily search for and find an answer."]}),"\n",(0,i.jsx)(t.h2,{id:"improving-technical-office-hours",children:"Improving Technical Office Hours"}),"\n",(0,i.jsx)(t.p,{children:"Over the last few months we have been holding regular monthly Office Hours meetings but they have not attracted as many participants as we would like. We would like to understand if there is something preventing people from attending (e.g perhaps the timing or dates are not convenient) so we are planning to send out a short community survey."}),"\n",(0,i.jsx)(t.p,{children:"If you have any ideas or comments about how we can improve our community office hours sessions then please include this in your feedback or contact us in the #community Slack channel."})]})}function h(e={}){const{wrapper:t}={...(0,a.R)(),...e.components};return t?(0,i.jsx)(t,{...e,children:(0,i.jsx)(l,{...e})}):l(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>s,x:()=>r});var o=n(6540);const i={},a=o.createContext(i);function s(e){const t=o.useContext(a);return o.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function r(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:s(e.components),o.createElement(a.Provider,{value:t},e.children)}},9476:e=>{e.exports=JSON.parse('{"permalink":"/Cadence-Docs/blog/2022/06/30/community-spotlight-update-june-2022","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2022-06-30-community-spotlight-update-june-2022.md","source":"@site/blog/2022-06-30-community-spotlight-update-june-2022.md","title":"Cadence Community Spotlight Update - June 2022","description":"It\u2019s time for our monthly Cadence Community Spotlight update with news from in and around the Cadence community!","date":"2022-06-30T00:00:00.000Z","tags":[{"inline":false,"label":"Community Spotlight","permalink":"/Cadence-Docs/blog/tags/community-spotlights","description":"Community Spotlight tag description"}],"readingTime":2.285,"hasTruncateMarker":true,"authors":[{"name":"Sharan Foga","title":"Director of Operations & Customer Success @ Encube Technologies","url":"https://www.linkedin.com/in/sfoga/","page":{"permalink":"/Cadence-Docs/blog/authors/sharanf"},"socials":{"linkedin":"https://www.linkedin.com/in/sfoga/","github":"https://github.com/sharanf"},"imageURL":"https://github.com/sharanf.png","key":"sharanf"}],"frontMatter":{"title":"Cadence Community Spotlight Update - June 2022","date":"2022-06-30T00:00:00.000Z","authors":"sharanf","tags":["community-spotlight"]},"unlisted":false,"prevItem":{"title":"Cadence Community Spotlight Update - July 2022","permalink":"/Cadence-Docs/blog/2022/07/31/community-spotlight-update-july-2022"},"nextItem":{"title":"Cadence Community Spotlight Update - May 2022","permalink":"/Cadence-Docs/blog/2022/05/31/community-spotlight-update-may-2022"}}')}}]); \ No newline at end of file diff --git a/assets/js/aacb5a6b.0f31c27b.js b/assets/js/aacb5a6b.0f31c27b.js new file mode 100644 index 000000000..601ec2d4b --- /dev/null +++ b/assets/js/aacb5a6b.0f31c27b.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[5620],{8146:(e,r,n)=>{n.r(r),n.d(r,{assets:()=>i,contentTitle:()=>s,default:()=>h,frontMatter:()=>c,metadata:()=>o,toc:()=>l});const o=JSON.parse('{"id":"go-client/error-handling","title":"Error handling","description":"An, or child, might fail and you could handle errors differently based on different","source":"@site/docs/05-go-client/07-error-handling.md","sourceDirName":"05-go-client","slug":"/go-client/error-handling","permalink":"/Cadence-Docs/docs/go-client/error-handling","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/05-go-client/07-error-handling.md","tags":[],"version":"current","sidebarPosition":7,"frontMatter":{"layout":"default","title":"Error handling","permalink":"/docs/go-client/error-handling"},"sidebar":"docsSidebar","previous":{"title":"Activity and workflow retries","permalink":"/Cadence-Docs/docs/go-client/retries"},"next":{"title":"Signals","permalink":"/Cadence-Docs/docs/go-client/signals"}}');var t=n(4848),a=n(8453);const c={layout:"default",title:"Error handling",permalink:"/docs/go-client/error-handling"},s="Error handling",i={},l=[];function d(e){const r={code:"code",h1:"h1",header:"header",p:"p",pre:"pre",...(0,a.R)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(r.header,{children:(0,t.jsx)(r.h1,{id:"error-handling",children:"Error handling"})}),"\n",(0,t.jsxs)(r.p,{children:["An activity, or child workflow, might fail and you could handle errors differently based on different\nerror cases. If the activity returns an error as ",(0,t.jsx)(r.code,{children:"errors.New()"})," or ",(0,t.jsx)(r.code,{children:"fmt.Errorf()"}),", those errors will\nbe converted to ",(0,t.jsx)(r.code,{children:"workflow.GenericError"}),". If the activity returns an error as\n",(0,t.jsx)(r.code,{children:"cadence.NewCustomError(\u201cerr-reason\u201d, details)"}),", that error will be converted to ",(0,t.jsx)(r.code,{children:"*cadence.CustomError"}),".\nThere are other types of errors such as ",(0,t.jsx)(r.code,{children:"workflow.TimeoutError"}),", ",(0,t.jsx)(r.code,{children:"workflow.CanceledError"})," and\n",(0,t.jsx)(r.code,{children:"workflow.PanicError"}),". Following is an example of what your error code might look like:"]}),"\n",(0,t.jsx)(r.pre,{children:(0,t.jsx)(r.code,{className:"language-go",children:'err := workflow.ExecuteActivity(ctx, YourActivityFunc).Get(ctx, nil)\nswitch err := err.(type) {\n case *cadence.CustomError:\n switch err.Reason() {\n case "err-reason-a":\n // Handle error-reason-a.\n var details YourErrorDetailsType\n err.Details(&details)\n // Deal with details.\n case "err-reason-b":\n // Handle error-reason-b.\n default:\n // Handle all other error reasons.\n }\n case *workflow.GenericError:\n switch err.Error() {\n case "err-msg-1":\n // Handle error with message "err-msg-1".\n case "err-msg-2":\n // Handle error with message "err-msg-2".\n default:\n // Handle all other generic errors.\n }\n case *workflow.TimeoutError:\n switch err.TimeoutType() {\n case shared.TimeoutTypeScheduleToStart:\n // Handle ScheduleToStart timeout.\n case shared.TimeoutTypeStartToClose:\n // Handle StartToClose timeout.\n case shared.TimeoutTypeHeartbeat:\n // Handle heartbeat timeout.\n default:\n }\n case *workflow.PanicError:\n // Handle panic error.\n case *cadence.CanceledError:\n // Handle canceled error.\n default:\n // All other cases (ideally, this should not happen).\n}\n'})})]})}function h(e={}){const{wrapper:r}={...(0,a.R)(),...e.components};return r?(0,t.jsx)(r,{...e,children:(0,t.jsx)(d,{...e})}):d(e)}},8453:(e,r,n)=>{n.d(r,{R:()=>c,x:()=>s});var o=n(6540);const t={},a=o.createContext(t);function c(e){const r=o.useContext(a);return o.useMemo((function(){return"function"==typeof e?e(r):{...r,...e}}),[r,e])}function s(e){let r;return r=e.disableParentContext?"function"==typeof e.components?e.components(t):e.components||t:c(e.components),o.createElement(a.Provider,{value:r},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/aacb5a6b.a80f14bb.js b/assets/js/aacb5a6b.a80f14bb.js deleted file mode 100644 index ebb05b309..000000000 --- a/assets/js/aacb5a6b.a80f14bb.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[5620],{8146:(e,r,n)=>{n.r(r),n.d(r,{assets:()=>i,contentTitle:()=>c,default:()=>h,frontMatter:()=>s,metadata:()=>o,toc:()=>l});const o=JSON.parse('{"id":"go-client/error-handling","title":"Error handling","description":"An, or child, might fail and you could handle errors differently based on different","source":"@site/docs/05-go-client/07-error-handling.md","sourceDirName":"05-go-client","slug":"/go-client/error-handling","permalink":"/docs/go-client/error-handling","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/05-go-client/07-error-handling.md","tags":[],"version":"current","sidebarPosition":7,"frontMatter":{"layout":"default","title":"Error handling","permalink":"/docs/go-client/error-handling"},"sidebar":"docsSidebar","previous":{"title":"Activity and workflow retries","permalink":"/docs/go-client/retries"},"next":{"title":"Signals","permalink":"/docs/go-client/signals"}}');var t=n(4848),a=n(8453);const s={layout:"default",title:"Error handling",permalink:"/docs/go-client/error-handling"},c="Error handling",i={},l=[];function d(e){const r={code:"code",h1:"h1",header:"header",p:"p",pre:"pre",...(0,a.R)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(r.header,{children:(0,t.jsx)(r.h1,{id:"error-handling",children:"Error handling"})}),"\n",(0,t.jsxs)(r.p,{children:["An activity, or child workflow, might fail and you could handle errors differently based on different\nerror cases. If the activity returns an error as ",(0,t.jsx)(r.code,{children:"errors.New()"})," or ",(0,t.jsx)(r.code,{children:"fmt.Errorf()"}),", those errors will\nbe converted to ",(0,t.jsx)(r.code,{children:"workflow.GenericError"}),". If the activity returns an error as\n",(0,t.jsx)(r.code,{children:"cadence.NewCustomError(\u201cerr-reason\u201d, details)"}),", that error will be converted to ",(0,t.jsx)(r.code,{children:"*cadence.CustomError"}),".\nThere are other types of errors such as ",(0,t.jsx)(r.code,{children:"workflow.TimeoutError"}),", ",(0,t.jsx)(r.code,{children:"workflow.CanceledError"})," and\n",(0,t.jsx)(r.code,{children:"workflow.PanicError"}),". Following is an example of what your error code might look like:"]}),"\n",(0,t.jsx)(r.pre,{children:(0,t.jsx)(r.code,{className:"language-go",children:'err := workflow.ExecuteActivity(ctx, YourActivityFunc).Get(ctx, nil)\nswitch err := err.(type) {\n case *cadence.CustomError:\n switch err.Reason() {\n case "err-reason-a":\n // Handle error-reason-a.\n var details YourErrorDetailsType\n err.Details(&details)\n // Deal with details.\n case "err-reason-b":\n // Handle error-reason-b.\n default:\n // Handle all other error reasons.\n }\n case *workflow.GenericError:\n switch err.Error() {\n case "err-msg-1":\n // Handle error with message "err-msg-1".\n case "err-msg-2":\n // Handle error with message "err-msg-2".\n default:\n // Handle all other generic errors.\n }\n case *workflow.TimeoutError:\n switch err.TimeoutType() {\n case shared.TimeoutTypeScheduleToStart:\n // Handle ScheduleToStart timeout.\n case shared.TimeoutTypeStartToClose:\n // Handle StartToClose timeout.\n case shared.TimeoutTypeHeartbeat:\n // Handle heartbeat timeout.\n default:\n }\n case *workflow.PanicError:\n // Handle panic error.\n case *cadence.CanceledError:\n // Handle canceled error.\n default:\n // All other cases (ideally, this should not happen).\n}\n'})})]})}function h(e={}){const{wrapper:r}={...(0,a.R)(),...e.components};return r?(0,t.jsx)(r,{...e,children:(0,t.jsx)(d,{...e})}):d(e)}},8453:(e,r,n)=>{n.d(r,{R:()=>s,x:()=>c});var o=n(6540);const t={},a=o.createContext(t);function s(e){const r=o.useContext(a);return o.useMemo((function(){return"function"==typeof e?e(r):{...r,...e}}),[r,e])}function c(e){let r;return r=e.disableParentContext?"function"==typeof e.components?e.components(t):e.components||t:s(e.components),o.createElement(a.Provider,{value:r},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/acecf23e.bc51da36.js b/assets/js/acecf23e.e0b0ec0e.js similarity index 55% rename from assets/js/acecf23e.bc51da36.js rename to assets/js/acecf23e.e0b0ec0e.js index e1c759307..a62ee1268 100644 --- a/assets/js/acecf23e.bc51da36.js +++ b/assets/js/acecf23e.e0b0ec0e.js @@ -1 +1 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[1903],{1912:e=>{e.exports=JSON.parse('{"blogBasePath":"/blog","blogTitle":"Cadence Blog","authorsListPath":"/blog/authors"}')}}]); \ No newline at end of file +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[1903],{1912:e=>{e.exports=JSON.parse('{"blogBasePath":"/Cadence-Docs/blog","blogTitle":"Cadence Blog","authorsListPath":"/Cadence-Docs/blog/authors"}')}}]); \ No newline at end of file diff --git a/assets/js/acfca6f1.1b17377c.js b/assets/js/acfca6f1.1b17377c.js new file mode 100644 index 000000000..52f6b0f06 --- /dev/null +++ b/assets/js/acfca6f1.1b17377c.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[5484],{4066:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>c,contentTitle:()=>r,default:()=>u,frontMatter:()=>s,metadata:()=>o,toc:()=>m});var o=n(4734),a=n(4848),i=n(8453);const s={title:"Cadence Community Spotlight Update - January 2022",date:new Date("2022-01-31T00:00:00.000Z"),authors:"sharanf",tags:["community-spotlight","roadmap"]},r=void 0,c={authorsImageUrls:[void 0]},m=[];function l(e){const t={p:"p",...(0,i.R)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(t.p,{children:"Welcome to our very first Cadence Community Spotlight update!"}),"\n",(0,a.jsx)(t.p,{children:"This monthly update focuses on news from the wider Cadence community and is all about what you have been doing with Cadence. Do you have an interesting project that uses Cadence? If so then we want to hear from you. Also if you have any news items, blogs, articles, videos or events where Cadence has been mentioned then that is good too. We want to showcase that our community is active and is doing exciting and interesting things."}),"\n",(0,a.jsx)(t.p,{children:"Please see below for a short round up of things that have happened recently in the community."})]})}function u(e={}){const{wrapper:t}={...(0,i.R)(),...e.components};return t?(0,a.jsx)(t,{...e,children:(0,a.jsx)(l,{...e})}):l(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>s,x:()=>r});var o=n(6540);const a={},i=o.createContext(a);function s(e){const t=o.useContext(i);return o.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function r(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:s(e.components),o.createElement(i.Provider,{value:t},e.children)}},4734:e=>{e.exports=JSON.parse('{"permalink":"/Cadence-Docs/blog/2022/01/31/community-spotlight-january-2022","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2022-01-31-community-spotlight-january-2022.md","source":"@site/blog/2022-01-31-community-spotlight-january-2022.md","title":"Cadence Community Spotlight Update - January 2022","description":"Welcome to our very first Cadence Community Spotlight update!","date":"2022-01-31T00:00:00.000Z","tags":[{"inline":false,"label":"Community Spotlight","permalink":"/Cadence-Docs/blog/tags/community-spotlights","description":"Community Spotlight tag description"},{"inline":false,"label":"Roadmap","permalink":"/Cadence-Docs/blog/tags/roadmap","description":"Roadmap tag description"}],"readingTime":2.04,"hasTruncateMarker":true,"authors":[{"name":"Sharan Foga","title":"Director of Operations & Customer Success @ Encube Technologies","url":"https://www.linkedin.com/in/sfoga/","page":{"permalink":"/Cadence-Docs/blog/authors/sharanf"},"socials":{"linkedin":"https://www.linkedin.com/in/sfoga/","github":"https://github.com/sharanf"},"imageURL":"https://github.com/sharanf.png","key":"sharanf"}],"frontMatter":{"title":"Cadence Community Spotlight Update - January 2022","date":"2022-01-31T00:00:00.000Z","authors":"sharanf","tags":["community-spotlight","roadmap"]},"unlisted":false,"prevItem":{"title":"Cadence Community Spotlight Update - February 2022","permalink":"/Cadence-Docs/blog/2022/02/28/community-spotlight-february-2022"},"nextItem":{"title":"Moving to gRPC","permalink":"/Cadence-Docs/blog/2021/10/19/2021-10-19-moving-to-grpc/moving-to-grpc"}}')}}]); \ No newline at end of file diff --git a/assets/js/acfca6f1.a19c40ea.js b/assets/js/acfca6f1.a19c40ea.js deleted file mode 100644 index 270c0bb54..000000000 --- a/assets/js/acfca6f1.a19c40ea.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[5484],{4066:(t,e,n)=>{n.r(e),n.d(e,{assets:()=>c,contentTitle:()=>r,default:()=>u,frontMatter:()=>s,metadata:()=>o,toc:()=>m});var o=n(4734),a=n(4848),i=n(8453);const s={title:"Cadence Community Spotlight Update - January 2022",date:new Date("2022-01-31T00:00:00.000Z"),authors:"sharanf",tags:["community-spotlight","roadmap"]},r=void 0,c={authorsImageUrls:[void 0]},m=[];function l(t){const e={p:"p",...(0,i.R)(),...t.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(e.p,{children:"Welcome to our very first Cadence Community Spotlight update!"}),"\n",(0,a.jsx)(e.p,{children:"This monthly update focuses on news from the wider Cadence community and is all about what you have been doing with Cadence. Do you have an interesting project that uses Cadence? If so then we want to hear from you. Also if you have any news items, blogs, articles, videos or events where Cadence has been mentioned then that is good too. We want to showcase that our community is active and is doing exciting and interesting things."}),"\n",(0,a.jsx)(e.p,{children:"Please see below for a short round up of things that have happened recently in the community."})]})}function u(t={}){const{wrapper:e}={...(0,i.R)(),...t.components};return e?(0,a.jsx)(e,{...t,children:(0,a.jsx)(l,{...t})}):l(t)}},8453:(t,e,n)=>{n.d(e,{R:()=>s,x:()=>r});var o=n(6540);const a={},i=o.createContext(a);function s(t){const e=o.useContext(i);return o.useMemo((function(){return"function"==typeof t?t(e):{...e,...t}}),[e,t])}function r(t){let e;return e=t.disableParentContext?"function"==typeof t.components?t.components(a):t.components||a:s(t.components),o.createElement(i.Provider,{value:e},t.children)}},4734:t=>{t.exports=JSON.parse('{"permalink":"/blog/2022/01/31/community-spotlight-january-2022","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2022-01-31-community-spotlight-january-2022.md","source":"@site/blog/2022-01-31-community-spotlight-january-2022.md","title":"Cadence Community Spotlight Update - January 2022","description":"Welcome to our very first Cadence Community Spotlight update!","date":"2022-01-31T00:00:00.000Z","tags":[{"inline":false,"label":"Community Spotlight","permalink":"/blog/tags/community-spotlights","description":"Community Spotlight tag description"},{"inline":false,"label":"Roadmap","permalink":"/blog/tags/roadmap","description":"Roadmap tag description"}],"readingTime":2.04,"hasTruncateMarker":true,"authors":[{"name":"Sharan Foga","title":"Director of Operations & Customer Success @ Encube Technologies","url":"https://www.linkedin.com/in/sfoga/","page":{"permalink":"/blog/authors/sharanf"},"socials":{"linkedin":"https://www.linkedin.com/in/sfoga/","github":"https://github.com/sharanf"},"imageURL":"https://github.com/sharanf.png","key":"sharanf"}],"frontMatter":{"title":"Cadence Community Spotlight Update - January 2022","date":"2022-01-31T00:00:00.000Z","authors":"sharanf","tags":["community-spotlight","roadmap"]},"unlisted":false,"prevItem":{"title":"Cadence Community Spotlight Update - February 2022","permalink":"/blog/2022/02/28/community-spotlight-february-2022"},"nextItem":{"title":"Moving to gRPC","permalink":"/blog/2021/10/19/2021-10-19-moving-to-grpc/moving-to-grpc"}}')}}]); \ No newline at end of file diff --git a/assets/js/ad4570fb.ca66dc6e.js b/assets/js/ad4570fb.ca66dc6e.js new file mode 100644 index 000000000..87de76a62 --- /dev/null +++ b/assets/js/ad4570fb.ca66dc6e.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[3700],{4772:e=>{e.exports=JSON.parse('{"metadata":{"permalink":"/Cadence-Docs/blog/page/2","page":2,"postsPerPage":10,"totalPages":4,"totalCount":35,"previousPage":"/Cadence-Docs/blog","nextPage":"/Cadence-Docs/blog/page/3","blogDescription":"The latest news and updates from the Cadence team","blogTitle":"Cadence Blog"}}')}}]); \ No newline at end of file diff --git a/assets/js/ad9e871f.a7318599.js b/assets/js/ad9e871f.a7318599.js deleted file mode 100644 index eb05e8ed9..000000000 --- a/assets/js/ad9e871f.a7318599.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[3992],{8696:(e,t,o)=>{o.r(t),o.d(t,{assets:()=>a,contentTitle:()=>l,default:()=>u,frontMatter:()=>i,metadata:()=>r,toc:()=>d});const r=JSON.parse('{"id":"get-started/video-tutorials","title":"Video Tutorials","description":"An Introduction to the Cadence programming model and value proposition.","source":"@site/docs/01-get-started/04-video-tutorials.md","sourceDirName":"01-get-started","slug":"/get-started/video-tutorials","permalink":"/docs/get-started/video-tutorials","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/01-get-started/04-video-tutorials.md","tags":[],"version":"current","sidebarPosition":4,"frontMatter":{"layout":"default","title":"Video Tutorials","permalink":"/docs/get-started/video-tutorials"},"sidebar":"docsSidebar","previous":{"title":"Golang hello world","permalink":"/docs/get-started/golang-hello-world"},"next":{"title":"Introduction","permalink":"/docs/use-cases/"}}');var n=o(4848),s=o(8453);const i={layout:"default",title:"Video Tutorials",permalink:"/docs/get-started/video-tutorials"},l="Overview",a={},d=[{value:"HelloWorld",id:"helloworld",level:2}];function c(e){const t={h1:"h1",h2:"h2",header:"header",p:"p",...(0,s.R)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(t.header,{children:(0,n.jsx)(t.h1,{id:"overview",children:"Overview"})}),"\n",(0,n.jsx)(t.p,{children:"An Introduction to the Cadence programming model and value proposition."}),"\n",(0,n.jsx)("figure",{class:"video-container",children:(0,n.jsx)("iframe",{src:"https://www.youtube.com/embed/llmsBGKOuWI",frameborder:"0",height:"315",allowfullscreen:!0,width:"560"})}),"\n",(0,n.jsx)(t.h2,{id:"helloworld",children:"HelloWorld"}),"\n",(0,n.jsx)(t.p,{children:"A step-by-step video tutorial about how to install and run HellowWorld(Java)."}),"\n",(0,n.jsx)("figure",{class:"video-container",children:(0,n.jsx)("iframe",{src:"https://www.youtube.com/embed/5mBLspVKOAI",frameborder:"0",height:"315",allowfullscreen:!0,width:"560"})})]})}function u(e={}){const{wrapper:t}={...(0,s.R)(),...e.components};return t?(0,n.jsx)(t,{...e,children:(0,n.jsx)(c,{...e})}):c(e)}},8453:(e,t,o)=>{o.d(t,{R:()=>i,x:()=>l});var r=o(6540);const n={},s=r.createContext(n);function i(e){const t=r.useContext(s);return r.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function l(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(n):e.components||n:i(e.components),r.createElement(s.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/ad9e871f.fd2309b0.js b/assets/js/ad9e871f.fd2309b0.js new file mode 100644 index 000000000..3cb05ca7a --- /dev/null +++ b/assets/js/ad9e871f.fd2309b0.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[3992],{8696:(e,t,o)=>{o.r(t),o.d(t,{assets:()=>d,contentTitle:()=>a,default:()=>u,frontMatter:()=>i,metadata:()=>r,toc:()=>l});const r=JSON.parse('{"id":"get-started/video-tutorials","title":"Video Tutorials","description":"An Introduction to the Cadence programming model and value proposition.","source":"@site/docs/01-get-started/04-video-tutorials.md","sourceDirName":"01-get-started","slug":"/get-started/video-tutorials","permalink":"/Cadence-Docs/docs/get-started/video-tutorials","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/01-get-started/04-video-tutorials.md","tags":[],"version":"current","sidebarPosition":4,"frontMatter":{"layout":"default","title":"Video Tutorials","permalink":"/docs/get-started/video-tutorials"},"sidebar":"docsSidebar","previous":{"title":"Golang hello world","permalink":"/Cadence-Docs/docs/get-started/golang-hello-world"},"next":{"title":"Introduction","permalink":"/Cadence-Docs/docs/use-cases/"}}');var n=o(4848),s=o(8453);const i={layout:"default",title:"Video Tutorials",permalink:"/docs/get-started/video-tutorials"},a="Overview",d={},l=[{value:"HelloWorld",id:"helloworld",level:2}];function c(e){const t={h1:"h1",h2:"h2",header:"header",p:"p",...(0,s.R)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(t.header,{children:(0,n.jsx)(t.h1,{id:"overview",children:"Overview"})}),"\n",(0,n.jsx)(t.p,{children:"An Introduction to the Cadence programming model and value proposition."}),"\n",(0,n.jsx)("figure",{class:"video-container",children:(0,n.jsx)("iframe",{src:"https://www.youtube.com/embed/llmsBGKOuWI",frameborder:"0",height:"315",allowfullscreen:!0,width:"560"})}),"\n",(0,n.jsx)(t.h2,{id:"helloworld",children:"HelloWorld"}),"\n",(0,n.jsx)(t.p,{children:"A step-by-step video tutorial about how to install and run HellowWorld(Java)."}),"\n",(0,n.jsx)("figure",{class:"video-container",children:(0,n.jsx)("iframe",{src:"https://www.youtube.com/embed/5mBLspVKOAI",frameborder:"0",height:"315",allowfullscreen:!0,width:"560"})})]})}function u(e={}){const{wrapper:t}={...(0,s.R)(),...e.components};return t?(0,n.jsx)(t,{...e,children:(0,n.jsx)(c,{...e})}):c(e)}},8453:(e,t,o)=>{o.d(t,{R:()=>i,x:()=>a});var r=o(6540);const n={},s=r.createContext(n);function i(e){const t=r.useContext(s);return r.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function a(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(n):e.components||n:i(e.components),r.createElement(s.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/aeb329ea.4aaeade0.js b/assets/js/aeb329ea.4aaeade0.js deleted file mode 100644 index caaeafbc5..000000000 --- a/assets/js/aeb329ea.4aaeade0.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[2937],{3347:(e,t,i)=>{i.r(t),i.d(t,{assets:()=>c,contentTitle:()=>r,default:()=>f,frontMatter:()=>s,metadata:()=>o,toc:()=>l});const o=JSON.parse('{"id":"glossary","title":"Glossary","description":"--\x3e","source":"@site/docs/GLOSSARY.md","sourceDirName":".","slug":"/glossary","permalink":"/docs/glossary","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/GLOSSARY.md","tags":[],"version":"current","frontMatter":{"id":"glossary","layout":"default","title":"Glossary","terms":{"activity":"A business-level function that implements your application logic such as calling a service or transcoding a media file. An activity usually implements a single well-defined action; it can be short or long running. An activity can be implemented as a synchronous method or fully asynchronously involving multiple processes. An activity can be retried indefinitely according to the provided exponential retry policy. If for any reason an activity is not completed within the specified timeout, an error is reported to the workflow and the workflow decides how to handle it. There is no limit on potential activity duration.","activity task":"A task that contains an activity invocation information that is delivered to an activity worker through and an activity task list. An activity worker upon receiving activity task executes a correponding activity","activity task list":"Task list that is used to deliver activity task to activity worker","activity worker":"An object that is executed in the client application and receives activity task from an activity task list it is subscribed to. Once task is received it invokes a correspondent activity.","archival":"Archival is a feature that automatically moves event history from persistence to a blobstore after the workflow retention period. The purpose of archival is to be able to keep histories as long as needed while not overwhelming the persistence store. There are two reasons you may want to keep the histories after the retention period has passed: 1. Compliance: For legal reasons, histories may need to be stored for a long period of time. 2. Debugging: Old histories can still be accessed for debugging.","CLI":"Cadence command-line interface.","client stub":"A client-side proxy used to make remote invocations to an entity that it represents. For example, to start a workflow, a stub object that represents this workflow is created through a special API. Then this stub is used to start, query, or signal the corresponding workflow.\\nThe Go client doesn\'t use this.","decision":"Any action taken by the workflow durable function is called a decision. For example: scheduling an activity, canceling a child workflow, or starting a timer. A decision task contains an optional list of decisions. Every decision is recorded in the event history as an event. See also [1] for more explanation","decision task":"Every time a new external event that might affect a workflow state is recorded, a decision task that contains it is added to a decision task list and then picked up by a workflow worker. After the new event is handled, the decision task is completed with a list of decision. Note that handling of a decision task is usually very fast and is not related to duration of operations that the workflow invokes. See also [1] for more explanation","decision task list":"Task list that is used to deliver decision task to workflow worker. From user\'s point of view, it can be viewed as a worker pool. It defines a pool of worker executing workflow or activity tasks.","domain":"Cadence is backed by a multitenant service. The unit of isolation is called a domain. Each domain acts as a namespace for task list names as well as workflow IDs. For example, when a workflow is started, it is started in a specific domain. Cadence guarantees a unique workflow ID within a domain, and supports running workflow executions to use the same workflow ID if they are in different domains. Various configuration options like retention period or archival destination are configured per domain as well through a special CRUD API or through the Cadence CLI. In the multi-cluster deployment, domain is a unit of fail-over. Each domain can only be active on a single Cadence cluster at a time. However, different domains can be active in different clusters and can fail-over independently.","event":"An indivisible operation performed by your application. For example, activity_task_started, task_failed, or timer_canceled. Events are recorded in the event history.","event history":"An append log of events for your application. History is durably persisted by the Cadence service, enabling seamless recovery of your application state from crashes or failures. It also serves as an audit log for debugging.","local activity":"A local activity is an activity that is invoked directly in the same process by a workflow code. It consumes much less resources than a normal activity, but imposes a lot of limitations like low duration and lack of rate limiting.","query":"A synchronous (from the caller\'s point of view) operation that is used to report a workflow state. Note that a query is inherently read only and cannot affect a workflow state.","run ID":"A UUID that a Cadence service assigns to each workflow run. If allowed by a configured policy, you might be able to re-execute a workflow, after it has closed or failed, with the same workflow id. Each such re-execution is called a run. run id is used to uniquely identify a run even if it shares a workflow id with others.","signal":"An external asynchronous request to a workflow. It can be used to deliver notifications or updates to a running workflow at any point in its existence.","task":"The context needed to execute a specific activity or workflow state transition. There are two types of tasks: an activity task and a decision task (aka workflow task). Note that a single activity execution corresponds to a single activity task, while a workflow execution employs multiple decision tasks.","task list":"Common name for activity task list and decision task list","task token":"A unique correlation ID for a Cadence activity. Activity completion calls take either task token or DomainName, WorkflowID, ActivityID arguments.","worker":"Also known as a worker service. A service that hosts the workflow and activity implementations. The worker polls the Cadence service for tasks, performs those tasks, and communicates task execution results back to the Cadence service. Worker services are developed, deployed, and operated by Cadence customers.","workflow":"A fault-oblivious stateful function that orchestrates activities. A workflow has full control over which activities are executed, and in which order. A workflow must not affect the external world directly, only through activities. What makes workflow code a workflow is that its state is preserved by Cadence. Therefore any failure of a worker process that hosts the workflow code does not affect the workflow execution. The workflow continues as if these failures did not happen. At the same time, activities can fail any moment for any reason. Because workflow code is fully fault-oblivious, it is guaranteed to get notifications about activity failures or timeouts and act accordingly. There is no limit on potential workflow duration.","workflow execution":"An instance of a workflow. The instance can be in the process of executing or it could have already completed execution.","workflow ID":"A unique identifier for a workflow execution. Cadence guarantees the uniqueness of an ID within a domain. An attempt to start a workflow with a duplicate ID results in an already started error.","workflow task":"Synonym of the decision task.","workflow worker":"An object that is executed in the client application and receives decision task from an decision task list it is subscribed to. Once task is received it is handled by a correponding workflow."}}}');var a=i(4848),n=i(8453);const s={id:"glossary",layout:"default",title:"Glossary",terms:{activity:"A business-level function that implements your application logic such as calling a service or transcoding a media file. An activity usually implements a single well-defined action; it can be short or long running. An activity can be implemented as a synchronous method or fully asynchronously involving multiple processes. An activity can be retried indefinitely according to the provided exponential retry policy. If for any reason an activity is not completed within the specified timeout, an error is reported to the workflow and the workflow decides how to handle it. There is no limit on potential activity duration.","activity task":"A task that contains an activity invocation information that is delivered to an activity worker through and an activity task list. An activity worker upon receiving activity task executes a correponding activity","activity task list":"Task list that is used to deliver activity task to activity worker","activity worker":"An object that is executed in the client application and receives activity task from an activity task list it is subscribed to. Once task is received it invokes a correspondent activity.",archival:"Archival is a feature that automatically moves event history from persistence to a blobstore after the workflow retention period. The purpose of archival is to be able to keep histories as long as needed while not overwhelming the persistence store. There are two reasons you may want to keep the histories after the retention period has passed: 1. Compliance: For legal reasons, histories may need to be stored for a long period of time. 2. Debugging: Old histories can still be accessed for debugging.",CLI:"Cadence command-line interface.","client stub":"A client-side proxy used to make remote invocations to an entity that it represents. For example, to start a workflow, a stub object that represents this workflow is created through a special API. Then this stub is used to start, query, or signal the corresponding workflow.\nThe Go client doesn't use this.",decision:"Any action taken by the workflow durable function is called a decision. For example: scheduling an activity, canceling a child workflow, or starting a timer. A decision task contains an optional list of decisions. Every decision is recorded in the event history as an event. See also [1] for more explanation","decision task":"Every time a new external event that might affect a workflow state is recorded, a decision task that contains it is added to a decision task list and then picked up by a workflow worker. After the new event is handled, the decision task is completed with a list of decision. Note that handling of a decision task is usually very fast and is not related to duration of operations that the workflow invokes. See also [1] for more explanation","decision task list":"Task list that is used to deliver decision task to workflow worker. From user's point of view, it can be viewed as a worker pool. It defines a pool of worker executing workflow or activity tasks.",domain:"Cadence is backed by a multitenant service. The unit of isolation is called a domain. Each domain acts as a namespace for task list names as well as workflow IDs. For example, when a workflow is started, it is started in a specific domain. Cadence guarantees a unique workflow ID within a domain, and supports running workflow executions to use the same workflow ID if they are in different domains. Various configuration options like retention period or archival destination are configured per domain as well through a special CRUD API or through the Cadence CLI. In the multi-cluster deployment, domain is a unit of fail-over. Each domain can only be active on a single Cadence cluster at a time. However, different domains can be active in different clusters and can fail-over independently.",event:"An indivisible operation performed by your application. For example, activity_task_started, task_failed, or timer_canceled. Events are recorded in the event history.","event history":"An append log of events for your application. History is durably persisted by the Cadence service, enabling seamless recovery of your application state from crashes or failures. It also serves as an audit log for debugging.","local activity":"A local activity is an activity that is invoked directly in the same process by a workflow code. It consumes much less resources than a normal activity, but imposes a lot of limitations like low duration and lack of rate limiting.",query:"A synchronous (from the caller's point of view) operation that is used to report a workflow state. Note that a query is inherently read only and cannot affect a workflow state.","run ID":"A UUID that a Cadence service assigns to each workflow run. If allowed by a configured policy, you might be able to re-execute a workflow, after it has closed or failed, with the same workflow id. Each such re-execution is called a run. run id is used to uniquely identify a run even if it shares a workflow id with others.",signal:"An external asynchronous request to a workflow. It can be used to deliver notifications or updates to a running workflow at any point in its existence.",task:"The context needed to execute a specific activity or workflow state transition. There are two types of tasks: an activity task and a decision task (aka workflow task). Note that a single activity execution corresponds to a single activity task, while a workflow execution employs multiple decision tasks.","task list":"Common name for activity task list and decision task list","task token":"A unique correlation ID for a Cadence activity. Activity completion calls take either task token or DomainName, WorkflowID, ActivityID arguments.",worker:"Also known as a worker service. A service that hosts the workflow and activity implementations. The worker polls the Cadence service for tasks, performs those tasks, and communicates task execution results back to the Cadence service. Worker services are developed, deployed, and operated by Cadence customers.",workflow:"A fault-oblivious stateful function that orchestrates activities. A workflow has full control over which activities are executed, and in which order. A workflow must not affect the external world directly, only through activities. What makes workflow code a workflow is that its state is preserved by Cadence. Therefore any failure of a worker process that hosts the workflow code does not affect the workflow execution. The workflow continues as if these failures did not happen. At the same time, activities can fail any moment for any reason. Because workflow code is fully fault-oblivious, it is guaranteed to get notifications about activity failures or timeouts and act accordingly. There is no limit on potential workflow duration.","workflow execution":"An instance of a workflow. The instance can be in the process of executing or it could have already completed execution.","workflow ID":"A unique identifier for a workflow execution. Cadence guarantees the uniqueness of an ID within a domain. An attempt to start a workflow with a duplicate ID results in an already started error.","workflow task":"Synonym of the decision task.","workflow worker":"An object that is executed in the client application and receives decision task from an decision task list it is subscribed to. Once task is received it is handled by a correponding workflow."}},r="Glossary",c={},l=[];function d(e){const t={a:"a",h1:"h1",header:"header",p:"p",...(0,n.R)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(t.header,{children:(0,a.jsx)(t.h1,{id:"glossary",children:"Glossary"})}),"\n",(0,a.jsx)(t.p,{children:(0,a.jsx)(t.a,{href:"https://stackoverflow.com/questions/62904129/what-exactly-is-a-cadence-decision-task/63964726#63964726",children:"1 What exactly is a Cadence decision task?"})})]})}function f(e={}){const{wrapper:t}={...(0,n.R)(),...e.components};return t?(0,a.jsx)(t,{...e,children:(0,a.jsx)(d,{...e})}):d(e)}},8453:(e,t,i)=>{i.d(t,{R:()=>s,x:()=>r});var o=i(6540);const a={},n=o.createContext(a);function s(e){const t=o.useContext(n);return o.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function r(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:s(e.components),o.createElement(n.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/aeb329ea.89bf067d.js b/assets/js/aeb329ea.89bf067d.js new file mode 100644 index 000000000..72c75dde6 --- /dev/null +++ b/assets/js/aeb329ea.89bf067d.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[2937],{3347:(e,t,i)=>{i.r(t),i.d(t,{assets:()=>c,contentTitle:()=>r,default:()=>f,frontMatter:()=>s,metadata:()=>o,toc:()=>l});const o=JSON.parse('{"id":"glossary","title":"Glossary","description":"--\x3e","source":"@site/docs/GLOSSARY.md","sourceDirName":".","slug":"/glossary","permalink":"/Cadence-Docs/docs/glossary","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/GLOSSARY.md","tags":[],"version":"current","frontMatter":{"id":"glossary","layout":"default","title":"Glossary","terms":{"activity":"A business-level function that implements your application logic such as calling a service or transcoding a media file. An activity usually implements a single well-defined action; it can be short or long running. An activity can be implemented as a synchronous method or fully asynchronously involving multiple processes. An activity can be retried indefinitely according to the provided exponential retry policy. If for any reason an activity is not completed within the specified timeout, an error is reported to the workflow and the workflow decides how to handle it. There is no limit on potential activity duration.","activity task":"A task that contains an activity invocation information that is delivered to an activity worker through and an activity task list. An activity worker upon receiving activity task executes a correponding activity","activity task list":"Task list that is used to deliver activity task to activity worker","activity worker":"An object that is executed in the client application and receives activity task from an activity task list it is subscribed to. Once task is received it invokes a correspondent activity.","archival":"Archival is a feature that automatically moves event history from persistence to a blobstore after the workflow retention period. The purpose of archival is to be able to keep histories as long as needed while not overwhelming the persistence store. There are two reasons you may want to keep the histories after the retention period has passed: 1. Compliance: For legal reasons, histories may need to be stored for a long period of time. 2. Debugging: Old histories can still be accessed for debugging.","CLI":"Cadence command-line interface.","client stub":"A client-side proxy used to make remote invocations to an entity that it represents. For example, to start a workflow, a stub object that represents this workflow is created through a special API. Then this stub is used to start, query, or signal the corresponding workflow.\\nThe Go client doesn\'t use this.","decision":"Any action taken by the workflow durable function is called a decision. For example: scheduling an activity, canceling a child workflow, or starting a timer. A decision task contains an optional list of decisions. Every decision is recorded in the event history as an event. See also [1] for more explanation","decision task":"Every time a new external event that might affect a workflow state is recorded, a decision task that contains it is added to a decision task list and then picked up by a workflow worker. After the new event is handled, the decision task is completed with a list of decision. Note that handling of a decision task is usually very fast and is not related to duration of operations that the workflow invokes. See also [1] for more explanation","decision task list":"Task list that is used to deliver decision task to workflow worker. From user\'s point of view, it can be viewed as a worker pool. It defines a pool of worker executing workflow or activity tasks.","domain":"Cadence is backed by a multitenant service. The unit of isolation is called a domain. Each domain acts as a namespace for task list names as well as workflow IDs. For example, when a workflow is started, it is started in a specific domain. Cadence guarantees a unique workflow ID within a domain, and supports running workflow executions to use the same workflow ID if they are in different domains. Various configuration options like retention period or archival destination are configured per domain as well through a special CRUD API or through the Cadence CLI. In the multi-cluster deployment, domain is a unit of fail-over. Each domain can only be active on a single Cadence cluster at a time. However, different domains can be active in different clusters and can fail-over independently.","event":"An indivisible operation performed by your application. For example, activity_task_started, task_failed, or timer_canceled. Events are recorded in the event history.","event history":"An append log of events for your application. History is durably persisted by the Cadence service, enabling seamless recovery of your application state from crashes or failures. It also serves as an audit log for debugging.","local activity":"A local activity is an activity that is invoked directly in the same process by a workflow code. It consumes much less resources than a normal activity, but imposes a lot of limitations like low duration and lack of rate limiting.","query":"A synchronous (from the caller\'s point of view) operation that is used to report a workflow state. Note that a query is inherently read only and cannot affect a workflow state.","run ID":"A UUID that a Cadence service assigns to each workflow run. If allowed by a configured policy, you might be able to re-execute a workflow, after it has closed or failed, with the same workflow id. Each such re-execution is called a run. run id is used to uniquely identify a run even if it shares a workflow id with others.","signal":"An external asynchronous request to a workflow. It can be used to deliver notifications or updates to a running workflow at any point in its existence.","task":"The context needed to execute a specific activity or workflow state transition. There are two types of tasks: an activity task and a decision task (aka workflow task). Note that a single activity execution corresponds to a single activity task, while a workflow execution employs multiple decision tasks.","task list":"Common name for activity task list and decision task list","task token":"A unique correlation ID for a Cadence activity. Activity completion calls take either task token or DomainName, WorkflowID, ActivityID arguments.","worker":"Also known as a worker service. A service that hosts the workflow and activity implementations. The worker polls the Cadence service for tasks, performs those tasks, and communicates task execution results back to the Cadence service. Worker services are developed, deployed, and operated by Cadence customers.","workflow":"A fault-oblivious stateful function that orchestrates activities. A workflow has full control over which activities are executed, and in which order. A workflow must not affect the external world directly, only through activities. What makes workflow code a workflow is that its state is preserved by Cadence. Therefore any failure of a worker process that hosts the workflow code does not affect the workflow execution. The workflow continues as if these failures did not happen. At the same time, activities can fail any moment for any reason. Because workflow code is fully fault-oblivious, it is guaranteed to get notifications about activity failures or timeouts and act accordingly. There is no limit on potential workflow duration.","workflow execution":"An instance of a workflow. The instance can be in the process of executing or it could have already completed execution.","workflow ID":"A unique identifier for a workflow execution. Cadence guarantees the uniqueness of an ID within a domain. An attempt to start a workflow with a duplicate ID results in an already started error.","workflow task":"Synonym of the decision task.","workflow worker":"An object that is executed in the client application and receives decision task from an decision task list it is subscribed to. Once task is received it is handled by a correponding workflow."}}}');var a=i(4848),n=i(8453);const s={id:"glossary",layout:"default",title:"Glossary",terms:{activity:"A business-level function that implements your application logic such as calling a service or transcoding a media file. An activity usually implements a single well-defined action; it can be short or long running. An activity can be implemented as a synchronous method or fully asynchronously involving multiple processes. An activity can be retried indefinitely according to the provided exponential retry policy. If for any reason an activity is not completed within the specified timeout, an error is reported to the workflow and the workflow decides how to handle it. There is no limit on potential activity duration.","activity task":"A task that contains an activity invocation information that is delivered to an activity worker through and an activity task list. An activity worker upon receiving activity task executes a correponding activity","activity task list":"Task list that is used to deliver activity task to activity worker","activity worker":"An object that is executed in the client application and receives activity task from an activity task list it is subscribed to. Once task is received it invokes a correspondent activity.",archival:"Archival is a feature that automatically moves event history from persistence to a blobstore after the workflow retention period. The purpose of archival is to be able to keep histories as long as needed while not overwhelming the persistence store. There are two reasons you may want to keep the histories after the retention period has passed: 1. Compliance: For legal reasons, histories may need to be stored for a long period of time. 2. Debugging: Old histories can still be accessed for debugging.",CLI:"Cadence command-line interface.","client stub":"A client-side proxy used to make remote invocations to an entity that it represents. For example, to start a workflow, a stub object that represents this workflow is created through a special API. Then this stub is used to start, query, or signal the corresponding workflow.\nThe Go client doesn't use this.",decision:"Any action taken by the workflow durable function is called a decision. For example: scheduling an activity, canceling a child workflow, or starting a timer. A decision task contains an optional list of decisions. Every decision is recorded in the event history as an event. See also [1] for more explanation","decision task":"Every time a new external event that might affect a workflow state is recorded, a decision task that contains it is added to a decision task list and then picked up by a workflow worker. After the new event is handled, the decision task is completed with a list of decision. Note that handling of a decision task is usually very fast and is not related to duration of operations that the workflow invokes. See also [1] for more explanation","decision task list":"Task list that is used to deliver decision task to workflow worker. From user's point of view, it can be viewed as a worker pool. It defines a pool of worker executing workflow or activity tasks.",domain:"Cadence is backed by a multitenant service. The unit of isolation is called a domain. Each domain acts as a namespace for task list names as well as workflow IDs. For example, when a workflow is started, it is started in a specific domain. Cadence guarantees a unique workflow ID within a domain, and supports running workflow executions to use the same workflow ID if they are in different domains. Various configuration options like retention period or archival destination are configured per domain as well through a special CRUD API or through the Cadence CLI. In the multi-cluster deployment, domain is a unit of fail-over. Each domain can only be active on a single Cadence cluster at a time. However, different domains can be active in different clusters and can fail-over independently.",event:"An indivisible operation performed by your application. For example, activity_task_started, task_failed, or timer_canceled. Events are recorded in the event history.","event history":"An append log of events for your application. History is durably persisted by the Cadence service, enabling seamless recovery of your application state from crashes or failures. It also serves as an audit log for debugging.","local activity":"A local activity is an activity that is invoked directly in the same process by a workflow code. It consumes much less resources than a normal activity, but imposes a lot of limitations like low duration and lack of rate limiting.",query:"A synchronous (from the caller's point of view) operation that is used to report a workflow state. Note that a query is inherently read only and cannot affect a workflow state.","run ID":"A UUID that a Cadence service assigns to each workflow run. If allowed by a configured policy, you might be able to re-execute a workflow, after it has closed or failed, with the same workflow id. Each such re-execution is called a run. run id is used to uniquely identify a run even if it shares a workflow id with others.",signal:"An external asynchronous request to a workflow. It can be used to deliver notifications or updates to a running workflow at any point in its existence.",task:"The context needed to execute a specific activity or workflow state transition. There are two types of tasks: an activity task and a decision task (aka workflow task). Note that a single activity execution corresponds to a single activity task, while a workflow execution employs multiple decision tasks.","task list":"Common name for activity task list and decision task list","task token":"A unique correlation ID for a Cadence activity. Activity completion calls take either task token or DomainName, WorkflowID, ActivityID arguments.",worker:"Also known as a worker service. A service that hosts the workflow and activity implementations. The worker polls the Cadence service for tasks, performs those tasks, and communicates task execution results back to the Cadence service. Worker services are developed, deployed, and operated by Cadence customers.",workflow:"A fault-oblivious stateful function that orchestrates activities. A workflow has full control over which activities are executed, and in which order. A workflow must not affect the external world directly, only through activities. What makes workflow code a workflow is that its state is preserved by Cadence. Therefore any failure of a worker process that hosts the workflow code does not affect the workflow execution. The workflow continues as if these failures did not happen. At the same time, activities can fail any moment for any reason. Because workflow code is fully fault-oblivious, it is guaranteed to get notifications about activity failures or timeouts and act accordingly. There is no limit on potential workflow duration.","workflow execution":"An instance of a workflow. The instance can be in the process of executing or it could have already completed execution.","workflow ID":"A unique identifier for a workflow execution. Cadence guarantees the uniqueness of an ID within a domain. An attempt to start a workflow with a duplicate ID results in an already started error.","workflow task":"Synonym of the decision task.","workflow worker":"An object that is executed in the client application and receives decision task from an decision task list it is subscribed to. Once task is received it is handled by a correponding workflow."}},r="Glossary",c={},l=[];function d(e){const t={a:"a",h1:"h1",header:"header",p:"p",...(0,n.R)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(t.header,{children:(0,a.jsx)(t.h1,{id:"glossary",children:"Glossary"})}),"\n",(0,a.jsx)(t.p,{children:(0,a.jsx)(t.a,{href:"https://stackoverflow.com/questions/62904129/what-exactly-is-a-cadence-decision-task/63964726#63964726",children:"1 What exactly is a Cadence decision task?"})})]})}function f(e={}){const{wrapper:t}={...(0,n.R)(),...e.components};return t?(0,a.jsx)(t,{...e,children:(0,a.jsx)(d,{...e})}):d(e)}},8453:(e,t,i)=>{i.d(t,{R:()=>s,x:()=>r});var o=i(6540);const a={},n=o.createContext(a);function s(e){const t=o.useContext(n);return o.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function r(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:s(e.components),o.createElement(n.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/b4266c8b.211c587f.js b/assets/js/b4266c8b.211c587f.js new file mode 100644 index 000000000..ab894eb55 --- /dev/null +++ b/assets/js/b4266c8b.211c587f.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[4962],{8060:(e,t,i)=>{i.r(t),i.d(t,{assets:()=>c,contentTitle:()=>r,default:()=>d,frontMatter:()=>a,metadata:()=>s,toc:()=>l});const s=JSON.parse('{"id":"concepts/activities","title":"Activities","description":"Fault-oblivious stateful code is the core abstraction of Cadence. But, due to deterministic execution requirements, they are not allowed to call any external API directly.","source":"@site/docs/03-concepts/02-activities.md","sourceDirName":"03-concepts","slug":"/concepts/activities","permalink":"/Cadence-Docs/docs/concepts/activities","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/03-concepts/02-activities.md","tags":[],"version":"current","sidebarPosition":2,"frontMatter":{"layout":"default","title":"Activities","permalink":"/docs/concepts/activities"},"sidebar":"docsSidebar","previous":{"title":"Introduction","permalink":"/Cadence-Docs/docs/concepts/"},"next":{"title":"Event handling","permalink":"/Cadence-Docs/docs/concepts/events"}}');var n=i(4848),o=i(8453);const a={layout:"default",title:"Activities",permalink:"/docs/concepts/activities"},r="Activities",c={},l=[{value:"Timeouts",id:"timeouts",level:2},{value:"Retries",id:"retries",level:2},{value:"Long Running Activities",id:"long-running-activities",level:2},{value:"Cancellation",id:"cancellation",level:2},{value:"Activity Task Routing through Task Lists",id:"activity-task-routing-through-task-lists",level:2},{value:"Asynchronous Activity Completion",id:"asynchronous-activity-completion",level:2},{value:"Local Activities",id:"local-activities",level:2}];function h(e){const t={a:"a",code:"code",em:"em",h1:"h1",h2:"h2",header:"header",li:"li",p:"p",ul:"ul",...(0,o.R)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(t.header,{children:(0,n.jsx)(t.h1,{id:"activities",children:"Activities"})}),"\n",(0,n.jsx)(t.p,{children:"Fault-oblivious stateful workflow code is the core abstraction of Cadence. But, due to deterministic execution requirements, they are not allowed to call any external API directly.\nInstead they orchestrate execution of activities. In its simplest form, a Cadence activity is a function or an object method in one of the supported languages.\nCadence does not recover activity state in case of failures. Therefore an activity function is allowed to contain any code without restrictions."}),"\n",(0,n.jsx)(t.p,{children:"Activities are invoked asynchronously through task_lists. A task_list is essentially a queue used to store an activity_task until it is picked up by an available worker. The worker processes an activity by invoking its implementation function. When the function returns, the worker reports the result back to the Cadence service which in turn notifies the workflow about completion. It is possible to implement an activity fully asynchronously by completing it from a different process."}),"\n",(0,n.jsx)(t.h2,{id:"timeouts",children:"Timeouts"}),"\n",(0,n.jsx)(t.p,{children:"Cadence does not impose any system limit on activity duration. It is up to the application to choose the timeouts for its execution. These are the configurable activity timeouts:"}),"\n",(0,n.jsxs)(t.ul,{children:["\n",(0,n.jsxs)(t.li,{children:[(0,n.jsx)(t.code,{children:"ScheduleToStart"})," is the maximum time from a workflow requesting activity execution to a worker starting its execution. The usual reason for this timeout to fire is all workers being down or not being able to keep up with the request rate. We recommend setting this timeout to the maximum time a workflow is willing to wait for an activity execution in the presence of all possible worker outages."]}),"\n",(0,n.jsxs)(t.li,{children:[(0,n.jsx)(t.code,{children:"StartToClose"})," is the maximum time an activity can execute after it was picked by a worker."]}),"\n",(0,n.jsxs)(t.li,{children:[(0,n.jsx)(t.code,{children:"ScheduleToClose"})," is the maximum time from the workflow requesting an activity execution to its completion."]}),"\n",(0,n.jsxs)(t.li,{children:[(0,n.jsx)(t.code,{children:"Heartbeat"})," is the maximum time between heartbeat requests. See ",(0,n.jsx)(t.a,{href:"#long-running-activities",children:"Long Running Activities"}),"."]}),"\n"]}),"\n",(0,n.jsxs)(t.p,{children:["Either ",(0,n.jsx)(t.code,{children:"ScheduleToClose"})," or both ",(0,n.jsx)(t.code,{children:"ScheduleToStart"})," and ",(0,n.jsx)(t.code,{children:"StartToClose"})," timeouts are required."]}),"\n",(0,n.jsxs)(t.p,{children:["Timeouts are the key to manage activities. For more tips of how to set proper timeout, read this ",(0,n.jsx)(t.a,{href:"https://stackoverflow.com/questions/65139178/how-to-set-proper-timeout-values-for-cadence-activitieslocal-and-regular-activi/65139179#65139179",children:"Stack Overflow QA"}),"."]}),"\n",(0,n.jsx)(t.h2,{id:"retries",children:"Retries"}),"\n",(0,n.jsx)(t.p,{children:"As Cadence doesn't recover an activity's state and they can communicate to any external system, failures are expected. Therefore, Cadence supports automatic activity retries. Any activity when invoked can have an associated retry policy. Here are the retry policy parameters:"}),"\n",(0,n.jsxs)(t.ul,{children:["\n",(0,n.jsxs)(t.li,{children:[(0,n.jsx)(t.code,{children:"InitialInterval"})," is a delay before the first retry."]}),"\n",(0,n.jsxs)(t.li,{children:[(0,n.jsx)(t.code,{children:"BackoffCoefficient"}),". Retry policies are exponential. The coefficient specifies how fast the retry interval is growing. The coefficient of 1 means that the retry interval is always equal to the ",(0,n.jsx)(t.code,{children:"InitialInterval"}),"."]}),"\n",(0,n.jsxs)(t.li,{children:[(0,n.jsx)(t.code,{children:"MaximumInterval"})," specifies the maximum interval between retries. Useful for coefficients more than 1."]}),"\n",(0,n.jsxs)(t.li,{children:[(0,n.jsx)(t.code,{children:"MaximumAttempts"})," specifies how many times to attempt to execute an activity in the presence of failures. If this limit is exceeded, the error is returned back to the workflow that invoked the activity. Not required if ",(0,n.jsx)(t.code,{children:"ExpirationInterval"})," is specified."]}),"\n",(0,n.jsxs)(t.li,{children:[(0,n.jsx)(t.code,{children:"ExpirationInterval"})," specifies for how long to attempt executing an activity in the presence of failures. If this interval is exceeded, the error is returned back to the workflow that invoked the activity. Not required if ",(0,n.jsx)(t.code,{children:"MaximumAttempts"})," is specified."]}),"\n",(0,n.jsxs)(t.li,{children:[(0,n.jsx)(t.code,{children:"NonRetryableErrorReasons"})," allows you to specify errors that shouldn't be retried. For example retrying invalid arguments error doesn't make sense in some scenarios."]}),"\n"]}),"\n",(0,n.jsx)(t.p,{children:"There are scenarios when not a single activity but rather the whole part of a workflow should be retried on failure. For example, a media encoding workflow that downloads a file to a host, processes it, and then uploads the result back to storage. In this workflow, if the host that hosts the worker dies, all three activities should be retried on a different host. Such retries should be handled by the workflow code as they are very use case specific."}),"\n",(0,n.jsx)(t.h2,{id:"long-running-activities",children:"Long Running Activities"}),"\n",(0,n.jsxs)(t.p,{children:["For long running activities, we recommended that you specify a relatively short heartbeat timeout and constantly heartbeat. This way worker failures for even very long running activities can be handled in a timely manner. An activity that specifies the heartbeat timeout is expected to call the heartbeat method ",(0,n.jsx)(t.em,{children:"periodically"})," from its implementation."]}),"\n",(0,n.jsx)(t.p,{children:"A heartbeat request can include application specific payload. This is useful to save activity execution progress. If an activity times out due to a missed heartbeat, the next attempt to execute it can access that progress and continue its execution from that point."}),"\n",(0,n.jsx)(t.p,{children:"Long running activities can be used as a special case of leader election. Cadence timeouts use second resolution. So it is not a solution for realtime applications. But if it is okay to react to the process failure within a few seconds, then a Cadence heartbeat activity is a good fit."}),"\n",(0,n.jsx)(t.p,{children:"One common use case for such leader election is monitoring. An activity executes an internal loop that periodically polls some API and checks for some condition. It also heartbeats on every iteration. If the condition is satisfied, the activity completes which lets its workflow to handle it. If the activity_worker dies, the activity times out after the heartbeat interval is exceeded and is retried on a different worker. The same pattern works for polling for new files in Amazon S3 buckets or responses in REST or other synchronous APIs."}),"\n",(0,n.jsx)(t.h2,{id:"cancellation",children:"Cancellation"}),"\n",(0,n.jsx)(t.p,{children:"A workflow can request an activity cancellation. Currently the only way for an activity to learn that it was cancelled is through heart beating. The heartbeat request fails with a special error indicating that the activity was cancelled. Then it is up to the activity implementation to perform all the necessary cleanup and report that it is done with it. It is up to the workflow implementation to decide if it wants to wait for the activity cancellation confirmation or just proceed without waiting."}),"\n",(0,n.jsx)(t.p,{children:"Another common case for activity heartbeat failure is that the workflow that invoked it is in a completed state. In this case an activity is expected to perform cleanup as well."}),"\n",(0,n.jsx)(t.h2,{id:"activity-task-routing-through-task-lists",children:"Activity Task Routing through Task Lists"}),"\n",(0,n.jsx)(t.p,{children:"Activities are dispatched to workers through task_lists. Task_lists are queues that workers listen on. Task_lists are highly dynamic and lightweight. They don't need to be explicitly registered. And it is okay to have one task_list per worker process. It is normal to have more than one activity type to be invoked through a single task_list. And it is normal in some cases (like host routing) to invoke the same activity type on multiple task_lists."}),"\n",(0,n.jsx)(t.p,{children:"Here are some use cases for employing multiple activity_task_lists in a single workflow:"}),"\n",(0,n.jsxs)(t.ul,{children:["\n",(0,n.jsxs)(t.li,{children:[(0,n.jsx)(t.em,{children:"Flow control"}),". A worker that consumes from a task_list asks for an activity_task only when it has available capacity. So workers are never overloaded by request spikes. If activity executions are requested faster than workers can process them, they are backlogged in the task_list."]}),"\n",(0,n.jsxs)(t.li,{children:[(0,n.jsx)(t.em,{children:"Throttling"}),". Each activity_worker can specify the maximum rate it is allowed to processes activities on a task_list. It does not exceed this limit even if it has spare capacity. There is also support for global task_list rate limiting. This limit works across all workers for the given task_list. It is frequently used to limit load on a downstream service that an activity calls into."]}),"\n",(0,n.jsxs)(t.li,{children:[(0,n.jsx)(t.em,{children:"Deploying a set of activities independently"}),". Think about a service that hosts activities and can be deployed independently from other activities and workflows. To send activity_tasks to this service, a separate task_list is needed."]}),"\n",(0,n.jsxs)(t.li,{children:[(0,n.jsx)(t.em,{children:"Workers with different capabilities"}),". For example, workers on GPU boxes vs non GPU boxes. Having two separate task_lists in this case allows workflows to pick which one to send activity an execution request to."]}),"\n",(0,n.jsxs)(t.li,{children:[(0,n.jsx)(t.em,{children:"Routing activity to a specific host"}),". For example, in the media encoding case the transform and upload activity have to run on the same host as the download one."]}),"\n",(0,n.jsxs)(t.li,{children:[(0,n.jsx)(t.em,{children:"Routing activity to a specific process"}),". For example, some activities load large data sets and caches it in the process. The activities that rely on this data set should be routed to the same process."]}),"\n",(0,n.jsxs)(t.li,{children:[(0,n.jsx)(t.em,{children:"Multiple priorities"}),". One task_list per priority and having a worker pool per priority."]}),"\n",(0,n.jsxs)(t.li,{children:[(0,n.jsx)(t.em,{children:"Versioning"}),". A new backwards incompatible implementation of an activity might use a different task_list."]}),"\n"]}),"\n",(0,n.jsx)(t.h2,{id:"asynchronous-activity-completion",children:"Asynchronous Activity Completion"}),"\n",(0,n.jsx)(t.p,{children:"By default an activity is a function or a method depending on a client side library language. As soon as the function returns, an activity completes. But in some cases an activity implementation is asynchronous. For example it is forwarded to an external system through a message queue. And the reply comes through a different queue."}),"\n",(0,n.jsx)(t.p,{children:"To support such use cases, Cadence allows activity implementations that do not complete upon activity function completions. A separate API should be used in this case to complete the activity. This API can be called from any process, even in a different programming language, that the original activity_worker used."}),"\n",(0,n.jsx)(t.h2,{id:"local-activities",children:"Local Activities"}),"\n",(0,n.jsxs)(t.p,{children:["Some of the activities are very short lived and do not need the queing semantic, flow control, rate limiting and routing capabilities. For these Cadence supports so called ",(0,n.jsx)(t.em,{children:"local_activity"})," feature. Local_activities are executed in the same worker process as the workflow that invoked them."]}),"\n",(0,n.jsx)(t.p,{children:"What you will trade off by using local activities"}),"\n",(0,n.jsxs)(t.ul,{children:["\n",(0,n.jsx)(t.li,{children:"Less Debuggability: There is no ActivityTaskScheduled and ActivityTaskStarted events. So you would not able to see the input."}),"\n",(0,n.jsx)(t.li,{children:"No tasklist dispatching: The worker is always the same as the workflow decision worker. You don't have a choice of using activity workers."}),"\n",(0,n.jsx)(t.li,{children:"More possibility of duplicated execution. Though regular activity could also execute multiple times when using retry policy, local activity has more chance of ocurring. Because local activity result is not recorded into history until DecisionTaskCompleted. Also when executing multiple local activities in a row, SDK(Java+Golang) would optimize recording in a way that only recording by interval(before current decision task timeout)."}),"\n",(0,n.jsx)(t.li,{children:"No long running capability with record heartbeat"}),"\n",(0,n.jsx)(t.li,{children:"No Tasklist global ratelimiting"}),"\n"]}),"\n",(0,n.jsx)(t.p,{children:"Consider using local_activities for functions that are:"}),"\n",(0,n.jsxs)(t.ul,{children:["\n",(0,n.jsx)(t.li,{children:"idempotent"}),"\n",(0,n.jsx)(t.li,{children:"no longer than a few seconds"}),"\n",(0,n.jsx)(t.li,{children:"do not require global rate limiting"}),"\n",(0,n.jsx)(t.li,{children:"do not require routing to specific workers or pools of workers"}),"\n",(0,n.jsx)(t.li,{children:"can be implemented in the same binary as the workflow that invokes them"}),"\n",(0,n.jsx)(t.li,{children:"non business critical so that losing some debuggability is okay(e.g. logging, loading config)"}),"\n",(0,n.jsx)(t.li,{children:"when you really need optimization. For example, if there are many timers firing at the same time to invoke activities, it could overload Cadence's server. Using local activities can help save the server capacity."}),"\n"]}),"\n",(0,n.jsx)(t.p,{children:"The main benefit of local_activities is that they are much more efficient in utilizing Cadence service resources and have much lower latency overhead comparing to the usual activity invocation."})]})}function d(e={}){const{wrapper:t}={...(0,o.R)(),...e.components};return t?(0,n.jsx)(t,{...e,children:(0,n.jsx)(h,{...e})}):h(e)}},8453:(e,t,i)=>{i.d(t,{R:()=>a,x:()=>r});var s=i(6540);const n={},o=s.createContext(n);function a(e){const t=s.useContext(o);return s.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function r(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(n):e.components||n:a(e.components),s.createElement(o.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/b4266c8b.393e8d17.js b/assets/js/b4266c8b.393e8d17.js deleted file mode 100644 index c023ab7df..000000000 --- a/assets/js/b4266c8b.393e8d17.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[4962],{8060:(e,t,i)=>{i.r(t),i.d(t,{assets:()=>c,contentTitle:()=>r,default:()=>d,frontMatter:()=>a,metadata:()=>s,toc:()=>l});const s=JSON.parse('{"id":"concepts/activities","title":"Activities","description":"Fault-oblivious stateful code is the core abstraction of Cadence. But, due to deterministic execution requirements, they are not allowed to call any external API directly.","source":"@site/docs/03-concepts/02-activities.md","sourceDirName":"03-concepts","slug":"/concepts/activities","permalink":"/docs/concepts/activities","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/03-concepts/02-activities.md","tags":[],"version":"current","sidebarPosition":2,"frontMatter":{"layout":"default","title":"Activities","permalink":"/docs/concepts/activities"},"sidebar":"docsSidebar","previous":{"title":"Introduction","permalink":"/docs/concepts/"},"next":{"title":"Event handling","permalink":"/docs/concepts/events"}}');var n=i(4848),o=i(8453);const a={layout:"default",title:"Activities",permalink:"/docs/concepts/activities"},r="Activities",c={},l=[{value:"Timeouts",id:"timeouts",level:2},{value:"Retries",id:"retries",level:2},{value:"Long Running Activities",id:"long-running-activities",level:2},{value:"Cancellation",id:"cancellation",level:2},{value:"Activity Task Routing through Task Lists",id:"activity-task-routing-through-task-lists",level:2},{value:"Asynchronous Activity Completion",id:"asynchronous-activity-completion",level:2},{value:"Local Activities",id:"local-activities",level:2}];function h(e){const t={a:"a",code:"code",em:"em",h1:"h1",h2:"h2",header:"header",li:"li",p:"p",ul:"ul",...(0,o.R)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(t.header,{children:(0,n.jsx)(t.h1,{id:"activities",children:"Activities"})}),"\n",(0,n.jsx)(t.p,{children:"Fault-oblivious stateful workflow code is the core abstraction of Cadence. But, due to deterministic execution requirements, they are not allowed to call any external API directly.\nInstead they orchestrate execution of activities. In its simplest form, a Cadence activity is a function or an object method in one of the supported languages.\nCadence does not recover activity state in case of failures. Therefore an activity function is allowed to contain any code without restrictions."}),"\n",(0,n.jsx)(t.p,{children:"Activities are invoked asynchronously through task_lists. A task_list is essentially a queue used to store an activity_task until it is picked up by an available worker. The worker processes an activity by invoking its implementation function. When the function returns, the worker reports the result back to the Cadence service which in turn notifies the workflow about completion. It is possible to implement an activity fully asynchronously by completing it from a different process."}),"\n",(0,n.jsx)(t.h2,{id:"timeouts",children:"Timeouts"}),"\n",(0,n.jsx)(t.p,{children:"Cadence does not impose any system limit on activity duration. It is up to the application to choose the timeouts for its execution. These are the configurable activity timeouts:"}),"\n",(0,n.jsxs)(t.ul,{children:["\n",(0,n.jsxs)(t.li,{children:[(0,n.jsx)(t.code,{children:"ScheduleToStart"})," is the maximum time from a workflow requesting activity execution to a worker starting its execution. The usual reason for this timeout to fire is all workers being down or not being able to keep up with the request rate. We recommend setting this timeout to the maximum time a workflow is willing to wait for an activity execution in the presence of all possible worker outages."]}),"\n",(0,n.jsxs)(t.li,{children:[(0,n.jsx)(t.code,{children:"StartToClose"})," is the maximum time an activity can execute after it was picked by a worker."]}),"\n",(0,n.jsxs)(t.li,{children:[(0,n.jsx)(t.code,{children:"ScheduleToClose"})," is the maximum time from the workflow requesting an activity execution to its completion."]}),"\n",(0,n.jsxs)(t.li,{children:[(0,n.jsx)(t.code,{children:"Heartbeat"})," is the maximum time between heartbeat requests. See ",(0,n.jsx)(t.a,{href:"#long-running-activities",children:"Long Running Activities"}),"."]}),"\n"]}),"\n",(0,n.jsxs)(t.p,{children:["Either ",(0,n.jsx)(t.code,{children:"ScheduleToClose"})," or both ",(0,n.jsx)(t.code,{children:"ScheduleToStart"})," and ",(0,n.jsx)(t.code,{children:"StartToClose"})," timeouts are required."]}),"\n",(0,n.jsxs)(t.p,{children:["Timeouts are the key to manage activities. For more tips of how to set proper timeout, read this ",(0,n.jsx)(t.a,{href:"https://stackoverflow.com/questions/65139178/how-to-set-proper-timeout-values-for-cadence-activitieslocal-and-regular-activi/65139179#65139179",children:"Stack Overflow QA"}),"."]}),"\n",(0,n.jsx)(t.h2,{id:"retries",children:"Retries"}),"\n",(0,n.jsx)(t.p,{children:"As Cadence doesn't recover an activity's state and they can communicate to any external system, failures are expected. Therefore, Cadence supports automatic activity retries. Any activity when invoked can have an associated retry policy. Here are the retry policy parameters:"}),"\n",(0,n.jsxs)(t.ul,{children:["\n",(0,n.jsxs)(t.li,{children:[(0,n.jsx)(t.code,{children:"InitialInterval"})," is a delay before the first retry."]}),"\n",(0,n.jsxs)(t.li,{children:[(0,n.jsx)(t.code,{children:"BackoffCoefficient"}),". Retry policies are exponential. The coefficient specifies how fast the retry interval is growing. The coefficient of 1 means that the retry interval is always equal to the ",(0,n.jsx)(t.code,{children:"InitialInterval"}),"."]}),"\n",(0,n.jsxs)(t.li,{children:[(0,n.jsx)(t.code,{children:"MaximumInterval"})," specifies the maximum interval between retries. Useful for coefficients more than 1."]}),"\n",(0,n.jsxs)(t.li,{children:[(0,n.jsx)(t.code,{children:"MaximumAttempts"})," specifies how many times to attempt to execute an activity in the presence of failures. If this limit is exceeded, the error is returned back to the workflow that invoked the activity. Not required if ",(0,n.jsx)(t.code,{children:"ExpirationInterval"})," is specified."]}),"\n",(0,n.jsxs)(t.li,{children:[(0,n.jsx)(t.code,{children:"ExpirationInterval"})," specifies for how long to attempt executing an activity in the presence of failures. If this interval is exceeded, the error is returned back to the workflow that invoked the activity. Not required if ",(0,n.jsx)(t.code,{children:"MaximumAttempts"})," is specified."]}),"\n",(0,n.jsxs)(t.li,{children:[(0,n.jsx)(t.code,{children:"NonRetryableErrorReasons"})," allows you to specify errors that shouldn't be retried. For example retrying invalid arguments error doesn't make sense in some scenarios."]}),"\n"]}),"\n",(0,n.jsx)(t.p,{children:"There are scenarios when not a single activity but rather the whole part of a workflow should be retried on failure. For example, a media encoding workflow that downloads a file to a host, processes it, and then uploads the result back to storage. In this workflow, if the host that hosts the worker dies, all three activities should be retried on a different host. Such retries should be handled by the workflow code as they are very use case specific."}),"\n",(0,n.jsx)(t.h2,{id:"long-running-activities",children:"Long Running Activities"}),"\n",(0,n.jsxs)(t.p,{children:["For long running activities, we recommended that you specify a relatively short heartbeat timeout and constantly heartbeat. This way worker failures for even very long running activities can be handled in a timely manner. An activity that specifies the heartbeat timeout is expected to call the heartbeat method ",(0,n.jsx)(t.em,{children:"periodically"})," from its implementation."]}),"\n",(0,n.jsx)(t.p,{children:"A heartbeat request can include application specific payload. This is useful to save activity execution progress. If an activity times out due to a missed heartbeat, the next attempt to execute it can access that progress and continue its execution from that point."}),"\n",(0,n.jsx)(t.p,{children:"Long running activities can be used as a special case of leader election. Cadence timeouts use second resolution. So it is not a solution for realtime applications. But if it is okay to react to the process failure within a few seconds, then a Cadence heartbeat activity is a good fit."}),"\n",(0,n.jsx)(t.p,{children:"One common use case for such leader election is monitoring. An activity executes an internal loop that periodically polls some API and checks for some condition. It also heartbeats on every iteration. If the condition is satisfied, the activity completes which lets its workflow to handle it. If the activity_worker dies, the activity times out after the heartbeat interval is exceeded and is retried on a different worker. The same pattern works for polling for new files in Amazon S3 buckets or responses in REST or other synchronous APIs."}),"\n",(0,n.jsx)(t.h2,{id:"cancellation",children:"Cancellation"}),"\n",(0,n.jsx)(t.p,{children:"A workflow can request an activity cancellation. Currently the only way for an activity to learn that it was cancelled is through heart beating. The heartbeat request fails with a special error indicating that the activity was cancelled. Then it is up to the activity implementation to perform all the necessary cleanup and report that it is done with it. It is up to the workflow implementation to decide if it wants to wait for the activity cancellation confirmation or just proceed without waiting."}),"\n",(0,n.jsx)(t.p,{children:"Another common case for activity heartbeat failure is that the workflow that invoked it is in a completed state. In this case an activity is expected to perform cleanup as well."}),"\n",(0,n.jsx)(t.h2,{id:"activity-task-routing-through-task-lists",children:"Activity Task Routing through Task Lists"}),"\n",(0,n.jsx)(t.p,{children:"Activities are dispatched to workers through task_lists. Task_lists are queues that workers listen on. Task_lists are highly dynamic and lightweight. They don't need to be explicitly registered. And it is okay to have one task_list per worker process. It is normal to have more than one activity type to be invoked through a single task_list. And it is normal in some cases (like host routing) to invoke the same activity type on multiple task_lists."}),"\n",(0,n.jsx)(t.p,{children:"Here are some use cases for employing multiple activity_task_lists in a single workflow:"}),"\n",(0,n.jsxs)(t.ul,{children:["\n",(0,n.jsxs)(t.li,{children:[(0,n.jsx)(t.em,{children:"Flow control"}),". A worker that consumes from a task_list asks for an activity_task only when it has available capacity. So workers are never overloaded by request spikes. If activity executions are requested faster than workers can process them, they are backlogged in the task_list."]}),"\n",(0,n.jsxs)(t.li,{children:[(0,n.jsx)(t.em,{children:"Throttling"}),". Each activity_worker can specify the maximum rate it is allowed to processes activities on a task_list. It does not exceed this limit even if it has spare capacity. There is also support for global task_list rate limiting. This limit works across all workers for the given task_list. It is frequently used to limit load on a downstream service that an activity calls into."]}),"\n",(0,n.jsxs)(t.li,{children:[(0,n.jsx)(t.em,{children:"Deploying a set of activities independently"}),". Think about a service that hosts activities and can be deployed independently from other activities and workflows. To send activity_tasks to this service, a separate task_list is needed."]}),"\n",(0,n.jsxs)(t.li,{children:[(0,n.jsx)(t.em,{children:"Workers with different capabilities"}),". For example, workers on GPU boxes vs non GPU boxes. Having two separate task_lists in this case allows workflows to pick which one to send activity an execution request to."]}),"\n",(0,n.jsxs)(t.li,{children:[(0,n.jsx)(t.em,{children:"Routing activity to a specific host"}),". For example, in the media encoding case the transform and upload activity have to run on the same host as the download one."]}),"\n",(0,n.jsxs)(t.li,{children:[(0,n.jsx)(t.em,{children:"Routing activity to a specific process"}),". For example, some activities load large data sets and caches it in the process. The activities that rely on this data set should be routed to the same process."]}),"\n",(0,n.jsxs)(t.li,{children:[(0,n.jsx)(t.em,{children:"Multiple priorities"}),". One task_list per priority and having a worker pool per priority."]}),"\n",(0,n.jsxs)(t.li,{children:[(0,n.jsx)(t.em,{children:"Versioning"}),". A new backwards incompatible implementation of an activity might use a different task_list."]}),"\n"]}),"\n",(0,n.jsx)(t.h2,{id:"asynchronous-activity-completion",children:"Asynchronous Activity Completion"}),"\n",(0,n.jsx)(t.p,{children:"By default an activity is a function or a method depending on a client side library language. As soon as the function returns, an activity completes. But in some cases an activity implementation is asynchronous. For example it is forwarded to an external system through a message queue. And the reply comes through a different queue."}),"\n",(0,n.jsx)(t.p,{children:"To support such use cases, Cadence allows activity implementations that do not complete upon activity function completions. A separate API should be used in this case to complete the activity. This API can be called from any process, even in a different programming language, that the original activity_worker used."}),"\n",(0,n.jsx)(t.h2,{id:"local-activities",children:"Local Activities"}),"\n",(0,n.jsxs)(t.p,{children:["Some of the activities are very short lived and do not need the queing semantic, flow control, rate limiting and routing capabilities. For these Cadence supports so called ",(0,n.jsx)(t.em,{children:"local_activity"})," feature. Local_activities are executed in the same worker process as the workflow that invoked them."]}),"\n",(0,n.jsx)(t.p,{children:"What you will trade off by using local activities"}),"\n",(0,n.jsxs)(t.ul,{children:["\n",(0,n.jsx)(t.li,{children:"Less Debuggability: There is no ActivityTaskScheduled and ActivityTaskStarted events. So you would not able to see the input."}),"\n",(0,n.jsx)(t.li,{children:"No tasklist dispatching: The worker is always the same as the workflow decision worker. You don't have a choice of using activity workers."}),"\n",(0,n.jsx)(t.li,{children:"More possibility of duplicated execution. Though regular activity could also execute multiple times when using retry policy, local activity has more chance of ocurring. Because local activity result is not recorded into history until DecisionTaskCompleted. Also when executing multiple local activities in a row, SDK(Java+Golang) would optimize recording in a way that only recording by interval(before current decision task timeout)."}),"\n",(0,n.jsx)(t.li,{children:"No long running capability with record heartbeat"}),"\n",(0,n.jsx)(t.li,{children:"No Tasklist global ratelimiting"}),"\n"]}),"\n",(0,n.jsx)(t.p,{children:"Consider using local_activities for functions that are:"}),"\n",(0,n.jsxs)(t.ul,{children:["\n",(0,n.jsx)(t.li,{children:"idempotent"}),"\n",(0,n.jsx)(t.li,{children:"no longer than a few seconds"}),"\n",(0,n.jsx)(t.li,{children:"do not require global rate limiting"}),"\n",(0,n.jsx)(t.li,{children:"do not require routing to specific workers or pools of workers"}),"\n",(0,n.jsx)(t.li,{children:"can be implemented in the same binary as the workflow that invokes them"}),"\n",(0,n.jsx)(t.li,{children:"non business critical so that losing some debuggability is okay(e.g. logging, loading config)"}),"\n",(0,n.jsx)(t.li,{children:"when you really need optimization. For example, if there are many timers firing at the same time to invoke activities, it could overload Cadence's server. Using local activities can help save the server capacity."}),"\n"]}),"\n",(0,n.jsx)(t.p,{children:"The main benefit of local_activities is that they are much more efficient in utilizing Cadence service resources and have much lower latency overhead comparing to the usual activity invocation."})]})}function d(e={}){const{wrapper:t}={...(0,o.R)(),...e.components};return t?(0,n.jsx)(t,{...e,children:(0,n.jsx)(h,{...e})}):h(e)}},8453:(e,t,i)=>{i.d(t,{R:()=>a,x:()=>r});var s=i(6540);const n={},o=s.createContext(n);function a(e){const t=s.useContext(o);return s.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function r(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(n):e.components||n:a(e.components),s.createElement(o.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/b69803f5.d3ed1ab6.js b/assets/js/b69803f5.8b7d5d22.js similarity index 79% rename from assets/js/b69803f5.d3ed1ab6.js rename to assets/js/b69803f5.8b7d5d22.js index 5186ca61f..96ca8c017 100644 --- a/assets/js/b69803f5.d3ed1ab6.js +++ b/assets/js/b69803f5.8b7d5d22.js @@ -1 +1 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[5552],{4055:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>c,contentTitle:()=>s,default:()=>d,frontMatter:()=>r,metadata:()=>o,toc:()=>l});var o=t(6109),a=t(4848),i=t(8453);const r={title:"Cadence Community Spotlight Update - May 2022",date:new Date("2022-05-31T00:00:00.000Z"),authors:"sharanf",tags:["community-spotlight"]},s=void 0,c={authorsImageUrls:[void 0]},l=[{value:"Cadence Polling Cookbook",id:"cadence-polling-cookbook",level:2},{value:"Congratulations to a First Time Contributor",id:"congratulations-to-a-first-time-contributor",level:2},{value:"Share Your News!",id:"share-your-news",level:2},{value:"Next Cadence Technical Office Hours: 3rd and 27th June 2022",id:"next-cadence-technical-office-hours-3rd-and--27th-june-2022",level:2},{value:"Cadence in the News!",id:"cadence-in-the-news",level:2},{value:"Upcoming Events",id:"upcoming-events",level:2}];function h(e){const n={a:"a",em:"em",h2:"h2",li:"li",p:"p",ul:"ul",...(0,i.R)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(n.p,{children:"Welcome to our regular Cadence Community Spotlight update!"}),"\n",(0,a.jsx)(n.p,{children:"This is our monthly blog post series focused on news from in and around the Cadence community."}),"\n",(0,a.jsx)(n.p,{children:"Please see below for a short activity roundup of what has happened recently in the community."}),"\n",(0,a.jsx)(n.h2,{id:"cadence-polling-cookbook",children:"Cadence Polling Cookbook"}),"\n",(0,a.jsxs)(n.p,{children:["Do you want to understand polling work and have an example of how to set it up in Cadence? Well a brand new ",(0,a.jsx)(n.a,{href:"https://info.instaclustr.com/rs/620-JHM-287/images/Cadence_Cookbook.pdf",children:"Cadence Polling cookbook"})," is now available that gives you all the details you need. The cookbook was created by several members of the ",(0,a.jsx)(n.a,{href:"https://www.instaclustr.com/",children:"Instaclustr"})," team and they are keen to share it with the community. The pdf version of the cookbook can found on the Cadence website under the ",(0,a.jsx)(n.em,{children:"Polling an external API for a specific resource to become available"})," section of the ",(0,a.jsx)(n.a,{href:"https://cadenceworkflow.io/docs/use-cases/polling/",children:"Polling Use cases"}),"."]}),"\n",(0,a.jsxs)(n.p,{children:["A ",(0,a.jsx)(n.a,{href:"https://github.com/instaclustr/cadence-cookbooks-instafood",children:"Github repository"})," has also been created with the sample cookbook code for you to try out for yourself."]}),"\n",(0,a.jsx)(n.p,{children:"So please go ahead and try out the cookbook and don\u2019t forget to let us have your feedback."}),"\n",(0,a.jsx)(n.h2,{id:"congratulations-to-a-first-time-contributor",children:"Congratulations to a First Time Contributor"}),"\n",(0,a.jsxs)(n.p,{children:["We are always looking for ways to encourage project participation. It doesn't matter how large the contribution is or whether it is coding or non coding related. This month one of our community members had ",(0,a.jsx)(n.a,{href:"https://github.com/cadence-workflow/Cadence-Docs/pull/107",children:"their first PR merged"}),"- so congratulations and many thanks for the contribution ",(0,a.jsx)(n.a,{href:"https://github.com/tonyxrandall",children:"tonyxrandall"}),"!"]}),"\n",(0,a.jsx)(n.h2,{id:"share-your-news",children:"Share Your News!"}),"\n",(0,a.jsxs)(n.p,{children:["Our #support ",(0,a.jsx)(n.a,{href:"http://t.uber.com/cadence-slack",children:"Slack"})," channel is always full of questions and activity so we know that there are are lot of people out there exploring, trying out and setting up Cadence. We are always interested in hearing about what the community are doing so if you have something to you want to share as a blog post or part of this montly update then please contact us in the #community ",(0,a.jsx)(n.a,{href:"http://t.uber.com/cadence-slack",children:"Slack"})," channel."]}),"\n",(0,a.jsx)(n.h2,{id:"next-cadence-technical-office-hours-3rd-and--27th-june-2022",children:"Next Cadence Technical Office Hours: 3rd and 27th June 2022"}),"\n",(0,a.jsx)(n.p,{children:"We will be having two Technical Office Hours sessions this month. As 30th May was a US holiday we have moved May\u2019s Technical Office Hours to Friday 3rd June at 11am PT. And we will be having our June call on 27th."}),"\n",(0,a.jsx)(n.p,{children:"Remember that in these Zoom sessions you can speak directly with some of our Cadence experts so if you have a question about Cadence or are facing a particular issue getting it setup then please come along and chat to one of our experts!"}),"\n",(0,a.jsx)(n.h2,{id:"cadence-in-the-news",children:"Cadence in the News!"}),"\n",(0,a.jsx)(n.p,{children:"Below are a selection of Cadence related articles, blogs and whitepapers. Please take a look and feel free to share via your own social media channels."}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsxs)(n.li,{children:["\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.a,{href:"https://www.instaclustr.com/blog/spinning-your-drones-with-cadence-and-apache-kafka-integration-patterns-and-new-cadence-features/",children:"Spinning Your Drones With Cadence and Apache Kafka \u2013 Integration Patterns and New Cadence Features"})}),"\n"]}),"\n",(0,a.jsxs)(n.li,{children:["\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.a,{href:"https://doordash.engineering/2022/05/18/enabling-faster-financial-partnership-integrations-using-cadence/",children:"Enabling Faster Financial Partnership Integrations Using Cadence"})}),"\n"]}),"\n",(0,a.jsxs)(n.li,{children:["\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.a,{href:"https://www.instaclustr.com/blog/spinning-your-drones-with-cadence-and-apache-kafka-architecture-order-and-delivery-workflows/",children:"Spinning Your Drones With Cadence and Apache Kafka\xae \u2013 Architecture, Order and Delivery Workflows"})}),"\n"]}),"\n"]}),"\n",(0,a.jsx)(n.h2,{id:"upcoming-events",children:"Upcoming Events"}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsxs)(n.li,{children:["\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.a,{href:"https://calendar.google.com/calendar/u/0/embed?src=e6r40gp3c2r01054id7e99dlac@group.calendar.google.com&ctz=America/Los_Angeles",children:"Cadence Technical Office Hours - 3rd June 2022 @ 11am PT"})}),"\n"]}),"\n",(0,a.jsxs)(n.li,{children:["\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.a,{href:"https://info.instaclustr.com/webinar-emea-spinning-workflows-cadence.html",children:"Webinar : Spinning up Your Workflows with Cadence : 20th June"})}),"\n"]}),"\n",(0,a.jsxs)(n.li,{children:["\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.a,{href:"https://calendar.google.com/calendar/u/0/embed?src=e6r40gp3c2r01054id7e99dlac@group.calendar.google.com&ctz=America/Los_Angeles",children:"Cadence Technical Office Hours - 27th June 2022 @ 9am PT"})}),"\n"]}),"\n",(0,a.jsxs)(n.li,{children:["\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.a,{href:"https://info.instaclustr.com/webinar-building-cadence-workflow",children:"Webinar: Building Your First Cadence Workflow with Java and Go - 19th July 2022"})}),"\n"]}),"\n"]}),"\n",(0,a.jsxs)(n.p,{children:["If you have any news or topics you'd like us to include in our next update then please join our ",(0,a.jsx)(n.a,{href:"http://t.uber.com/cadence-slack",children:"Slack"}),"#community channel."]}),"\n",(0,a.jsxs)(n.p,{children:["Please remember that this update is for you - so if you have any comments or feedback that could help us improve it then please share it with us in the #community ",(0,a.jsx)(n.a,{href:"http://t.uber.com/cadence-slack",children:"Slack"})," channel."]})]})}function d(e={}){const{wrapper:n}={...(0,i.R)(),...e.components};return n?(0,a.jsx)(n,{...e,children:(0,a.jsx)(h,{...e})}):h(e)}},8453:(e,n,t)=>{t.d(n,{R:()=>r,x:()=>s});var o=t(6540);const a={},i=o.createContext(a);function r(e){const n=o.useContext(i);return o.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function s(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:r(e.components),o.createElement(i.Provider,{value:n},e.children)}},6109:e=>{e.exports=JSON.parse('{"permalink":"/blog/2022/05/31/community-spotlight-update-may-2022","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2022-05-31-community-spotlight-update-may-2022.md","source":"@site/blog/2022-05-31-community-spotlight-update-may-2022.md","title":"Cadence Community Spotlight Update - May 2022","description":"Welcome to our regular Cadence Community Spotlight update!","date":"2022-05-31T00:00:00.000Z","tags":[{"inline":false,"label":"Community Spotlight","permalink":"/blog/tags/community-spotlights","description":"Community Spotlight tag description"}],"readingTime":2.905,"hasTruncateMarker":true,"authors":[{"name":"Sharan Foga","title":"Director of Operations & Customer Success @ Encube Technologies","url":"https://www.linkedin.com/in/sfoga/","page":{"permalink":"/blog/authors/sharanf"},"socials":{"linkedin":"https://www.linkedin.com/in/sfoga/","github":"https://github.com/sharanf"},"imageURL":"https://github.com/sharanf.png","key":"sharanf"}],"frontMatter":{"title":"Cadence Community Spotlight Update - May 2022","date":"2022-05-31T00:00:00.000Z","authors":"sharanf","tags":["community-spotlight"]},"unlisted":false,"prevItem":{"title":"Cadence Community Spotlight Update - June 2022","permalink":"/blog/2022/06/30/community-spotlight-update-june-2022"},"nextItem":{"title":"Cadence Community Spotlight Update - April 2022","permalink":"/blog/2022/04/30/community-spotlight-update-april-2022"}}')}}]); \ No newline at end of file +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[5552],{4055:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>c,contentTitle:()=>r,default:()=>d,frontMatter:()=>s,metadata:()=>o,toc:()=>l});var o=t(6109),a=t(4848),i=t(8453);const s={title:"Cadence Community Spotlight Update - May 2022",date:new Date("2022-05-31T00:00:00.000Z"),authors:"sharanf",tags:["community-spotlight"]},r=void 0,c={authorsImageUrls:[void 0]},l=[{value:"Cadence Polling Cookbook",id:"cadence-polling-cookbook",level:2},{value:"Congratulations to a First Time Contributor",id:"congratulations-to-a-first-time-contributor",level:2},{value:"Share Your News!",id:"share-your-news",level:2},{value:"Next Cadence Technical Office Hours: 3rd and 27th June 2022",id:"next-cadence-technical-office-hours-3rd-and--27th-june-2022",level:2},{value:"Cadence in the News!",id:"cadence-in-the-news",level:2},{value:"Upcoming Events",id:"upcoming-events",level:2}];function h(e){const n={a:"a",em:"em",h2:"h2",li:"li",p:"p",ul:"ul",...(0,i.R)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(n.p,{children:"Welcome to our regular Cadence Community Spotlight update!"}),"\n",(0,a.jsx)(n.p,{children:"This is our monthly blog post series focused on news from in and around the Cadence community."}),"\n",(0,a.jsx)(n.p,{children:"Please see below for a short activity roundup of what has happened recently in the community."}),"\n",(0,a.jsx)(n.h2,{id:"cadence-polling-cookbook",children:"Cadence Polling Cookbook"}),"\n",(0,a.jsxs)(n.p,{children:["Do you want to understand polling work and have an example of how to set it up in Cadence? Well a brand new ",(0,a.jsx)(n.a,{href:"https://info.instaclustr.com/rs/620-JHM-287/images/Cadence_Cookbook.pdf",children:"Cadence Polling cookbook"})," is now available that gives you all the details you need. The cookbook was created by several members of the ",(0,a.jsx)(n.a,{href:"https://www.instaclustr.com/",children:"Instaclustr"})," team and they are keen to share it with the community. The pdf version of the cookbook can found on the Cadence website under the ",(0,a.jsx)(n.em,{children:"Polling an external API for a specific resource to become available"})," section of the ",(0,a.jsx)(n.a,{href:"https://cadenceworkflow.io/docs/use-cases/polling/",children:"Polling Use cases"}),"."]}),"\n",(0,a.jsxs)(n.p,{children:["A ",(0,a.jsx)(n.a,{href:"https://github.com/instaclustr/cadence-cookbooks-instafood",children:"Github repository"})," has also been created with the sample cookbook code for you to try out for yourself."]}),"\n",(0,a.jsx)(n.p,{children:"So please go ahead and try out the cookbook and don\u2019t forget to let us have your feedback."}),"\n",(0,a.jsx)(n.h2,{id:"congratulations-to-a-first-time-contributor",children:"Congratulations to a First Time Contributor"}),"\n",(0,a.jsxs)(n.p,{children:["We are always looking for ways to encourage project participation. It doesn't matter how large the contribution is or whether it is coding or non coding related. This month one of our community members had ",(0,a.jsx)(n.a,{href:"https://github.com/cadence-workflow/Cadence-Docs/pull/107",children:"their first PR merged"}),"- so congratulations and many thanks for the contribution ",(0,a.jsx)(n.a,{href:"https://github.com/tonyxrandall",children:"tonyxrandall"}),"!"]}),"\n",(0,a.jsx)(n.h2,{id:"share-your-news",children:"Share Your News!"}),"\n",(0,a.jsxs)(n.p,{children:["Our #support ",(0,a.jsx)(n.a,{href:"http://t.uber.com/cadence-slack",children:"Slack"})," channel is always full of questions and activity so we know that there are are lot of people out there exploring, trying out and setting up Cadence. We are always interested in hearing about what the community are doing so if you have something to you want to share as a blog post or part of this montly update then please contact us in the #community ",(0,a.jsx)(n.a,{href:"http://t.uber.com/cadence-slack",children:"Slack"})," channel."]}),"\n",(0,a.jsx)(n.h2,{id:"next-cadence-technical-office-hours-3rd-and--27th-june-2022",children:"Next Cadence Technical Office Hours: 3rd and 27th June 2022"}),"\n",(0,a.jsx)(n.p,{children:"We will be having two Technical Office Hours sessions this month. As 30th May was a US holiday we have moved May\u2019s Technical Office Hours to Friday 3rd June at 11am PT. And we will be having our June call on 27th."}),"\n",(0,a.jsx)(n.p,{children:"Remember that in these Zoom sessions you can speak directly with some of our Cadence experts so if you have a question about Cadence or are facing a particular issue getting it setup then please come along and chat to one of our experts!"}),"\n",(0,a.jsx)(n.h2,{id:"cadence-in-the-news",children:"Cadence in the News!"}),"\n",(0,a.jsx)(n.p,{children:"Below are a selection of Cadence related articles, blogs and whitepapers. Please take a look and feel free to share via your own social media channels."}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsxs)(n.li,{children:["\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.a,{href:"https://www.instaclustr.com/blog/spinning-your-drones-with-cadence-and-apache-kafka-integration-patterns-and-new-cadence-features/",children:"Spinning Your Drones With Cadence and Apache Kafka \u2013 Integration Patterns and New Cadence Features"})}),"\n"]}),"\n",(0,a.jsxs)(n.li,{children:["\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.a,{href:"https://doordash.engineering/2022/05/18/enabling-faster-financial-partnership-integrations-using-cadence/",children:"Enabling Faster Financial Partnership Integrations Using Cadence"})}),"\n"]}),"\n",(0,a.jsxs)(n.li,{children:["\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.a,{href:"https://www.instaclustr.com/blog/spinning-your-drones-with-cadence-and-apache-kafka-architecture-order-and-delivery-workflows/",children:"Spinning Your Drones With Cadence and Apache Kafka\xae \u2013 Architecture, Order and Delivery Workflows"})}),"\n"]}),"\n"]}),"\n",(0,a.jsx)(n.h2,{id:"upcoming-events",children:"Upcoming Events"}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsxs)(n.li,{children:["\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.a,{href:"https://calendar.google.com/calendar/u/0/embed?src=e6r40gp3c2r01054id7e99dlac@group.calendar.google.com&ctz=America/Los_Angeles",children:"Cadence Technical Office Hours - 3rd June 2022 @ 11am PT"})}),"\n"]}),"\n",(0,a.jsxs)(n.li,{children:["\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.a,{href:"https://info.instaclustr.com/webinar-emea-spinning-workflows-cadence.html",children:"Webinar : Spinning up Your Workflows with Cadence : 20th June"})}),"\n"]}),"\n",(0,a.jsxs)(n.li,{children:["\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.a,{href:"https://calendar.google.com/calendar/u/0/embed?src=e6r40gp3c2r01054id7e99dlac@group.calendar.google.com&ctz=America/Los_Angeles",children:"Cadence Technical Office Hours - 27th June 2022 @ 9am PT"})}),"\n"]}),"\n",(0,a.jsxs)(n.li,{children:["\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.a,{href:"https://info.instaclustr.com/webinar-building-cadence-workflow",children:"Webinar: Building Your First Cadence Workflow with Java and Go - 19th July 2022"})}),"\n"]}),"\n"]}),"\n",(0,a.jsxs)(n.p,{children:["If you have any news or topics you'd like us to include in our next update then please join our ",(0,a.jsx)(n.a,{href:"http://t.uber.com/cadence-slack",children:"Slack"}),"#community channel."]}),"\n",(0,a.jsxs)(n.p,{children:["Please remember that this update is for you - so if you have any comments or feedback that could help us improve it then please share it with us in the #community ",(0,a.jsx)(n.a,{href:"http://t.uber.com/cadence-slack",children:"Slack"})," channel."]})]})}function d(e={}){const{wrapper:n}={...(0,i.R)(),...e.components};return n?(0,a.jsx)(n,{...e,children:(0,a.jsx)(h,{...e})}):h(e)}},8453:(e,n,t)=>{t.d(n,{R:()=>s,x:()=>r});var o=t(6540);const a={},i=o.createContext(a);function s(e){const n=o.useContext(i);return o.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function r(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:s(e.components),o.createElement(i.Provider,{value:n},e.children)}},6109:e=>{e.exports=JSON.parse('{"permalink":"/Cadence-Docs/blog/2022/05/31/community-spotlight-update-may-2022","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2022-05-31-community-spotlight-update-may-2022.md","source":"@site/blog/2022-05-31-community-spotlight-update-may-2022.md","title":"Cadence Community Spotlight Update - May 2022","description":"Welcome to our regular Cadence Community Spotlight update!","date":"2022-05-31T00:00:00.000Z","tags":[{"inline":false,"label":"Community Spotlight","permalink":"/Cadence-Docs/blog/tags/community-spotlights","description":"Community Spotlight tag description"}],"readingTime":2.905,"hasTruncateMarker":true,"authors":[{"name":"Sharan Foga","title":"Director of Operations & Customer Success @ Encube Technologies","url":"https://www.linkedin.com/in/sfoga/","page":{"permalink":"/Cadence-Docs/blog/authors/sharanf"},"socials":{"linkedin":"https://www.linkedin.com/in/sfoga/","github":"https://github.com/sharanf"},"imageURL":"https://github.com/sharanf.png","key":"sharanf"}],"frontMatter":{"title":"Cadence Community Spotlight Update - May 2022","date":"2022-05-31T00:00:00.000Z","authors":"sharanf","tags":["community-spotlight"]},"unlisted":false,"prevItem":{"title":"Cadence Community Spotlight Update - June 2022","permalink":"/Cadence-Docs/blog/2022/06/30/community-spotlight-update-june-2022"},"nextItem":{"title":"Cadence Community Spotlight Update - April 2022","permalink":"/Cadence-Docs/blog/2022/04/30/community-spotlight-update-april-2022"}}')}}]); \ No newline at end of file diff --git a/assets/js/bc79ac75.31de2fc6.js b/assets/js/bc79ac75.31de2fc6.js deleted file mode 100644 index dc8653dc9..000000000 --- a/assets/js/bc79ac75.31de2fc6.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[1662],{1241:(e,i,t)=>{t.r(i),t.d(i,{assets:()=>a,contentTitle:()=>c,default:()=>l,frontMatter:()=>s,metadata:()=>o,toc:()=>d});const o=JSON.parse('{"id":"use-cases/periodic-execution","title":"Periodic execution","description":"Periodic execution, frequently referred to as distributed cron, is when you execute business logic periodically. The advantage of Cadence for these scenarios is that it guarantees execution, sophisticated error handling, retry policies, and visibility into execution history.","source":"@site/docs/02-use-cases/01-periodic-execution.md","sourceDirName":"02-use-cases","slug":"/use-cases/periodic-execution","permalink":"/docs/use-cases/periodic-execution","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/02-use-cases/01-periodic-execution.md","tags":[],"version":"current","sidebarPosition":1,"frontMatter":{"layout":"default","title":"Periodic execution","permalink":"/docs/use-cases/periodic-execution"},"sidebar":"docsSidebar","previous":{"title":"Introduction","permalink":"/docs/use-cases/"},"next":{"title":"Orchestration","permalink":"/docs/use-cases/orchestration"}}');var n=t(4848),r=t(8453);const s={layout:"default",title:"Periodic execution",permalink:"/docs/use-cases/periodic-execution"},c="Periodic execution (aka Distributed Cron)",a={},d=[];function u(e){const i={a:"a",h1:"h1",header:"header",li:"li",p:"p",ul:"ul",...(0,r.R)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(i.header,{children:(0,n.jsx)(i.h1,{id:"periodic-execution-aka-distributed-cron",children:"Periodic execution (aka Distributed Cron)"})}),"\n",(0,n.jsx)(i.p,{children:"Periodic execution, frequently referred to as distributed cron, is when you execute business logic periodically. The advantage of Cadence for these scenarios is that it guarantees execution, sophisticated error handling, retry policies, and visibility into execution history."}),"\n",(0,n.jsx)(i.p,{children:"Another important dimension is scale. Some use cases require periodic execution for a large number of entities.\nAt Uber, there are applications that create periodic workflows per customer.\nImagine 100+ million parallel cron jobs that don't require a separate batch processing framework."}),"\n",(0,n.jsx)(i.p,{children:"Periodic execution is often part of other use cases. For example, once a month report generation is a periodic service orchestration. Or an event-driven workflow that accumulates loyalty points for a customer and applies those points once a month."}),"\n",(0,n.jsx)(i.p,{children:"There are many real-world examples of Cadence periodic executions. Such as the following:"}),"\n",(0,n.jsxs)(i.ul,{children:["\n",(0,n.jsxs)(i.li,{children:["An Uber backend service that recalculates various statistics for each ",(0,n.jsx)(i.a,{href:"https://eng.uber.com/h3/",children:"hex"})," in each city once a minute."]}),"\n",(0,n.jsx)(i.li,{children:"Monthly Uber for Business report generation."}),"\n"]})]})}function l(e={}){const{wrapper:i}={...(0,r.R)(),...e.components};return i?(0,n.jsx)(i,{...e,children:(0,n.jsx)(u,{...e})}):u(e)}},8453:(e,i,t)=>{t.d(i,{R:()=>s,x:()=>c});var o=t(6540);const n={},r=o.createContext(n);function s(e){const i=o.useContext(r);return o.useMemo((function(){return"function"==typeof e?e(i):{...i,...e}}),[i,e])}function c(e){let i;return i=e.disableParentContext?"function"==typeof e.components?e.components(n):e.components||n:s(e.components),o.createElement(r.Provider,{value:i},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/bc79ac75.5aaf5895.js b/assets/js/bc79ac75.5aaf5895.js new file mode 100644 index 000000000..14bc76e25 --- /dev/null +++ b/assets/js/bc79ac75.5aaf5895.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[1662],{1241:(e,i,t)=>{t.r(i),t.d(i,{assets:()=>a,contentTitle:()=>c,default:()=>l,frontMatter:()=>s,metadata:()=>o,toc:()=>d});const o=JSON.parse('{"id":"use-cases/periodic-execution","title":"Periodic execution","description":"Periodic execution, frequently referred to as distributed cron, is when you execute business logic periodically. The advantage of Cadence for these scenarios is that it guarantees execution, sophisticated error handling, retry policies, and visibility into execution history.","source":"@site/docs/02-use-cases/01-periodic-execution.md","sourceDirName":"02-use-cases","slug":"/use-cases/periodic-execution","permalink":"/Cadence-Docs/docs/use-cases/periodic-execution","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/02-use-cases/01-periodic-execution.md","tags":[],"version":"current","sidebarPosition":1,"frontMatter":{"layout":"default","title":"Periodic execution","permalink":"/docs/use-cases/periodic-execution"},"sidebar":"docsSidebar","previous":{"title":"Introduction","permalink":"/Cadence-Docs/docs/use-cases/"},"next":{"title":"Orchestration","permalink":"/Cadence-Docs/docs/use-cases/orchestration"}}');var n=t(4848),r=t(8453);const s={layout:"default",title:"Periodic execution",permalink:"/docs/use-cases/periodic-execution"},c="Periodic execution (aka Distributed Cron)",a={},d=[];function u(e){const i={a:"a",h1:"h1",header:"header",li:"li",p:"p",ul:"ul",...(0,r.R)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(i.header,{children:(0,n.jsx)(i.h1,{id:"periodic-execution-aka-distributed-cron",children:"Periodic execution (aka Distributed Cron)"})}),"\n",(0,n.jsx)(i.p,{children:"Periodic execution, frequently referred to as distributed cron, is when you execute business logic periodically. The advantage of Cadence for these scenarios is that it guarantees execution, sophisticated error handling, retry policies, and visibility into execution history."}),"\n",(0,n.jsx)(i.p,{children:"Another important dimension is scale. Some use cases require periodic execution for a large number of entities.\nAt Uber, there are applications that create periodic workflows per customer.\nImagine 100+ million parallel cron jobs that don't require a separate batch processing framework."}),"\n",(0,n.jsx)(i.p,{children:"Periodic execution is often part of other use cases. For example, once a month report generation is a periodic service orchestration. Or an event-driven workflow that accumulates loyalty points for a customer and applies those points once a month."}),"\n",(0,n.jsx)(i.p,{children:"There are many real-world examples of Cadence periodic executions. Such as the following:"}),"\n",(0,n.jsxs)(i.ul,{children:["\n",(0,n.jsxs)(i.li,{children:["An Uber backend service that recalculates various statistics for each ",(0,n.jsx)(i.a,{href:"https://eng.uber.com/h3/",children:"hex"})," in each city once a minute."]}),"\n",(0,n.jsx)(i.li,{children:"Monthly Uber for Business report generation."}),"\n"]})]})}function l(e={}){const{wrapper:i}={...(0,r.R)(),...e.components};return i?(0,n.jsx)(i,{...e,children:(0,n.jsx)(u,{...e})}):u(e)}},8453:(e,i,t)=>{t.d(i,{R:()=>s,x:()=>c});var o=t(6540);const n={},r=o.createContext(n);function s(e){const i=o.useContext(r);return o.useMemo((function(){return"function"==typeof e?e(i):{...i,...e}}),[i,e])}function c(e){let i;return i=e.disableParentContext?"function"==typeof e.components?e.components(n):e.components||n:s(e.components),o.createElement(r.Provider,{value:i},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/bde620bf.dd0e3f78.js b/assets/js/bde620bf.dd0e3f78.js new file mode 100644 index 000000000..a298e2396 --- /dev/null +++ b/assets/js/bde620bf.dd0e3f78.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[3890],{4591:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>l,contentTitle:()=>a,default:()=>h,frontMatter:()=>s,metadata:()=>i,toc:()=>r});const i=JSON.parse('{"id":"go-client/activity-async-completion","title":"Async activity completion","description":"There are certain scenarios when completing an upon completion of its function is not possible","source":"@site/docs/05-go-client/12-activity-async-completion.md","sourceDirName":"05-go-client","slug":"/go-client/activity-async-completion","permalink":"/Cadence-Docs/docs/go-client/activity-async-completion","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/05-go-client/12-activity-async-completion.md","tags":[],"version":"current","sidebarPosition":12,"frontMatter":{"layout":"default","title":"Async activity completion","permalink":"/docs/go-client/activity-async-completion"},"sidebar":"docsSidebar","previous":{"title":"Queries","permalink":"/Cadence-Docs/docs/go-client/queries"},"next":{"title":"Testing","permalink":"/Cadence-Docs/docs/go-client/workflow-testing"}}');var c=n(4848),o=n(8453);const s={layout:"default",title:"Async activity completion",permalink:"/docs/go-client/activity-async-completion"},a="Asynchronous activity completion",l={},r=[];function d(e){const t={code:"code",h1:"h1",header:"header",li:"li",ol:"ol",p:"p",pre:"pre",ul:"ul",...(0,o.R)(),...e.components};return(0,c.jsxs)(c.Fragment,{children:[(0,c.jsx)(t.header,{children:(0,c.jsx)(t.h1,{id:"asynchronous-activity-completion",children:"Asynchronous activity completion"})}),"\n",(0,c.jsx)(t.p,{children:"There are certain scenarios when completing an activity upon completion of its function is not possible\nor desirable. For example, you might have an application that requires user input in order to complete\nthe activity. You could implement the activity with a polling mechanism, but a simpler and less\nresource-intensive implementation is to asynchronously complete a Cadence activity."}),"\n",(0,c.jsx)(t.p,{children:"There two parts to implementing an asynchronously completed activity:"}),"\n",(0,c.jsxs)(t.ol,{children:["\n",(0,c.jsx)(t.li,{children:"The activity provides the information necessary for completion from an external system and notifies\nthe Cadence service that it is waiting for that outside callback."}),"\n",(0,c.jsx)(t.li,{children:"The external service calls the Cadence service to complete the activity."}),"\n"]}),"\n",(0,c.jsx)(t.p,{children:"The following example demonstrates the first part:"}),"\n",(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:"language-go",children:'// Retrieve the activity information needed to asynchronously complete the activity.\nactivityInfo := cadence.GetActivityInfo(ctx)\ntaskToken := activityInfo.TaskToken\n\n// Send the taskToken to the external service that will complete the activity.\n...\n\n// Return from the activity a function indicating that Cadence should wait for an async completion\n// message.\nreturn "", activity.ErrResultPending\n'})}),"\n",(0,c.jsx)(t.p,{children:"The following code demonstrates how to complete the activity successfully:"}),"\n",(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:"language-go",children:"// Instantiate a Cadence service client.\n// The same client can be used to complete or fail any number of activities.\ncadence.Client client = cadence.NewClient(...)\n\n// Complete the activity.\nclient.CompleteActivity(taskToken, result, nil)\n"})}),"\n",(0,c.jsx)(t.p,{children:"To fail the activity, you would do the following:"}),"\n",(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:"language-go",children:"// Fail the activity.\nclient.CompleteActivity(taskToken, nil, err)\n"})}),"\n",(0,c.jsxs)(t.p,{children:["Following are the parameters of the ",(0,c.jsx)(t.code,{children:"CompleteActivity"})," function:"]}),"\n",(0,c.jsxs)(t.ul,{children:["\n",(0,c.jsxs)(t.li,{children:[(0,c.jsx)(t.code,{children:"taskToken"}),": The value of the binary ",(0,c.jsx)(t.code,{children:"TaskToken"})," field of the ",(0,c.jsx)(t.code,{children:"ActivityInfo"})," struct retrieved inside\nthe activity."]}),"\n",(0,c.jsxs)(t.li,{children:[(0,c.jsx)(t.code,{children:"result"}),": The return value to record for the activity. The type of this value must match the type\nof the return value declared by the activity function."]}),"\n",(0,c.jsxs)(t.li,{children:[(0,c.jsx)(t.code,{children:"err"}),": The error code to return if the activity terminates with an error."]}),"\n"]}),"\n",(0,c.jsxs)(t.p,{children:["If ",(0,c.jsx)(t.code,{children:"error"})," is not null, the value of the ",(0,c.jsx)(t.code,{children:"result"})," field is ignored."]})]})}function h(e={}){const{wrapper:t}={...(0,o.R)(),...e.components};return t?(0,c.jsx)(t,{...e,children:(0,c.jsx)(d,{...e})}):d(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>s,x:()=>a});var i=n(6540);const c={},o=i.createContext(c);function s(e){const t=i.useContext(o);return i.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function a(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(c):e.components||c:s(e.components),i.createElement(o.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/bde620bf.e3193c79.js b/assets/js/bde620bf.e3193c79.js deleted file mode 100644 index 191b96cb6..000000000 --- a/assets/js/bde620bf.e3193c79.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[3890],{4591:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>l,contentTitle:()=>a,default:()=>h,frontMatter:()=>s,metadata:()=>i,toc:()=>r});const i=JSON.parse('{"id":"go-client/activity-async-completion","title":"Async activity completion","description":"There are certain scenarios when completing an upon completion of its function is not possible","source":"@site/docs/05-go-client/12-activity-async-completion.md","sourceDirName":"05-go-client","slug":"/go-client/activity-async-completion","permalink":"/docs/go-client/activity-async-completion","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/05-go-client/12-activity-async-completion.md","tags":[],"version":"current","sidebarPosition":12,"frontMatter":{"layout":"default","title":"Async activity completion","permalink":"/docs/go-client/activity-async-completion"},"sidebar":"docsSidebar","previous":{"title":"Queries","permalink":"/docs/go-client/queries"},"next":{"title":"Testing","permalink":"/docs/go-client/workflow-testing"}}');var c=n(4848),o=n(8453);const s={layout:"default",title:"Async activity completion",permalink:"/docs/go-client/activity-async-completion"},a="Asynchronous activity completion",l={},r=[];function d(e){const t={code:"code",h1:"h1",header:"header",li:"li",ol:"ol",p:"p",pre:"pre",ul:"ul",...(0,o.R)(),...e.components};return(0,c.jsxs)(c.Fragment,{children:[(0,c.jsx)(t.header,{children:(0,c.jsx)(t.h1,{id:"asynchronous-activity-completion",children:"Asynchronous activity completion"})}),"\n",(0,c.jsx)(t.p,{children:"There are certain scenarios when completing an activity upon completion of its function is not possible\nor desirable. For example, you might have an application that requires user input in order to complete\nthe activity. You could implement the activity with a polling mechanism, but a simpler and less\nresource-intensive implementation is to asynchronously complete a Cadence activity."}),"\n",(0,c.jsx)(t.p,{children:"There two parts to implementing an asynchronously completed activity:"}),"\n",(0,c.jsxs)(t.ol,{children:["\n",(0,c.jsx)(t.li,{children:"The activity provides the information necessary for completion from an external system and notifies\nthe Cadence service that it is waiting for that outside callback."}),"\n",(0,c.jsx)(t.li,{children:"The external service calls the Cadence service to complete the activity."}),"\n"]}),"\n",(0,c.jsx)(t.p,{children:"The following example demonstrates the first part:"}),"\n",(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:"language-go",children:'// Retrieve the activity information needed to asynchronously complete the activity.\nactivityInfo := cadence.GetActivityInfo(ctx)\ntaskToken := activityInfo.TaskToken\n\n// Send the taskToken to the external service that will complete the activity.\n...\n\n// Return from the activity a function indicating that Cadence should wait for an async completion\n// message.\nreturn "", activity.ErrResultPending\n'})}),"\n",(0,c.jsx)(t.p,{children:"The following code demonstrates how to complete the activity successfully:"}),"\n",(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:"language-go",children:"// Instantiate a Cadence service client.\n// The same client can be used to complete or fail any number of activities.\ncadence.Client client = cadence.NewClient(...)\n\n// Complete the activity.\nclient.CompleteActivity(taskToken, result, nil)\n"})}),"\n",(0,c.jsx)(t.p,{children:"To fail the activity, you would do the following:"}),"\n",(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:"language-go",children:"// Fail the activity.\nclient.CompleteActivity(taskToken, nil, err)\n"})}),"\n",(0,c.jsxs)(t.p,{children:["Following are the parameters of the ",(0,c.jsx)(t.code,{children:"CompleteActivity"})," function:"]}),"\n",(0,c.jsxs)(t.ul,{children:["\n",(0,c.jsxs)(t.li,{children:[(0,c.jsx)(t.code,{children:"taskToken"}),": The value of the binary ",(0,c.jsx)(t.code,{children:"TaskToken"})," field of the ",(0,c.jsx)(t.code,{children:"ActivityInfo"})," struct retrieved inside\nthe activity."]}),"\n",(0,c.jsxs)(t.li,{children:[(0,c.jsx)(t.code,{children:"result"}),": The return value to record for the activity. The type of this value must match the type\nof the return value declared by the activity function."]}),"\n",(0,c.jsxs)(t.li,{children:[(0,c.jsx)(t.code,{children:"err"}),": The error code to return if the activity terminates with an error."]}),"\n"]}),"\n",(0,c.jsxs)(t.p,{children:["If ",(0,c.jsx)(t.code,{children:"error"})," is not null, the value of the ",(0,c.jsx)(t.code,{children:"result"})," field is ignored."]})]})}function h(e={}){const{wrapper:t}={...(0,o.R)(),...e.components};return t?(0,c.jsx)(t,{...e,children:(0,c.jsx)(d,{...e})}):d(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>s,x:()=>a});var i=n(6540);const c={},o=i.createContext(c);function s(e){const t=i.useContext(o);return i.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function a(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(c):e.components||c:s(e.components),i.createElement(o.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/c0e193ae.17b89c8d.js b/assets/js/c0e193ae.17b89c8d.js new file mode 100644 index 000000000..1267af3cc --- /dev/null +++ b/assets/js/c0e193ae.17b89c8d.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[4582],{8374:a=>{a.exports=JSON.parse('{"tag":{"label":"Roadmap","permalink":"/Cadence-Docs/blog/tags/roadmap","description":"Roadmap tag description","allTagsPath":"/Cadence-Docs/blog/tags","count":3,"unlisted":false},"listMetadata":{"permalink":"/Cadence-Docs/blog/tags/roadmap","page":1,"postsPerPage":10,"totalPages":1,"totalCount":3,"blogDescription":"The latest news and updates from the Cadence team","blogTitle":"Cadence Blog"}}')}}]); \ No newline at end of file diff --git a/assets/js/c15d9823.22d444d3.js b/assets/js/c15d9823.22d444d3.js deleted file mode 100644 index 99f727def..000000000 --- a/assets/js/c15d9823.22d444d3.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[8146],{6947:e=>{e.exports=JSON.parse('{"metadata":{"permalink":"/blog","page":1,"postsPerPage":10,"totalPages":4,"totalCount":35,"nextPage":"/blog/page/2","blogDescription":"The latest news and updates from the Cadence team","blogTitle":"Cadence Blog"}}')}}]); \ No newline at end of file diff --git a/assets/js/c47f6b82.215fc5e7.js b/assets/js/c47f6b82.34ea6b4c.js similarity index 94% rename from assets/js/c47f6b82.215fc5e7.js rename to assets/js/c47f6b82.34ea6b4c.js index 18e312aeb..1c6ac9a48 100644 --- a/assets/js/c47f6b82.215fc5e7.js +++ b/assets/js/c47f6b82.34ea6b4c.js @@ -1 +1 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[9855],{4281:(e,i,n)=>{n.r(i),n.d(i,{assets:()=>l,contentTitle:()=>r,default:()=>h,frontMatter:()=>s,metadata:()=>t,toc:()=>d});var t=n(4568),a=n(4848),o=n(8453);const s={title:"2024 Cadence Yearly Roadmap Update",date:new Date("2024-07-11T00:00:00.000Z"),authors:"enderdemirkaya",tags:["roadmap","deep-dive"]},r=void 0,l={authorsImageUrls:[void 0]},d=[{value:"Introduction",id:"introduction",level:2},{value:"What is a Workflow?",id:"what-is-a-workflow",level:3},{value:"Code-Driven Workflows",id:"code-driven-workflows",level:3},{value:"Benefits",id:"benefits",level:3},{value:"Project Support",id:"project-support",level:2},{value:"Team",id:"team",level:3},{value:"Community",id:"community",level:3},{value:"Scale",id:"scale",level:3},{value:"Managed Solutions",id:"managed-solutions",level:3},{value:"After V1 Release",id:"after-v1-release",level:2},{value:"Frequent Releases",id:"frequent-releases",level:3},{value:"Zonal Isolation",id:"zonal-isolation",level:3},{value:"Narrowing Blast Radius",id:"narrowing-blast-radius",level:3},{value:"Async APIs",id:"async-apis",level:3},{value:"Pinot as Visibility Store",id:"pinot-as-visibility-store",level:3},{value:"Code Coverage",id:"code-coverage",level:3},{value:"Replayer Improvements",id:"replayer-improvements",level:3},{value:"Global Rate Limiters",id:"global-rate-limiters",level:3},{value:"Regular Failover Drills",id:"regular-failover-drills",level:3},{value:"Cadence Web v4",id:"cadence-web-v4",level:3},{value:"Code Review Time Non-determinism Checks",id:"code-review-time-non-determinism-checks",level:3},{value:"Domain Reports",id:"domain-reports",level:3},{value:"Client Based Migrations",id:"client-based-migrations",level:3},{value:"Roadmap (Next Year)",id:"roadmap-next-year",level:2},{value:"Database efficiency",id:"database-efficiency",level:3},{value:"Helm Charts",id:"helm-charts",level:3},{value:"Dashboard Templates",id:"dashboard-templates",level:3},{value:"Client V2 Modernization",id:"client-v2-modernization",level:3},{value:"Higher Parallelization and Prioritization in Task Processing",id:"higher-parallelization-and-prioritization-in-task-processing",level:3},{value:"Timer and Cron Burst Handling",id:"timer-and-cron-burst-handling",level:3},{value:"High zonal skew handling",id:"high-zonal-skew-handling",level:3},{value:"Tasklist Improvements",id:"tasklist-improvements",level:3},{value:"Shard Movement/Assignment Improvements",id:"shard-movementassignment-improvements",level:3},{value:"Worker Heartbeats",id:"worker-heartbeats",level:3},{value:"Domain and Workflow Diagnostics",id:"domain-and-workflow-diagnostics",level:3},{value:"Self Serve Operations",id:"self-serve-operations",level:3},{value:"Cost Estimation",id:"cost-estimation",level:3},{value:"Domain Reports (continue)",id:"domain-reports-continue",level:3},{value:"Non-determinism Detection Improvements (continue)",id:"non-determinism-detection-improvements-continue",level:3},{value:"Domain Migrations (continue)",id:"domain-migrations-continue",level:3},{value:"Community",id:"community-1",level:2}];function c(e){const i={a:"a",h2:"h2",h3:"h3",img:"img",li:"li",p:"p",ul:"ul",...(0,o.R)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(i.h2,{id:"introduction",children:"Introduction"}),"\n",(0,a.jsx)(i.p,{children:"If you haven\u2019t heard about Cadence, this section is for you. In a short description, Cadence is a code-driven workflow orchestration engine. The definition itself may not tell enough, so it would help splitting it into three parts:"}),"\n",(0,a.jsxs)(i.ul,{children:["\n",(0,a.jsx)(i.li,{children:"What\u2019s a workflow? (everyone has a different definition)"}),"\n",(0,a.jsx)(i.li,{children:"Why does it matter to be code-driven?"}),"\n",(0,a.jsx)(i.li,{children:"Benefits of Cadence"}),"\n"]}),"\n",(0,a.jsx)(i.h3,{id:"what-is-a-workflow",children:"What is a Workflow?"}),"\n",(0,a.jsx)(i.p,{children:(0,a.jsx)(i.img,{alt:"workflow.png",src:n(5177).A+"",width:"650",height:"394"})}),"\n",(0,a.jsx)(i.p,{children:"In the simplest definition, it is \u201ca multi-step execution\u201d. Step here represents individual operations that are a little heavier than small in-process function calls. Although they are not limited to those: it could be a separate service call, processing a large dataset, map-reduce, thread sleep, scheduling next run, waiting for an external input, starting a sub workflow etc. It\u2019s anything a user thinks as a single unit of logic in their code. Those steps often have dependencies among themselves. Some steps, including the very first step, might require external triggers (e.g. button click) or schedules. In the more broader meaning, any multi-step function or service is a workflow in principle."}),"\n",(0,a.jsx)(i.p,{children:"While the above is a more correct way to define workflows, specialized workflows are more widely known: such as data pipelines, directed acyclic graphs, state machines, cron jobs, (micro)service orchestration, etc. This is why typically everyone has a different workflow meaning in mind. Specialized workflows also have simplified interfaces such as UI, configs or a DSL (domain specific language) to make it easy to express the workflow definition."}),"\n",(0,a.jsx)(i.h3,{id:"code-driven-workflows",children:"Code-Driven Workflows"}),"\n",(0,a.jsx)(i.p,{children:"Over time, any workflow interface evolves to support more scenarios. For any non-code (UI, config, DSL) technology, this means more APIs, concepts and tooling. However, eventually, the technology\u2019s capabilities will be limited by its interface itself. Otherwise the interface will get more complicated to operate."}),"\n",(0,a.jsx)(i.p,{children:"What happens here is users love the seamless way of creating workflow applications and try to fit more scenarios into it. Natural user tendency is to be able to write any program with such simplicity and confidence."}),"\n",(0,a.jsx)(i.p,{children:"Given this natural evolution of workflow requirements, it\u2019s better to have a code-driven workflow orchestration engine that can meet any future needs with its powerful expressiveness. On top of this, it is ideal if the interface is seamless, where engineers learn as little as possible and change almost nothing in their local code to write a distributed and durable workflow code. This would virtually remove any limitation and enable implementing any service as a workflow. This is what Cadence aims for."}),"\n",(0,a.jsx)(i.h3,{id:"benefits",children:"Benefits"}),"\n",(0,a.jsx)(i.p,{children:(0,a.jsx)(i.img,{alt:"cadence-benefits.png",src:n(9160).A+"",width:"694",height:"360"})}),"\n",(0,a.jsxs)(i.p,{children:["With Cadence, many overheads that need to be built for any well-supported service come for free. Here are some highlights (see ",(0,a.jsx)(i.a,{href:"http://cadenceworkflow.io",children:"cadenceworkflow.io"}),"):"]}),"\n",(0,a.jsxs)(i.ul,{children:["\n",(0,a.jsx)(i.li,{children:"Disaster recovery is supported by default through data replication and failovers"}),"\n",(0,a.jsx)(i.li,{children:"Strong multi tenancy support in Cadence clusters. Capacity and traffic management."}),"\n",(0,a.jsx)(i.li,{children:"Users can use Cadence APIs to start and interact with their workflows instead of writing new APIs for them"}),"\n",(0,a.jsx)(i.li,{children:"They can schedule their workflows (distributed cron, scheduled start) or any step in their workflows"}),"\n",(0,a.jsx)(i.li,{children:"They have tooling to get updates or cancel their workflows."}),"\n",(0,a.jsx)(i.li,{children:"Cadence comes with default metrics and logging support so users already get great insights about their workflows without implementing any observability tooling."}),"\n",(0,a.jsx)(i.li,{children:"Cadence has a web UI where users can list and filter their workflows, inspect workflow/activity inputs and outputs."}),"\n",(0,a.jsx)(i.li,{children:"They can scale their service just like true stateless services even though their workflows maintain a certain state."}),"\n",(0,a.jsx)(i.li,{children:"Behavior on failure modes can easily be configured with a few lines, providing high reliability."}),"\n",(0,a.jsx)(i.li,{children:"With Cadence testing capabilities, they can write unit tests or test against production data to prevent backward incompatibility issues."}),"\n",(0,a.jsx)(i.li,{children:"\u2026"}),"\n"]}),"\n",(0,a.jsx)(i.h2,{id:"project-support",children:"Project Support"}),"\n",(0,a.jsx)(i.h3,{id:"team",children:"Team"}),"\n",(0,a.jsx)(i.p,{children:"Today the Cadence team comprises 26 people. We have people working from Uber\u2019s US offices (Seattle, San Francisco and Sunnyvale) as well as Europe offices (Aarhus-DK and Amsterdam-NL)."}),"\n",(0,a.jsx)(i.h3,{id:"community",children:"Community"}),"\n",(0,a.jsxs)(i.p,{children:["Cadence is an actively built open source project. We invest in both our internal and open source community (",(0,a.jsx)(i.a,{href:"http://t.uber.com/cadence-slack",children:"Slack"}),", ",(0,a.jsx)(i.a,{href:"https://github.com/cadence-workflow/cadence/issues",children:"Github"}),"), responding to new features and enhancements."]}),"\n",(0,a.jsx)(i.h3,{id:"scale",children:"Scale"}),"\n",(0,a.jsx)(i.p,{children:"It\u2019s one of the most popular platforms at Uber executing ~100K workflow updates per second. There are about 30 different Cadence clusters, several of which serve hundreds of domains. There are ~1000 domains (use cases) varying from tier 0 (most critical) to tier 5 scenarios."}),"\n",(0,a.jsx)(i.h3,{id:"managed-solutions",children:"Managed Solutions"}),"\n",(0,a.jsxs)(i.p,{children:["While Uber doesn\u2019t officially sell a managed Cadence solution, there are companies (e.g. ",(0,a.jsx)(i.a,{href:"https://www.instaclustr.com/platform/managed-cadence/",children:"Instaclustr"}),") in our community that we work closely with selling Managed Cadence. Due to efficiency investments and other factors, it\u2019s significantly cheaper than its competitors. It can be run in users\u2019 on-prem machines or their cloud service of choice. Pricing is defined based on allocated hosts instead of number of requests so users can get more with the same resources by utilizing multi-tenant clusters."]}),"\n",(0,a.jsx)(i.h2,{id:"after-v1-release",children:"After V1 Release"}),"\n",(0,a.jsxs)(i.p,{children:["Last year, around this time we announced ",(0,a.jsx)(i.a,{href:"https://www.uber.com/blog/announcing-cadence/",children:"Cadence V1"})," and shared our roadmap. In this section we will talk about updates since then. At a high level, you will notice that we continue investing in high reliability and efficiency while also developing new features."]}),"\n",(0,a.jsx)(i.h3,{id:"frequent-releases",children:"Frequent Releases"}),"\n",(0,a.jsx)(i.p,{children:"We announced plans to make more frequent releases last year and started making more frequent releases. Today we aim to release biweekly and sometimes release as frequently as weekly. About the format, we listened to our community and heard about having too frequent releases potentially being painful. Therefore, we decided to increment the patch version with releases while incrementing the minor version close to quarterly. This helped us ship much more robust releases and improved our reliability. Here are some highlights:"}),"\n",(0,a.jsx)(i.h3,{id:"zonal-isolation",children:"Zonal Isolation"}),"\n",(0,a.jsx)(i.p,{children:"Cadence clusters have already been regionally isolated until this change. However, in the cloud, inter-zone communications matter as they are more expensive and their latencies are higher. Zones can individually have problems without impacting other cloud zones. In a regional architecture, a single zone problem might impact every request; however, with zonal isolation traffic from a zone with issues can easily be failed over to other zones, eliminating its impact on the whole cluster. Therefore, we implemented zonal isolation keeping domain traffic inside a single zone to help improve efficiency and reliability."}),"\n",(0,a.jsx)(i.h3,{id:"narrowing-blast-radius",children:"Narrowing Blast Radius"}),"\n",(0,a.jsx)(i.p,{children:"When there are issues in a Cadence cluster, it\u2019s often from a single misbehaving workflow. When this happens the whole domain or the cluster could have had issues until the specific workflow is addressed. With this change, we are able to contain the issue only to the offending workflow without impacting others. This is the narrowest blast radius possible."}),"\n",(0,a.jsx)(i.h3,{id:"async-apis",children:"Async APIs"}),"\n",(0,a.jsx)(i.p,{children:"At Uber, there are many batch work streams that run a high number of workflows (thousands to millions) at the same time causing bottlenecks for Cadence clusters, causing noisy neighbor issues. This is because StartWorkflow and SignalWorkflow APIs are synchronous, which means when Cadence acks the user requests are successfully saved in their workflow history."}),"\n",(0,a.jsx)(i.p,{children:"Even after successful initiations, users would then need to deal with high concurrency. This often means constant worker cache thrashing, followed by history rebuilds at every update, increasing workflow execution complexity to O(n^2) from O(n). Alternatively, they would need to quickly scale out and down their service hosts in a very short amount of time to avoid this."}),"\n",(0,a.jsx)(i.p,{children:"When we took a step back and analyzed such scenarios, we realized that users simply wanted to \u201ccomplete N workflows (jobs) in K time\u201d. The guarantees around starts and signals were not really important for their use cases. Therefore, we implemented async versions of our sync API, by which we can control the consumption rate, guaranteeing the fastest execution with no disruption in the cluster."}),"\n",(0,a.jsx)(i.p,{children:"Later this year, we plan to expand this feature to cron workflows and timers as well."}),"\n",(0,a.jsx)(i.h3,{id:"pinot-as-visibility-store",children:"Pinot as Visibility Store"}),"\n",(0,a.jsxs)(i.p,{children:[(0,a.jsx)(i.a,{href:"https://pinot.apache.org/",children:"Apache Pinot"})," is becoming popular due to its cost efficient nature. Several teams reported significant savings by changing their observability storage to Pinot. Cadence now has a Pinot plugin for its visibility store. We are still rolling out this change. Latencies and cost savings will be shared later."]}),"\n",(0,a.jsx)(i.h3,{id:"code-coverage",children:"Code Coverage"}),"\n",(0,a.jsx)(i.p,{children:"We have received many requests from our community to actively contribute to our codebase, especially after our V1 release. While we have been already collaborating with some companies, this is a challenge with individuals who are just learning about Cadence. One of the main reasons was to avoid bugs that can be introduced."}),"\n",(0,a.jsx)(i.p,{children:"While Cadence has many integration tests, its unit test coverage was lower than desired. With better unit test coverage we can catch changes that break previous logic and prevent them getting into the main branch. Our team covered additional 50K+ lines in various Cadence repos. We hope to bring our code coverage to 85%+ by the end of year so we can welcome such inquiries a lot easier."}),"\n",(0,a.jsx)(i.h3,{id:"replayer-improvements",children:"Replayer Improvements"}),"\n",(0,a.jsx)(i.p,{children:"This is still an ongoing project. As mentioned in our V1 release, we are revisiting some core parts of Cadence where less-than-ideal architectural decisions were made in the past. Replayer/shadower is one of such parts. We have been working on improving its precision, eliminating false negatives and positives."}),"\n",(0,a.jsx)(i.h3,{id:"global-rate-limiters",children:"Global Rate Limiters"}),"\n",(0,a.jsx)(i.p,{children:"Cadence rate limiters are equally distributed across zones and hosts. However, when the user's traffic is skewed, rate limits can get activated even though the user has more capacity. To avoid this, we built global rate limiters. This will make rate limits much more predictable and capacity management a lot easier."}),"\n",(0,a.jsx)(i.h3,{id:"regular-failover-drills",children:"Regular Failover Drills"}),"\n",(0,a.jsx)(i.p,{children:"Cadence has been performing monthly regional and zonal failover drills to ensure its failover operations are working properly in case we need it. We are failing over hundreds of domains at the same time to validate the scale of this operation, capacity elasticity and correctness of workflows."}),"\n",(0,a.jsx)(i.h3,{id:"cadence-web-v4",children:"Cadence Web v4"}),"\n",(0,a.jsx)(i.p,{children:"We are migrating Cadence web from Vue.js to React.js to use a more modern infrastructure and to have better feature velocity. We are about 70% complete with this migration and hope to release the new version of it soon."}),"\n",(0,a.jsx)(i.h3,{id:"code-review-time-non-determinism-checks",children:"Code Review Time Non-determinism Checks"}),"\n",(0,a.jsx)(i.p,{children:"(This is an internal-only feature that we hope to release soon) Cadence non-determinism errors and versioning were common pain points for our customers. There are available tools but they require ongoing effort to validate. We have built a tool that generates a shadower test with a single line command (one time only operation) and continuously validates any code change against production data."}),"\n",(0,a.jsx)(i.p,{children:"This feature reduced the detect-and-fix time from days/weeks to minutes. Just by launching this feature to the domains with the most non-determinism errors, the number of related incidents reduced by 40%. We have already blocked 500+ diffs that would potentially impact production negatively. This boosted our users\u2019 confidence in using Cadence."}),"\n",(0,a.jsx)(i.h3,{id:"domain-reports",children:"Domain Reports"}),"\n",(0,a.jsx)(i.p,{children:"(This is an internal-only feature that we hope to release soon) We are able to detect potential issues (bugs, antipatterns, inefficiencies, failures) with domains upon manual investigation. We have automated this process and now generate reports for each domain. This information can be accessed historically (to see the progression over time) and on-demand (to see the current state). This has already driven domain reliability and efficiency improvements."}),"\n",(0,a.jsx)(i.p,{children:"This feature and above are at MVP level where we plan to generalize, expand and release for open source soon. In the V1 release, we have mentioned that we would build certain features internally first to be able to have enough velocity, to see where they are going and to make breaking changes until it\u2019s mature."}),"\n",(0,a.jsx)(i.h3,{id:"client-based-migrations",children:"Client Based Migrations"}),"\n",(0,a.jsx)(i.p,{children:"With 30 clusters and ~1000 domains in production, migrating a domain from a cluster to another became a somewhat frequent operation for Cadence. While this feature is mostly automated, we would like to fully automate it to a level that this would be a single click or command operation. Client based migrations (as opposed to server based ones) give us big flexibility that we can have migrations from many to many environments at the same time. Each migration happens in isolation without impacting any other domain or the cluster."}),"\n",(0,a.jsx)(i.p,{children:"This is an ongoing project where remaining parts are migrating long running workflows faster and seamless technology to technology migrations even if the \u201cfrom-technology\u201d is not Cadence in the first place. There are many users that migrated from Cadence-like or different technologies to Cadence so we hope to remove the repeating overhead for such users."}),"\n",(0,a.jsx)(i.h2,{id:"roadmap-next-year",children:"Roadmap (Next Year)"}),"\n",(0,a.jsx)(i.p,{children:"Our priorities for next year look similar with reliability, efficiency, and new features as our focus. We have seen significant improvements especially in our users\u2019 reliability and efficiency on top of the improvements in our servers. This both reduces operational load on our users and makes Cadence one step closer to being a standard way to build services. Here is a short list of what's coming over the next 12 months:"}),"\n",(0,a.jsx)(i.h3,{id:"database-efficiency",children:"Database efficiency"}),"\n",(0,a.jsx)(i.p,{children:"We are increasing our investment in improving Cadence\u2019s database usage. Even though Cadence\u2019s cost looks a lot better compared to the same family of technologies, it can still be significantly improved by eliminating certain bottlenecks coming from its original design."}),"\n",(0,a.jsx)(i.h3,{id:"helm-charts",children:"Helm Charts"}),"\n",(0,a.jsx)(i.p,{children:"We are grateful to the Cadence community for introducing and maintaining our Helm charts for operating Cadence clusters. We are taking its ownership so it can be officially released and tested. We expect to release this in 2024."}),"\n",(0,a.jsx)(i.h3,{id:"dashboard-templates",children:"Dashboard Templates"}),"\n",(0,a.jsx)(i.p,{children:"During our tech talks, demos and user talks, we have received inquiries about what metrics care about. We plan to release templates for our dashboards so our community would look at a similar picture."}),"\n",(0,a.jsx)(i.h3,{id:"client-v2-modernization",children:"Client V2 Modernization"}),"\n",(0,a.jsx)(i.p,{children:"As we announced last year that we plan to make breaking changes to significantly improve our interfaces, we are working on modernizing our client interface."}),"\n",(0,a.jsx)(i.h3,{id:"higher-parallelization-and-prioritization-in-task-processing",children:"Higher Parallelization and Prioritization in Task Processing"}),"\n",(0,a.jsx)(i.p,{children:"In an effort to have better domain prioritization in multitenant Cadence clusters, we are improving our task processing with higher parallelization and better prioritization. This is a lot better model than just having domains with defined limits. We expect to provide more resources to high priority domains during their peak hours while allowing low priority domains to consume much bigger resources than allocated during quiet times."}),"\n",(0,a.jsx)(i.h3,{id:"timer-and-cron-burst-handling",children:"Timer and Cron Burst Handling"}),"\n",(0,a.jsx)(i.p,{children:"After addressing start and signal burst scenarios, we are continuing with bursty timers and cron jobs. Many users set their schedules and timers for the same second with the intention of being able to finish N jobs within a certain amount of time. Current scheduling design isn\u2019t friendly for such intents and high loads can cause temporary starvation in the cluster. By introducing better batch scheduling support, clusters can continue with no disruption while timers are processed in the most efficient way."}),"\n",(0,a.jsx)(i.h3,{id:"high-zonal-skew-handling",children:"High zonal skew handling"}),"\n",(0,a.jsx)(i.p,{children:"For users operating in their own cloud and having multiple independent zones in every region, zonal skews can be a problem and can create unnecessary bottlenecks when Zonal Isolation feature is enabled. We are working on addressing such issues to improve task matching across zones when skew is detected."}),"\n",(0,a.jsx)(i.h3,{id:"tasklist-improvements",children:"Tasklist Improvements"}),"\n",(0,a.jsx)(i.p,{children:"When a user scenario grows, there are many knobs that need to be manually adjusted. We would like to automatically partition and smartly forward tasks to improve tasklist efficiency significantly to avoid backlogs, timeouts and hot shards."}),"\n",(0,a.jsx)(i.h3,{id:"shard-movementassignment-improvements",children:"Shard Movement/Assignment Improvements"}),"\n",(0,a.jsx)(i.p,{children:"Cadence shard movements are based on consistent hash and this can be a limiting factor for many different reasons. Certain hosts can end up getting unlucky by having many shards, or having heavy shards. During deployments we might observe a much higher number of shard movements than desired, which reduces the availability. With improved shard movements and assignments we can have more homogenous load among hosts while also having a minimum amount of shard movements during deployments with much better availability."}),"\n",(0,a.jsx)(i.h3,{id:"worker-heartbeats",children:"Worker Heartbeats"}),"\n",(0,a.jsx)(i.p,{children:"Today, there\u2019s no worker liveliness tracking in Cadence. Instead, task or activity heartbeat timeouts are used to reassign tasks to different workers. For latency sensitive users this can become a big disruption. For long activities without heartbeats, this can cause big delays. This feature is to eliminate depending on manual timeout or heartbeat configs to reassign tasks by tracking if workers are still healthy. This feature will also enable so many other new efficiency and reliability features we would like to get to in the future."}),"\n",(0,a.jsx)(i.h3,{id:"domain-and-workflow-diagnostics",children:"Domain and Workflow Diagnostics"}),"\n",(0,a.jsx)(i.p,{children:"Probably the two most common user questions are \u201cWhat\u2019s wrong with my domain?\u201d and \u201cWhat\u2019s wrong with my workflow?\u201d. Today, diagnosing what happened and what could be wrong isn\u2019t that easy apart from some basic cases. We are working on tools that would run diagnostics on workflows and domains to point out things that might potentially be wrong with public runbook links attached. This feature will not only help diagnose what is wrong with our workflows and domains but will also help fix them."}),"\n",(0,a.jsx)(i.h3,{id:"self-serve-operations",children:"Self Serve Operations"}),"\n",(0,a.jsx)(i.p,{children:"Certain Cadence operations are performed through admin CLI operations. However, these should be able to be done via Cadence UI by users. Admins shouldn\u2019t need to be involved in every step or the checks they validate should be able to be automated. This is what the initiative is about including domain registration, auth/authz onboarding or adding new search attributes but it\u2019s not limited to these operations."}),"\n",(0,a.jsx)(i.h3,{id:"cost-estimation",children:"Cost Estimation"}),"\n",(0,a.jsx)(i.p,{children:"One big question we receive when users are onboarding to Cadence is \u201cHow much will this cost me?\u201d. This is not an easy question to answer since data and traffic load can be quite different. We plan to automate this process to help users understand how much resources they will need. Especially in multi-tenant clusters, this will help users understand how much room they still have in their clusters and how much the new scenario will consume."}),"\n",(0,a.jsx)(i.h3,{id:"domain-reports-continue",children:"Domain Reports (continue)"}),"\n",(0,a.jsx)(i.p,{children:"We plan to release this internal feature to open source as soon as possible. On top of presenting this data on built-in Cadence surfaces (web, CLI. etc.) we will create APIs to make it integratable with deployment systems, user service UIs, periodic reports and any other service that would like to consume."}),"\n",(0,a.jsx)(i.h3,{id:"non-determinism-detection-improvements-continue",children:"Non-determinism Detection Improvements (continue)"}),"\n",(0,a.jsx)(i.p,{children:"We have seen great reliability improvements and reduction in incidents with this feature on the user side last year. We continue to invest in this feature and make it available in open source as soon as possible."}),"\n",(0,a.jsx)(i.h3,{id:"domain-migrations-continue",children:"Domain Migrations (continue)"}),"\n",(0,a.jsx)(i.p,{children:"In the next year, we plan to finish our seamless client based migration to be able to safely migrate domains from one cluster to another, one technology (even if it\u2019s not Cadence) to another and one cloud solution to another. There are only a few features left to achieve this."}),"\n",(0,a.jsx)(i.h2,{id:"community-1",children:"Community"}),"\n",(0,a.jsx)(i.p,{children:"Do you want to hear more about Cadence? Do you need help with your set-up or usage? Are you evaluating your options? Do you want to contribute? Feel free to join our community and reach out to us."}),"\n",(0,a.jsxs)(i.p,{children:["Slack: ",(0,a.jsx)(i.a,{href:"https://uber-cadence.slack.com/",children:"https://uber-cadence.slack.com/"})]}),"\n",(0,a.jsxs)(i.p,{children:["Github: ",(0,a.jsx)(i.a,{href:"https://github.com/cadence-workflow/cadence",children:"https://github.com/cadence-workflow/cadence"})]}),"\n",(0,a.jsx)(i.p,{children:"Since last year, we have been contacted by various companies to take on bigger projects on the Cadence project. As we have been investing in code coverage and refactoring Cadence for a cleaner codebase, this will be a lot easier now. Let us know if you have project ideas to contribute or if you\u2019d like to pick something we already planned."}),"\n",(0,a.jsx)(i.p,{children:"Our monthly community meetings are still ongoing, too. That is the best place to get heard and be involved in our decision-making process. Let us know so we can send you an invite. We are also working on a broader governing model to open up this project to more people. Stay tuned for updates on this topic!"})]})}function h(e={}){const{wrapper:i}={...(0,o.R)(),...e.components};return i?(0,a.jsx)(i,{...e,children:(0,a.jsx)(c,{...e})}):c(e)}},9160:(e,i,n)=>{n.d(i,{A:()=>t});const t=n.p+"assets/images/cadence-benefits-2bab00edd6033ae128d39367af8ed72a.png"},5177:(e,i,n)=>{n.d(i,{A:()=>t});const t=n.p+"assets/images/workflow-84ef76d93c7ff138714a0aa7c9b92841.png"},8453:(e,i,n)=>{n.d(i,{R:()=>s,x:()=>r});var t=n(6540);const a={},o=t.createContext(a);function s(e){const i=t.useContext(o);return t.useMemo((function(){return"function"==typeof e?e(i):{...i,...e}}),[i,e])}function r(e){let i;return i=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:s(e.components),t.createElement(o.Provider,{value:i},e.children)}},4568:e=>{e.exports=JSON.parse('{"permalink":"/blog/2024/07/11/2024-07-11-yearly-roadmap-update/yearly-roadmap-update","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2024-07-11-yearly-roadmap-update/2024-07-11-yearly-roadmap-update.md","source":"@site/blog/2024-07-11-yearly-roadmap-update/2024-07-11-yearly-roadmap-update.md","title":"2024 Cadence Yearly Roadmap Update","description":"Introduction","date":"2024-07-11T00:00:00.000Z","tags":[{"inline":false,"label":"Roadmap","permalink":"/blog/tags/roadmap","description":"Roadmap tag description"},{"inline":false,"label":"Deep Dives","permalink":"/blog/tags/deep-dives","description":"Deep Dives tag description"}],"readingTime":16.31,"hasTruncateMarker":true,"authors":[{"name":"Ender Demirkaya","title":"Senior Manager at Uber, Cadence. Author of the Software Engineering Handbook","url":"https://www.linkedin.com/in/enderdemirkaya/","page":{"permalink":"/blog/authors/enderdemirkaya"},"socials":{"linkedin":"https://www.linkedin.com/in/enderdemirkaya/","github":"https://github.com/demirkayaender"},"imageURL":"https://github.com/demirkayaender.png","key":"enderdemirkaya"}],"frontMatter":{"title":"2024 Cadence Yearly Roadmap Update","date":"2024-07-11T00:00:00.000Z","authors":"enderdemirkaya","tags":["roadmap","deep-dive"]},"unlisted":false,"prevItem":{"title":"Minimizing blast radius in Cadence: Introducing Workflow ID-based Rate Limits","permalink":"/blog/2024/09/05/workflow-specific-rate-limits"},"nextItem":{"title":"Cadence non-derministic errors common question Q&A (part 1)","permalink":"/blog/2024/02/15/cadence-non-deterministic-common-qa"}}')}}]); \ No newline at end of file +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[9855],{4281:(e,i,n)=>{n.r(i),n.d(i,{assets:()=>l,contentTitle:()=>r,default:()=>h,frontMatter:()=>s,metadata:()=>t,toc:()=>d});var t=n(4568),a=n(4848),o=n(8453);const s={title:"2024 Cadence Yearly Roadmap Update",date:new Date("2024-07-11T00:00:00.000Z"),authors:"enderdemirkaya",tags:["roadmap","deep-dive"]},r=void 0,l={authorsImageUrls:[void 0]},d=[{value:"Introduction",id:"introduction",level:2},{value:"What is a Workflow?",id:"what-is-a-workflow",level:3},{value:"Code-Driven Workflows",id:"code-driven-workflows",level:3},{value:"Benefits",id:"benefits",level:3},{value:"Project Support",id:"project-support",level:2},{value:"Team",id:"team",level:3},{value:"Community",id:"community",level:3},{value:"Scale",id:"scale",level:3},{value:"Managed Solutions",id:"managed-solutions",level:3},{value:"After V1 Release",id:"after-v1-release",level:2},{value:"Frequent Releases",id:"frequent-releases",level:3},{value:"Zonal Isolation",id:"zonal-isolation",level:3},{value:"Narrowing Blast Radius",id:"narrowing-blast-radius",level:3},{value:"Async APIs",id:"async-apis",level:3},{value:"Pinot as Visibility Store",id:"pinot-as-visibility-store",level:3},{value:"Code Coverage",id:"code-coverage",level:3},{value:"Replayer Improvements",id:"replayer-improvements",level:3},{value:"Global Rate Limiters",id:"global-rate-limiters",level:3},{value:"Regular Failover Drills",id:"regular-failover-drills",level:3},{value:"Cadence Web v4",id:"cadence-web-v4",level:3},{value:"Code Review Time Non-determinism Checks",id:"code-review-time-non-determinism-checks",level:3},{value:"Domain Reports",id:"domain-reports",level:3},{value:"Client Based Migrations",id:"client-based-migrations",level:3},{value:"Roadmap (Next Year)",id:"roadmap-next-year",level:2},{value:"Database efficiency",id:"database-efficiency",level:3},{value:"Helm Charts",id:"helm-charts",level:3},{value:"Dashboard Templates",id:"dashboard-templates",level:3},{value:"Client V2 Modernization",id:"client-v2-modernization",level:3},{value:"Higher Parallelization and Prioritization in Task Processing",id:"higher-parallelization-and-prioritization-in-task-processing",level:3},{value:"Timer and Cron Burst Handling",id:"timer-and-cron-burst-handling",level:3},{value:"High zonal skew handling",id:"high-zonal-skew-handling",level:3},{value:"Tasklist Improvements",id:"tasklist-improvements",level:3},{value:"Shard Movement/Assignment Improvements",id:"shard-movementassignment-improvements",level:3},{value:"Worker Heartbeats",id:"worker-heartbeats",level:3},{value:"Domain and Workflow Diagnostics",id:"domain-and-workflow-diagnostics",level:3},{value:"Self Serve Operations",id:"self-serve-operations",level:3},{value:"Cost Estimation",id:"cost-estimation",level:3},{value:"Domain Reports (continue)",id:"domain-reports-continue",level:3},{value:"Non-determinism Detection Improvements (continue)",id:"non-determinism-detection-improvements-continue",level:3},{value:"Domain Migrations (continue)",id:"domain-migrations-continue",level:3},{value:"Community",id:"community-1",level:2}];function c(e){const i={a:"a",h2:"h2",h3:"h3",img:"img",li:"li",p:"p",ul:"ul",...(0,o.R)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(i.h2,{id:"introduction",children:"Introduction"}),"\n",(0,a.jsx)(i.p,{children:"If you haven\u2019t heard about Cadence, this section is for you. In a short description, Cadence is a code-driven workflow orchestration engine. The definition itself may not tell enough, so it would help splitting it into three parts:"}),"\n",(0,a.jsxs)(i.ul,{children:["\n",(0,a.jsx)(i.li,{children:"What\u2019s a workflow? (everyone has a different definition)"}),"\n",(0,a.jsx)(i.li,{children:"Why does it matter to be code-driven?"}),"\n",(0,a.jsx)(i.li,{children:"Benefits of Cadence"}),"\n"]}),"\n",(0,a.jsx)(i.h3,{id:"what-is-a-workflow",children:"What is a Workflow?"}),"\n",(0,a.jsx)(i.p,{children:(0,a.jsx)(i.img,{alt:"workflow.png",src:n(5177).A+"",width:"650",height:"394"})}),"\n",(0,a.jsx)(i.p,{children:"In the simplest definition, it is \u201ca multi-step execution\u201d. Step here represents individual operations that are a little heavier than small in-process function calls. Although they are not limited to those: it could be a separate service call, processing a large dataset, map-reduce, thread sleep, scheduling next run, waiting for an external input, starting a sub workflow etc. It\u2019s anything a user thinks as a single unit of logic in their code. Those steps often have dependencies among themselves. Some steps, including the very first step, might require external triggers (e.g. button click) or schedules. In the more broader meaning, any multi-step function or service is a workflow in principle."}),"\n",(0,a.jsx)(i.p,{children:"While the above is a more correct way to define workflows, specialized workflows are more widely known: such as data pipelines, directed acyclic graphs, state machines, cron jobs, (micro)service orchestration, etc. This is why typically everyone has a different workflow meaning in mind. Specialized workflows also have simplified interfaces such as UI, configs or a DSL (domain specific language) to make it easy to express the workflow definition."}),"\n",(0,a.jsx)(i.h3,{id:"code-driven-workflows",children:"Code-Driven Workflows"}),"\n",(0,a.jsx)(i.p,{children:"Over time, any workflow interface evolves to support more scenarios. For any non-code (UI, config, DSL) technology, this means more APIs, concepts and tooling. However, eventually, the technology\u2019s capabilities will be limited by its interface itself. Otherwise the interface will get more complicated to operate."}),"\n",(0,a.jsx)(i.p,{children:"What happens here is users love the seamless way of creating workflow applications and try to fit more scenarios into it. Natural user tendency is to be able to write any program with such simplicity and confidence."}),"\n",(0,a.jsx)(i.p,{children:"Given this natural evolution of workflow requirements, it\u2019s better to have a code-driven workflow orchestration engine that can meet any future needs with its powerful expressiveness. On top of this, it is ideal if the interface is seamless, where engineers learn as little as possible and change almost nothing in their local code to write a distributed and durable workflow code. This would virtually remove any limitation and enable implementing any service as a workflow. This is what Cadence aims for."}),"\n",(0,a.jsx)(i.h3,{id:"benefits",children:"Benefits"}),"\n",(0,a.jsx)(i.p,{children:(0,a.jsx)(i.img,{alt:"cadence-benefits.png",src:n(9160).A+"",width:"694",height:"360"})}),"\n",(0,a.jsxs)(i.p,{children:["With Cadence, many overheads that need to be built for any well-supported service come for free. Here are some highlights (see ",(0,a.jsx)(i.a,{href:"http://cadenceworkflow.io",children:"cadenceworkflow.io"}),"):"]}),"\n",(0,a.jsxs)(i.ul,{children:["\n",(0,a.jsx)(i.li,{children:"Disaster recovery is supported by default through data replication and failovers"}),"\n",(0,a.jsx)(i.li,{children:"Strong multi tenancy support in Cadence clusters. Capacity and traffic management."}),"\n",(0,a.jsx)(i.li,{children:"Users can use Cadence APIs to start and interact with their workflows instead of writing new APIs for them"}),"\n",(0,a.jsx)(i.li,{children:"They can schedule their workflows (distributed cron, scheduled start) or any step in their workflows"}),"\n",(0,a.jsx)(i.li,{children:"They have tooling to get updates or cancel their workflows."}),"\n",(0,a.jsx)(i.li,{children:"Cadence comes with default metrics and logging support so users already get great insights about their workflows without implementing any observability tooling."}),"\n",(0,a.jsx)(i.li,{children:"Cadence has a web UI where users can list and filter their workflows, inspect workflow/activity inputs and outputs."}),"\n",(0,a.jsx)(i.li,{children:"They can scale their service just like true stateless services even though their workflows maintain a certain state."}),"\n",(0,a.jsx)(i.li,{children:"Behavior on failure modes can easily be configured with a few lines, providing high reliability."}),"\n",(0,a.jsx)(i.li,{children:"With Cadence testing capabilities, they can write unit tests or test against production data to prevent backward incompatibility issues."}),"\n",(0,a.jsx)(i.li,{children:"\u2026"}),"\n"]}),"\n",(0,a.jsx)(i.h2,{id:"project-support",children:"Project Support"}),"\n",(0,a.jsx)(i.h3,{id:"team",children:"Team"}),"\n",(0,a.jsx)(i.p,{children:"Today the Cadence team comprises 26 people. We have people working from Uber\u2019s US offices (Seattle, San Francisco and Sunnyvale) as well as Europe offices (Aarhus-DK and Amsterdam-NL)."}),"\n",(0,a.jsx)(i.h3,{id:"community",children:"Community"}),"\n",(0,a.jsxs)(i.p,{children:["Cadence is an actively built open source project. We invest in both our internal and open source community (",(0,a.jsx)(i.a,{href:"http://t.uber.com/cadence-slack",children:"Slack"}),", ",(0,a.jsx)(i.a,{href:"https://github.com/cadence-workflow/cadence/issues",children:"Github"}),"), responding to new features and enhancements."]}),"\n",(0,a.jsx)(i.h3,{id:"scale",children:"Scale"}),"\n",(0,a.jsx)(i.p,{children:"It\u2019s one of the most popular platforms at Uber executing ~100K workflow updates per second. There are about 30 different Cadence clusters, several of which serve hundreds of domains. There are ~1000 domains (use cases) varying from tier 0 (most critical) to tier 5 scenarios."}),"\n",(0,a.jsx)(i.h3,{id:"managed-solutions",children:"Managed Solutions"}),"\n",(0,a.jsxs)(i.p,{children:["While Uber doesn\u2019t officially sell a managed Cadence solution, there are companies (e.g. ",(0,a.jsx)(i.a,{href:"https://www.instaclustr.com/platform/managed-cadence/",children:"Instaclustr"}),") in our community that we work closely with selling Managed Cadence. Due to efficiency investments and other factors, it\u2019s significantly cheaper than its competitors. It can be run in users\u2019 on-prem machines or their cloud service of choice. Pricing is defined based on allocated hosts instead of number of requests so users can get more with the same resources by utilizing multi-tenant clusters."]}),"\n",(0,a.jsx)(i.h2,{id:"after-v1-release",children:"After V1 Release"}),"\n",(0,a.jsxs)(i.p,{children:["Last year, around this time we announced ",(0,a.jsx)(i.a,{href:"https://www.uber.com/blog/announcing-cadence/",children:"Cadence V1"})," and shared our roadmap. In this section we will talk about updates since then. At a high level, you will notice that we continue investing in high reliability and efficiency while also developing new features."]}),"\n",(0,a.jsx)(i.h3,{id:"frequent-releases",children:"Frequent Releases"}),"\n",(0,a.jsx)(i.p,{children:"We announced plans to make more frequent releases last year and started making more frequent releases. Today we aim to release biweekly and sometimes release as frequently as weekly. About the format, we listened to our community and heard about having too frequent releases potentially being painful. Therefore, we decided to increment the patch version with releases while incrementing the minor version close to quarterly. This helped us ship much more robust releases and improved our reliability. Here are some highlights:"}),"\n",(0,a.jsx)(i.h3,{id:"zonal-isolation",children:"Zonal Isolation"}),"\n",(0,a.jsx)(i.p,{children:"Cadence clusters have already been regionally isolated until this change. However, in the cloud, inter-zone communications matter as they are more expensive and their latencies are higher. Zones can individually have problems without impacting other cloud zones. In a regional architecture, a single zone problem might impact every request; however, with zonal isolation traffic from a zone with issues can easily be failed over to other zones, eliminating its impact on the whole cluster. Therefore, we implemented zonal isolation keeping domain traffic inside a single zone to help improve efficiency and reliability."}),"\n",(0,a.jsx)(i.h3,{id:"narrowing-blast-radius",children:"Narrowing Blast Radius"}),"\n",(0,a.jsx)(i.p,{children:"When there are issues in a Cadence cluster, it\u2019s often from a single misbehaving workflow. When this happens the whole domain or the cluster could have had issues until the specific workflow is addressed. With this change, we are able to contain the issue only to the offending workflow without impacting others. This is the narrowest blast radius possible."}),"\n",(0,a.jsx)(i.h3,{id:"async-apis",children:"Async APIs"}),"\n",(0,a.jsx)(i.p,{children:"At Uber, there are many batch work streams that run a high number of workflows (thousands to millions) at the same time causing bottlenecks for Cadence clusters, causing noisy neighbor issues. This is because StartWorkflow and SignalWorkflow APIs are synchronous, which means when Cadence acks the user requests are successfully saved in their workflow history."}),"\n",(0,a.jsx)(i.p,{children:"Even after successful initiations, users would then need to deal with high concurrency. This often means constant worker cache thrashing, followed by history rebuilds at every update, increasing workflow execution complexity to O(n^2) from O(n). Alternatively, they would need to quickly scale out and down their service hosts in a very short amount of time to avoid this."}),"\n",(0,a.jsx)(i.p,{children:"When we took a step back and analyzed such scenarios, we realized that users simply wanted to \u201ccomplete N workflows (jobs) in K time\u201d. The guarantees around starts and signals were not really important for their use cases. Therefore, we implemented async versions of our sync API, by which we can control the consumption rate, guaranteeing the fastest execution with no disruption in the cluster."}),"\n",(0,a.jsx)(i.p,{children:"Later this year, we plan to expand this feature to cron workflows and timers as well."}),"\n",(0,a.jsx)(i.h3,{id:"pinot-as-visibility-store",children:"Pinot as Visibility Store"}),"\n",(0,a.jsxs)(i.p,{children:[(0,a.jsx)(i.a,{href:"https://pinot.apache.org/",children:"Apache Pinot"})," is becoming popular due to its cost efficient nature. Several teams reported significant savings by changing their observability storage to Pinot. Cadence now has a Pinot plugin for its visibility store. We are still rolling out this change. Latencies and cost savings will be shared later."]}),"\n",(0,a.jsx)(i.h3,{id:"code-coverage",children:"Code Coverage"}),"\n",(0,a.jsx)(i.p,{children:"We have received many requests from our community to actively contribute to our codebase, especially after our V1 release. While we have been already collaborating with some companies, this is a challenge with individuals who are just learning about Cadence. One of the main reasons was to avoid bugs that can be introduced."}),"\n",(0,a.jsx)(i.p,{children:"While Cadence has many integration tests, its unit test coverage was lower than desired. With better unit test coverage we can catch changes that break previous logic and prevent them getting into the main branch. Our team covered additional 50K+ lines in various Cadence repos. We hope to bring our code coverage to 85%+ by the end of year so we can welcome such inquiries a lot easier."}),"\n",(0,a.jsx)(i.h3,{id:"replayer-improvements",children:"Replayer Improvements"}),"\n",(0,a.jsx)(i.p,{children:"This is still an ongoing project. As mentioned in our V1 release, we are revisiting some core parts of Cadence where less-than-ideal architectural decisions were made in the past. Replayer/shadower is one of such parts. We have been working on improving its precision, eliminating false negatives and positives."}),"\n",(0,a.jsx)(i.h3,{id:"global-rate-limiters",children:"Global Rate Limiters"}),"\n",(0,a.jsx)(i.p,{children:"Cadence rate limiters are equally distributed across zones and hosts. However, when the user's traffic is skewed, rate limits can get activated even though the user has more capacity. To avoid this, we built global rate limiters. This will make rate limits much more predictable and capacity management a lot easier."}),"\n",(0,a.jsx)(i.h3,{id:"regular-failover-drills",children:"Regular Failover Drills"}),"\n",(0,a.jsx)(i.p,{children:"Cadence has been performing monthly regional and zonal failover drills to ensure its failover operations are working properly in case we need it. We are failing over hundreds of domains at the same time to validate the scale of this operation, capacity elasticity and correctness of workflows."}),"\n",(0,a.jsx)(i.h3,{id:"cadence-web-v4",children:"Cadence Web v4"}),"\n",(0,a.jsx)(i.p,{children:"We are migrating Cadence web from Vue.js to React.js to use a more modern infrastructure and to have better feature velocity. We are about 70% complete with this migration and hope to release the new version of it soon."}),"\n",(0,a.jsx)(i.h3,{id:"code-review-time-non-determinism-checks",children:"Code Review Time Non-determinism Checks"}),"\n",(0,a.jsx)(i.p,{children:"(This is an internal-only feature that we hope to release soon) Cadence non-determinism errors and versioning were common pain points for our customers. There are available tools but they require ongoing effort to validate. We have built a tool that generates a shadower test with a single line command (one time only operation) and continuously validates any code change against production data."}),"\n",(0,a.jsx)(i.p,{children:"This feature reduced the detect-and-fix time from days/weeks to minutes. Just by launching this feature to the domains with the most non-determinism errors, the number of related incidents reduced by 40%. We have already blocked 500+ diffs that would potentially impact production negatively. This boosted our users\u2019 confidence in using Cadence."}),"\n",(0,a.jsx)(i.h3,{id:"domain-reports",children:"Domain Reports"}),"\n",(0,a.jsx)(i.p,{children:"(This is an internal-only feature that we hope to release soon) We are able to detect potential issues (bugs, antipatterns, inefficiencies, failures) with domains upon manual investigation. We have automated this process and now generate reports for each domain. This information can be accessed historically (to see the progression over time) and on-demand (to see the current state). This has already driven domain reliability and efficiency improvements."}),"\n",(0,a.jsx)(i.p,{children:"This feature and above are at MVP level where we plan to generalize, expand and release for open source soon. In the V1 release, we have mentioned that we would build certain features internally first to be able to have enough velocity, to see where they are going and to make breaking changes until it\u2019s mature."}),"\n",(0,a.jsx)(i.h3,{id:"client-based-migrations",children:"Client Based Migrations"}),"\n",(0,a.jsx)(i.p,{children:"With 30 clusters and ~1000 domains in production, migrating a domain from a cluster to another became a somewhat frequent operation for Cadence. While this feature is mostly automated, we would like to fully automate it to a level that this would be a single click or command operation. Client based migrations (as opposed to server based ones) give us big flexibility that we can have migrations from many to many environments at the same time. Each migration happens in isolation without impacting any other domain or the cluster."}),"\n",(0,a.jsx)(i.p,{children:"This is an ongoing project where remaining parts are migrating long running workflows faster and seamless technology to technology migrations even if the \u201cfrom-technology\u201d is not Cadence in the first place. There are many users that migrated from Cadence-like or different technologies to Cadence so we hope to remove the repeating overhead for such users."}),"\n",(0,a.jsx)(i.h2,{id:"roadmap-next-year",children:"Roadmap (Next Year)"}),"\n",(0,a.jsx)(i.p,{children:"Our priorities for next year look similar with reliability, efficiency, and new features as our focus. We have seen significant improvements especially in our users\u2019 reliability and efficiency on top of the improvements in our servers. This both reduces operational load on our users and makes Cadence one step closer to being a standard way to build services. Here is a short list of what's coming over the next 12 months:"}),"\n",(0,a.jsx)(i.h3,{id:"database-efficiency",children:"Database efficiency"}),"\n",(0,a.jsx)(i.p,{children:"We are increasing our investment in improving Cadence\u2019s database usage. Even though Cadence\u2019s cost looks a lot better compared to the same family of technologies, it can still be significantly improved by eliminating certain bottlenecks coming from its original design."}),"\n",(0,a.jsx)(i.h3,{id:"helm-charts",children:"Helm Charts"}),"\n",(0,a.jsx)(i.p,{children:"We are grateful to the Cadence community for introducing and maintaining our Helm charts for operating Cadence clusters. We are taking its ownership so it can be officially released and tested. We expect to release this in 2024."}),"\n",(0,a.jsx)(i.h3,{id:"dashboard-templates",children:"Dashboard Templates"}),"\n",(0,a.jsx)(i.p,{children:"During our tech talks, demos and user talks, we have received inquiries about what metrics care about. We plan to release templates for our dashboards so our community would look at a similar picture."}),"\n",(0,a.jsx)(i.h3,{id:"client-v2-modernization",children:"Client V2 Modernization"}),"\n",(0,a.jsx)(i.p,{children:"As we announced last year that we plan to make breaking changes to significantly improve our interfaces, we are working on modernizing our client interface."}),"\n",(0,a.jsx)(i.h3,{id:"higher-parallelization-and-prioritization-in-task-processing",children:"Higher Parallelization and Prioritization in Task Processing"}),"\n",(0,a.jsx)(i.p,{children:"In an effort to have better domain prioritization in multitenant Cadence clusters, we are improving our task processing with higher parallelization and better prioritization. This is a lot better model than just having domains with defined limits. We expect to provide more resources to high priority domains during their peak hours while allowing low priority domains to consume much bigger resources than allocated during quiet times."}),"\n",(0,a.jsx)(i.h3,{id:"timer-and-cron-burst-handling",children:"Timer and Cron Burst Handling"}),"\n",(0,a.jsx)(i.p,{children:"After addressing start and signal burst scenarios, we are continuing with bursty timers and cron jobs. Many users set their schedules and timers for the same second with the intention of being able to finish N jobs within a certain amount of time. Current scheduling design isn\u2019t friendly for such intents and high loads can cause temporary starvation in the cluster. By introducing better batch scheduling support, clusters can continue with no disruption while timers are processed in the most efficient way."}),"\n",(0,a.jsx)(i.h3,{id:"high-zonal-skew-handling",children:"High zonal skew handling"}),"\n",(0,a.jsx)(i.p,{children:"For users operating in their own cloud and having multiple independent zones in every region, zonal skews can be a problem and can create unnecessary bottlenecks when Zonal Isolation feature is enabled. We are working on addressing such issues to improve task matching across zones when skew is detected."}),"\n",(0,a.jsx)(i.h3,{id:"tasklist-improvements",children:"Tasklist Improvements"}),"\n",(0,a.jsx)(i.p,{children:"When a user scenario grows, there are many knobs that need to be manually adjusted. We would like to automatically partition and smartly forward tasks to improve tasklist efficiency significantly to avoid backlogs, timeouts and hot shards."}),"\n",(0,a.jsx)(i.h3,{id:"shard-movementassignment-improvements",children:"Shard Movement/Assignment Improvements"}),"\n",(0,a.jsx)(i.p,{children:"Cadence shard movements are based on consistent hash and this can be a limiting factor for many different reasons. Certain hosts can end up getting unlucky by having many shards, or having heavy shards. During deployments we might observe a much higher number of shard movements than desired, which reduces the availability. With improved shard movements and assignments we can have more homogenous load among hosts while also having a minimum amount of shard movements during deployments with much better availability."}),"\n",(0,a.jsx)(i.h3,{id:"worker-heartbeats",children:"Worker Heartbeats"}),"\n",(0,a.jsx)(i.p,{children:"Today, there\u2019s no worker liveliness tracking in Cadence. Instead, task or activity heartbeat timeouts are used to reassign tasks to different workers. For latency sensitive users this can become a big disruption. For long activities without heartbeats, this can cause big delays. This feature is to eliminate depending on manual timeout or heartbeat configs to reassign tasks by tracking if workers are still healthy. This feature will also enable so many other new efficiency and reliability features we would like to get to in the future."}),"\n",(0,a.jsx)(i.h3,{id:"domain-and-workflow-diagnostics",children:"Domain and Workflow Diagnostics"}),"\n",(0,a.jsx)(i.p,{children:"Probably the two most common user questions are \u201cWhat\u2019s wrong with my domain?\u201d and \u201cWhat\u2019s wrong with my workflow?\u201d. Today, diagnosing what happened and what could be wrong isn\u2019t that easy apart from some basic cases. We are working on tools that would run diagnostics on workflows and domains to point out things that might potentially be wrong with public runbook links attached. This feature will not only help diagnose what is wrong with our workflows and domains but will also help fix them."}),"\n",(0,a.jsx)(i.h3,{id:"self-serve-operations",children:"Self Serve Operations"}),"\n",(0,a.jsx)(i.p,{children:"Certain Cadence operations are performed through admin CLI operations. However, these should be able to be done via Cadence UI by users. Admins shouldn\u2019t need to be involved in every step or the checks they validate should be able to be automated. This is what the initiative is about including domain registration, auth/authz onboarding or adding new search attributes but it\u2019s not limited to these operations."}),"\n",(0,a.jsx)(i.h3,{id:"cost-estimation",children:"Cost Estimation"}),"\n",(0,a.jsx)(i.p,{children:"One big question we receive when users are onboarding to Cadence is \u201cHow much will this cost me?\u201d. This is not an easy question to answer since data and traffic load can be quite different. We plan to automate this process to help users understand how much resources they will need. Especially in multi-tenant clusters, this will help users understand how much room they still have in their clusters and how much the new scenario will consume."}),"\n",(0,a.jsx)(i.h3,{id:"domain-reports-continue",children:"Domain Reports (continue)"}),"\n",(0,a.jsx)(i.p,{children:"We plan to release this internal feature to open source as soon as possible. On top of presenting this data on built-in Cadence surfaces (web, CLI. etc.) we will create APIs to make it integratable with deployment systems, user service UIs, periodic reports and any other service that would like to consume."}),"\n",(0,a.jsx)(i.h3,{id:"non-determinism-detection-improvements-continue",children:"Non-determinism Detection Improvements (continue)"}),"\n",(0,a.jsx)(i.p,{children:"We have seen great reliability improvements and reduction in incidents with this feature on the user side last year. We continue to invest in this feature and make it available in open source as soon as possible."}),"\n",(0,a.jsx)(i.h3,{id:"domain-migrations-continue",children:"Domain Migrations (continue)"}),"\n",(0,a.jsx)(i.p,{children:"In the next year, we plan to finish our seamless client based migration to be able to safely migrate domains from one cluster to another, one technology (even if it\u2019s not Cadence) to another and one cloud solution to another. There are only a few features left to achieve this."}),"\n",(0,a.jsx)(i.h2,{id:"community-1",children:"Community"}),"\n",(0,a.jsx)(i.p,{children:"Do you want to hear more about Cadence? Do you need help with your set-up or usage? Are you evaluating your options? Do you want to contribute? Feel free to join our community and reach out to us."}),"\n",(0,a.jsxs)(i.p,{children:["Slack: ",(0,a.jsx)(i.a,{href:"https://uber-cadence.slack.com/",children:"https://uber-cadence.slack.com/"})]}),"\n",(0,a.jsxs)(i.p,{children:["Github: ",(0,a.jsx)(i.a,{href:"https://github.com/cadence-workflow/cadence",children:"https://github.com/cadence-workflow/cadence"})]}),"\n",(0,a.jsx)(i.p,{children:"Since last year, we have been contacted by various companies to take on bigger projects on the Cadence project. As we have been investing in code coverage and refactoring Cadence for a cleaner codebase, this will be a lot easier now. Let us know if you have project ideas to contribute or if you\u2019d like to pick something we already planned."}),"\n",(0,a.jsx)(i.p,{children:"Our monthly community meetings are still ongoing, too. That is the best place to get heard and be involved in our decision-making process. Let us know so we can send you an invite. We are also working on a broader governing model to open up this project to more people. Stay tuned for updates on this topic!"})]})}function h(e={}){const{wrapper:i}={...(0,o.R)(),...e.components};return i?(0,a.jsx)(i,{...e,children:(0,a.jsx)(c,{...e})}):c(e)}},9160:(e,i,n)=>{n.d(i,{A:()=>t});const t=n.p+"assets/images/cadence-benefits-2bab00edd6033ae128d39367af8ed72a.png"},5177:(e,i,n)=>{n.d(i,{A:()=>t});const t=n.p+"assets/images/workflow-84ef76d93c7ff138714a0aa7c9b92841.png"},8453:(e,i,n)=>{n.d(i,{R:()=>s,x:()=>r});var t=n(6540);const a={},o=t.createContext(a);function s(e){const i=t.useContext(o);return t.useMemo((function(){return"function"==typeof e?e(i):{...i,...e}}),[i,e])}function r(e){let i;return i=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:s(e.components),t.createElement(o.Provider,{value:i},e.children)}},4568:e=>{e.exports=JSON.parse('{"permalink":"/Cadence-Docs/blog/2024/07/11/2024-07-11-yearly-roadmap-update/yearly-roadmap-update","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2024-07-11-yearly-roadmap-update/2024-07-11-yearly-roadmap-update.md","source":"@site/blog/2024-07-11-yearly-roadmap-update/2024-07-11-yearly-roadmap-update.md","title":"2024 Cadence Yearly Roadmap Update","description":"Introduction","date":"2024-07-11T00:00:00.000Z","tags":[{"inline":false,"label":"Roadmap","permalink":"/Cadence-Docs/blog/tags/roadmap","description":"Roadmap tag description"},{"inline":false,"label":"Deep Dives","permalink":"/Cadence-Docs/blog/tags/deep-dives","description":"Deep Dives tag description"}],"readingTime":16.31,"hasTruncateMarker":true,"authors":[{"name":"Ender Demirkaya","title":"Senior Manager at Uber, Cadence. Author of the Software Engineering Handbook","url":"https://www.linkedin.com/in/enderdemirkaya/","page":{"permalink":"/Cadence-Docs/blog/authors/enderdemirkaya"},"socials":{"linkedin":"https://www.linkedin.com/in/enderdemirkaya/","github":"https://github.com/demirkayaender"},"imageURL":"https://github.com/demirkayaender.png","key":"enderdemirkaya"}],"frontMatter":{"title":"2024 Cadence Yearly Roadmap Update","date":"2024-07-11T00:00:00.000Z","authors":"enderdemirkaya","tags":["roadmap","deep-dive"]},"unlisted":false,"prevItem":{"title":"Minimizing blast radius in Cadence: Introducing Workflow ID-based Rate Limits","permalink":"/Cadence-Docs/blog/2024/09/05/workflow-specific-rate-limits"},"nextItem":{"title":"Cadence non-derministic errors common question Q&A (part 1)","permalink":"/Cadence-Docs/blog/2024/02/15/cadence-non-deterministic-common-qa"}}')}}]); \ No newline at end of file diff --git a/assets/js/c4da92db.1142d0ee.js b/assets/js/c4da92db.1142d0ee.js deleted file mode 100644 index b527ee7d1..000000000 --- a/assets/js/c4da92db.1142d0ee.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[1700],{8863:(e,t,a)=>{a.r(t),a.d(t,{assets:()=>o,contentTitle:()=>r,default:()=>d,frontMatter:()=>i,metadata:()=>n,toc:()=>l});const n=JSON.parse('{"id":"use-cases/interactive","title":"Interactive application","description":"Cadence is performant and scalable enough to support interactive applications. It can be used to track UI session state and","source":"@site/docs/02-use-cases/10-interactive.md","sourceDirName":"02-use-cases","slug":"/use-cases/interactive","permalink":"/docs/use-cases/interactive","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/02-use-cases/10-interactive.md","tags":[],"version":"current","sidebarPosition":10,"frontMatter":{"layout":"default","title":"Interactive application","permalink":"/docs/use-cases/interactive"},"sidebar":"docsSidebar","previous":{"title":"Operational management","permalink":"/docs/use-cases/operational-management"},"next":{"title":"DSL workflows","permalink":"/docs/use-cases/dsl"}}');var s=a(4848),c=a(8453);const i={layout:"default",title:"Interactive application",permalink:"/docs/use-cases/interactive"},r="Interactive application",o={},l=[];function u(e){const t={h1:"h1",header:"header",p:"p",...(0,c.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(t.header,{children:(0,s.jsx)(t.h1,{id:"interactive-application",children:"Interactive application"})}),"\n",(0,s.jsx)(t.p,{children:"Cadence is performant and scalable enough to support interactive applications. It can be used to track UI session state and\nat the same time execute background operations. For example, while placing an order a customer might need to go through several screens while a background task evaluates the customer for fraudulent activity."})]})}function d(e={}){const{wrapper:t}={...(0,c.R)(),...e.components};return t?(0,s.jsx)(t,{...e,children:(0,s.jsx)(u,{...e})}):u(e)}},8453:(e,t,a)=>{a.d(t,{R:()=>i,x:()=>r});var n=a(6540);const s={},c=n.createContext(s);function i(e){const t=n.useContext(c);return n.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function r(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:i(e.components),n.createElement(c.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/c4da92db.9beb5e3e.js b/assets/js/c4da92db.9beb5e3e.js new file mode 100644 index 000000000..273ebeb8f --- /dev/null +++ b/assets/js/c4da92db.9beb5e3e.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[1700],{8863:(e,t,a)=>{a.r(t),a.d(t,{assets:()=>r,contentTitle:()=>o,default:()=>u,frontMatter:()=>i,metadata:()=>n,toc:()=>d});const n=JSON.parse('{"id":"use-cases/interactive","title":"Interactive application","description":"Cadence is performant and scalable enough to support interactive applications. It can be used to track UI session state and","source":"@site/docs/02-use-cases/10-interactive.md","sourceDirName":"02-use-cases","slug":"/use-cases/interactive","permalink":"/Cadence-Docs/docs/use-cases/interactive","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/02-use-cases/10-interactive.md","tags":[],"version":"current","sidebarPosition":10,"frontMatter":{"layout":"default","title":"Interactive application","permalink":"/docs/use-cases/interactive"},"sidebar":"docsSidebar","previous":{"title":"Operational management","permalink":"/Cadence-Docs/docs/use-cases/operational-management"},"next":{"title":"DSL workflows","permalink":"/Cadence-Docs/docs/use-cases/dsl"}}');var s=a(4848),c=a(8453);const i={layout:"default",title:"Interactive application",permalink:"/docs/use-cases/interactive"},o="Interactive application",r={},d=[];function l(e){const t={h1:"h1",header:"header",p:"p",...(0,c.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(t.header,{children:(0,s.jsx)(t.h1,{id:"interactive-application",children:"Interactive application"})}),"\n",(0,s.jsx)(t.p,{children:"Cadence is performant and scalable enough to support interactive applications. It can be used to track UI session state and\nat the same time execute background operations. For example, while placing an order a customer might need to go through several screens while a background task evaluates the customer for fraudulent activity."})]})}function u(e={}){const{wrapper:t}={...(0,c.R)(),...e.components};return t?(0,s.jsx)(t,{...e,children:(0,s.jsx)(l,{...e})}):l(e)}},8453:(e,t,a)=>{a.d(t,{R:()=>i,x:()=>o});var n=a(6540);const s={},c=n.createContext(s);function i(e){const t=n.useContext(c);return n.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function o(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:i(e.components),n.createElement(c.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/c5abbc6d.4ee0aba8.js b/assets/js/c5abbc6d.4ee0aba8.js new file mode 100644 index 000000000..345ac082b --- /dev/null +++ b/assets/js/c5abbc6d.4ee0aba8.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[1337],{9976:(e,s,n)=>{n.r(s),n.d(s,{assets:()=>c,contentTitle:()=>a,default:()=>h,frontMatter:()=>r,metadata:()=>t,toc:()=>l});const t=JSON.parse('{"id":"go-client/sessions","title":"Sessions","description":"The session framework provides a straightforward interface for scheduling multipleactivitiesworkertask_list: name. It also includes features like concurrent session limitation and worker failure detection.","source":"@site/docs/05-go-client/15-sessions.md","sourceDirName":"05-go-client","slug":"/go-client/sessions","permalink":"/Cadence-Docs/docs/go-client/sessions","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/05-go-client/15-sessions.md","tags":[],"version":"current","sidebarPosition":15,"frontMatter":{"layout":"default","title":"Sessions","permalink":"/docs/go-client/sessions"},"sidebar":"docsSidebar","previous":{"title":"Versioning","permalink":"/Cadence-Docs/docs/go-client/workflow-versioning"},"next":{"title":"Distributed CRON","permalink":"/Cadence-Docs/docs/go-client/distributed-cron"}}');var o=n(4848),i=n(8453);const r={layout:"default",title:"Sessions",permalink:"/docs/go-client/sessions"},a="Sessions",c={},l=[{value:"Use Cases",id:"use-cases",level:2},{value:"Basic Usage",id:"basic-usage",level:2},{value:"Sample Code",id:"sample-code",level:3},{value:"Session Metadata",id:"session-metadata",level:2},{value:"Concurrent Session Limitation",id:"concurrent-session-limitation",level:2},{value:"Recreate Session",id:"recreate-session",level:2},{value:"Q & A",id:"q--a",level:2},{value:"Is there a complete example?",id:"is-there-a-complete-example",level:3},{value:"What happens to my activity if the worker dies?",id:"what-happens-to-my-activity-if-the-worker-dies",level:3},{value:"Is the concurrent session limitation per process or per host?",id:"is-the-concurrent-session-limitation-per-process-or-per-host",level:3},{value:"Future Work",id:"future-work",level:2}];function d(e){const s={a:"a",code:"code",h1:"h1",h2:"h2",h3:"h3",header:"header",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,i.R)(),...e.components};return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsx)(s.header,{children:(0,o.jsx)(s.h1,{id:"sessions",children:"Sessions"})}),"\n",(0,o.jsxs)(s.p,{children:["The session framework provides a straightforward interface for scheduling multiple activities on a single worker without requiring you to manually specify the task_list name. It also includes features like ",(0,o.jsx)(s.strong,{children:"concurrent session limitation"})," and ",(0,o.jsx)(s.strong,{children:"worker failure detection"}),"."]}),"\n",(0,o.jsx)(s.h2,{id:"use-cases",children:"Use Cases"}),"\n",(0,o.jsxs)(s.ul,{children:["\n",(0,o.jsxs)(s.li,{children:["\n",(0,o.jsxs)(s.p,{children:[(0,o.jsx)(s.strong,{children:"File Processing"}),": You may want to implement a workflow that can download a file, process it, and then upload the modified version. If these three steps are implemented as three different activities, all of them should be executed by the same worker."]}),"\n"]}),"\n",(0,o.jsxs)(s.li,{children:["\n",(0,o.jsxs)(s.p,{children:[(0,o.jsx)(s.strong,{children:"Machine Learning Model Training"}),": Training a machine learning model typically involves three stages: download the data set, optimize the model, and upload the trained parameter. Since the models may consume a large amount of resources (GPU memory for example), the number of models processed on a host needs to be limited."]}),"\n"]}),"\n"]}),"\n",(0,o.jsx)(s.h2,{id:"basic-usage",children:"Basic Usage"}),"\n",(0,o.jsxs)(s.p,{children:["Before using the session framework to write your workflow code, you need to configure your worker to process sessions. To do that, set the ",(0,o.jsx)(s.code,{children:"EnableSessionWorker"})," field of ",(0,o.jsx)(s.code,{children:"worker.Options"})," to ",(0,o.jsx)(s.code,{children:"true"})," when starting your worker."]}),"\n",(0,o.jsxs)(s.p,{children:["The most important APIs provided by the session framework are ",(0,o.jsx)(s.code,{children:"workflow.CreateSession()"})," and ",(0,o.jsx)(s.code,{children:"workflow.CompleteSession()"}),". The basic idea is that all the activities executed within a session will be processed by the same worker and these two APIs allow you to create new sessions and close them after all activities finish executing."]}),"\n",(0,o.jsx)(s.p,{children:"Here's a more detailed description of these two APIs:"}),"\n",(0,o.jsx)(s.pre,{children:(0,o.jsx)(s.code,{className:"language-go",children:"type SessionOptions struct {\n // ExecutionTimeout: required, no default.\n // Specifies the maximum amount of time the session can run.\n ExecutionTimeout time.Duration\n\n // CreationTimeout: required, no default.\n // Specifies how long session creation can take before returning an error.\n CreationTimeout time.Duration\n}\n\nfunc CreateSession(ctx Context, sessionOptions *SessionOptions) (Context, error)\n"})}),"\n",(0,o.jsxs)(s.p,{children:[(0,o.jsx)(s.code,{children:"CreateSession()"})," takes in ",(0,o.jsx)(s.code,{children:"workflow.Context"}),", ",(0,o.jsx)(s.code,{children:"sessionOptions"})," and returns a new context which contains metadata information of the created session (referred to as the ",(0,o.jsx)(s.strong,{children:"session context"})," below). When it's called, it will check the task_list name specified in the ",(0,o.jsx)(s.code,{children:"ActivityOptions"})," (or in the ",(0,o.jsx)(s.code,{children:"StartWorkflowOptions"})," if the task_list name is not specified in ",(0,o.jsx)(s.code,{children:"ActivityOptions"}),"), and create the session on one of the workers which is polling that task_list."]}),"\n",(0,o.jsxs)(s.p,{children:["The returned session context should be used to execute all activities belonging to the session. The context will be cancelled if the worker executing this session dies or ",(0,o.jsx)(s.code,{children:"CompleteSession()"})," is called. When using the returned session context to execute activities, a ",(0,o.jsx)(s.code,{children:"workflow.ErrSessionFailed"})," error may be returned if the session framework detects that the worker executing this session has died. The failure of your activities won't affect the state of the session, so you still need to handle the errors returned from your activities and call ",(0,o.jsx)(s.code,{children:"CompleteSession()"})," if necessary."]}),"\n",(0,o.jsxs)(s.p,{children:[(0,o.jsx)(s.code,{children:"CreateSession()"})," will return an error if the context passed in already contains an open session. If all the workers are currently busy and unable to handle new sessions, the framework will keep retrying until the ",(0,o.jsx)(s.code,{children:"CreationTimeout"})," you specified in ",(0,o.jsx)(s.code,{children:"SessionOptions"})," has passed before returning an error (check the ",(0,o.jsx)(s.strong,{children:"Concurrent Session Limitation"})," section for more details)."]}),"\n",(0,o.jsx)(s.pre,{children:(0,o.jsx)(s.code,{className:"language-go",children:"func CompleteSession(ctx Context)\n"})}),"\n",(0,o.jsxs)(s.p,{children:[(0,o.jsx)(s.code,{children:"CompleteSession()"})," releases the resources reserved on the worker, so it's important to call it as soon as you no longer need the session. It will cancel the session context and therefore all the activities using that session context. Note that it's safe to call ",(0,o.jsx)(s.code,{children:"CompleteSession()"})," on a failed session, meaning that you can call it from a ",(0,o.jsx)(s.code,{children:"defer"})," function after the session is successfully created."]}),"\n",(0,o.jsx)(s.h3,{id:"sample-code",children:"Sample Code"}),"\n",(0,o.jsx)(s.pre,{children:(0,o.jsx)(s.code,{className:"language-go",children:"func FileProcessingWorkflow(ctx workflow.Context, fileID string) (err error) {\n ao := workflow.ActivityOptions{\n ScheduleToStartTimeout: time.Second * 5,\n StartToCloseTimeout: time.Minute,\n }\n ctx = workflow.WithActivityOptions(ctx, ao)\n\n so := &workflow.SessionOptions{\n CreationTimeout: time.Minute,\n ExecutionTimeout: time.Minute,\n }\n sessionCtx, err := workflow.CreateSession(ctx, so)\n if err != nil {\n return err\n }\n defer workflow.CompleteSession(sessionCtx)\n\n var fInfo *fileInfo\n err = workflow.ExecuteActivity(sessionCtx, downloadFileActivityName, fileID).Get(sessionCtx, &fInfo)\n if err != nil {\n return err\n }\n\n var fInfoProcessed *fileInfo\n err = workflow.ExecuteActivity(sessionCtx, processFileActivityName, *fInfo).Get(sessionCtx, &fInfoProcessed)\n if err != nil {\n return err\n }\n\n return workflow.ExecuteActivity(sessionCtx, uploadFileActivityName, *fInfoProcessed).Get(sessionCtx, nil)\n}\n"})}),"\n",(0,o.jsx)(s.h2,{id:"session-metadata",children:"Session Metadata"}),"\n",(0,o.jsx)(s.pre,{children:(0,o.jsx)(s.code,{className:"language-go",children:"type SessionInfo struct {\n // A unique ID for the session\n SessionID string\n\n // The hostname of the worker that is executing the session\n HostName string\n\n // ... other unexported fields\n}\n\nfunc GetSessionInfo(ctx Context) *SessionInfo\n"})}),"\n",(0,o.jsxs)(s.p,{children:["The session context also stores some session metadata, which can be retrieved by the ",(0,o.jsx)(s.code,{children:"GetSessionInfo()"})," API. If the context passed in doesn't contain any session metadata, this API will return a ",(0,o.jsx)(s.code,{children:"nil"})," pointer."]}),"\n",(0,o.jsx)(s.h2,{id:"concurrent-session-limitation",children:"Concurrent Session Limitation"}),"\n",(0,o.jsxs)(s.p,{children:["To limit the number of concurrent sessions running on a worker, set the ",(0,o.jsx)(s.code,{children:"MaxConcurrentSessionExecutionSize"})," field of ",(0,o.jsx)(s.code,{children:"worker.Options"})," to the desired value. By default this field is set to a very large value, so there's no need to manually set it if no limitation is needed."]}),"\n",(0,o.jsxs)(s.p,{children:["If a worker hits this limitation, it won't accept any new ",(0,o.jsx)(s.code,{children:"CreateSession()"})," requests until one of the existing sessions is completed. ",(0,o.jsx)(s.code,{children:"CreateSession()"})," will return an error if the session can't be created within ",(0,o.jsx)(s.code,{children:"CreationTimeout"}),"."]}),"\n",(0,o.jsx)(s.h2,{id:"recreate-session",children:"Recreate Session"}),"\n",(0,o.jsxs)(s.p,{children:["For long-running sessions, you may want to use the ",(0,o.jsx)(s.code,{children:"ContinueAsNew"})," feature to split the workflow into multiple runs when all activities need to be executed by the same worker. The ",(0,o.jsx)(s.code,{children:"RecreateSession()"})," API is designed for such a use case."]}),"\n",(0,o.jsx)(s.pre,{children:(0,o.jsx)(s.code,{className:"language-go",children:"func RecreateSession(ctx Context, recreateToken []byte, sessionOptions *SessionOptions) (Context, error)\n"})}),"\n",(0,o.jsxs)(s.p,{children:["Its usage is the same as ",(0,o.jsx)(s.code,{children:"CreateSession()"})," except that it also takes in a ",(0,o.jsx)(s.code,{children:"recreateToken"}),", which is needed to create a new session on the same worker as the previous one. You can get the token by calling the ",(0,o.jsx)(s.code,{children:"GetRecreateToken()"})," method of the ",(0,o.jsx)(s.code,{children:"SessionInfo"})," object."]}),"\n",(0,o.jsx)(s.pre,{children:(0,o.jsx)(s.code,{className:"language-go",children:"token := workflow.GetSessionInfo(sessionCtx).GetRecreateToken()\n"})}),"\n",(0,o.jsx)(s.h2,{id:"q--a",children:"Q & A"}),"\n",(0,o.jsx)(s.h3,{id:"is-there-a-complete-example",children:"Is there a complete example?"}),"\n",(0,o.jsxs)(s.p,{children:["Yes, the ",(0,o.jsx)(s.a,{href:"https://github.com/cadence-workflow/cadence-samples/blob/master/cmd/samples/fileprocessing/workflow.go",children:"file processing example"})," in the cadence-sample repo has been updated to use the session framework."]}),"\n",(0,o.jsx)(s.h3,{id:"what-happens-to-my-activity-if-the-worker-dies",children:"What happens to my activity if the worker dies?"}),"\n",(0,o.jsxs)(s.p,{children:["If your activity has already been scheduled, it will be cancelled. If not, you will get a ",(0,o.jsx)(s.code,{children:"workflow.ErrSessionFailed"})," error when you call ",(0,o.jsx)(s.code,{children:"workflow.ExecuteActivity()"}),"."]}),"\n",(0,o.jsx)(s.h3,{id:"is-the-concurrent-session-limitation-per-process-or-per-host",children:"Is the concurrent session limitation per process or per host?"}),"\n",(0,o.jsx)(s.p,{children:"It's per worker process, so make sure there's only one worker process running on the host if you plan to use that feature."}),"\n",(0,o.jsx)(s.h2,{id:"future-work",children:"Future Work"}),"\n",(0,o.jsxs)(s.ul,{children:["\n",(0,o.jsxs)(s.li,{children:["\n",(0,o.jsxs)(s.p,{children:[(0,o.jsx)(s.strong,{children:(0,o.jsx)(s.a,{href:"https://github.com/cadence-workflow/cadence-go-client/issues/775",children:"Support automatic session re-establishing"})}),"\nRight now a session is considered failed if the worker process dies. However, for some use cases, you may only care whether worker host is alive or not. For these uses cases, the session should be automatically re-established if the worker process is restarted."]}),"\n"]}),"\n",(0,o.jsxs)(s.li,{children:["\n",(0,o.jsxs)(s.p,{children:[(0,o.jsx)(s.strong,{children:(0,o.jsx)(s.a,{href:"https://github.com/cadence-workflow/cadence-go-client/issues/776",children:"Support fine-grained concurrent session limitation"})}),"\nThe current implementation assumes that all sessions are consuming the same type of resource and there's only one global limitation. Our plan is to allow you to specify what type of resource your session will consume and enforce different limitations on different types of resources."]}),"\n"]}),"\n"]})]})}function h(e={}){const{wrapper:s}={...(0,i.R)(),...e.components};return s?(0,o.jsx)(s,{...e,children:(0,o.jsx)(d,{...e})}):d(e)}},8453:(e,s,n)=>{n.d(s,{R:()=>r,x:()=>a});var t=n(6540);const o={},i=t.createContext(o);function r(e){const s=t.useContext(i);return t.useMemo((function(){return"function"==typeof e?e(s):{...s,...e}}),[s,e])}function a(e){let s;return s=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:r(e.components),t.createElement(i.Provider,{value:s},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/c5abbc6d.d0022e8b.js b/assets/js/c5abbc6d.d0022e8b.js deleted file mode 100644 index d243491e2..000000000 --- a/assets/js/c5abbc6d.d0022e8b.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[1337],{9976:(e,s,n)=>{n.r(s),n.d(s,{assets:()=>c,contentTitle:()=>a,default:()=>h,frontMatter:()=>r,metadata:()=>t,toc:()=>l});const t=JSON.parse('{"id":"go-client/sessions","title":"Sessions","description":"The session framework provides a straightforward interface for scheduling multipleactivitiesworkertask_list: name. It also includes features like concurrent session limitation and worker failure detection.","source":"@site/docs/05-go-client/15-sessions.md","sourceDirName":"05-go-client","slug":"/go-client/sessions","permalink":"/docs/go-client/sessions","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/05-go-client/15-sessions.md","tags":[],"version":"current","sidebarPosition":15,"frontMatter":{"layout":"default","title":"Sessions","permalink":"/docs/go-client/sessions"},"sidebar":"docsSidebar","previous":{"title":"Versioning","permalink":"/docs/go-client/workflow-versioning"},"next":{"title":"Distributed CRON","permalink":"/docs/go-client/distributed-cron"}}');var o=n(4848),i=n(8453);const r={layout:"default",title:"Sessions",permalink:"/docs/go-client/sessions"},a="Sessions",c={},l=[{value:"Use Cases",id:"use-cases",level:2},{value:"Basic Usage",id:"basic-usage",level:2},{value:"Sample Code",id:"sample-code",level:3},{value:"Session Metadata",id:"session-metadata",level:2},{value:"Concurrent Session Limitation",id:"concurrent-session-limitation",level:2},{value:"Recreate Session",id:"recreate-session",level:2},{value:"Q & A",id:"q--a",level:2},{value:"Is there a complete example?",id:"is-there-a-complete-example",level:3},{value:"What happens to my activity if the worker dies?",id:"what-happens-to-my-activity-if-the-worker-dies",level:3},{value:"Is the concurrent session limitation per process or per host?",id:"is-the-concurrent-session-limitation-per-process-or-per-host",level:3},{value:"Future Work",id:"future-work",level:2}];function d(e){const s={a:"a",code:"code",h1:"h1",h2:"h2",h3:"h3",header:"header",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,i.R)(),...e.components};return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsx)(s.header,{children:(0,o.jsx)(s.h1,{id:"sessions",children:"Sessions"})}),"\n",(0,o.jsxs)(s.p,{children:["The session framework provides a straightforward interface for scheduling multiple activities on a single worker without requiring you to manually specify the task_list name. It also includes features like ",(0,o.jsx)(s.strong,{children:"concurrent session limitation"})," and ",(0,o.jsx)(s.strong,{children:"worker failure detection"}),"."]}),"\n",(0,o.jsx)(s.h2,{id:"use-cases",children:"Use Cases"}),"\n",(0,o.jsxs)(s.ul,{children:["\n",(0,o.jsxs)(s.li,{children:["\n",(0,o.jsxs)(s.p,{children:[(0,o.jsx)(s.strong,{children:"File Processing"}),": You may want to implement a workflow that can download a file, process it, and then upload the modified version. If these three steps are implemented as three different activities, all of them should be executed by the same worker."]}),"\n"]}),"\n",(0,o.jsxs)(s.li,{children:["\n",(0,o.jsxs)(s.p,{children:[(0,o.jsx)(s.strong,{children:"Machine Learning Model Training"}),": Training a machine learning model typically involves three stages: download the data set, optimize the model, and upload the trained parameter. Since the models may consume a large amount of resources (GPU memory for example), the number of models processed on a host needs to be limited."]}),"\n"]}),"\n"]}),"\n",(0,o.jsx)(s.h2,{id:"basic-usage",children:"Basic Usage"}),"\n",(0,o.jsxs)(s.p,{children:["Before using the session framework to write your workflow code, you need to configure your worker to process sessions. To do that, set the ",(0,o.jsx)(s.code,{children:"EnableSessionWorker"})," field of ",(0,o.jsx)(s.code,{children:"worker.Options"})," to ",(0,o.jsx)(s.code,{children:"true"})," when starting your worker."]}),"\n",(0,o.jsxs)(s.p,{children:["The most important APIs provided by the session framework are ",(0,o.jsx)(s.code,{children:"workflow.CreateSession()"})," and ",(0,o.jsx)(s.code,{children:"workflow.CompleteSession()"}),". The basic idea is that all the activities executed within a session will be processed by the same worker and these two APIs allow you to create new sessions and close them after all activities finish executing."]}),"\n",(0,o.jsx)(s.p,{children:"Here's a more detailed description of these two APIs:"}),"\n",(0,o.jsx)(s.pre,{children:(0,o.jsx)(s.code,{className:"language-go",children:"type SessionOptions struct {\n // ExecutionTimeout: required, no default.\n // Specifies the maximum amount of time the session can run.\n ExecutionTimeout time.Duration\n\n // CreationTimeout: required, no default.\n // Specifies how long session creation can take before returning an error.\n CreationTimeout time.Duration\n}\n\nfunc CreateSession(ctx Context, sessionOptions *SessionOptions) (Context, error)\n"})}),"\n",(0,o.jsxs)(s.p,{children:[(0,o.jsx)(s.code,{children:"CreateSession()"})," takes in ",(0,o.jsx)(s.code,{children:"workflow.Context"}),", ",(0,o.jsx)(s.code,{children:"sessionOptions"})," and returns a new context which contains metadata information of the created session (referred to as the ",(0,o.jsx)(s.strong,{children:"session context"})," below). When it's called, it will check the task_list name specified in the ",(0,o.jsx)(s.code,{children:"ActivityOptions"})," (or in the ",(0,o.jsx)(s.code,{children:"StartWorkflowOptions"})," if the task_list name is not specified in ",(0,o.jsx)(s.code,{children:"ActivityOptions"}),"), and create the session on one of the workers which is polling that task_list."]}),"\n",(0,o.jsxs)(s.p,{children:["The returned session context should be used to execute all activities belonging to the session. The context will be cancelled if the worker executing this session dies or ",(0,o.jsx)(s.code,{children:"CompleteSession()"})," is called. When using the returned session context to execute activities, a ",(0,o.jsx)(s.code,{children:"workflow.ErrSessionFailed"})," error may be returned if the session framework detects that the worker executing this session has died. The failure of your activities won't affect the state of the session, so you still need to handle the errors returned from your activities and call ",(0,o.jsx)(s.code,{children:"CompleteSession()"})," if necessary."]}),"\n",(0,o.jsxs)(s.p,{children:[(0,o.jsx)(s.code,{children:"CreateSession()"})," will return an error if the context passed in already contains an open session. If all the workers are currently busy and unable to handle new sessions, the framework will keep retrying until the ",(0,o.jsx)(s.code,{children:"CreationTimeout"})," you specified in ",(0,o.jsx)(s.code,{children:"SessionOptions"})," has passed before returning an error (check the ",(0,o.jsx)(s.strong,{children:"Concurrent Session Limitation"})," section for more details)."]}),"\n",(0,o.jsx)(s.pre,{children:(0,o.jsx)(s.code,{className:"language-go",children:"func CompleteSession(ctx Context)\n"})}),"\n",(0,o.jsxs)(s.p,{children:[(0,o.jsx)(s.code,{children:"CompleteSession()"})," releases the resources reserved on the worker, so it's important to call it as soon as you no longer need the session. It will cancel the session context and therefore all the activities using that session context. Note that it's safe to call ",(0,o.jsx)(s.code,{children:"CompleteSession()"})," on a failed session, meaning that you can call it from a ",(0,o.jsx)(s.code,{children:"defer"})," function after the session is successfully created."]}),"\n",(0,o.jsx)(s.h3,{id:"sample-code",children:"Sample Code"}),"\n",(0,o.jsx)(s.pre,{children:(0,o.jsx)(s.code,{className:"language-go",children:"func FileProcessingWorkflow(ctx workflow.Context, fileID string) (err error) {\n ao := workflow.ActivityOptions{\n ScheduleToStartTimeout: time.Second * 5,\n StartToCloseTimeout: time.Minute,\n }\n ctx = workflow.WithActivityOptions(ctx, ao)\n\n so := &workflow.SessionOptions{\n CreationTimeout: time.Minute,\n ExecutionTimeout: time.Minute,\n }\n sessionCtx, err := workflow.CreateSession(ctx, so)\n if err != nil {\n return err\n }\n defer workflow.CompleteSession(sessionCtx)\n\n var fInfo *fileInfo\n err = workflow.ExecuteActivity(sessionCtx, downloadFileActivityName, fileID).Get(sessionCtx, &fInfo)\n if err != nil {\n return err\n }\n\n var fInfoProcessed *fileInfo\n err = workflow.ExecuteActivity(sessionCtx, processFileActivityName, *fInfo).Get(sessionCtx, &fInfoProcessed)\n if err != nil {\n return err\n }\n\n return workflow.ExecuteActivity(sessionCtx, uploadFileActivityName, *fInfoProcessed).Get(sessionCtx, nil)\n}\n"})}),"\n",(0,o.jsx)(s.h2,{id:"session-metadata",children:"Session Metadata"}),"\n",(0,o.jsx)(s.pre,{children:(0,o.jsx)(s.code,{className:"language-go",children:"type SessionInfo struct {\n // A unique ID for the session\n SessionID string\n\n // The hostname of the worker that is executing the session\n HostName string\n\n // ... other unexported fields\n}\n\nfunc GetSessionInfo(ctx Context) *SessionInfo\n"})}),"\n",(0,o.jsxs)(s.p,{children:["The session context also stores some session metadata, which can be retrieved by the ",(0,o.jsx)(s.code,{children:"GetSessionInfo()"})," API. If the context passed in doesn't contain any session metadata, this API will return a ",(0,o.jsx)(s.code,{children:"nil"})," pointer."]}),"\n",(0,o.jsx)(s.h2,{id:"concurrent-session-limitation",children:"Concurrent Session Limitation"}),"\n",(0,o.jsxs)(s.p,{children:["To limit the number of concurrent sessions running on a worker, set the ",(0,o.jsx)(s.code,{children:"MaxConcurrentSessionExecutionSize"})," field of ",(0,o.jsx)(s.code,{children:"worker.Options"})," to the desired value. By default this field is set to a very large value, so there's no need to manually set it if no limitation is needed."]}),"\n",(0,o.jsxs)(s.p,{children:["If a worker hits this limitation, it won't accept any new ",(0,o.jsx)(s.code,{children:"CreateSession()"})," requests until one of the existing sessions is completed. ",(0,o.jsx)(s.code,{children:"CreateSession()"})," will return an error if the session can't be created within ",(0,o.jsx)(s.code,{children:"CreationTimeout"}),"."]}),"\n",(0,o.jsx)(s.h2,{id:"recreate-session",children:"Recreate Session"}),"\n",(0,o.jsxs)(s.p,{children:["For long-running sessions, you may want to use the ",(0,o.jsx)(s.code,{children:"ContinueAsNew"})," feature to split the workflow into multiple runs when all activities need to be executed by the same worker. The ",(0,o.jsx)(s.code,{children:"RecreateSession()"})," API is designed for such a use case."]}),"\n",(0,o.jsx)(s.pre,{children:(0,o.jsx)(s.code,{className:"language-go",children:"func RecreateSession(ctx Context, recreateToken []byte, sessionOptions *SessionOptions) (Context, error)\n"})}),"\n",(0,o.jsxs)(s.p,{children:["Its usage is the same as ",(0,o.jsx)(s.code,{children:"CreateSession()"})," except that it also takes in a ",(0,o.jsx)(s.code,{children:"recreateToken"}),", which is needed to create a new session on the same worker as the previous one. You can get the token by calling the ",(0,o.jsx)(s.code,{children:"GetRecreateToken()"})," method of the ",(0,o.jsx)(s.code,{children:"SessionInfo"})," object."]}),"\n",(0,o.jsx)(s.pre,{children:(0,o.jsx)(s.code,{className:"language-go",children:"token := workflow.GetSessionInfo(sessionCtx).GetRecreateToken()\n"})}),"\n",(0,o.jsx)(s.h2,{id:"q--a",children:"Q & A"}),"\n",(0,o.jsx)(s.h3,{id:"is-there-a-complete-example",children:"Is there a complete example?"}),"\n",(0,o.jsxs)(s.p,{children:["Yes, the ",(0,o.jsx)(s.a,{href:"https://github.com/cadence-workflow/cadence-samples/blob/master/cmd/samples/fileprocessing/workflow.go",children:"file processing example"})," in the cadence-sample repo has been updated to use the session framework."]}),"\n",(0,o.jsx)(s.h3,{id:"what-happens-to-my-activity-if-the-worker-dies",children:"What happens to my activity if the worker dies?"}),"\n",(0,o.jsxs)(s.p,{children:["If your activity has already been scheduled, it will be cancelled. If not, you will get a ",(0,o.jsx)(s.code,{children:"workflow.ErrSessionFailed"})," error when you call ",(0,o.jsx)(s.code,{children:"workflow.ExecuteActivity()"}),"."]}),"\n",(0,o.jsx)(s.h3,{id:"is-the-concurrent-session-limitation-per-process-or-per-host",children:"Is the concurrent session limitation per process or per host?"}),"\n",(0,o.jsx)(s.p,{children:"It's per worker process, so make sure there's only one worker process running on the host if you plan to use that feature."}),"\n",(0,o.jsx)(s.h2,{id:"future-work",children:"Future Work"}),"\n",(0,o.jsxs)(s.ul,{children:["\n",(0,o.jsxs)(s.li,{children:["\n",(0,o.jsxs)(s.p,{children:[(0,o.jsx)(s.strong,{children:(0,o.jsx)(s.a,{href:"https://github.com/cadence-workflow/cadence-go-client/issues/775",children:"Support automatic session re-establishing"})}),"\nRight now a session is considered failed if the worker process dies. However, for some use cases, you may only care whether worker host is alive or not. For these uses cases, the session should be automatically re-established if the worker process is restarted."]}),"\n"]}),"\n",(0,o.jsxs)(s.li,{children:["\n",(0,o.jsxs)(s.p,{children:[(0,o.jsx)(s.strong,{children:(0,o.jsx)(s.a,{href:"https://github.com/cadence-workflow/cadence-go-client/issues/776",children:"Support fine-grained concurrent session limitation"})}),"\nThe current implementation assumes that all sessions are consuming the same type of resource and there's only one global limitation. Our plan is to allow you to specify what type of resource your session will consume and enforce different limitations on different types of resources."]}),"\n"]}),"\n"]})]})}function h(e={}){const{wrapper:s}={...(0,i.R)(),...e.components};return s?(0,o.jsx)(s,{...e,children:(0,o.jsx)(d,{...e})}):d(e)}},8453:(e,s,n)=>{n.d(s,{R:()=>r,x:()=>a});var t=n(6540);const o={},i=t.createContext(o);function r(e){const s=t.useContext(i);return t.useMemo((function(){return"function"==typeof e?e(s):{...s,...e}}),[s,e])}function a(e){let s;return s=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:r(e.components),t.createElement(i.Provider,{value:s},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/c74af710.8d0deb15.js b/assets/js/c74af710.8d0deb15.js new file mode 100644 index 000000000..42e2813b0 --- /dev/null +++ b/assets/js/c74af710.8d0deb15.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[2010],{4095:e=>{e.exports=JSON.parse('{"author":{"name":"Sharan Foga","title":"Director of Operations & Customer Success @ Encube Technologies","url":"https://www.linkedin.com/in/sfoga/","page":{"permalink":"/Cadence-Docs/blog/authors/sharanf"},"socials":{"linkedin":"https://www.linkedin.com/in/sfoga/","github":"https://github.com/sharanf"},"imageURL":"https://github.com/sharanf.png","key":"sharanf","count":19},"listMetadata":{"permalink":"/Cadence-Docs/blog/authors/sharanf/authors/2","page":2,"postsPerPage":10,"totalPages":2,"totalCount":19,"previousPage":"/Cadence-Docs/blog/authors/sharanf","blogDescription":"The latest news and updates from the Cadence team","blogTitle":"Cadence Blog"}}')}}]); \ No newline at end of file diff --git a/assets/js/c7e5f436.c393799e.js b/assets/js/c7e5f436.c393799e.js new file mode 100644 index 000000000..fa72633c9 --- /dev/null +++ b/assets/js/c7e5f436.c393799e.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[5078],{177:e=>{e.exports=JSON.parse('{"metadata":{"permalink":"/Cadence-Docs/blog/page/3","page":3,"postsPerPage":10,"totalPages":4,"totalCount":35,"previousPage":"/Cadence-Docs/blog/page/2","nextPage":"/Cadence-Docs/blog/page/4","blogDescription":"The latest news and updates from the Cadence team","blogTitle":"Cadence Blog"}}')}}]); \ No newline at end of file diff --git a/assets/js/cccd73f1.4d013750.js b/assets/js/cccd73f1.4d013750.js new file mode 100644 index 000000000..7fc2d41d4 --- /dev/null +++ b/assets/js/cccd73f1.4d013750.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[9513],{5441:(e,t,a)=>{a.r(t),a.d(t,{assets:()=>i,contentTitle:()=>c,default:()=>h,frontMatter:()=>o,metadata:()=>s,toc:()=>l});const s=JSON.parse('{"id":"get-started/index","title":"Overview","description":"A large number of use cases span beyond a single request-reply, require tracking of a complex state, respond to asynchronous events, and communicate to external unreliable dependencies.","source":"@site/docs/01-get-started/index.md","sourceDirName":"01-get-started","slug":"/get-started/","permalink":"/Cadence-Docs/docs/get-started/","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/01-get-started/index.md","tags":[],"version":"current","frontMatter":{"layout":"default","title":"Overview","description":"A large number of use cases span beyond a single request-reply, require tracking of a complex state, respond to asynchronous events, and communicate to external unreliable dependencies.","permalink":"/docs/get-started/"},"sidebar":"docsSidebar","next":{"title":"Server Installation","permalink":"/Cadence-Docs/docs/get-started/server-installation"}}');var n=a(4848),r=a(8453);const o={layout:"default",title:"Overview",description:"A large number of use cases span beyond a single request-reply, require tracking of a complex state, respond to asynchronous events, and communicate to external unreliable dependencies.",permalink:"/docs/get-started/"},c="Overview",i={},l=[{value:"What's Next",id:"whats-next",level:2}];function d(e){const t={a:"a",em:"em",h1:"h1",h2:"h2",header:"header",p:"p",...(0,r.R)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(t.header,{children:(0,n.jsx)(t.h1,{id:"overview",children:"Overview"})}),"\n",(0,n.jsx)(t.p,{children:"A large number of use cases span beyond a single request-reply, require tracking\nof a complex state, respond to asynchronous events, and communicate to external unreliable dependencies.\nThe usual approach to building such applications is a hodgepodge of stateless services,\ndatabases, cron jobs, and queuing systems. This negatively impacts the developer productivity as most of the code is\ndedicated to plumbing, obscuring the actual business logic behind a myriad of low-level details. Such systems frequently have availability problems as it is hard to keep all the components healthy."}),"\n",(0,n.jsxs)(t.p,{children:["The Cadence solution is a ",(0,n.jsxs)(t.a,{href:"/docs/concepts/workflows",children:[(0,n.jsx)(t.em,{children:"fault-oblivious stateful"})," programming model"]})," that obscures most of the complexities of building scalable distributed applications. In essence, Cadence provides a durable virtual memory that is not\nlinked to a specific process, and preserves the full application state, including function stacks, with local variables across all sorts of host and software failures.\nThis allows you to write code using the full power of a programming language while Cadence takes care of durability, availability, and scalability of the application."]}),"\n",(0,n.jsxs)(t.p,{children:["Cadence consists of a programming framework (or client library) and a managed service (or backend).\nThe framework enables developers to author and coordinate tasks in familiar languages\n(",(0,n.jsx)(t.a,{href:"https://github.com/cadence-workflow/cadence-go-client/",children:"Go"})," and ",(0,n.jsx)(t.a,{href:"https://github.com/cadence-workflow/cadence-java-client",children:"Java"}),"\nare supported officially, and ",(0,n.jsx)(t.a,{href:"https://github.com/firdaus/cadence-python",children:"Python"})," and\n",(0,n.jsx)(t.a,{href:"https://github.com/coinbase/cadence-ruby",children:"Ruby"})," by the community)."]}),"\n",(0,n.jsxs)(t.p,{children:["You can also use ",(0,n.jsx)(t.a,{href:"https://github.com/indeedeng/iwf",children:"iWF"})," as a DSL framework on top of Cadence."]}),"\n",(0,n.jsxs)(t.p,{children:["The Cadence backend service is stateless and relies on a persistent store. Currently, Cassandra and MySQL/Postgres storages\nare supported. An adapter to any other database that provides multi-row single shard transactions\ncan be added. There are different service deployment models. At Uber, our team operates multitenant clusters\nthat are shared by hundreds of applications. See service ",(0,n.jsx)(t.a,{href:"/docs/concepts/topology",children:"topology"})," to understand the overall architecture. The GitHub repo for the Cadence server is ",(0,n.jsx)(t.a,{href:"https://github.com/cadence-workflow/cadence",children:"cadence-workflow/cadence"}),". The docker\nimage for the Cadence server is available on Docker Hub at\n",(0,n.jsx)(t.a,{href:"https://hub.docker.com/r/ubercadence/server",children:"ubercadence/server"}),"."]}),"\n",(0,n.jsx)(t.h2,{id:"whats-next",children:"What's Next"}),"\n",(0,n.jsxs)(t.p,{children:["Let's try with some sample workflows.\nTo start with, go to ",(0,n.jsx)(t.a,{href:"/docs/get-started/server-installation",children:"server installation"})," to install cadence locally, and run a HelloWorld sample with ",(0,n.jsx)(t.a,{href:"/docs/get-started/java-hello-world",children:"Java"})," or ",(0,n.jsx)(t.a,{href:"/docs/get-started/golang-hello-world",children:"Golang"}),"."]}),"\n",(0,n.jsxs)(t.p,{children:["When you have any trouble with the instructions, you can watch the ",(0,n.jsx)(t.a,{href:"/docs/get-started/video-tutorials",children:"video tutorials"}),", and reach out to us on ",(0,n.jsx)(t.a,{href:"http://t.uber.com/cadence-slack",children:"Slack Channel"}),", or raise any question on ",(0,n.jsx)(t.a,{href:"https://stackoverflow.com/questions/tagged/cadence-workflow",children:"StackOverflow"})," or open an ",(0,n.jsx)(t.a,{href:"https://github.com/cadence-workflow/cadence/issues/new/choose",children:"Github issue"}),"."]})]})}function h(e={}){const{wrapper:t}={...(0,r.R)(),...e.components};return t?(0,n.jsx)(t,{...e,children:(0,n.jsx)(d,{...e})}):d(e)}},8453:(e,t,a)=>{a.d(t,{R:()=>o,x:()=>c});var s=a(6540);const n={},r=s.createContext(n);function o(e){const t=s.useContext(r);return s.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function c(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(n):e.components||n:o(e.components),s.createElement(r.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/cccd73f1.d85dafd4.js b/assets/js/cccd73f1.d85dafd4.js deleted file mode 100644 index 506dba4e6..000000000 --- a/assets/js/cccd73f1.d85dafd4.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[9513],{5441:(e,t,a)=>{a.r(t),a.d(t,{assets:()=>c,contentTitle:()=>i,default:()=>h,frontMatter:()=>o,metadata:()=>s,toc:()=>l});const s=JSON.parse('{"id":"get-started/index","title":"Overview","description":"A large number of use cases span beyond a single request-reply, require tracking of a complex state, respond to asynchronous events, and communicate to external unreliable dependencies.","source":"@site/docs/01-get-started/index.md","sourceDirName":"01-get-started","slug":"/get-started/","permalink":"/docs/get-started/","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/01-get-started/index.md","tags":[],"version":"current","frontMatter":{"layout":"default","title":"Overview","description":"A large number of use cases span beyond a single request-reply, require tracking of a complex state, respond to asynchronous events, and communicate to external unreliable dependencies.","permalink":"/docs/get-started/"},"sidebar":"docsSidebar","next":{"title":"Server Installation","permalink":"/docs/get-started/server-installation"}}');var n=a(4848),r=a(8453);const o={layout:"default",title:"Overview",description:"A large number of use cases span beyond a single request-reply, require tracking of a complex state, respond to asynchronous events, and communicate to external unreliable dependencies.",permalink:"/docs/get-started/"},i="Overview",c={},l=[{value:"What's Next",id:"whats-next",level:2}];function d(e){const t={a:"a",em:"em",h1:"h1",h2:"h2",header:"header",p:"p",...(0,r.R)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(t.header,{children:(0,n.jsx)(t.h1,{id:"overview",children:"Overview"})}),"\n",(0,n.jsx)(t.p,{children:"A large number of use cases span beyond a single request-reply, require tracking\nof a complex state, respond to asynchronous events, and communicate to external unreliable dependencies.\nThe usual approach to building such applications is a hodgepodge of stateless services,\ndatabases, cron jobs, and queuing systems. This negatively impacts the developer productivity as most of the code is\ndedicated to plumbing, obscuring the actual business logic behind a myriad of low-level details. Such systems frequently have availability problems as it is hard to keep all the components healthy."}),"\n",(0,n.jsxs)(t.p,{children:["The Cadence solution is a ",(0,n.jsxs)(t.a,{href:"/docs/concepts/workflows",children:[(0,n.jsx)(t.em,{children:"fault-oblivious stateful"})," programming model"]})," that obscures most of the complexities of building scalable distributed applications. In essence, Cadence provides a durable virtual memory that is not\nlinked to a specific process, and preserves the full application state, including function stacks, with local variables across all sorts of host and software failures.\nThis allows you to write code using the full power of a programming language while Cadence takes care of durability, availability, and scalability of the application."]}),"\n",(0,n.jsxs)(t.p,{children:["Cadence consists of a programming framework (or client library) and a managed service (or backend).\nThe framework enables developers to author and coordinate tasks in familiar languages\n(",(0,n.jsx)(t.a,{href:"https://github.com/cadence-workflow/cadence-go-client/",children:"Go"})," and ",(0,n.jsx)(t.a,{href:"https://github.com/cadence-workflow/cadence-java-client",children:"Java"}),"\nare supported officially, and ",(0,n.jsx)(t.a,{href:"https://github.com/firdaus/cadence-python",children:"Python"})," and\n",(0,n.jsx)(t.a,{href:"https://github.com/coinbase/cadence-ruby",children:"Ruby"})," by the community)."]}),"\n",(0,n.jsxs)(t.p,{children:["You can also use ",(0,n.jsx)(t.a,{href:"https://github.com/indeedeng/iwf",children:"iWF"})," as a DSL framework on top of Cadence."]}),"\n",(0,n.jsxs)(t.p,{children:["The Cadence backend service is stateless and relies on a persistent store. Currently, Cassandra and MySQL/Postgres storages\nare supported. An adapter to any other database that provides multi-row single shard transactions\ncan be added. There are different service deployment models. At Uber, our team operates multitenant clusters\nthat are shared by hundreds of applications. See service ",(0,n.jsx)(t.a,{href:"/docs/concepts/topology",children:"topology"})," to understand the overall architecture. The GitHub repo for the Cadence server is ",(0,n.jsx)(t.a,{href:"https://github.com/cadence-workflow/cadence",children:"cadence-workflow/cadence"}),". The docker\nimage for the Cadence server is available on Docker Hub at\n",(0,n.jsx)(t.a,{href:"https://hub.docker.com/r/ubercadence/server",children:"ubercadence/server"}),"."]}),"\n",(0,n.jsx)(t.h2,{id:"whats-next",children:"What's Next"}),"\n",(0,n.jsxs)(t.p,{children:["Let's try with some sample workflows.\nTo start with, go to ",(0,n.jsx)(t.a,{href:"/docs/get-started/server-installation",children:"server installation"})," to install cadence locally, and run a HelloWorld sample with ",(0,n.jsx)(t.a,{href:"/docs/get-started/java-hello-world",children:"Java"})," or ",(0,n.jsx)(t.a,{href:"/docs/get-started/golang-hello-world",children:"Golang"}),"."]}),"\n",(0,n.jsxs)(t.p,{children:["When you have any trouble with the instructions, you can watch the ",(0,n.jsx)(t.a,{href:"/docs/get-started/video-tutorials",children:"video tutorials"}),", and reach out to us on ",(0,n.jsx)(t.a,{href:"http://t.uber.com/cadence-slack",children:"Slack Channel"}),", or raise any question on ",(0,n.jsx)(t.a,{href:"https://stackoverflow.com/questions/tagged/cadence-workflow",children:"StackOverflow"})," or open an ",(0,n.jsx)(t.a,{href:"https://github.com/cadence-workflow/cadence/issues/new/choose",children:"Github issue"}),"."]})]})}function h(e={}){const{wrapper:t}={...(0,r.R)(),...e.components};return t?(0,n.jsx)(t,{...e,children:(0,n.jsx)(d,{...e})}):d(e)}},8453:(e,t,a)=>{a.d(t,{R:()=>o,x:()=>i});var s=a(6540);const n={},r=s.createContext(n);function o(e){const t=s.useContext(r);return s.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function i(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(n):e.components||n:o(e.components),s.createElement(r.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/cd7e9a8f.33b0f1d1.js b/assets/js/cd7e9a8f.33b0f1d1.js new file mode 100644 index 000000000..b593c038b --- /dev/null +++ b/assets/js/cd7e9a8f.33b0f1d1.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[7338],{3907:(e,n,s)=>{s.r(n),s.d(n,{assets:()=>a,contentTitle:()=>i,default:()=>h,frontMatter:()=>d,metadata:()=>l,toc:()=>t});const l=JSON.parse('{"id":"concepts/http-api","title":"HTTP API","description":"Introduction","source":"@site/docs/03-concepts/10-http-api.md","sourceDirName":"03-concepts","slug":"/concepts/http-api","permalink":"/Cadence-Docs/docs/concepts/http-api","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/03-concepts/10-http-api.md","tags":[],"version":"current","sidebarPosition":10,"frontMatter":{"layout":"default","title":"HTTP API","permalink":"/docs/concepts/http-api"},"sidebar":"docsSidebar","previous":{"title":"Search workflows(Advanced visibility)","permalink":"/Cadence-Docs/docs/concepts/search-workflows"},"next":{"title":"Introduction","permalink":"/Cadence-Docs/docs/java-client/"}}');var r=s(4848),c=s(8453);const d={layout:"default",title:"HTTP API",permalink:"/docs/concepts/http-api"},i="Using HTTP API",a={},t=[{value:"Introduction",id:"introduction",level:2},{value:"Setup",id:"setup",level:2},{value:"Updating Cadence configuration files",id:"updating-cadence-configuration-files",level:3},{value:"Using local binaries",id:"using-local-binaries",level:3},{value:"Using \u201cdocker run\u201d command",id:"using-docker-run-command",level:3},{value:"Using docker-compose",id:"using-docker-compose",level:3},{value:"Using HTTP API",id:"using-http-api-1",level:2},{value:"HTTP API Reference",id:"http-api-reference",level:2},{value:"Admin API",id:"admin-api",level:3},{value:"Add search attributes to whitelist",id:"add-search-attributes-to-whitelist",level:4},{value:"Headers",id:"headers",level:5},{value:"Example payload",id:"example-payload",level:5},{value:"Example cURL",id:"example-curl",level:5},{value:"Example successful response",id:"example-successful-response",level:5},{value:"Close a shard given a shard ID",id:"close-a-shard-given-a-shard-id",level:4},{value:"Headers",id:"headers-1",level:5},{value:"Example payload",id:"example-payload-1",level:5},{value:"Example cURL",id:"example-curl-1",level:5},{value:"Example successful response",id:"example-successful-response-1",level:5},{value:"Count DLQ messages",id:"count-dlq-messages",level:4},{value:"Headers",id:"headers-2",level:5},{value:"Example payload",id:"example-payload-2",level:5},{value:"Example cURL",id:"example-curl-2",level:5},{value:"Example successful response",id:"example-successful-response-2",level:5},{value:"Describe cluster information",id:"describe-cluster-information",level:4},{value:"Headers",id:"headers-3",level:5},{value:"Example payload",id:"example-payload-3",level:5},{value:"Example cURL",id:"example-curl-3",level:5},{value:"Example successful response",id:"example-successful-response-3",level:5},{value:"Describe internal information of history host",id:"describe-internal-information-of-history-host",level:4},{value:"Headers",id:"headers-4",level:5},{value:"Example payload",id:"example-payload-4",level:5},{value:"Example cURL",id:"example-curl-4",level:5},{value:"Example successful response",id:"example-successful-response-4",level:5},{value:"List shard distribution",id:"list-shard-distribution",level:4},{value:"Headers",id:"headers-5",level:5},{value:"Example payload",id:"example-payload-5",level:5},{value:"Example cURL",id:"example-curl-5",level:5},{value:"Example successful response",id:"example-successful-response-5",level:5},{value:"Describe internal information of workflow execution",id:"describe-internal-information-of-workflow-execution",level:4},{value:"Headers",id:"headers-6",level:5},{value:"Example payload",id:"example-payload-6",level:5},{value:"Example cURL",id:"example-curl-6",level:5},{value:"Example successful response",id:"example-successful-response-6",level:5},{value:"Domain API",id:"domain-api",level:3},{value:"Describe existing workflow domain",id:"describe-existing-workflow-domain",level:4},{value:"Headers",id:"headers-7",level:5},{value:"Example payload",id:"example-payload-7",level:5},{value:"Example cURL",id:"example-curl-7",level:5},{value:"Example successful response",id:"example-successful-response-7",level:5},{value:"List all domains in the cluster",id:"list-all-domains-in-the-cluster",level:4},{value:"Headers",id:"headers-8",level:5},{value:"Example payload",id:"example-payload-8",level:5},{value:"Example cURL",id:"example-curl-8",level:5},{value:"Example successful response",id:"example-successful-response-8",level:5},{value:"Meta API",id:"meta-api",level:3},{value:"Health check",id:"health-check",level:4},{value:"Headers",id:"headers-9",level:5},{value:"Example payload",id:"example-payload-9",level:5},{value:"Example cURL",id:"example-curl-9",level:5},{value:"Example successful response",id:"example-successful-response-9",level:5},{value:"Visibility API",id:"visibility-api",level:3},{value:"Get search attributes",id:"get-search-attributes",level:4},{value:"Headers",id:"headers-10",level:5},{value:"Example payload",id:"example-payload-10",level:5},{value:"Example cURL",id:"example-curl-10",level:5},{value:"Example successful response",id:"example-successful-response-10",level:5},{value:"List closed workflow executions in a domain",id:"list-closed-workflow-executions-in-a-domain",level:4},{value:"Headers",id:"headers-11",level:5},{value:"Example payloads",id:"example-payloads",level:5},{value:"Example cURL",id:"example-curl-11",level:5},{value:"Example successful response",id:"example-successful-response-11",level:5},{value:"List open workflow executions in a domain",id:"list-open-workflow-executions-in-a-domain",level:4},{value:"Headers",id:"headers-12",level:5},{value:"Example payloads",id:"example-payloads-1",level:5},{value:"Example cURL",id:"example-curl-12",level:5},{value:"Example successful response",id:"example-successful-response-12",level:5},{value:"Workflow API",id:"workflow-api",level:3},{value:"Describe pollers info of tasklist",id:"describe-pollers-info-of-tasklist",level:4},{value:"Headers",id:"headers-13",level:5},{value:"Example payload",id:"example-payload-11",level:5},{value:"Example cURL",id:"example-curl-13",level:5},{value:"Example successful response",id:"example-successful-response-13",level:5},{value:"Describe a workflow execution",id:"describe-a-workflow-execution",level:4},{value:"Headers",id:"headers-14",level:5},{value:"Example payload",id:"example-payload-12",level:5},{value:"Example cURL",id:"example-curl-14",level:5},{value:"Example successful response",id:"example-successful-response-14",level:5},{value:"Get supported client versions for the cluster",id:"get-supported-client-versions-for-the-cluster",level:4},{value:"Headers",id:"headers-15",level:5},{value:"Example payload",id:"example-payload-13",level:5},{value:"Example cURL",id:"example-curl-15",level:5},{value:"Example successful response",id:"example-successful-response-15",level:5},{value:"Get the task lists in a domain",id:"get-the-task-lists-in-a-domain",level:4},{value:"Headers",id:"headers-16",level:5},{value:"Example payload",id:"example-payload-14",level:5},{value:"Example cURL",id:"example-curl-16",level:5},{value:"Example successful response",id:"example-successful-response-16",level:5},{value:"Get the history of workflow executions",id:"get-the-history-of-workflow-executions",level:4},{value:"Headers",id:"headers-17",level:5},{value:"Example payload",id:"example-payload-15",level:5},{value:"Example cURL",id:"example-curl-17",level:5},{value:"Example successful response",id:"example-successful-response-17",level:5},{value:"List all the task list partitions and the hostname for partitions",id:"list-all-the-task-list-partitions-and-the-hostname-for-partitions",level:4},{value:"Headers",id:"headers-18",level:5},{value:"Example payload",id:"example-payload-16",level:5},{value:"Example cURL",id:"example-curl-18",level:5},{value:"Example successful response",id:"example-successful-response-18",level:5},{value:"Refresh all the tasks of a workflow",id:"refresh-all-the-tasks-of-a-workflow",level:4},{value:"Headers",id:"headers-19",level:5},{value:"Example payload",id:"example-payload-17",level:5},{value:"Example cURL",id:"example-curl-19",level:5},{value:"Example successful response",id:"example-successful-response-19",level:5},{value:"Cancel a workflow execution",id:"cancel-a-workflow-execution",level:4},{value:"Headers",id:"headers-20",level:5},{value:"Example payload",id:"example-payload-18",level:5},{value:"Example cURL",id:"example-curl-20",level:5},{value:"Example successful response",id:"example-successful-response-20",level:5},{value:"Restart a previous workflow execution",id:"restart-a-previous-workflow-execution",level:4},{value:"Headers",id:"headers-21",level:5},{value:"Example payload",id:"example-payload-19",level:5},{value:"Example cURL",id:"example-curl-21",level:5},{value:"Example successful response",id:"example-successful-response-21",level:5},{value:"Signal the current open workflow if exists, or attempt to start a new run based on IDResuePolicy and signals it",id:"signal-the-current-open-workflow-if-exists-or-attempt-to-start-a-new-run-based-on-idresuepolicy-and-signals-it",level:4},{value:"Headers",id:"headers-22",level:5},{value:"Example payload",id:"example-payload-20",level:5},{value:"Example cURL",id:"example-curl-22",level:5},{value:"Example successful response",id:"example-successful-response-22",level:5},{value:"Signal a workflow execution",id:"signal-a-workflow-execution",level:4},{value:"Headers",id:"headers-23",level:5},{value:"Example payload",id:"example-payload-21",level:5},{value:"Example cURL",id:"example-curl-23",level:5},{value:"Example successful response",id:"example-successful-response-23",level:5},{value:"Start a new workflow execution",id:"start-a-new-workflow-execution",level:4},{value:"Headers",id:"headers-24",level:5},{value:"Example payload",id:"example-payload-22",level:5},{value:"Example cURL",id:"example-curl-24",level:5},{value:"Example successful response",id:"example-successful-response-24",level:5},{value:"Terminate a new workflow execution",id:"terminate-a-new-workflow-execution",level:4},{value:"Headers",id:"headers-25",level:5},{value:"Example payloads",id:"example-payloads-2",level:5},{value:"Example cURL",id:"example-curl-25",level:5},{value:"Example successful response",id:"example-successful-response-25",level:5}];function o(e){const n={a:"a",code:"code",h1:"h1",h2:"h2",h3:"h3",h4:"h4",h5:"h5",header:"header",hr:"hr",p:"p",pre:"pre",strong:"strong",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",...(0,c.R)(),...e.components},{Details:s}=n;return s||function(e,n){throw new Error("Expected "+(n?"component":"object")+" `"+e+"` to be defined: you likely forgot to import, pass, or provide it.")}("Details",!0),(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(n.header,{children:(0,r.jsx)(n.h1,{id:"using-http-api",children:"Using HTTP API"})}),"\n",(0,r.jsx)(n.h2,{id:"introduction",children:"Introduction"}),"\n",(0,r.jsxs)(n.p,{children:["From ",(0,r.jsx)(n.strong,{children:"version 1.2.0"})," onwards, Cadence has introduced HTTP API support, which allows you to interact with the Cadence server\nusing the HTTP protocol. To put this into perspective, HTTP/JSON communication is a flexible method for server interaction.\nIn the context of Cadence, this implies that a range of RPC methods can be exposed and invoked using the HTTP protocol.\nThis enhancement broadens the scope of interaction with the Cadence server, enabling the use of any programming language that supports HTTP.\nConsequently, you can leverage this functionality to initiate or terminate workflows from your bash scripts, monitor the\nstatus of your cluster, or execute any other operation that the Cadence RPC declaration supports."]}),"\n",(0,r.jsx)(n.h2,{id:"setup",children:"Setup"}),"\n",(0,r.jsx)(n.h3,{id:"updating-cadence-configuration-files",children:"Updating Cadence configuration files"}),"\n",(0,r.jsxs)(n.p,{children:["To enable \u201cstart workflow\u201d HTTP API, add ",(0,r.jsx)(n.code,{children:"http"})," section to Cadence RPC configuration settings (e.g., in ",(0,r.jsx)(n.code,{children:"base.yaml"})," or ",(0,r.jsx)(n.code,{children:"development.yaml"}),"):"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-yaml",children:"services:\n frontend:\n rpc:\n # ...\n http:\n port: 8800\n procedures:\n - uber.cadence.api.v1.WorkflowAPI::StartWorkflowExecution\n"})}),"\n",(0,r.jsx)(n.p,{children:"Then you can run Cadence server in the following ways to use HTTP API."}),"\n",(0,r.jsx)(n.h3,{id:"using-local-binaries",children:"Using local binaries"}),"\n",(0,r.jsxs)(n.p,{children:["Build and run ",(0,r.jsx)(n.code,{children:"./cadence-server"})," as described in ",(0,r.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence/blob/master/CONTRIBUTING.md",children:"Developing Cadence"}),"."]}),"\n",(0,r.jsx)(n.h3,{id:"using-docker-run-command",children:"Using \u201cdocker run\u201d command"}),"\n",(0,r.jsxs)(n.p,{children:["Refer to instructions described\nin ",(0,r.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence/tree/master/docker#using-docker-image-for-production",children:"Using docker image for production"}),"."]}),"\n",(0,r.jsx)(n.p,{children:"Additionally add two more environment variables:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-bash",children:"docker run\n<...>\n -e FRONTEND_HTTP_PORT=8800 -- HTTP PORT TO LISTEN\n -e FRONTEND_HTTP_PROCEDURES=uber.cadence.api.v1.WorkflowAPI::StartWorkflowExecution -- List of API methods exposed\n ubercadence/server:<tag>\n"})}),"\n",(0,r.jsx)(n.h3,{id:"using-docker-compose",children:"Using docker-compose"}),"\n",(0,r.jsxs)(n.p,{children:["Add HTTP environment variables to ",(0,r.jsx)(n.code,{children:"docker/docker-compose.yml"})," configuration:"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-yaml",children:'cadence:\n image: ubercadence/server:master-auto-setup\n ports:\n - "8000:8000"\n - "8001:8001"\n - "8002:8002"\n - "8003:8003"\n - "7933:7933"\n - "7934:7934"\n - "7935:7935"\n - "7939:7939"\n - "7833:7833"\n - "8800:8800"\n environment:\n - "CASSANDRA_SEEDS=cassandra"\n - "PROMETHEUS_ENDPOINT_0=0.0.0.0:8000"\n - "PROMETHEUS_ENDPOINT_1=0.0.0.0:8001"\n - "PROMETHEUS_ENDPOINT_2=0.0.0.0:8002"\n - "PROMETHEUS_ENDPOINT_3=0.0.0.0:8003"\n - "DYNAMIC_CONFIG_FILE_PATH=config/dynamicconfig/development.yaml"\n - "FRONTEND_HTTP_PORT=8800"\n - "FRONTEND_HTTP_PROCEDURES=uber.cadence.api.v1.WorkflowAPI::StartWorkflowExecution"\n'})}),"\n",(0,r.jsx)(n.h2,{id:"using-http-api-1",children:"Using HTTP API"}),"\n",(0,r.jsx)(n.p,{children:"Start a workflow using curl command"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-bash",children:"curl -X POST http://0.0.0.0:8800 \\\n -H 'context-ttl-ms: 2000' \\\n -H 'rpc-caller: rpc-client-name' \\\n -H 'rpc-service: cadence-frontend' \\\n -H 'rpc-encoding: json' \\\n -H 'rpc-procedure: uber.cadence.api.v1.WorkflowAPI::StartWorkflowExecution' \\\n -d @data.json\n"})}),"\n",(0,r.jsxs)(n.p,{children:["Where ",(0,r.jsx)(n.code,{children:"data.json"})," content looks something like this:"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-json",children:'{\n "domain": "sample-domain",\n "workflowId": "workflowid123",\n "execution_start_to_close_timeout": "11s",\n "task_start_to_close_timeout": "10s",\n "workflowType": {\n "name": "workflow_type"\n },\n "taskList": {\n "name": "tasklist-name"\n },\n "identity": "My custom caller identity",\n "requestId": "4D1E4058-6FCF-4BA8-BF16-8FA8B02F9651"\n}\n'})}),"\n",(0,r.jsx)(n.h2,{id:"http-api-reference",children:"HTTP API Reference"}),"\n",(0,r.jsx)(n.h3,{id:"admin-api",children:"Admin API"}),"\n",(0,r.jsx)(n.hr,{}),"\n",(0,r.jsxs)(s,{children:[(0,r.jsxs)("summary",{children:[(0,r.jsx)("code",{children:"POST"})," ",(0,r.jsx)("code",{children:(0,r.jsx)("b",{children:"uber.cadence.admin.v1.AdminAPIAddSearchAttribute"})})]}),(0,r.jsx)(n.h4,{id:"add-search-attributes-to-whitelist",children:"Add search attributes to whitelist"}),(0,r.jsx)(n.h5,{id:"headers",children:"Headers"}),(0,r.jsxs)(n.table,{children:[(0,r.jsx)(n.thead,{children:(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.th,{children:"name"}),(0,r.jsx)(n.th,{children:"example"})]})}),(0,r.jsxs)(n.tbody,{children:[(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"context-ttl-ms"}),(0,r.jsx)(n.td,{children:"2000"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-caller"}),(0,r.jsx)(n.td,{children:"curl-client"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-service"}),(0,r.jsx)(n.td,{children:"cadence-frontend"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-encoding"}),(0,r.jsx)(n.td,{children:"json"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-procedure"}),(0,r.jsx)(n.td,{children:"uber.cadence.admin.v1.AdminAPIAddSearchAttribute"})]})]})]}),(0,r.jsx)(n.h5,{id:"example-payload",children:"Example payload"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-json",children:'{\n "search_attribute": {\n "custom_key": 1\n }\n}\n'})}),(0,r.jsx)(n.p,{children:"Search attribute types"}),(0,r.jsxs)(n.table,{children:[(0,r.jsx)(n.thead,{children:(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.th,{children:"type"}),(0,r.jsx)(n.th,{children:"value"})]})}),(0,r.jsxs)(n.tbody,{children:[(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"String"}),(0,r.jsx)(n.td,{children:"1"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"Keyword"}),(0,r.jsx)(n.td,{children:"2"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"Int"}),(0,r.jsx)(n.td,{children:"3"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"Double"}),(0,r.jsx)(n.td,{children:"4"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"DateTime"}),(0,r.jsx)(n.td,{children:"5"})]})]})]}),(0,r.jsx)(n.h5,{id:"example-curl",children:"Example cURL"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-bash",children:"curl -X POST http://0.0.0.0:8800 \\\n -H 'context-ttl-ms: 2000' \\\n -H 'rpc-caller: curl-client' \\\n -H 'rpc-service: cadence-frontend' \\\n -H 'rpc-encoding: json' \\\n -H 'rpc-procedure: uber.cadence.admin.v1.AdminAPI::AddSearchAttribute' \\\n -d \\\n '{\n \"search_attribute\": {\n \"custom_key\": 1\n }\n }'\n"})}),(0,r.jsx)(n.h5,{id:"example-successful-response",children:"Example successful response"}),(0,r.jsx)(n.p,{children:"HTTP code: 200"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-json",children:"{}\n"})})]}),"\n",(0,r.jsx)(n.hr,{}),"\n",(0,r.jsxs)(s,{children:[(0,r.jsxs)("summary",{children:[(0,r.jsx)("code",{children:"POST"})," ",(0,r.jsx)("code",{children:(0,r.jsx)("b",{children:"uber.cadence.admin.v1.AdminAPICloseShard"})})]}),(0,r.jsx)(n.h4,{id:"close-a-shard-given-a-shard-id",children:"Close a shard given a shard ID"}),(0,r.jsx)(n.h5,{id:"headers-1",children:"Headers"}),(0,r.jsxs)(n.table,{children:[(0,r.jsx)(n.thead,{children:(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.th,{children:"name"}),(0,r.jsx)(n.th,{children:"example"})]})}),(0,r.jsxs)(n.tbody,{children:[(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"context-ttl-ms"}),(0,r.jsx)(n.td,{children:"2000"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-caller"}),(0,r.jsx)(n.td,{children:"curl-client"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-service"}),(0,r.jsx)(n.td,{children:"cadence-frontend"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-encoding"}),(0,r.jsx)(n.td,{children:"json"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-procedure"}),(0,r.jsx)(n.td,{children:"uber.cadence.admin.v1.AdminAPICloseShard"})]})]})]}),(0,r.jsx)(n.h5,{id:"example-payload-1",children:"Example payload"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-json",children:'{\n "shard_id": 0\n}\n'})}),(0,r.jsx)(n.h5,{id:"example-curl-1",children:"Example cURL"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-bash",children:"curl -X POST http://0.0.0.0:8800 \\\n -H 'context-ttl-ms: 2000' \\\n -H 'rpc-caller: curl-client' \\\n -H 'rpc-service: cadence-frontend' \\\n -H 'rpc-encoding: json' \\\n -H 'rpc-procedure: uber.cadence.admin.v1.AdminAPI::CloseShard' \\\n -d \\\n '{\n \"shard_id\": 0\n }'\n"})}),(0,r.jsx)(n.h5,{id:"example-successful-response-1",children:"Example successful response"}),(0,r.jsx)(n.p,{children:"HTTP code: 200"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-json",children:"{}\n"})})]}),"\n",(0,r.jsx)(n.hr,{}),"\n",(0,r.jsxs)(s,{children:[(0,r.jsxs)("summary",{children:[(0,r.jsx)("code",{children:"POST"})," ",(0,r.jsx)("code",{children:(0,r.jsx)("b",{children:"uber.cadence.admin.v1.AdminAPICountDLQMessages"})})]}),(0,r.jsx)(n.h4,{id:"count-dlq-messages",children:"Count DLQ messages"}),(0,r.jsx)(n.h5,{id:"headers-2",children:"Headers"}),(0,r.jsxs)(n.table,{children:[(0,r.jsx)(n.thead,{children:(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.th,{children:"name"}),(0,r.jsx)(n.th,{children:"example"})]})}),(0,r.jsxs)(n.tbody,{children:[(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"context-ttl-ms"}),(0,r.jsx)(n.td,{children:"2000"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-caller"}),(0,r.jsx)(n.td,{children:"curl-client"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-service"}),(0,r.jsx)(n.td,{children:"cadence-frontend"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-encoding"}),(0,r.jsx)(n.td,{children:"json"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-procedure"}),(0,r.jsx)(n.td,{children:"uber.cadence.admin.v1.AdminAPICountDLQMessages"})]})]})]}),(0,r.jsx)(n.h5,{id:"example-payload-2",children:"Example payload"}),(0,r.jsx)(n.p,{children:"None"}),(0,r.jsx)(n.h5,{id:"example-curl-2",children:"Example cURL"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-bash",children:"curl -X POST http://0.0.0.0:8800 \\\n -H 'context-ttl-ms: 2000' \\\n -H 'rpc-caller: curl-client' \\\n -H 'rpc-service: cadence-frontend' \\\n -H 'rpc-encoding: json' \\\n -H 'rpc-procedure: uber.cadence.admin.v1.AdminAPI::CountDLQMessages'\n"})}),(0,r.jsx)(n.h5,{id:"example-successful-response-2",children:"Example successful response"}),(0,r.jsx)(n.p,{children:"HTTP code: 200"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-json",children:'{\n "history": []\n}\n'})})]}),"\n",(0,r.jsx)(n.hr,{}),"\n",(0,r.jsxs)(s,{children:[(0,r.jsxs)("summary",{children:[(0,r.jsx)("code",{children:"POST"})," ",(0,r.jsx)("code",{children:(0,r.jsx)("b",{children:"uber.cadence.admin.v1.AdminAPIDescribeCluster"})})]}),(0,r.jsx)(n.h4,{id:"describe-cluster-information",children:"Describe cluster information"}),(0,r.jsx)(n.h5,{id:"headers-3",children:"Headers"}),(0,r.jsxs)(n.table,{children:[(0,r.jsx)(n.thead,{children:(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.th,{children:"name"}),(0,r.jsx)(n.th,{children:"example"})]})}),(0,r.jsxs)(n.tbody,{children:[(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"context-ttl-ms"}),(0,r.jsx)(n.td,{children:"2000"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-caller"}),(0,r.jsx)(n.td,{children:"curl-client"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-service"}),(0,r.jsx)(n.td,{children:"cadence-frontend"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-encoding"}),(0,r.jsx)(n.td,{children:"json"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-procedure"}),(0,r.jsx)(n.td,{children:"uber.cadence.admin.v1.AdminAPIDescribeCluster"})]})]})]}),(0,r.jsx)(n.h5,{id:"example-payload-3",children:"Example payload"}),(0,r.jsx)(n.p,{children:"None"}),(0,r.jsx)(n.h5,{id:"example-curl-3",children:"Example cURL"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-bash",children:"curl -X POST http://0.0.0.0:8800 \\\n -H 'context-ttl-ms: 2000' \\\n -H 'rpc-caller: curl-client' \\\n -H 'rpc-service: cadence-frontend' \\\n -H 'rpc-encoding: json' \\\n -H 'rpc-procedure: uber.cadence.admin.v1.AdminAPI::DescribeCluster'\n"})}),(0,r.jsx)(n.h5,{id:"example-successful-response-3",children:"Example successful response"}),(0,r.jsx)(n.p,{children:"HTTP code: 200"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-json",children:'{\n "supportedClientVersions": {\n "goSdk": "1.7.0",\n "javaSdk": "1.5.0"\n },\n "membershipInfo": {\n "currentHost": {\n "identity": "127.0.0.1:7933"\n },\n "reachableMembers": [\n "127.0.0.1:7933",\n "127.0.0.1:7934",\n "127.0.0.1:7935",\n "127.0.0.1:7939"\n ],\n "rings": [\n {\n "role": "cadence-frontend",\n "memberCount": 1,\n "members": [\n {\n "identity": "127.0.0.1:7933"\n }\n ]\n },\n {\n "role": "cadence-history",\n "memberCount": 1,\n "members": [\n {\n "identity": "127.0.0.1:7934"\n }\n ]\n },\n {\n "role": "cadence-matching",\n "memberCount": 1,\n "members": [\n {\n "identity": "127.0.0.1:7935"\n }\n ]\n },\n {\n "role": "cadence-worker",\n "memberCount": 1,\n "members": [\n {\n "identity": "127.0.0.1:7939"\n }\n ]\n }\n ]\n },\n "persistenceInfo": {\n "historyStore": {\n "backend": "shardedNosql"\n },\n "visibilityStore": {\n "backend": "cassandra",\n "features": [\n {\n "key": "advancedVisibilityEnabled"\n }\n ]\n }\n }\n}\n'})})]}),"\n",(0,r.jsx)(n.hr,{}),"\n",(0,r.jsxs)(s,{children:[(0,r.jsxs)("summary",{children:[(0,r.jsx)("code",{children:"POST"})," ",(0,r.jsx)("code",{children:(0,r.jsx)("b",{children:"uber.cadence.admin.v1.AdminAPIDescribeHistoryHost"})})]}),(0,r.jsx)(n.h4,{id:"describe-internal-information-of-history-host",children:"Describe internal information of history host"}),(0,r.jsx)(n.h5,{id:"headers-4",children:"Headers"}),(0,r.jsxs)(n.table,{children:[(0,r.jsx)(n.thead,{children:(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.th,{children:"name"}),(0,r.jsx)(n.th,{children:"example"})]})}),(0,r.jsxs)(n.tbody,{children:[(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"context-ttl-ms"}),(0,r.jsx)(n.td,{children:"2000"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-caller"}),(0,r.jsx)(n.td,{children:"curl-client"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-service"}),(0,r.jsx)(n.td,{children:"cadence-frontend"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-encoding"}),(0,r.jsx)(n.td,{children:"json"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-procedure"}),(0,r.jsx)(n.td,{children:"uber.cadence.admin.v1.AdminAPIDescribeHistoryHost"})]})]})]}),(0,r.jsx)(n.h5,{id:"example-payload-4",children:"Example payload"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-json",children:'{\n "host_address": "127.0.0.1:7934"\n}\n'})}),(0,r.jsx)(n.h5,{id:"example-curl-4",children:"Example cURL"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-bash",children:"curl -X POST http://0.0.0.0:8800 \\\n -H 'context-ttl-ms: 2000' \\\n -H 'rpc-caller: curl-client' \\\n -H 'rpc-service: cadence-frontend' \\\n -H 'rpc-encoding: json' \\\n -H 'rpc-procedure: uber.cadence.admin.v1.AdminAPI::DescribeHistoryHost' \\\n -d \\\n '{\n \"host_address\": \"127.0.0.1:7934\"\n }'\n"})}),(0,r.jsx)(n.h5,{id:"example-successful-response-4",children:"Example successful response"}),(0,r.jsx)(n.p,{children:"HTTP code: 200"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-json",children:'{\n "numberOfShards": 4,\n "domainCache": {\n "numOfItemsInCacheByID": 5,\n "numOfItemsInCacheByName": 5\n },\n "shardControllerStatus": "started",\n "address": "127.0.0.1:7934"\n}\n'})})]}),"\n",(0,r.jsx)(n.hr,{}),"\n",(0,r.jsxs)(s,{children:[(0,r.jsxs)("summary",{children:[(0,r.jsx)("code",{children:"POST"})," ",(0,r.jsx)("code",{children:(0,r.jsx)("b",{children:"uber.cadence.admin.v1.AdminAPIDescribeShardDistribution"})})]}),(0,r.jsx)(n.h4,{id:"list-shard-distribution",children:"List shard distribution"}),(0,r.jsx)(n.h5,{id:"headers-5",children:"Headers"}),(0,r.jsxs)(n.table,{children:[(0,r.jsx)(n.thead,{children:(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.th,{children:"name"}),(0,r.jsx)(n.th,{children:"example"})]})}),(0,r.jsxs)(n.tbody,{children:[(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"context-ttl-ms"}),(0,r.jsx)(n.td,{children:"2000"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-caller"}),(0,r.jsx)(n.td,{children:"curl-client"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-service"}),(0,r.jsx)(n.td,{children:"cadence-frontend"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-encoding"}),(0,r.jsx)(n.td,{children:"json"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-procedure"}),(0,r.jsx)(n.td,{children:"uber.cadence.admin.v1.AdminAPIDescribeShardDistribution"})]})]})]}),(0,r.jsx)(n.h5,{id:"example-payload-5",children:"Example payload"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-json",children:'{\n "page_size": 100,\n "page_id": 0\n}\n'})}),(0,r.jsx)(n.h5,{id:"example-curl-5",children:"Example cURL"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-bash",children:"curl -X POST http://0.0.0.0:8800 \\\n -H 'context-ttl-ms: 2000' \\\n -H 'rpc-caller: curl-client' \\\n -H 'rpc-service: cadence-frontend' \\\n -H 'rpc-encoding: json' \\\n -H 'rpc-procedure: uber.cadence.admin.v1.AdminAPI::DescribeShardDistribution' \\\n -d \\\n '{\n \"page_size\": 100,\n \"page_id\": 0\n }'\n"})}),(0,r.jsx)(n.h5,{id:"example-successful-response-5",children:"Example successful response"}),(0,r.jsx)(n.p,{children:"HTTP code: 200"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-json",children:'{\n "numberOfShards": 4,\n "shards": {\n "0": "127.0.0.1:7934",\n "1": "127.0.0.1:7934",\n "2": "127.0.0.1:7934",\n "3": "127.0.0.1:7934"\n }\n}\n'})})]}),"\n",(0,r.jsx)(n.hr,{}),"\n",(0,r.jsxs)(s,{children:[(0,r.jsxs)("summary",{children:[(0,r.jsx)("code",{children:"POST"})," ",(0,r.jsx)("code",{children:(0,r.jsx)("b",{children:"uber.cadence.admin.v1.AdminAPIDescribeWorkflowExecution"})})]}),(0,r.jsx)(n.h4,{id:"describe-internal-information-of-workflow-execution",children:"Describe internal information of workflow execution"}),(0,r.jsx)(n.h5,{id:"headers-6",children:"Headers"}),(0,r.jsxs)(n.table,{children:[(0,r.jsx)(n.thead,{children:(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.th,{children:"name"}),(0,r.jsx)(n.th,{children:"example"})]})}),(0,r.jsxs)(n.tbody,{children:[(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"context-ttl-ms"}),(0,r.jsx)(n.td,{children:"2000"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-caller"}),(0,r.jsx)(n.td,{children:"curl-client"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-service"}),(0,r.jsx)(n.td,{children:"cadence-frontend"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-encoding"}),(0,r.jsx)(n.td,{children:"json"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-procedure"}),(0,r.jsx)(n.td,{children:"uber.cadence.admin.v1.AdminAPIDescribeWorkflowExecution"})]})]})]}),(0,r.jsx)(n.h5,{id:"example-payload-6",children:"Example payload"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-json",children:'{\n "domain": "sample-domain",\n "workflow_execution": {\n "workflow_id": "sample-workflow-id",\n "run_id": "cc09d5dd-b2fa-46d8-b426-54c96b12d18f"\n }\n}\n'})}),(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"run_id"})," is optional and allows to describe a specific run."]}),(0,r.jsx)(n.h5,{id:"example-curl-6",children:"Example cURL"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-bash",children:"curl -X POST http://0.0.0.0:8800 \\\n -H 'context-ttl-ms: 2000' \\\n -H 'rpc-caller: curl-client' \\\n -H 'rpc-service: cadence-frontend' \\\n -H 'rpc-encoding: json' \\\n -H 'rpc-procedure: uber.cadence.admin.v1.AdminAPI::DescribeWorkflowExecution' \\\n -d \\\n '{\n \"domain\": \"sample-domain\",\n \"workflow_execution\": {\n \"workflow_id\": \"sample-workflow-id\",\n \"run_id\": \"cc09d5dd-b2fa-46d8-b426-54c96b12d18f\"\n }\n }' | tr -d '\\'\n"})}),(0,r.jsx)(n.h5,{id:"example-successful-response-6",children:"Example successful response"}),(0,r.jsx)(n.p,{children:"HTTP code: 200"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-json",children:'{\n "shardId": 3,\n "historyAddr": "127.0.0.1:7934",\n "mutableStateInDatabase": {\n "ActivityInfos": {},\n "TimerInfos": {},\n "ChildExecutionInfos": {},\n "RequestCancelInfos": {},\n "SignalInfos": {},\n "SignalRequestedIDs": {},\n "ExecutionInfo": {\n "DomainID": "d7aff879-f524-43a8-b340-5a223a69d75b",\n "WorkflowID": "sample-workflow-id",\n "RunID": "cc09d5dd-b2fa-46d8-b426-54c96b12d18f",\n "FirstExecutionRunID": "cc09d5dd-b2fa-46d8-b426-54c96b12d18f",\n "ParentDomainID": "",\n "ParentWorkflowID": "",\n "ParentRunID": "",\n "InitiatedID": -7,\n "CompletionEventBatchID": 3,\n "CompletionEvent": null,\n "TaskList": "sample-task-list",\n "WorkflowTypeName": "sample-workflow-type",\n "WorkflowTimeout": 11,\n "DecisionStartToCloseTimeout": 10,\n "ExecutionContext": null,\n "State": 2,\n "CloseStatus": 6,\n "LastFirstEventID": 3,\n "LastEventTaskID": 8388614,\n "NextEventID": 4,\n "LastProcessedEvent": -23,\n "StartTimestamp": "2023-09-08T05:13:04.24Z",\n "LastUpdatedTimestamp": "2023-09-08T05:13:15.247Z",\n "CreateRequestID": "8049b932-6c2f-415a-9bb2-241dcf4cfc9c",\n "SignalCount": 0,\n "DecisionVersion": 0,\n "DecisionScheduleID": 2,\n "DecisionStartedID": -23,\n "DecisionRequestID": "emptyUuid",\n "DecisionTimeout": 10,\n "DecisionAttempt": 0,\n "DecisionStartedTimestamp": 0,\n "DecisionScheduledTimestamp": 1694149984240504000,\n "DecisionOriginalScheduledTimestamp": 1694149984240503000,\n "CancelRequested": false,\n "CancelRequestID": "",\n "StickyTaskList": "",\n "StickyScheduleToStartTimeout": 0,\n "ClientLibraryVersion": "",\n "ClientFeatureVersion": "",\n "ClientImpl": "",\n "AutoResetPoints": {},\n "Memo": null,\n "SearchAttributes": null,\n "PartitionConfig": null,\n "Attempt": 0,\n "HasRetryPolicy": false,\n "InitialInterval": 0,\n "BackoffCoefficient": 0,\n "MaximumInterval": 0,\n "ExpirationTime": "0001-01-01T00:00:00Z",\n "MaximumAttempts": 0,\n "NonRetriableErrors": null,\n "BranchToken": null,\n "CronSchedule": "",\n "IsCron": false,\n "ExpirationSeconds": 0\n },\n "ExecutionStats": null,\n "BufferedEvents": [],\n "VersionHistories": {\n "CurrentVersionHistoryIndex": 0,\n "Histories": [\n {\n "BranchToken": "WQsACgAAACRjYzA5ZDVkZC1iMmZhLTQ2ZDgtYjQyNi01NGM5NmIxMmQxOGYLABQAAAAkYWM5YmIwMmUtMjllYy00YWEyLTlkZGUtZWQ0YWU1NWRhMjlhDwAeDAAAAAAA",\n "Items": [\n {\n "EventID": 3,\n "Version": 0\n }\n ]\n }\n ]\n },\n "ReplicationState": null,\n "Checksum": {\n "Version": 0,\n "Flavor": 0,\n "Value": null\n }\n }\n}\n'})})]}),"\n",(0,r.jsx)(n.hr,{}),"\n",(0,r.jsx)(n.h3,{id:"domain-api",children:"Domain API"}),"\n",(0,r.jsx)(n.hr,{}),"\n",(0,r.jsxs)(s,{children:[(0,r.jsxs)("summary",{children:[(0,r.jsx)("code",{children:"POST"})," ",(0,r.jsx)("code",{children:(0,r.jsx)("b",{children:"uber.cadence.api.v1.DomainAPIDescribeDomain"})})]}),(0,r.jsx)(n.h4,{id:"describe-existing-workflow-domain",children:"Describe existing workflow domain"}),(0,r.jsx)(n.h5,{id:"headers-7",children:"Headers"}),(0,r.jsxs)(n.table,{children:[(0,r.jsx)(n.thead,{children:(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.th,{children:"name"}),(0,r.jsx)(n.th,{children:"example"})]})}),(0,r.jsxs)(n.tbody,{children:[(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"context-ttl-ms"}),(0,r.jsx)(n.td,{children:"2000"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-caller"}),(0,r.jsx)(n.td,{children:"curl-client"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-service"}),(0,r.jsx)(n.td,{children:"cadence-frontend"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-encoding"}),(0,r.jsx)(n.td,{children:"json"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-procedure"}),(0,r.jsx)(n.td,{children:"uber.cadence.api.v1.DomainAPIDescribeDomain"})]})]})]}),(0,r.jsx)(n.h5,{id:"example-payload-7",children:"Example payload"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-json",children:'{\n "name": "sample-domain",\n "uuid": "d7aff879-f524-43a8-b340-5a223a69d75b"\n}\n'})}),(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"uuid"})," of the domain is optional."]}),(0,r.jsx)(n.h5,{id:"example-curl-7",children:"Example cURL"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-bash",children:"curl -X POST http://0.0.0.0:8800 \\\n -H 'context-ttl-ms: 2000' \\\n -H 'rpc-caller: curl-client' \\\n -H 'rpc-service: cadence-frontend' \\\n -H 'rpc-encoding: json' \\\n -H 'rpc-procedure: uber.cadence.api.v1.DomainAPI::DescribeDomain' \\\n -d \\\n '{\n \"name\": \"sample-domain\"\n }'\n"})}),(0,r.jsx)(n.h5,{id:"example-successful-response-7",children:"Example successful response"}),(0,r.jsx)(n.p,{children:"HTTP code: 200"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-json",children:'{\n "domain": {\n "id": "d7aff879-f524-43a8-b340-5a223a69d75b",\n "name": "sample-domain",\n "status": "DOMAIN_STATUS_REGISTERED",\n "data": {},\n "workflowExecutionRetentionPeriod": "259200s",\n "badBinaries": {\n "binaries": {}\n },\n "historyArchivalStatus": "ARCHIVAL_STATUS_ENABLED",\n "historyArchivalUri": "file:///tmp/cadence_archival/development",\n "visibilityArchivalStatus": "ARCHIVAL_STATUS_ENABLED",\n "visibilityArchivalUri": "file:///tmp/cadence_vis_archival/development",\n "activeClusterName": "cluster0",\n "clusters": [\n {\n "clusterName": "cluster0"\n }\n ],\n "isGlobalDomain": true,\n "isolationGroups": {}\n }\n}\n'})})]}),"\n",(0,r.jsx)(n.hr,{}),"\n",(0,r.jsxs)(s,{children:[(0,r.jsxs)("summary",{children:[(0,r.jsx)("code",{children:"POST"})," ",(0,r.jsx)("code",{children:(0,r.jsx)("b",{children:"uber.cadence.api.v1.DomainAPIListDomains"})})]}),(0,r.jsx)(n.h4,{id:"list-all-domains-in-the-cluster",children:"List all domains in the cluster"}),(0,r.jsx)(n.h5,{id:"headers-8",children:"Headers"}),(0,r.jsxs)(n.table,{children:[(0,r.jsx)(n.thead,{children:(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.th,{children:"name"}),(0,r.jsx)(n.th,{children:"example"})]})}),(0,r.jsxs)(n.tbody,{children:[(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"context-ttl-ms"}),(0,r.jsx)(n.td,{children:"2000"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-caller"}),(0,r.jsx)(n.td,{children:"curl-client"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-service"}),(0,r.jsx)(n.td,{children:"cadence-frontend"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-encoding"}),(0,r.jsx)(n.td,{children:"json"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-procedure"}),(0,r.jsx)(n.td,{children:"uber.cadence.api.v1.DomainAPIListDomains"})]})]})]}),(0,r.jsx)(n.h5,{id:"example-payload-8",children:"Example payload"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-json",children:'{\n "page_size": 100\n}\n'})}),(0,r.jsx)(n.h5,{id:"example-curl-8",children:"Example cURL"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-bash",children:"curl -X POST http://0.0.0.0:8800 \\\n -H 'context-ttl-ms: 2000' \\\n -H 'rpc-caller: curl-client' \\\n -H 'rpc-service: cadence-frontend' \\\n -H 'rpc-encoding: json' \\\n -H 'rpc-procedure: uber.cadence.api.v1.DomainAPI::ListDomains' \\\n -d \\\n '{\n \"page_size\": 100\n }'\n"})}),(0,r.jsx)(n.h5,{id:"example-successful-response-8",children:"Example successful response"}),(0,r.jsx)(n.p,{children:"HTTP code: 200"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-json",children:'{\n "domains": [\n {\n "id": "3116607e-419b-4783-85fc-47726a4c3fe9",\n "name": "cadence-batcher",\n "status": "DOMAIN_STATUS_REGISTERED",\n "description": "Cadence internal system domain",\n "data": {},\n "workflowExecutionRetentionPeriod": "604800s",\n "badBinaries": {\n "binaries": {}\n },\n "historyArchivalStatus": "ARCHIVAL_STATUS_DISABLED",\n "visibilityArchivalStatus": "ARCHIVAL_STATUS_DISABLED",\n "activeClusterName": "cluster0",\n "clusters": [\n {\n "clusterName": "cluster0"\n }\n ],\n "failoverVersion": "-24",\n "isolationGroups": {}\n },\n {\n "id": "59c51119-1b41-4a28-986d-d6e377716f82",\n "name": "cadence-shadower",\n "status": "DOMAIN_STATUS_REGISTERED",\n "description": "Cadence internal system domain",\n "data": {},\n "workflowExecutionRetentionPeriod": "604800s",\n "badBinaries": {\n "binaries": {}\n },\n "historyArchivalStatus": "ARCHIVAL_STATUS_DISABLED",\n "visibilityArchivalStatus": "ARCHIVAL_STATUS_DISABLED",\n "activeClusterName": "cluster0",\n "clusters": [\n {\n "clusterName": "cluster0"\n }\n ],\n "failoverVersion": "-24",\n "isolationGroups": {}\n },\n {\n "id": "32049b68-7872-4094-8e63-d0dd59896a83",\n "name": "cadence-system",\n "status": "DOMAIN_STATUS_REGISTERED",\n "description": "cadence system workflow domain",\n "ownerEmail": "cadence-dev-group@uber.com",\n "data": {},\n "workflowExecutionRetentionPeriod": "259200s",\n "badBinaries": {\n "binaries": {}\n },\n "historyArchivalStatus": "ARCHIVAL_STATUS_DISABLED",\n "visibilityArchivalStatus": "ARCHIVAL_STATUS_DISABLED",\n "activeClusterName": "cluster0",\n "clusters": [\n {\n "clusterName": "cluster0"\n }\n ],\n "failoverVersion": "-24",\n "isolationGroups": {}\n },\n {\n "id": "d7aff879-f524-43a8-b340-5a223a69d75b",\n "name": "sample-domain",\n "status": "DOMAIN_STATUS_REGISTERED",\n "data": {},\n "workflowExecutionRetentionPeriod": "259200s",\n "badBinaries": {\n "binaries": {}\n },\n "historyArchivalStatus": "ARCHIVAL_STATUS_ENABLED",\n "historyArchivalUri": "file:///tmp/cadence_archival/development",\n "visibilityArchivalStatus": "ARCHIVAL_STATUS_ENABLED",\n "visibilityArchivalUri": "file:///tmp/cadence_vis_archival/development",\n "activeClusterName": "cluster0",\n "clusters": [\n {\n "clusterName": "cluster0"\n }\n ],\n "isGlobalDomain": true,\n "isolationGroups": {}\n }\n ],\n "nextPageToken": ""\n}\n'})})]}),"\n",(0,r.jsx)(n.hr,{}),"\n",(0,r.jsx)(n.h3,{id:"meta-api",children:"Meta API"}),"\n",(0,r.jsx)(n.hr,{}),"\n",(0,r.jsxs)(s,{children:[(0,r.jsxs)("summary",{children:[(0,r.jsx)("code",{children:"POST"})," ",(0,r.jsx)("code",{children:(0,r.jsx)("b",{children:"uber.cadence.api.v1.MetaAPIHealth"})})]}),(0,r.jsx)(n.h4,{id:"health-check",children:"Health check"}),(0,r.jsx)(n.h5,{id:"headers-9",children:"Headers"}),(0,r.jsxs)(n.table,{children:[(0,r.jsx)(n.thead,{children:(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.th,{children:"name"}),(0,r.jsx)(n.th,{children:"example"})]})}),(0,r.jsxs)(n.tbody,{children:[(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"context-ttl-ms"}),(0,r.jsx)(n.td,{children:"2000"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-caller"}),(0,r.jsx)(n.td,{children:"curl-client"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-service"}),(0,r.jsx)(n.td,{children:"cadence-frontend"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-encoding"}),(0,r.jsx)(n.td,{children:"json"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-procedure"}),(0,r.jsx)(n.td,{children:"uber.cadence.api.v1.MetaAPIHealth"})]})]})]}),(0,r.jsx)(n.h5,{id:"example-payload-9",children:"Example payload"}),(0,r.jsx)(n.p,{children:"None"}),(0,r.jsx)(n.h5,{id:"example-curl-9",children:"Example cURL"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-bash",children:"curl -X POST http://0.0.0.0:8800 \\\n -H 'context-ttl-ms: 2000' \\\n -H 'rpc-caller: curl-client' \\\n -H 'rpc-service: cadence-frontend' \\\n -H 'rpc-encoding: json' \\\n -H 'rpc-procedure: uber.cadence.api.v1.MetaAPI::Health'\n"})}),(0,r.jsx)(n.h5,{id:"example-successful-response-9",children:"Example successful response"}),(0,r.jsx)(n.p,{children:"HTTP code: 200"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-json",children:'{\n "ok": true,\n "message": "OK"\n}\n'})})]}),"\n",(0,r.jsx)(n.hr,{}),"\n",(0,r.jsx)(n.h3,{id:"visibility-api",children:"Visibility API"}),"\n",(0,r.jsx)(n.hr,{}),"\n",(0,r.jsxs)(s,{children:[(0,r.jsxs)("summary",{children:[(0,r.jsx)("code",{children:"POST"})," ",(0,r.jsx)("code",{children:(0,r.jsx)("b",{children:"uber.cadence.api.v1.VisibilityAPIGetSearchAttributes"})})]}),(0,r.jsx)(n.h4,{id:"get-search-attributes",children:"Get search attributes"}),(0,r.jsx)(n.h5,{id:"headers-10",children:"Headers"}),(0,r.jsxs)(n.table,{children:[(0,r.jsx)(n.thead,{children:(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.th,{children:"name"}),(0,r.jsx)(n.th,{children:"example"})]})}),(0,r.jsxs)(n.tbody,{children:[(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"context-ttl-ms"}),(0,r.jsx)(n.td,{children:"2000"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-caller"}),(0,r.jsx)(n.td,{children:"curl-client"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-service"}),(0,r.jsx)(n.td,{children:"cadence-frontend"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-encoding"}),(0,r.jsx)(n.td,{children:"json"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-procedure"}),(0,r.jsx)(n.td,{children:"uber.cadence.api.v1.VisibilityAPIGetSearchAttributes"})]})]})]}),(0,r.jsx)(n.h5,{id:"example-payload-10",children:"Example payload"}),(0,r.jsx)(n.p,{children:"None"}),(0,r.jsx)(n.h5,{id:"example-curl-10",children:"Example cURL"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-bash",children:"curl -X POST http://0.0.0.0:8800 \\\n -H 'context-ttl-ms: 2000' \\\n -H 'rpc-caller: curl-client' \\\n -H 'rpc-service: cadence-frontend' \\\n -H 'rpc-encoding: json' \\\n -H 'rpc-procedure: uber.cadence.api.v1.VisibilityAPI::GetSearchAttributes'\n"})}),(0,r.jsx)(n.h5,{id:"example-successful-response-10",children:"Example successful response"}),(0,r.jsx)(n.p,{children:"HTTP code: 200"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-json",children:'{\n "keys": {\n "BinaryChecksums": "INDEXED_VALUE_TYPE_KEYWORD",\n "CadenceChangeVersion": "INDEXED_VALUE_TYPE_KEYWORD",\n "CloseStatus": "INDEXED_VALUE_TYPE_INT",\n "CloseTime": "INDEXED_VALUE_TYPE_INT",\n "CustomBoolField": "INDEXED_VALUE_TYPE_BOOL",\n "CustomDatetimeField": "INDEXED_VALUE_TYPE_DATETIME",\n "CustomDomain": "INDEXED_VALUE_TYPE_KEYWORD",\n "CustomDoubleField": "INDEXED_VALUE_TYPE_DOUBLE",\n "CustomIntField": "INDEXED_VALUE_TYPE_INT",\n "CustomKeywordField": "INDEXED_VALUE_TYPE_KEYWORD",\n "CustomStringField": "INDEXED_VALUE_TYPE_STRING",\n "DomainID": "INDEXED_VALUE_TYPE_KEYWORD",\n "ExecutionTime": "INDEXED_VALUE_TYPE_INT",\n "HistoryLength": "INDEXED_VALUE_TYPE_INT",\n "IsCron": "INDEXED_VALUE_TYPE_KEYWORD",\n "NewKey": "INDEXED_VALUE_TYPE_KEYWORD",\n "NumClusters": "INDEXED_VALUE_TYPE_INT",\n "Operator": "INDEXED_VALUE_TYPE_KEYWORD",\n "Passed": "INDEXED_VALUE_TYPE_BOOL",\n "RolloutID": "INDEXED_VALUE_TYPE_KEYWORD",\n "RunID": "INDEXED_VALUE_TYPE_KEYWORD",\n "ShardID": "INDEXED_VALUE_TYPE_INT",\n "StartTime": "INDEXED_VALUE_TYPE_INT",\n "TaskList": "INDEXED_VALUE_TYPE_KEYWORD",\n "TestNewKey": "INDEXED_VALUE_TYPE_STRING",\n "UpdateTime": "INDEXED_VALUE_TYPE_INT",\n "WorkflowID": "INDEXED_VALUE_TYPE_KEYWORD",\n "WorkflowType": "INDEXED_VALUE_TYPE_KEYWORD",\n "addon": "INDEXED_VALUE_TYPE_KEYWORD",\n "addon-type": "INDEXED_VALUE_TYPE_KEYWORD",\n "environment": "INDEXED_VALUE_TYPE_KEYWORD",\n "project": "INDEXED_VALUE_TYPE_KEYWORD",\n "service": "INDEXED_VALUE_TYPE_KEYWORD",\n "user": "INDEXED_VALUE_TYPE_KEYWORD"\n }\n}\n'})})]}),"\n",(0,r.jsx)(n.hr,{}),"\n",(0,r.jsxs)(s,{children:[(0,r.jsxs)("summary",{children:[(0,r.jsx)("code",{children:"POST"})," ",(0,r.jsx)("code",{children:(0,r.jsx)("b",{children:"uber.cadence.api.v1.VisibilityAPIListClosedWorkflowExecutions"})})]}),(0,r.jsx)(n.h4,{id:"list-closed-workflow-executions-in-a-domain",children:"List closed workflow executions in a domain"}),(0,r.jsx)(n.h5,{id:"headers-11",children:"Headers"}),(0,r.jsxs)(n.table,{children:[(0,r.jsx)(n.thead,{children:(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.th,{children:"name"}),(0,r.jsx)(n.th,{children:"example"})]})}),(0,r.jsxs)(n.tbody,{children:[(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"context-ttl-ms"}),(0,r.jsx)(n.td,{children:"2000"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-caller"}),(0,r.jsx)(n.td,{children:"curl-client"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-service"}),(0,r.jsx)(n.td,{children:"cadence-frontend"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-encoding"}),(0,r.jsx)(n.td,{children:"json"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-procedure"}),(0,r.jsx)(n.td,{children:"uber.cadence.api.v1.VisibilityAPIListClosedWorkflowExecutions"})]})]})]}),(0,r.jsx)(n.h5,{id:"example-payloads",children:"Example payloads"}),(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"startTimeFilter"})," is required while ",(0,r.jsx)(n.code,{children:"executionFilter"})," and ",(0,r.jsx)(n.code,{children:"typeFilter"})," are optional."]}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-json",children:'{\n "domain": "sample-domain",\n "start_time_filter": {\n "earliest_time": "2023-01-01T00:00:00Z",\n "latest_time": "2023-12-31T00:00:00Z"\n }\n}\n'})}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-json",children:'{\n "domain": "sample-domain",\n "start_time_filter": {\n "earliest_time": "2023-01-01T00:00:00Z",\n "latest_time": "2023-12-31T00:00:00Z"\n },\n "execution_filter": {\n "workflow_id": "sample-workflow-id",\n "run_id": "71c3d47b-454a-4315-97c7-15355140094b"\n }\n}\n'})}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-json",children:'{\n "domain": "sample-domain",\n "start_time_filter": {\n "earliest_time": "2023-01-01T00:00:00Z",\n "latest_time": "2023-12-31T00:00:00Z"\n },\n "type_filter": {\n "name": "sample-workflow-type"\n }\n}\n'})}),(0,r.jsx)(n.h5,{id:"example-curl-11",children:"Example cURL"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-bash",children:'curl -X POST http://0.0.0.0:8800 \\\n -H \'context-ttl-ms: 2000\' \\\n -H \'rpc-caller: curl-client\' \\\n -H \'rpc-service: cadence-frontend\' \\\n -H \'rpc-encoding: json\' \\\n -H \'rpc-procedure: uber.cadence.api.v1.VisibilityAPI::ListClosedWorkflowExecutions\' \\\n -d \\\n \'{\n "domain": "sample-domain",\n "start_time_filter": {\n "earliest_time": "2023-01-01T00:00:00Z",\n "latest_time": "2023-12-31T00:00:00Z"\n }\n }\'\n'})}),(0,r.jsx)(n.h5,{id:"example-successful-response-11",children:"Example successful response"}),(0,r.jsx)(n.p,{children:"HTTP code: 200"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-json",children:'{\n "executions": [\n {\n "workflowExecution": {\n "workflowId": "sample-workflow-id",\n "runId": "71c3d47b-454a-4315-97c7-15355140094b"\n },\n "type": {\n "name": "sample-workflow-type"\n },\n "startTime": "2023-09-08T06:31:18.778Z",\n "closeTime": "2023-09-08T06:32:18.782Z",\n "closeStatus": "WORKFLOW_EXECUTION_CLOSE_STATUS_TIMED_OUT",\n "historyLength": "5",\n "executionTime": "2023-09-08T06:31:18.778Z",\n "memo": {},\n "searchAttributes": {\n "indexedFields": {}\n },\n "taskList": "sample-task-list"\n }\n ],\n "nextPageToken": ""\n}\n'})})]}),"\n",(0,r.jsx)(n.hr,{}),"\n",(0,r.jsxs)(s,{children:[(0,r.jsxs)("summary",{children:[(0,r.jsx)("code",{children:"POST"})," ",(0,r.jsx)("code",{children:(0,r.jsx)("b",{children:"uber.cadence.api.v1.VisibilityAPIListOpenWorkflowExecutions"})})]}),(0,r.jsx)(n.h4,{id:"list-open-workflow-executions-in-a-domain",children:"List open workflow executions in a domain"}),(0,r.jsx)(n.h5,{id:"headers-12",children:"Headers"}),(0,r.jsxs)(n.table,{children:[(0,r.jsx)(n.thead,{children:(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.th,{children:"name"}),(0,r.jsx)(n.th,{children:"example"})]})}),(0,r.jsxs)(n.tbody,{children:[(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"context-ttl-ms"}),(0,r.jsx)(n.td,{children:"2000"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-caller"}),(0,r.jsx)(n.td,{children:"curl-client"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-service"}),(0,r.jsx)(n.td,{children:"cadence-frontend"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-encoding"}),(0,r.jsx)(n.td,{children:"json"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-procedure"}),(0,r.jsx)(n.td,{children:"uber.cadence.api.v1.VisibilityAPIListOpenWorkflowExecutions"})]})]})]}),(0,r.jsx)(n.h5,{id:"example-payloads-1",children:"Example payloads"}),(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"startTimeFilter"})," is required while ",(0,r.jsx)(n.code,{children:"executionFilter"})," and ",(0,r.jsx)(n.code,{children:"typeFilter"})," are optional."]}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-json",children:'{\n "domain": "sample-domain",\n "start_time_filter": {\n "earliest_time": "2023-01-01T00:00:00Z",\n "latest_time": "2023-12-31T00:00:00Z"\n }\n}\n'})}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-json",children:'{\n "domain": "sample-domain",\n "start_time_filter": {\n "earliest_time": "2023-01-01T00:00:00Z",\n "latest_time": "2023-12-31T00:00:00Z"\n },\n "execution_filter": {\n "workflow_id": "sample-workflow-id",\n "run_id": "71c3d47b-454a-4315-97c7-15355140094b"\n }\n}\n'})}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-json",children:'{\n "domain": "sample-domain",\n "start_time_filter": {\n "earliest_time": "2023-01-01T00:00:00Z",\n "latest_time": "2023-12-31T00:00:00Z"\n },\n "type_filter": {\n "name": "sample-workflow-type"\n }\n}\n'})}),(0,r.jsx)(n.h5,{id:"example-curl-12",children:"Example cURL"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-bash",children:'curl -X POST http://0.0.0.0:8800 \\\n -H \'context-ttl-ms: 2000\' \\\n -H \'rpc-caller: curl-client\' \\\n -H \'rpc-service: cadence-frontend\' \\\n -H \'rpc-encoding: json\' \\\n -H \'rpc-procedure: uber.cadence.api.v1.VisibilityAPI::ListOpenWorkflowExecutions\' \\\n -d \\\n \'{\n "domain": "sample-domain",\n "start_time_filter": {\n "earliest_time": "2023-01-01T00:00:00Z",\n "latest_time": "2023-12-31T00:00:00Z"\n }\n }\'\n'})}),(0,r.jsx)(n.h5,{id:"example-successful-response-12",children:"Example successful response"}),(0,r.jsx)(n.p,{children:"HTTP code: 200"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-json",children:'{\n "executions": [\n {\n "workflowExecution": {\n "workflowId": "sample-workflow-id",\n "runId": "5dbabeeb-82a2-41ed-bf55-dc732a4d46ce"\n },\n "type": {\n "name": "sample-workflow-type"\n },\n "startTime": "2023-09-12T02:17:46.596Z",\n "executionTime": "2023-09-12T02:17:46.596Z",\n "memo": {},\n "searchAttributes": {\n "indexedFields": {}\n },\n "taskList": "sample-task-list"\n }\n ],\n "nextPageToken": ""\n}\n'})})]}),"\n",(0,r.jsx)(n.hr,{}),"\n",(0,r.jsx)(n.h3,{id:"workflow-api",children:"Workflow API"}),"\n",(0,r.jsx)(n.hr,{}),"\n",(0,r.jsxs)(s,{children:[(0,r.jsxs)("summary",{children:[(0,r.jsx)("code",{children:"POST"})," ",(0,r.jsx)("code",{children:(0,r.jsx)("b",{children:"uber.cadence.api.v1.WorkflowAPIDescribeTaskList"})})]}),(0,r.jsx)(n.h4,{id:"describe-pollers-info-of-tasklist",children:"Describe pollers info of tasklist"}),(0,r.jsx)(n.h5,{id:"headers-13",children:"Headers"}),(0,r.jsxs)(n.table,{children:[(0,r.jsx)(n.thead,{children:(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.th,{children:"name"}),(0,r.jsx)(n.th,{children:"example"})]})}),(0,r.jsxs)(n.tbody,{children:[(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"context-ttl-ms"}),(0,r.jsx)(n.td,{children:"2000"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-caller"}),(0,r.jsx)(n.td,{children:"curl-client"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-service"}),(0,r.jsx)(n.td,{children:"cadence-frontend"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-encoding"}),(0,r.jsx)(n.td,{children:"json"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-procedure"}),(0,r.jsx)(n.td,{children:"uber.cadence.api.v1.WorkflowAPIDescribeTaskList"})]})]})]}),(0,r.jsx)(n.h5,{id:"example-payload-11",children:"Example payload"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-json",children:'{\n "domain": "sample-domain",\n "task_list": {\n "name": "sample-task-list",\n "kind": 1\n },\n "task_list_type": 1,\n "include_task_list_status": true\n}\n'})}),(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"task_list"})," kind is optional."]}),(0,r.jsx)(n.p,{children:"Task list kinds"}),(0,r.jsxs)(n.table,{children:[(0,r.jsx)(n.thead,{children:(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.th,{children:"type"}),(0,r.jsx)(n.th,{children:"value"})]})}),(0,r.jsxs)(n.tbody,{children:[(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"TaskListKindNormal"}),(0,r.jsx)(n.td,{children:"1"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"TaskListKindSticky"}),(0,r.jsx)(n.td,{children:"2"})]})]})]}),(0,r.jsx)(n.p,{children:"Task list types"}),(0,r.jsxs)(n.table,{children:[(0,r.jsx)(n.thead,{children:(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.th,{children:"type"}),(0,r.jsx)(n.th,{children:"value"})]})}),(0,r.jsxs)(n.tbody,{children:[(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"TaskListTypeDecision"}),(0,r.jsx)(n.td,{children:"1"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"TaskListTypeActivity"}),(0,r.jsx)(n.td,{children:"2"})]})]})]}),(0,r.jsx)(n.h5,{id:"example-curl-13",children:"Example cURL"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-bash",children:'curl -X POST http://0.0.0.0:8800 \\\n -H \'context-ttl-ms: 2000\' \\\n -H \'rpc-caller: curl-client\' \\\n -H \'rpc-service: cadence-frontend\' \\\n -H \'rpc-encoding: json\' \\\n -H \'rpc-procedure: uber.cadence.api.v1.WorkflowAPI::DescribeTaskList\' \\\n -d \\\n \'{\n "domain": "sample-domain",\n "task_list": {\n "name": "sample-task-list",\n "kind": 1\n },\n "task_list_type": 1,\n "include_task_list_status": true\n }\'\n'})}),(0,r.jsx)(n.h5,{id:"example-successful-response-13",children:"Example successful response"}),(0,r.jsx)(n.p,{children:"HTTP code: 200"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-json",children:'{\n "taskListStatus": {\n "readLevel": "200000",\n "ratePerSecond": 100000,\n "taskIdBlock": {\n "startId": "200001",\n "endId": "300000"\n }\n }\n}\n'})})]}),"\n",(0,r.jsx)(n.hr,{}),"\n",(0,r.jsxs)(s,{children:[(0,r.jsxs)("summary",{children:[(0,r.jsx)("code",{children:"POST"})," ",(0,r.jsx)("code",{children:(0,r.jsx)("b",{children:"uber.cadence.api.v1.WorkflowAPIDescribeWorkflowExecution"})})]}),(0,r.jsx)(n.h4,{id:"describe-a-workflow-execution",children:"Describe a workflow execution"}),(0,r.jsx)(n.h5,{id:"headers-14",children:"Headers"}),(0,r.jsxs)(n.table,{children:[(0,r.jsx)(n.thead,{children:(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.th,{children:"name"}),(0,r.jsx)(n.th,{children:"example"})]})}),(0,r.jsxs)(n.tbody,{children:[(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"context-ttl-ms"}),(0,r.jsx)(n.td,{children:"2000"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-caller"}),(0,r.jsx)(n.td,{children:"curl-client"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-service"}),(0,r.jsx)(n.td,{children:"cadence-frontend"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-encoding"}),(0,r.jsx)(n.td,{children:"json"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-procedure"}),(0,r.jsx)(n.td,{children:"uber.cadence.api.v1.WorkflowAPIDescribeWorkflowExecution"})]})]})]}),(0,r.jsx)(n.h5,{id:"example-payload-12",children:"Example payload"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-json",children:'{\n "domain": "sample-domain",\n "workflow_execution": {\n "workflow_id": "sample-workflow-id",\n "run_id": "5dbabeeb-82a2-41ed-bf55-dc732a4d46ce"\n }\n}\n'})}),(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"run_id"})," is optional and allows to describe a specific run."]}),(0,r.jsx)(n.h5,{id:"example-curl-14",children:"Example cURL"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-bash",children:'curl -X POST http://0.0.0.0:8800 \\\n -H \'context-ttl-ms: 2000\' \\\n -H \'rpc-caller: curl-client\' \\\n -H \'rpc-service: cadence-frontend\' \\\n -H \'rpc-encoding: json\' \\\n -H \'rpc-procedure: uber.cadence.api.v1.WorkflowAPI::DescribeWorkflowExecution\' \\\n -d \\\n \'{\n "domain": "sample-domain",\n "workflow_execution": {\n "workflow_id": "sample-workflow-id",\n "run_id": "5dbabeeb-82a2-41ed-bf55-dc732a4d46ce"\n }\n }\'\n'})}),(0,r.jsx)(n.h5,{id:"example-successful-response-14",children:"Example successful response"}),(0,r.jsx)(n.p,{children:"HTTP code: 200"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-json",children:'{\n "executionConfiguration": {\n "taskList": {\n "name": "sample-task-list"\n },\n "executionStartToCloseTimeout": "11s",\n "taskStartToCloseTimeout": "10s"\n },\n "workflowExecutionInfo": {\n "workflowExecution": {\n "workflowId": "sample-workflow-id",\n "runId": "5dbabeeb-82a2-41ed-bf55-dc732a4d46ce"\n },\n "type": {\n "name": "sample-workflow-type"\n },\n "startTime": "2023-09-12T02:17:46.596Z",\n "closeTime": "2023-09-12T02:17:57.602707Z",\n "closeStatus": "WORKFLOW_EXECUTION_CLOSE_STATUS_TIMED_OUT",\n "historyLength": "3",\n "executionTime": "2023-09-12T02:17:46.596Z",\n "memo": {},\n "searchAttributes": {},\n "autoResetPoints": {}\n },\n "pendingDecision": {\n "state": "PENDING_DECISION_STATE_SCHEDULED",\n "scheduledTime": "2023-09-12T02:17:46.596982Z",\n "originalScheduledTime": "2023-09-12T02:17:46.596982Z"\n }\n}\n'})})]}),"\n",(0,r.jsx)(n.hr,{}),"\n",(0,r.jsxs)(s,{children:[(0,r.jsxs)("summary",{children:[(0,r.jsx)("code",{children:"POST"})," ",(0,r.jsx)("code",{children:(0,r.jsx)("b",{children:"uber.cadence.api.v1.WorkflowAPIGetClusterInfo"})})]}),(0,r.jsx)(n.h4,{id:"get-supported-client-versions-for-the-cluster",children:"Get supported client versions for the cluster"}),(0,r.jsx)(n.h5,{id:"headers-15",children:"Headers"}),(0,r.jsxs)(n.table,{children:[(0,r.jsx)(n.thead,{children:(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.th,{children:"name"}),(0,r.jsx)(n.th,{children:"example"})]})}),(0,r.jsxs)(n.tbody,{children:[(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"context-ttl-ms"}),(0,r.jsx)(n.td,{children:"2000"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-caller"}),(0,r.jsx)(n.td,{children:"curl-client"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-service"}),(0,r.jsx)(n.td,{children:"cadence-frontend"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-encoding"}),(0,r.jsx)(n.td,{children:"json"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-procedure"}),(0,r.jsx)(n.td,{children:"uber.cadence.api.v1.WorkflowAPIGetClusterInfo"})]})]})]}),(0,r.jsx)(n.h5,{id:"example-payload-13",children:"Example payload"}),(0,r.jsx)(n.p,{children:"None"}),(0,r.jsx)(n.h5,{id:"example-curl-15",children:"Example cURL"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-bash",children:"curl -X POST http://0.0.0.0:8800 \\\n -H 'context-ttl-ms: 2000' \\\n -H 'rpc-caller: curl-client' \\\n -H 'rpc-service: cadence-frontend' \\\n -H 'rpc-encoding: json' \\\n -H 'rpc-procedure: uber.cadence.api.v1.WorkflowAPI::GetClusterInfo'\n"})}),(0,r.jsx)(n.h5,{id:"example-successful-response-15",children:"Example successful response"}),(0,r.jsx)(n.p,{children:"HTTP code: 200"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-json",children:'{\n "supportedClientVersions": {\n "goSdk": "1.7.0",\n "javaSdk": "1.5.0"\n }\n}\n'})})]}),"\n",(0,r.jsx)(n.hr,{}),"\n",(0,r.jsxs)(s,{children:[(0,r.jsxs)("summary",{children:[(0,r.jsx)("code",{children:"POST"})," ",(0,r.jsx)("code",{children:(0,r.jsx)("b",{children:"uber.cadence.api.v1.WorkflowAPIGetTaskListsByDomain"})})]}),(0,r.jsx)(n.h4,{id:"get-the-task-lists-in-a-domain",children:"Get the task lists in a domain"}),(0,r.jsx)(n.h5,{id:"headers-16",children:"Headers"}),(0,r.jsxs)(n.table,{children:[(0,r.jsx)(n.thead,{children:(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.th,{children:"name"}),(0,r.jsx)(n.th,{children:"example"})]})}),(0,r.jsxs)(n.tbody,{children:[(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"context-ttl-ms"}),(0,r.jsx)(n.td,{children:"2000"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-caller"}),(0,r.jsx)(n.td,{children:"curl-client"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-service"}),(0,r.jsx)(n.td,{children:"cadence-frontend"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-encoding"}),(0,r.jsx)(n.td,{children:"json"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-procedure"}),(0,r.jsx)(n.td,{children:"uber.cadence.api.v1.WorkflowAPIGetTaskListsByDomain"})]})]})]}),(0,r.jsx)(n.h5,{id:"example-payload-14",children:"Example payload"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-json",children:'{\n "domain": "sample-domain"\n}\n'})}),(0,r.jsx)(n.h5,{id:"example-curl-16",children:"Example cURL"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-bash",children:"curl -X POST http://0.0.0.0:8800 \\\n -H 'context-ttl-ms: 2000' \\\n -H 'rpc-caller: curl-client' \\\n -H 'rpc-service: cadence-frontend' \\\n -H 'rpc-encoding: json' \\\n -H 'rpc-procedure: uber.cadence.api.v1.WorkflowAPI::GetTaskListsByDomain' \\\n -d \\\n '{\n \"domain\": \"sample-domain\"\n }'\n"})}),(0,r.jsx)(n.h5,{id:"example-successful-response-16",children:"Example successful response"}),(0,r.jsx)(n.p,{children:"HTTP code: 200"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-json",children:'{\n "decisionTaskListMap": {},\n "activityTaskListMap": {}\n}\n'})})]}),"\n",(0,r.jsx)(n.hr,{}),"\n",(0,r.jsxs)(s,{children:[(0,r.jsxs)("summary",{children:[(0,r.jsx)("code",{children:"POST"})," ",(0,r.jsx)("code",{children:(0,r.jsx)("b",{children:"uber.cadence.api.v1.WorkflowAPIGetWorkflowExecutionHistory"})})]}),(0,r.jsx)(n.h4,{id:"get-the-history-of-workflow-executions",children:"Get the history of workflow executions"}),(0,r.jsx)(n.h5,{id:"headers-17",children:"Headers"}),(0,r.jsxs)(n.table,{children:[(0,r.jsx)(n.thead,{children:(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.th,{children:"name"}),(0,r.jsx)(n.th,{children:"example"})]})}),(0,r.jsxs)(n.tbody,{children:[(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"context-ttl-ms"}),(0,r.jsx)(n.td,{children:"2000"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-caller"}),(0,r.jsx)(n.td,{children:"curl-client"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-service"}),(0,r.jsx)(n.td,{children:"cadence-frontend"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-encoding"}),(0,r.jsx)(n.td,{children:"json"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-procedure"}),(0,r.jsx)(n.td,{children:"uber.cadence.api.v1.WorkflowAPIGetWorkflowExecutionHistory"})]})]})]}),(0,r.jsx)(n.h5,{id:"example-payload-15",children:"Example payload"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-json",children:'{\n "domain": "sample-domain",\n "workflow_execution": {\n "workflow_id": "sample-workflow-id"\n }\n}\n'})}),(0,r.jsx)(n.h5,{id:"example-curl-17",children:"Example cURL"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-bash",children:"curl -X POST http://0.0.0.0:8800 \\\n -H 'context-ttl-ms: 2000' \\\n -H 'rpc-caller: curl-client' \\\n -H 'rpc-service: cadence-frontend' \\\n -H 'rpc-encoding: json' \\\n -H 'rpc-procedure: uber.cadence.api.v1.WorkflowAPI::GetWorkflowExecutionHistory' \\\n -d \\\n '{\n \"domain\": \"sample-domain\",\n \"workflow_execution\": {\n \"workflow_id\": \"sample-workflow-id\"\n }\n }'\n"})}),(0,r.jsx)(n.h5,{id:"example-successful-response-17",children:"Example successful response"}),(0,r.jsx)(n.p,{children:"HTTP code: 200"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-json",children:'{\n "history": {\n "events": [\n {\n "eventId": "1",\n "eventTime": "2023-09-12T05:34:46.107550Z",\n "taskId": "9437321",\n "workflowExecutionStartedEventAttributes": {\n "workflowType": {\n "name": "sample-workflow-type"\n },\n "taskList": {\n "name": "sample-task-list"\n },\n "input": {\n "data": "IkN1cmwhIg=="\n },\n "executionStartToCloseTimeout": "61s",\n "taskStartToCloseTimeout": "60s",\n "originalExecutionRunId": "fd7c2283-79dd-458c-8306-e2d1d8217613",\n "identity": "client-name-visible-in-history",\n "firstExecutionRunId": "fd7c2283-79dd-458c-8306-e2d1d8217613",\n "firstDecisionTaskBackoff": "0s"\n }\n },\n {\n "eventId": "2",\n "eventTime": "2023-09-12T05:34:46.107565Z",\n "taskId": "9437322",\n "decisionTaskScheduledEventAttributes": {\n "taskList": {\n "name": "sample-task-list"\n },\n "startToCloseTimeout": "60s"\n }\n },\n {\n "eventId": "3",\n "eventTime": "2023-09-12T05:34:59.184511Z",\n "taskId": "9437330",\n "workflowExecutionCancelRequestedEventAttributes": {\n "cause": "dummy",\n "identity": "client-name-visible-in-history"\n }\n },\n {\n "eventId": "4",\n "eventTime": "2023-09-12T05:35:47.112156Z",\n "taskId": "9437332",\n "workflowExecutionTimedOutEventAttributes": {\n "timeoutType": "TIMEOUT_TYPE_START_TO_CLOSE"\n }\n }\n ]\n }\n}\n'})})]}),"\n",(0,r.jsx)(n.hr,{}),"\n",(0,r.jsxs)(s,{children:[(0,r.jsxs)("summary",{children:[(0,r.jsx)("code",{children:"POST"})," ",(0,r.jsx)("code",{children:(0,r.jsx)("b",{children:"uber.cadence.api.v1.WorkflowAPIListTaskListPartitions"})})]}),(0,r.jsx)(n.h4,{id:"list-all-the-task-list-partitions-and-the-hostname-for-partitions",children:"List all the task list partitions and the hostname for partitions"}),(0,r.jsx)(n.h5,{id:"headers-18",children:"Headers"}),(0,r.jsxs)(n.table,{children:[(0,r.jsx)(n.thead,{children:(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.th,{children:"name"}),(0,r.jsx)(n.th,{children:"example"})]})}),(0,r.jsxs)(n.tbody,{children:[(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"context-ttl-ms"}),(0,r.jsx)(n.td,{children:"2000"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-caller"}),(0,r.jsx)(n.td,{children:"curl-client"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-service"}),(0,r.jsx)(n.td,{children:"cadence-frontend"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-encoding"}),(0,r.jsx)(n.td,{children:"json"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-procedure"}),(0,r.jsx)(n.td,{children:"uber.cadence.api.v1.WorkflowAPIListTaskListPartitions"})]})]})]}),(0,r.jsx)(n.h5,{id:"example-payload-16",children:"Example payload"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-json",children:'{\n "domain": "sample-domain",\n "task_list": {\n "name": "sample-task-list"\n }\n}\n'})}),(0,r.jsx)(n.h5,{id:"example-curl-18",children:"Example cURL"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-bash",children:"curl -X POST http://0.0.0.0:8800 \\\n -H 'context-ttl-ms: 2000' \\\n -H 'rpc-caller: curl-client' \\\n -H 'rpc-service: cadence-frontend' \\\n -H 'rpc-encoding: json' \\\n -H 'rpc-procedure: uber.cadence.api.v1.WorkflowAPI::ListTaskListPartitions' \\\n -d \\\n '{\n \"domain\": \"sample-domain\",\n \"task_list\": {\n \"name\": \"sample-task-list\"\n }\n }'\n"})}),(0,r.jsx)(n.h5,{id:"example-successful-response-18",children:"Example successful response"}),(0,r.jsx)(n.p,{children:"HTTP code: 200"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-json",children:'{\n "activityTaskListPartitions": [\n {\n "key": "sample-task-list",\n "ownerHostName": "127.0.0.1:7935"\n }\n ],\n "decisionTaskListPartitions": [\n {\n "key": "sample-task-list",\n "ownerHostName": "127.0.0.1:7935"\n }\n ]\n}\n'})})]}),"\n",(0,r.jsx)(n.hr,{}),"\n",(0,r.jsxs)(s,{children:[(0,r.jsxs)("summary",{children:[(0,r.jsx)("code",{children:"POST"})," ",(0,r.jsx)("code",{children:(0,r.jsx)("b",{children:"uber.cadence.api.v1.WorkflowAPIRefreshWorkflowTasks"})})]}),(0,r.jsx)(n.h4,{id:"refresh-all-the-tasks-of-a-workflow",children:"Refresh all the tasks of a workflow"}),(0,r.jsx)(n.h5,{id:"headers-19",children:"Headers"}),(0,r.jsxs)(n.table,{children:[(0,r.jsx)(n.thead,{children:(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.th,{children:"name"}),(0,r.jsx)(n.th,{children:"example"})]})}),(0,r.jsxs)(n.tbody,{children:[(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"context-ttl-ms"}),(0,r.jsx)(n.td,{children:"2000"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-caller"}),(0,r.jsx)(n.td,{children:"curl-client"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-service"}),(0,r.jsx)(n.td,{children:"cadence-frontend"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-encoding"}),(0,r.jsx)(n.td,{children:"json"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-procedure"}),(0,r.jsx)(n.td,{children:"uber.cadence.api.v1.WorkflowAPIRefreshWorkflowTasks"})]})]})]}),(0,r.jsx)(n.h5,{id:"example-payload-17",children:"Example payload"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-json",children:'{\n "domain": "sample-domain",\n "workflow_execution": {\n "workflow_id": "sample-workflow-id",\n "run_id": "b7973fb8-2229-4fe7-ad70-c919c1ae8774"\n }\n}\n'})}),(0,r.jsx)(n.h5,{id:"example-curl-19",children:"Example cURL"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-bash",children:'curl -X POST http://0.0.0.0:8800 \\\n -H \'context-ttl-ms: 2000\' \\\n -H \'rpc-caller: curl-client\' \\\n -H \'rpc-service: cadence-frontend\' \\\n -H \'rpc-encoding: json\' \\\n -H \'rpc-procedure: uber.cadence.api.v1.WorkflowAPI::RefreshWorkflowTasks\' \\\n -d \\\n \'{\n "domain": "sample-domain",\n "workflow_execution": {\n "workflow_id": "sample-workflow-id",\n "run_id": "b7973fb8-2229-4fe7-ad70-c919c1ae8774"\n }\n }\'\n'})}),(0,r.jsx)(n.h5,{id:"example-successful-response-19",children:"Example successful response"}),(0,r.jsx)(n.p,{children:"HTTP code: 200"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-json",children:"{}\n"})})]}),"\n",(0,r.jsx)(n.hr,{}),"\n",(0,r.jsxs)(s,{children:[(0,r.jsxs)("summary",{children:[(0,r.jsx)("code",{children:"POST"})," ",(0,r.jsx)("code",{children:(0,r.jsx)("b",{children:"uber.cadence.api.v1.WorkflowAPIRequestCancelWorkflowExecution"})})]}),(0,r.jsx)(n.h4,{id:"cancel-a-workflow-execution",children:"Cancel a workflow execution"}),(0,r.jsx)(n.h5,{id:"headers-20",children:"Headers"}),(0,r.jsxs)(n.table,{children:[(0,r.jsx)(n.thead,{children:(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.th,{children:"name"}),(0,r.jsx)(n.th,{children:"example"})]})}),(0,r.jsxs)(n.tbody,{children:[(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"context-ttl-ms"}),(0,r.jsx)(n.td,{children:"2000"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-caller"}),(0,r.jsx)(n.td,{children:"curl-client"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-service"}),(0,r.jsx)(n.td,{children:"cadence-frontend"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-encoding"}),(0,r.jsx)(n.td,{children:"json"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-procedure"}),(0,r.jsx)(n.td,{children:"uber.cadence.api.v1.WorkflowAPIRequestCancelWorkflowExecution"})]})]})]}),(0,r.jsx)(n.h5,{id:"example-payload-18",children:"Example payload"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-json",children:'{\n "domain": "sample-domain",\n "workflow_execution": {\n "workflow_id": "sample-workflow-id",\n "run_id": "b7973fb8-2229-4fe7-ad70-c919c1ae8774"\n },\n "request_id": "8049B932-6C2F-415A-9BB2-241DCF4CFC9C",\n "cause": "dummy",\n "identity": "client-name-visible-in-history",\n "first_execution_run_id": "b7973fb8-2229-4fe7-ad70-c919c1ae8774"\n}\n'})}),(0,r.jsx)(n.h5,{id:"example-curl-20",children:"Example cURL"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-bash",children:'curl -X POST http://0.0.0.0:8800 \\\n -H \'context-ttl-ms: 2000\' \\\n -H \'rpc-caller: curl-client\' \\\n -H \'rpc-service: cadence-frontend\' \\\n -H \'rpc-encoding: json\' \\\n -H \'rpc-procedure: uber.cadence.api.v1.WorkflowAPI::RequestCancelWorkflowExecution\' \\\n -d \\\n \'{\n "domain": "sample-domain",\n "workflow_execution": {\n "workflow_id": "sample-workflow-id",\n "run_id": "fd7c2283-79dd-458c-8306-e2d1d8217613"\n },\n "request_id": "8049B932-6C2F-415A-9BB2-241DCF4CFC9C",\n "cause": "dummy",\n "identity": "client-name-visible-in-history",\n "first_execution_run_id": "fd7c2283-79dd-458c-8306-e2d1d8217613"\n }\'\n'})}),(0,r.jsx)(n.h5,{id:"example-successful-response-20",children:"Example successful response"}),(0,r.jsx)(n.p,{children:"HTTP code: 200"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-json",children:"{}\n"})})]}),"\n",(0,r.jsx)(n.hr,{}),"\n",(0,r.jsxs)(s,{children:[(0,r.jsxs)("summary",{children:[(0,r.jsx)("code",{children:"POST"})," ",(0,r.jsx)("code",{children:(0,r.jsx)("b",{children:"uber.cadence.api.v1.WorkflowAPIRestartWorkflowExecution"})})]}),(0,r.jsx)(n.h4,{id:"restart-a-previous-workflow-execution",children:"Restart a previous workflow execution"}),(0,r.jsx)(n.h5,{id:"headers-21",children:"Headers"}),(0,r.jsxs)(n.table,{children:[(0,r.jsx)(n.thead,{children:(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.th,{children:"name"}),(0,r.jsx)(n.th,{children:"example"})]})}),(0,r.jsxs)(n.tbody,{children:[(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"context-ttl-ms"}),(0,r.jsx)(n.td,{children:"2000"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-caller"}),(0,r.jsx)(n.td,{children:"curl-client"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-service"}),(0,r.jsx)(n.td,{children:"cadence-frontend"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-encoding"}),(0,r.jsx)(n.td,{children:"json"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-procedure"}),(0,r.jsx)(n.td,{children:"uber.cadence.api.v1.WorkflowAPIRestartWorkflowExecution"})]})]})]}),(0,r.jsx)(n.h5,{id:"example-payload-19",children:"Example payload"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-json",children:'{\n "domain": "sample-domain",\n "workflow_execution": {\n "workflow_id": "sample-workflow-id",\n "run_id": "0f95ad5b-03bc-4c6b-8cf0-1f3ea08eb86a"\n },\n "identity": "client-name-visible-in-history",\n "reason": "dummy"\n}\n'})}),(0,r.jsx)(n.h5,{id:"example-curl-21",children:"Example cURL"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-bash",children:'curl -X POST http://0.0.0.0:8800 \\\n -H \'context-ttl-ms: 2000\' \\\n -H \'rpc-caller: curl-client\' \\\n -H \'rpc-service: cadence-frontend\' \\\n -H \'rpc-encoding: json\' \\\n -H \'rpc-procedure: uber.cadence.api.v1.WorkflowAPI::RestartWorkflowExecution\' \\\n -d \\\n \'{\n "domain": "sample-domain",\n "workflow_execution": {\n "workflow_id": "sample-workflow-id",\n "run_id": "0f95ad5b-03bc-4c6b-8cf0-1f3ea08eb86a"\n },\n "identity": "client-name-visible-in-history",\n "reason": "dummy"\n }\'\n'})}),(0,r.jsx)(n.h5,{id:"example-successful-response-21",children:"Example successful response"}),(0,r.jsx)(n.p,{children:"HTTP code: 200"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-json",children:'{\n "runId": "82914458-3221-42b4-ae54-2e66dff864f7"\n}\n'})})]}),"\n",(0,r.jsx)(n.hr,{}),"\n",(0,r.jsxs)(s,{children:[(0,r.jsxs)("summary",{children:[(0,r.jsx)("code",{children:"POST"})," ",(0,r.jsx)("code",{children:(0,r.jsx)("b",{children:"uber.cadence.api.v1.WorkflowAPISignalWithStartWorkflowExecution"})})]}),(0,r.jsx)(n.h4,{id:"signal-the-current-open-workflow-if-exists-or-attempt-to-start-a-new-run-based-on-idresuepolicy-and-signals-it",children:"Signal the current open workflow if exists, or attempt to start a new run based on IDResuePolicy and signals it"}),(0,r.jsx)(n.h5,{id:"headers-22",children:"Headers"}),(0,r.jsxs)(n.table,{children:[(0,r.jsx)(n.thead,{children:(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.th,{children:"name"}),(0,r.jsx)(n.th,{children:"example"})]})}),(0,r.jsxs)(n.tbody,{children:[(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"context-ttl-ms"}),(0,r.jsx)(n.td,{children:"2000"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-caller"}),(0,r.jsx)(n.td,{children:"curl-client"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-service"}),(0,r.jsx)(n.td,{children:"cadence-frontend"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-encoding"}),(0,r.jsx)(n.td,{children:"json"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-procedure"}),(0,r.jsx)(n.td,{children:"uber.cadence.api.v1.WorkflowAPISignalWithStartWorkflowExecution"})]})]})]}),(0,r.jsx)(n.h5,{id:"example-payload-20",children:"Example payload"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-json",children:'{\n "start_request": {\n "domain": "sample-domain",\n "workflow_id": "sample-workflow-id",\n "execution_start_to_close_timeout": "61s",\n "task_start_to_close_timeout": "60s",\n "workflow_type": {\n "name": "sample-workflow-type"\n },\n "task_list": {\n "name": "sample-task-list"\n },\n "identity": "client-name-visible-in-history",\n "request_id": "8049B932-6C2F-415A-9BB2-241DCF4CFC9C",\n "input": {\n "data": "IkN1cmwhIg=="\n }\n },\n "signal_name": "channelA",\n "signal_input": {\n "data": "MTA="\n }\n}\n'})}),(0,r.jsx)(n.h5,{id:"example-curl-22",children:"Example cURL"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-bash",children:'curl -X POST http://0.0.0.0:8800 \\\n -H \'context-ttl-ms: 2000\' \\\n -H \'rpc-caller: curl-client\' \\\n -H \'rpc-service: cadence-frontend\' \\\n -H \'rpc-encoding: json\' \\\n -H \'rpc-procedure: uber.cadence.api.v1.WorkflowAPI::SignalWithStartWorkflowExecution\' \\\n -d \\\n \'{\n "start_request": {\n "domain": "sample-domain",\n "workflow_id": "sample-workflow-id",\n "execution_start_to_close_timeout": "61s",\n "task_start_to_close_timeout": "60s",\n "workflow_type": {\n "name": "sample-workflow-type"\n },\n "task_list": {\n "name": "sample-task-list"\n },\n "identity": "client-name-visible-in-history",\n "request_id": "8049B932-6C2F-415A-9BB2-241DCF4CFC9C",\n "input": {\n "data": "IkN1cmwhIg=="\n }\n },\n "signal_name": "channelA",\n "signal_input": {\n "data": "MTA="\n }\n }\'\n'})}),(0,r.jsx)(n.h5,{id:"example-successful-response-22",children:"Example successful response"}),(0,r.jsx)(n.p,{children:"HTTP code: 200"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-json",children:'{\n "runId": "cc09d5dd-b2fa-46d8-b426-54c96b12d18f"\n}\n'})})]}),"\n",(0,r.jsx)(n.hr,{}),"\n",(0,r.jsxs)(s,{children:[(0,r.jsxs)("summary",{children:[(0,r.jsx)("code",{children:"POST"})," ",(0,r.jsx)("code",{children:(0,r.jsx)("b",{children:"uber.cadence.api.v1.WorkflowAPISignalWorkflowExecution"})})]}),(0,r.jsx)(n.h4,{id:"signal-a-workflow-execution",children:"Signal a workflow execution"}),(0,r.jsx)(n.h5,{id:"headers-23",children:"Headers"}),(0,r.jsxs)(n.table,{children:[(0,r.jsx)(n.thead,{children:(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.th,{children:"name"}),(0,r.jsx)(n.th,{children:"example"})]})}),(0,r.jsxs)(n.tbody,{children:[(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"context-ttl-ms"}),(0,r.jsx)(n.td,{children:"2000"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-caller"}),(0,r.jsx)(n.td,{children:"curl-client"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-service"}),(0,r.jsx)(n.td,{children:"cadence-frontend"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-encoding"}),(0,r.jsx)(n.td,{children:"json"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-procedure"}),(0,r.jsx)(n.td,{children:"uber.cadence.api.v1.WorkflowAPISignalWorkflowExecution"})]})]})]}),(0,r.jsx)(n.h5,{id:"example-payload-21",children:"Example payload"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-json",children:'{\n "domain": "sample-domain",\n "workflow_execution": {\n "workflow_id": "sample-workflow-id",\n "run_id": "cc09d5dd-b2fa-46d8-b426-54c96b12d18f"\n },\n "signal_name": "channelA",\n "signal_input": {\n "data": "MTA="\n }\n}\n'})}),(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"run_id"})," is optional and allows to signal a specific run."]}),(0,r.jsx)(n.h5,{id:"example-curl-23",children:"Example cURL"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-bash",children:'curl -X POST http://0.0.0.0:8800 \\\n -H \'context-ttl-ms: 2000\' \\\n -H \'rpc-caller: curl-client\' \\\n -H \'rpc-service: cadence-frontend\' \\\n -H \'rpc-encoding: json\' \\\n -H \'rpc-procedure: uber.cadence.api.v1.WorkflowAPI::SignalWorkflowExecution\' \\\n -d \\\n \'{\n "domain": "sample-domain",\n "workflow_execution": {\n "workflow_id": "sample-workflow-id"\n },\n "signal_name": "channelA",\n "signal_input": {\n "data": "MTA="\n }\n }\'\n'})}),(0,r.jsx)(n.h5,{id:"example-successful-response-23",children:"Example successful response"}),(0,r.jsx)(n.p,{children:"HTTP code: 200"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-json",children:"{}\n"})})]}),"\n",(0,r.jsx)(n.hr,{}),"\n",(0,r.jsxs)(s,{children:[(0,r.jsxs)("summary",{children:[(0,r.jsx)("code",{children:"POST"})," ",(0,r.jsx)("code",{children:(0,r.jsx)("b",{children:"uber.cadence.api.v1.WorkflowAPIStartWorkflowExecution"})})]}),(0,r.jsx)(n.h4,{id:"start-a-new-workflow-execution",children:"Start a new workflow execution"}),(0,r.jsx)(n.h5,{id:"headers-24",children:"Headers"}),(0,r.jsxs)(n.table,{children:[(0,r.jsx)(n.thead,{children:(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.th,{children:"name"}),(0,r.jsx)(n.th,{children:"example"})]})}),(0,r.jsxs)(n.tbody,{children:[(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"context-ttl-ms"}),(0,r.jsx)(n.td,{children:"2000"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-caller"}),(0,r.jsx)(n.td,{children:"curl-client"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-service"}),(0,r.jsx)(n.td,{children:"cadence-frontend"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-encoding"}),(0,r.jsx)(n.td,{children:"json"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-procedure"}),(0,r.jsx)(n.td,{children:"uber.cadence.api.v1.WorkflowAPIStartWorkflowExecution"})]})]})]}),(0,r.jsx)(n.h5,{id:"example-payload-22",children:"Example payload"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-json",children:'{\n "domain": "sample-domain",\n "workflow_id": "sample-workflow-id",\n "execution_start_to_close_timeout": "61s",\n "task_start_to_close_timeout": "60s",\n "workflow_type": {\n "name": "sample-workflow-type"\n },\n "task_list": {\n "name": "sample-task-list"\n },\n "identity": "client-name-visible-in-history",\n "request_id": "8049B932-6C2F-415A-9BB2-241DCF4CFC9C",\n "input": {\n "data": "IkN1cmwhIg=="\n }\n}\n'})}),(0,r.jsx)(n.h5,{id:"example-curl-24",children:"Example cURL"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-bash",children:'curl -X POST http://0.0.0.0:8800 \\\n -H \'context-ttl-ms: 2000\' \\\n -H \'rpc-caller: curl-client\' \\\n -H \'rpc-service: cadence-frontend\' \\\n -H \'rpc-encoding: json\' \\\n -H \'rpc-procedure: uber.cadence.api.v1.WorkflowAPI::StartWorkflowExecution\' \\\n -d \\\n \'{\n "domain": "sample-domain",\n "workflow_id": "sample-workflow-id",\n "execution_start_to_close_timeout": "61s",\n "task_start_to_close_timeout": "60s",\n "workflow_type": {\n "name": "sample-workflow-type"\n },\n "task_list": {\n "name": "sample-task-list"\n },\n "identity": "client-name-visible-in-history",\n "request_id": "8049B932-6C2F-415A-9BB2-241DCF4CFC9C",\n "input": {\n "data": "IkN1cmwhIg=="\n }\n }\'\n'})}),(0,r.jsx)(n.h5,{id:"example-successful-response-24",children:"Example successful response"}),(0,r.jsx)(n.p,{children:"HTTP code: 200"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-json",children:'{\n "runId": "cc09d5dd-b2fa-46d8-b426-54c96b12d18f"\n}\n'})})]}),"\n",(0,r.jsx)(n.hr,{}),"\n",(0,r.jsxs)(s,{children:[(0,r.jsxs)("summary",{children:[(0,r.jsx)("code",{children:"POST"})," ",(0,r.jsx)("code",{children:(0,r.jsx)("b",{children:"uber.cadence.api.v1.WorkflowAPITerminateWorkflowExecution"})})]}),(0,r.jsx)(n.h4,{id:"terminate-a-new-workflow-execution",children:"Terminate a new workflow execution"}),(0,r.jsx)(n.h5,{id:"headers-25",children:"Headers"}),(0,r.jsxs)(n.table,{children:[(0,r.jsx)(n.thead,{children:(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.th,{children:"name"}),(0,r.jsx)(n.th,{children:"example"})]})}),(0,r.jsxs)(n.tbody,{children:[(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"context-ttl-ms"}),(0,r.jsx)(n.td,{children:"2000"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-caller"}),(0,r.jsx)(n.td,{children:"curl-client"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-service"}),(0,r.jsx)(n.td,{children:"cadence-frontend"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-encoding"}),(0,r.jsx)(n.td,{children:"json"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-procedure"}),(0,r.jsx)(n.td,{children:"uber.cadence.api.v1.WorkflowAPITerminateWorkflowExecution"})]})]})]}),(0,r.jsx)(n.h5,{id:"example-payloads-2",children:"Example payloads"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-json",children:'{\n "domain": "sample-domain",\n "workflow_execution": {\n "workflow_id": "sample-workflow-id"\n }\n}\n'})}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-json",children:'{\n "domain": "sample-domain",\n "workflow_execution": {\n "workflow_id": "sample-workflow-id",\n "run_id": "0f95ad5b-03bc-4c6b-8cf0-1f3ea08eb86a"\n },\n "reason": "dummy",\n "identity": "client-name-visible-in-history",\n "first_execution_run_id": "0f95ad5b-03bc-4c6b-8cf0-1f3ea08eb86a"\n}\n'})}),(0,r.jsx)(n.h5,{id:"example-curl-25",children:"Example cURL"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-bash",children:"curl -X POST http://0.0.0.0:8800 \\\n -H 'context-ttl-ms: 2000' \\\n -H 'rpc-caller: curl-client' \\\n -H 'rpc-service: cadence-frontend' \\\n -H 'rpc-encoding: json' \\\n -H 'rpc-procedure: uber.cadence.api.v1.WorkflowAPI::TerminateWorkflowExecution' \\\n -d \\\n '{\n \"domain\": \"sample-domain\",\n \"workflow_execution\": {\n \"workflow_id\": \"sample-workflow-id\"\n }\n }'\n"})}),(0,r.jsx)(n.h5,{id:"example-successful-response-25",children:"Example successful response"}),(0,r.jsx)(n.p,{children:"HTTP code: 200"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-json",children:"{}\n"})})]}),"\n",(0,r.jsx)(n.hr,{})]})}function h(e={}){const{wrapper:n}={...(0,c.R)(),...e.components};return n?(0,r.jsx)(n,{...e,children:(0,r.jsx)(o,{...e})}):o(e)}},8453:(e,n,s)=>{s.d(n,{R:()=>d,x:()=>i});var l=s(6540);const r={},c=l.createContext(r);function d(e){const n=l.useContext(c);return l.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function i(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:d(e.components),l.createElement(c.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/cd7e9a8f.e870c77c.js b/assets/js/cd7e9a8f.e870c77c.js deleted file mode 100644 index b4c961db3..000000000 --- a/assets/js/cd7e9a8f.e870c77c.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[7338],{3907:(e,n,s)=>{s.r(n),s.d(n,{assets:()=>a,contentTitle:()=>i,default:()=>h,frontMatter:()=>d,metadata:()=>l,toc:()=>t});const l=JSON.parse('{"id":"concepts/http-api","title":"HTTP API","description":"Introduction","source":"@site/docs/03-concepts/10-http-api.md","sourceDirName":"03-concepts","slug":"/concepts/http-api","permalink":"/docs/concepts/http-api","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/03-concepts/10-http-api.md","tags":[],"version":"current","sidebarPosition":10,"frontMatter":{"layout":"default","title":"HTTP API","permalink":"/docs/concepts/http-api"},"sidebar":"docsSidebar","previous":{"title":"Search workflows(Advanced visibility)","permalink":"/docs/concepts/search-workflows"},"next":{"title":"Introduction","permalink":"/docs/java-client/"}}');var r=s(4848),c=s(8453);const d={layout:"default",title:"HTTP API",permalink:"/docs/concepts/http-api"},i="Using HTTP API",a={},t=[{value:"Introduction",id:"introduction",level:2},{value:"Setup",id:"setup",level:2},{value:"Updating Cadence configuration files",id:"updating-cadence-configuration-files",level:3},{value:"Using local binaries",id:"using-local-binaries",level:3},{value:"Using \u201cdocker run\u201d command",id:"using-docker-run-command",level:3},{value:"Using docker-compose",id:"using-docker-compose",level:3},{value:"Using HTTP API",id:"using-http-api-1",level:2},{value:"HTTP API Reference",id:"http-api-reference",level:2},{value:"Admin API",id:"admin-api",level:3},{value:"Add search attributes to whitelist",id:"add-search-attributes-to-whitelist",level:4},{value:"Headers",id:"headers",level:5},{value:"Example payload",id:"example-payload",level:5},{value:"Example cURL",id:"example-curl",level:5},{value:"Example successful response",id:"example-successful-response",level:5},{value:"Close a shard given a shard ID",id:"close-a-shard-given-a-shard-id",level:4},{value:"Headers",id:"headers-1",level:5},{value:"Example payload",id:"example-payload-1",level:5},{value:"Example cURL",id:"example-curl-1",level:5},{value:"Example successful response",id:"example-successful-response-1",level:5},{value:"Count DLQ messages",id:"count-dlq-messages",level:4},{value:"Headers",id:"headers-2",level:5},{value:"Example payload",id:"example-payload-2",level:5},{value:"Example cURL",id:"example-curl-2",level:5},{value:"Example successful response",id:"example-successful-response-2",level:5},{value:"Describe cluster information",id:"describe-cluster-information",level:4},{value:"Headers",id:"headers-3",level:5},{value:"Example payload",id:"example-payload-3",level:5},{value:"Example cURL",id:"example-curl-3",level:5},{value:"Example successful response",id:"example-successful-response-3",level:5},{value:"Describe internal information of history host",id:"describe-internal-information-of-history-host",level:4},{value:"Headers",id:"headers-4",level:5},{value:"Example payload",id:"example-payload-4",level:5},{value:"Example cURL",id:"example-curl-4",level:5},{value:"Example successful response",id:"example-successful-response-4",level:5},{value:"List shard distribution",id:"list-shard-distribution",level:4},{value:"Headers",id:"headers-5",level:5},{value:"Example payload",id:"example-payload-5",level:5},{value:"Example cURL",id:"example-curl-5",level:5},{value:"Example successful response",id:"example-successful-response-5",level:5},{value:"Describe internal information of workflow execution",id:"describe-internal-information-of-workflow-execution",level:4},{value:"Headers",id:"headers-6",level:5},{value:"Example payload",id:"example-payload-6",level:5},{value:"Example cURL",id:"example-curl-6",level:5},{value:"Example successful response",id:"example-successful-response-6",level:5},{value:"Domain API",id:"domain-api",level:3},{value:"Describe existing workflow domain",id:"describe-existing-workflow-domain",level:4},{value:"Headers",id:"headers-7",level:5},{value:"Example payload",id:"example-payload-7",level:5},{value:"Example cURL",id:"example-curl-7",level:5},{value:"Example successful response",id:"example-successful-response-7",level:5},{value:"List all domains in the cluster",id:"list-all-domains-in-the-cluster",level:4},{value:"Headers",id:"headers-8",level:5},{value:"Example payload",id:"example-payload-8",level:5},{value:"Example cURL",id:"example-curl-8",level:5},{value:"Example successful response",id:"example-successful-response-8",level:5},{value:"Meta API",id:"meta-api",level:3},{value:"Health check",id:"health-check",level:4},{value:"Headers",id:"headers-9",level:5},{value:"Example payload",id:"example-payload-9",level:5},{value:"Example cURL",id:"example-curl-9",level:5},{value:"Example successful response",id:"example-successful-response-9",level:5},{value:"Visibility API",id:"visibility-api",level:3},{value:"Get search attributes",id:"get-search-attributes",level:4},{value:"Headers",id:"headers-10",level:5},{value:"Example payload",id:"example-payload-10",level:5},{value:"Example cURL",id:"example-curl-10",level:5},{value:"Example successful response",id:"example-successful-response-10",level:5},{value:"List closed workflow executions in a domain",id:"list-closed-workflow-executions-in-a-domain",level:4},{value:"Headers",id:"headers-11",level:5},{value:"Example payloads",id:"example-payloads",level:5},{value:"Example cURL",id:"example-curl-11",level:5},{value:"Example successful response",id:"example-successful-response-11",level:5},{value:"List open workflow executions in a domain",id:"list-open-workflow-executions-in-a-domain",level:4},{value:"Headers",id:"headers-12",level:5},{value:"Example payloads",id:"example-payloads-1",level:5},{value:"Example cURL",id:"example-curl-12",level:5},{value:"Example successful response",id:"example-successful-response-12",level:5},{value:"Workflow API",id:"workflow-api",level:3},{value:"Describe pollers info of tasklist",id:"describe-pollers-info-of-tasklist",level:4},{value:"Headers",id:"headers-13",level:5},{value:"Example payload",id:"example-payload-11",level:5},{value:"Example cURL",id:"example-curl-13",level:5},{value:"Example successful response",id:"example-successful-response-13",level:5},{value:"Describe a workflow execution",id:"describe-a-workflow-execution",level:4},{value:"Headers",id:"headers-14",level:5},{value:"Example payload",id:"example-payload-12",level:5},{value:"Example cURL",id:"example-curl-14",level:5},{value:"Example successful response",id:"example-successful-response-14",level:5},{value:"Get supported client versions for the cluster",id:"get-supported-client-versions-for-the-cluster",level:4},{value:"Headers",id:"headers-15",level:5},{value:"Example payload",id:"example-payload-13",level:5},{value:"Example cURL",id:"example-curl-15",level:5},{value:"Example successful response",id:"example-successful-response-15",level:5},{value:"Get the task lists in a domain",id:"get-the-task-lists-in-a-domain",level:4},{value:"Headers",id:"headers-16",level:5},{value:"Example payload",id:"example-payload-14",level:5},{value:"Example cURL",id:"example-curl-16",level:5},{value:"Example successful response",id:"example-successful-response-16",level:5},{value:"Get the history of workflow executions",id:"get-the-history-of-workflow-executions",level:4},{value:"Headers",id:"headers-17",level:5},{value:"Example payload",id:"example-payload-15",level:5},{value:"Example cURL",id:"example-curl-17",level:5},{value:"Example successful response",id:"example-successful-response-17",level:5},{value:"List all the task list partitions and the hostname for partitions",id:"list-all-the-task-list-partitions-and-the-hostname-for-partitions",level:4},{value:"Headers",id:"headers-18",level:5},{value:"Example payload",id:"example-payload-16",level:5},{value:"Example cURL",id:"example-curl-18",level:5},{value:"Example successful response",id:"example-successful-response-18",level:5},{value:"Refresh all the tasks of a workflow",id:"refresh-all-the-tasks-of-a-workflow",level:4},{value:"Headers",id:"headers-19",level:5},{value:"Example payload",id:"example-payload-17",level:5},{value:"Example cURL",id:"example-curl-19",level:5},{value:"Example successful response",id:"example-successful-response-19",level:5},{value:"Cancel a workflow execution",id:"cancel-a-workflow-execution",level:4},{value:"Headers",id:"headers-20",level:5},{value:"Example payload",id:"example-payload-18",level:5},{value:"Example cURL",id:"example-curl-20",level:5},{value:"Example successful response",id:"example-successful-response-20",level:5},{value:"Restart a previous workflow execution",id:"restart-a-previous-workflow-execution",level:4},{value:"Headers",id:"headers-21",level:5},{value:"Example payload",id:"example-payload-19",level:5},{value:"Example cURL",id:"example-curl-21",level:5},{value:"Example successful response",id:"example-successful-response-21",level:5},{value:"Signal the current open workflow if exists, or attempt to start a new run based on IDResuePolicy and signals it",id:"signal-the-current-open-workflow-if-exists-or-attempt-to-start-a-new-run-based-on-idresuepolicy-and-signals-it",level:4},{value:"Headers",id:"headers-22",level:5},{value:"Example payload",id:"example-payload-20",level:5},{value:"Example cURL",id:"example-curl-22",level:5},{value:"Example successful response",id:"example-successful-response-22",level:5},{value:"Signal a workflow execution",id:"signal-a-workflow-execution",level:4},{value:"Headers",id:"headers-23",level:5},{value:"Example payload",id:"example-payload-21",level:5},{value:"Example cURL",id:"example-curl-23",level:5},{value:"Example successful response",id:"example-successful-response-23",level:5},{value:"Start a new workflow execution",id:"start-a-new-workflow-execution",level:4},{value:"Headers",id:"headers-24",level:5},{value:"Example payload",id:"example-payload-22",level:5},{value:"Example cURL",id:"example-curl-24",level:5},{value:"Example successful response",id:"example-successful-response-24",level:5},{value:"Terminate a new workflow execution",id:"terminate-a-new-workflow-execution",level:4},{value:"Headers",id:"headers-25",level:5},{value:"Example payloads",id:"example-payloads-2",level:5},{value:"Example cURL",id:"example-curl-25",level:5},{value:"Example successful response",id:"example-successful-response-25",level:5}];function o(e){const n={a:"a",code:"code",h1:"h1",h2:"h2",h3:"h3",h4:"h4",h5:"h5",header:"header",hr:"hr",p:"p",pre:"pre",strong:"strong",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",...(0,c.R)(),...e.components},{Details:s}=n;return s||function(e,n){throw new Error("Expected "+(n?"component":"object")+" `"+e+"` to be defined: you likely forgot to import, pass, or provide it.")}("Details",!0),(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(n.header,{children:(0,r.jsx)(n.h1,{id:"using-http-api",children:"Using HTTP API"})}),"\n",(0,r.jsx)(n.h2,{id:"introduction",children:"Introduction"}),"\n",(0,r.jsxs)(n.p,{children:["From ",(0,r.jsx)(n.strong,{children:"version 1.2.0"})," onwards, Cadence has introduced HTTP API support, which allows you to interact with the Cadence server\nusing the HTTP protocol. To put this into perspective, HTTP/JSON communication is a flexible method for server interaction.\nIn the context of Cadence, this implies that a range of RPC methods can be exposed and invoked using the HTTP protocol.\nThis enhancement broadens the scope of interaction with the Cadence server, enabling the use of any programming language that supports HTTP.\nConsequently, you can leverage this functionality to initiate or terminate workflows from your bash scripts, monitor the\nstatus of your cluster, or execute any other operation that the Cadence RPC declaration supports."]}),"\n",(0,r.jsx)(n.h2,{id:"setup",children:"Setup"}),"\n",(0,r.jsx)(n.h3,{id:"updating-cadence-configuration-files",children:"Updating Cadence configuration files"}),"\n",(0,r.jsxs)(n.p,{children:["To enable \u201cstart workflow\u201d HTTP API, add ",(0,r.jsx)(n.code,{children:"http"})," section to Cadence RPC configuration settings (e.g., in ",(0,r.jsx)(n.code,{children:"base.yaml"})," or ",(0,r.jsx)(n.code,{children:"development.yaml"}),"):"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-yaml",children:"services:\n frontend:\n rpc:\n # ...\n http:\n port: 8800\n procedures:\n - uber.cadence.api.v1.WorkflowAPI::StartWorkflowExecution\n"})}),"\n",(0,r.jsx)(n.p,{children:"Then you can run Cadence server in the following ways to use HTTP API."}),"\n",(0,r.jsx)(n.h3,{id:"using-local-binaries",children:"Using local binaries"}),"\n",(0,r.jsxs)(n.p,{children:["Build and run ",(0,r.jsx)(n.code,{children:"./cadence-server"})," as described in ",(0,r.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence/blob/master/CONTRIBUTING.md",children:"Developing Cadence"}),"."]}),"\n",(0,r.jsx)(n.h3,{id:"using-docker-run-command",children:"Using \u201cdocker run\u201d command"}),"\n",(0,r.jsxs)(n.p,{children:["Refer to instructions described\nin ",(0,r.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence/tree/master/docker#using-docker-image-for-production",children:"Using docker image for production"}),"."]}),"\n",(0,r.jsx)(n.p,{children:"Additionally add two more environment variables:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-bash",children:"docker run\n<...>\n -e FRONTEND_HTTP_PORT=8800 -- HTTP PORT TO LISTEN\n -e FRONTEND_HTTP_PROCEDURES=uber.cadence.api.v1.WorkflowAPI::StartWorkflowExecution -- List of API methods exposed\n ubercadence/server:<tag>\n"})}),"\n",(0,r.jsx)(n.h3,{id:"using-docker-compose",children:"Using docker-compose"}),"\n",(0,r.jsxs)(n.p,{children:["Add HTTP environment variables to ",(0,r.jsx)(n.code,{children:"docker/docker-compose.yml"})," configuration:"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-yaml",children:'cadence:\n image: ubercadence/server:master-auto-setup\n ports:\n - "8000:8000"\n - "8001:8001"\n - "8002:8002"\n - "8003:8003"\n - "7933:7933"\n - "7934:7934"\n - "7935:7935"\n - "7939:7939"\n - "7833:7833"\n - "8800:8800"\n environment:\n - "CASSANDRA_SEEDS=cassandra"\n - "PROMETHEUS_ENDPOINT_0=0.0.0.0:8000"\n - "PROMETHEUS_ENDPOINT_1=0.0.0.0:8001"\n - "PROMETHEUS_ENDPOINT_2=0.0.0.0:8002"\n - "PROMETHEUS_ENDPOINT_3=0.0.0.0:8003"\n - "DYNAMIC_CONFIG_FILE_PATH=config/dynamicconfig/development.yaml"\n - "FRONTEND_HTTP_PORT=8800"\n - "FRONTEND_HTTP_PROCEDURES=uber.cadence.api.v1.WorkflowAPI::StartWorkflowExecution"\n'})}),"\n",(0,r.jsx)(n.h2,{id:"using-http-api-1",children:"Using HTTP API"}),"\n",(0,r.jsx)(n.p,{children:"Start a workflow using curl command"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-bash",children:"curl -X POST http://0.0.0.0:8800 \\\n -H 'context-ttl-ms: 2000' \\\n -H 'rpc-caller: rpc-client-name' \\\n -H 'rpc-service: cadence-frontend' \\\n -H 'rpc-encoding: json' \\\n -H 'rpc-procedure: uber.cadence.api.v1.WorkflowAPI::StartWorkflowExecution' \\\n -d @data.json\n"})}),"\n",(0,r.jsxs)(n.p,{children:["Where ",(0,r.jsx)(n.code,{children:"data.json"})," content looks something like this:"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-json",children:'{\n "domain": "sample-domain",\n "workflowId": "workflowid123",\n "execution_start_to_close_timeout": "11s",\n "task_start_to_close_timeout": "10s",\n "workflowType": {\n "name": "workflow_type"\n },\n "taskList": {\n "name": "tasklist-name"\n },\n "identity": "My custom caller identity",\n "requestId": "4D1E4058-6FCF-4BA8-BF16-8FA8B02F9651"\n}\n'})}),"\n",(0,r.jsx)(n.h2,{id:"http-api-reference",children:"HTTP API Reference"}),"\n",(0,r.jsx)(n.h3,{id:"admin-api",children:"Admin API"}),"\n",(0,r.jsx)(n.hr,{}),"\n",(0,r.jsxs)(s,{children:[(0,r.jsxs)("summary",{children:[(0,r.jsx)("code",{children:"POST"})," ",(0,r.jsx)("code",{children:(0,r.jsx)("b",{children:"uber.cadence.admin.v1.AdminAPIAddSearchAttribute"})})]}),(0,r.jsx)(n.h4,{id:"add-search-attributes-to-whitelist",children:"Add search attributes to whitelist"}),(0,r.jsx)(n.h5,{id:"headers",children:"Headers"}),(0,r.jsxs)(n.table,{children:[(0,r.jsx)(n.thead,{children:(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.th,{children:"name"}),(0,r.jsx)(n.th,{children:"example"})]})}),(0,r.jsxs)(n.tbody,{children:[(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"context-ttl-ms"}),(0,r.jsx)(n.td,{children:"2000"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-caller"}),(0,r.jsx)(n.td,{children:"curl-client"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-service"}),(0,r.jsx)(n.td,{children:"cadence-frontend"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-encoding"}),(0,r.jsx)(n.td,{children:"json"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-procedure"}),(0,r.jsx)(n.td,{children:"uber.cadence.admin.v1.AdminAPIAddSearchAttribute"})]})]})]}),(0,r.jsx)(n.h5,{id:"example-payload",children:"Example payload"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-json",children:'{\n "search_attribute": {\n "custom_key": 1\n }\n}\n'})}),(0,r.jsx)(n.p,{children:"Search attribute types"}),(0,r.jsxs)(n.table,{children:[(0,r.jsx)(n.thead,{children:(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.th,{children:"type"}),(0,r.jsx)(n.th,{children:"value"})]})}),(0,r.jsxs)(n.tbody,{children:[(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"String"}),(0,r.jsx)(n.td,{children:"1"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"Keyword"}),(0,r.jsx)(n.td,{children:"2"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"Int"}),(0,r.jsx)(n.td,{children:"3"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"Double"}),(0,r.jsx)(n.td,{children:"4"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"DateTime"}),(0,r.jsx)(n.td,{children:"5"})]})]})]}),(0,r.jsx)(n.h5,{id:"example-curl",children:"Example cURL"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-bash",children:"curl -X POST http://0.0.0.0:8800 \\\n -H 'context-ttl-ms: 2000' \\\n -H 'rpc-caller: curl-client' \\\n -H 'rpc-service: cadence-frontend' \\\n -H 'rpc-encoding: json' \\\n -H 'rpc-procedure: uber.cadence.admin.v1.AdminAPI::AddSearchAttribute' \\\n -d \\\n '{\n \"search_attribute\": {\n \"custom_key\": 1\n }\n }'\n"})}),(0,r.jsx)(n.h5,{id:"example-successful-response",children:"Example successful response"}),(0,r.jsx)(n.p,{children:"HTTP code: 200"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-json",children:"{}\n"})})]}),"\n",(0,r.jsx)(n.hr,{}),"\n",(0,r.jsxs)(s,{children:[(0,r.jsxs)("summary",{children:[(0,r.jsx)("code",{children:"POST"})," ",(0,r.jsx)("code",{children:(0,r.jsx)("b",{children:"uber.cadence.admin.v1.AdminAPICloseShard"})})]}),(0,r.jsx)(n.h4,{id:"close-a-shard-given-a-shard-id",children:"Close a shard given a shard ID"}),(0,r.jsx)(n.h5,{id:"headers-1",children:"Headers"}),(0,r.jsxs)(n.table,{children:[(0,r.jsx)(n.thead,{children:(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.th,{children:"name"}),(0,r.jsx)(n.th,{children:"example"})]})}),(0,r.jsxs)(n.tbody,{children:[(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"context-ttl-ms"}),(0,r.jsx)(n.td,{children:"2000"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-caller"}),(0,r.jsx)(n.td,{children:"curl-client"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-service"}),(0,r.jsx)(n.td,{children:"cadence-frontend"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-encoding"}),(0,r.jsx)(n.td,{children:"json"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-procedure"}),(0,r.jsx)(n.td,{children:"uber.cadence.admin.v1.AdminAPICloseShard"})]})]})]}),(0,r.jsx)(n.h5,{id:"example-payload-1",children:"Example payload"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-json",children:'{\n "shard_id": 0\n}\n'})}),(0,r.jsx)(n.h5,{id:"example-curl-1",children:"Example cURL"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-bash",children:"curl -X POST http://0.0.0.0:8800 \\\n -H 'context-ttl-ms: 2000' \\\n -H 'rpc-caller: curl-client' \\\n -H 'rpc-service: cadence-frontend' \\\n -H 'rpc-encoding: json' \\\n -H 'rpc-procedure: uber.cadence.admin.v1.AdminAPI::CloseShard' \\\n -d \\\n '{\n \"shard_id\": 0\n }'\n"})}),(0,r.jsx)(n.h5,{id:"example-successful-response-1",children:"Example successful response"}),(0,r.jsx)(n.p,{children:"HTTP code: 200"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-json",children:"{}\n"})})]}),"\n",(0,r.jsx)(n.hr,{}),"\n",(0,r.jsxs)(s,{children:[(0,r.jsxs)("summary",{children:[(0,r.jsx)("code",{children:"POST"})," ",(0,r.jsx)("code",{children:(0,r.jsx)("b",{children:"uber.cadence.admin.v1.AdminAPICountDLQMessages"})})]}),(0,r.jsx)(n.h4,{id:"count-dlq-messages",children:"Count DLQ messages"}),(0,r.jsx)(n.h5,{id:"headers-2",children:"Headers"}),(0,r.jsxs)(n.table,{children:[(0,r.jsx)(n.thead,{children:(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.th,{children:"name"}),(0,r.jsx)(n.th,{children:"example"})]})}),(0,r.jsxs)(n.tbody,{children:[(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"context-ttl-ms"}),(0,r.jsx)(n.td,{children:"2000"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-caller"}),(0,r.jsx)(n.td,{children:"curl-client"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-service"}),(0,r.jsx)(n.td,{children:"cadence-frontend"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-encoding"}),(0,r.jsx)(n.td,{children:"json"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-procedure"}),(0,r.jsx)(n.td,{children:"uber.cadence.admin.v1.AdminAPICountDLQMessages"})]})]})]}),(0,r.jsx)(n.h5,{id:"example-payload-2",children:"Example payload"}),(0,r.jsx)(n.p,{children:"None"}),(0,r.jsx)(n.h5,{id:"example-curl-2",children:"Example cURL"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-bash",children:"curl -X POST http://0.0.0.0:8800 \\\n -H 'context-ttl-ms: 2000' \\\n -H 'rpc-caller: curl-client' \\\n -H 'rpc-service: cadence-frontend' \\\n -H 'rpc-encoding: json' \\\n -H 'rpc-procedure: uber.cadence.admin.v1.AdminAPI::CountDLQMessages'\n"})}),(0,r.jsx)(n.h5,{id:"example-successful-response-2",children:"Example successful response"}),(0,r.jsx)(n.p,{children:"HTTP code: 200"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-json",children:'{\n "history": []\n}\n'})})]}),"\n",(0,r.jsx)(n.hr,{}),"\n",(0,r.jsxs)(s,{children:[(0,r.jsxs)("summary",{children:[(0,r.jsx)("code",{children:"POST"})," ",(0,r.jsx)("code",{children:(0,r.jsx)("b",{children:"uber.cadence.admin.v1.AdminAPIDescribeCluster"})})]}),(0,r.jsx)(n.h4,{id:"describe-cluster-information",children:"Describe cluster information"}),(0,r.jsx)(n.h5,{id:"headers-3",children:"Headers"}),(0,r.jsxs)(n.table,{children:[(0,r.jsx)(n.thead,{children:(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.th,{children:"name"}),(0,r.jsx)(n.th,{children:"example"})]})}),(0,r.jsxs)(n.tbody,{children:[(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"context-ttl-ms"}),(0,r.jsx)(n.td,{children:"2000"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-caller"}),(0,r.jsx)(n.td,{children:"curl-client"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-service"}),(0,r.jsx)(n.td,{children:"cadence-frontend"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-encoding"}),(0,r.jsx)(n.td,{children:"json"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-procedure"}),(0,r.jsx)(n.td,{children:"uber.cadence.admin.v1.AdminAPIDescribeCluster"})]})]})]}),(0,r.jsx)(n.h5,{id:"example-payload-3",children:"Example payload"}),(0,r.jsx)(n.p,{children:"None"}),(0,r.jsx)(n.h5,{id:"example-curl-3",children:"Example cURL"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-bash",children:"curl -X POST http://0.0.0.0:8800 \\\n -H 'context-ttl-ms: 2000' \\\n -H 'rpc-caller: curl-client' \\\n -H 'rpc-service: cadence-frontend' \\\n -H 'rpc-encoding: json' \\\n -H 'rpc-procedure: uber.cadence.admin.v1.AdminAPI::DescribeCluster'\n"})}),(0,r.jsx)(n.h5,{id:"example-successful-response-3",children:"Example successful response"}),(0,r.jsx)(n.p,{children:"HTTP code: 200"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-json",children:'{\n "supportedClientVersions": {\n "goSdk": "1.7.0",\n "javaSdk": "1.5.0"\n },\n "membershipInfo": {\n "currentHost": {\n "identity": "127.0.0.1:7933"\n },\n "reachableMembers": [\n "127.0.0.1:7933",\n "127.0.0.1:7934",\n "127.0.0.1:7935",\n "127.0.0.1:7939"\n ],\n "rings": [\n {\n "role": "cadence-frontend",\n "memberCount": 1,\n "members": [\n {\n "identity": "127.0.0.1:7933"\n }\n ]\n },\n {\n "role": "cadence-history",\n "memberCount": 1,\n "members": [\n {\n "identity": "127.0.0.1:7934"\n }\n ]\n },\n {\n "role": "cadence-matching",\n "memberCount": 1,\n "members": [\n {\n "identity": "127.0.0.1:7935"\n }\n ]\n },\n {\n "role": "cadence-worker",\n "memberCount": 1,\n "members": [\n {\n "identity": "127.0.0.1:7939"\n }\n ]\n }\n ]\n },\n "persistenceInfo": {\n "historyStore": {\n "backend": "shardedNosql"\n },\n "visibilityStore": {\n "backend": "cassandra",\n "features": [\n {\n "key": "advancedVisibilityEnabled"\n }\n ]\n }\n }\n}\n'})})]}),"\n",(0,r.jsx)(n.hr,{}),"\n",(0,r.jsxs)(s,{children:[(0,r.jsxs)("summary",{children:[(0,r.jsx)("code",{children:"POST"})," ",(0,r.jsx)("code",{children:(0,r.jsx)("b",{children:"uber.cadence.admin.v1.AdminAPIDescribeHistoryHost"})})]}),(0,r.jsx)(n.h4,{id:"describe-internal-information-of-history-host",children:"Describe internal information of history host"}),(0,r.jsx)(n.h5,{id:"headers-4",children:"Headers"}),(0,r.jsxs)(n.table,{children:[(0,r.jsx)(n.thead,{children:(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.th,{children:"name"}),(0,r.jsx)(n.th,{children:"example"})]})}),(0,r.jsxs)(n.tbody,{children:[(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"context-ttl-ms"}),(0,r.jsx)(n.td,{children:"2000"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-caller"}),(0,r.jsx)(n.td,{children:"curl-client"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-service"}),(0,r.jsx)(n.td,{children:"cadence-frontend"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-encoding"}),(0,r.jsx)(n.td,{children:"json"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-procedure"}),(0,r.jsx)(n.td,{children:"uber.cadence.admin.v1.AdminAPIDescribeHistoryHost"})]})]})]}),(0,r.jsx)(n.h5,{id:"example-payload-4",children:"Example payload"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-json",children:'{\n "host_address": "127.0.0.1:7934"\n}\n'})}),(0,r.jsx)(n.h5,{id:"example-curl-4",children:"Example cURL"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-bash",children:"curl -X POST http://0.0.0.0:8800 \\\n -H 'context-ttl-ms: 2000' \\\n -H 'rpc-caller: curl-client' \\\n -H 'rpc-service: cadence-frontend' \\\n -H 'rpc-encoding: json' \\\n -H 'rpc-procedure: uber.cadence.admin.v1.AdminAPI::DescribeHistoryHost' \\\n -d \\\n '{\n \"host_address\": \"127.0.0.1:7934\"\n }'\n"})}),(0,r.jsx)(n.h5,{id:"example-successful-response-4",children:"Example successful response"}),(0,r.jsx)(n.p,{children:"HTTP code: 200"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-json",children:'{\n "numberOfShards": 4,\n "domainCache": {\n "numOfItemsInCacheByID": 5,\n "numOfItemsInCacheByName": 5\n },\n "shardControllerStatus": "started",\n "address": "127.0.0.1:7934"\n}\n'})})]}),"\n",(0,r.jsx)(n.hr,{}),"\n",(0,r.jsxs)(s,{children:[(0,r.jsxs)("summary",{children:[(0,r.jsx)("code",{children:"POST"})," ",(0,r.jsx)("code",{children:(0,r.jsx)("b",{children:"uber.cadence.admin.v1.AdminAPIDescribeShardDistribution"})})]}),(0,r.jsx)(n.h4,{id:"list-shard-distribution",children:"List shard distribution"}),(0,r.jsx)(n.h5,{id:"headers-5",children:"Headers"}),(0,r.jsxs)(n.table,{children:[(0,r.jsx)(n.thead,{children:(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.th,{children:"name"}),(0,r.jsx)(n.th,{children:"example"})]})}),(0,r.jsxs)(n.tbody,{children:[(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"context-ttl-ms"}),(0,r.jsx)(n.td,{children:"2000"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-caller"}),(0,r.jsx)(n.td,{children:"curl-client"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-service"}),(0,r.jsx)(n.td,{children:"cadence-frontend"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-encoding"}),(0,r.jsx)(n.td,{children:"json"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-procedure"}),(0,r.jsx)(n.td,{children:"uber.cadence.admin.v1.AdminAPIDescribeShardDistribution"})]})]})]}),(0,r.jsx)(n.h5,{id:"example-payload-5",children:"Example payload"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-json",children:'{\n "page_size": 100,\n "page_id": 0\n}\n'})}),(0,r.jsx)(n.h5,{id:"example-curl-5",children:"Example cURL"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-bash",children:"curl -X POST http://0.0.0.0:8800 \\\n -H 'context-ttl-ms: 2000' \\\n -H 'rpc-caller: curl-client' \\\n -H 'rpc-service: cadence-frontend' \\\n -H 'rpc-encoding: json' \\\n -H 'rpc-procedure: uber.cadence.admin.v1.AdminAPI::DescribeShardDistribution' \\\n -d \\\n '{\n \"page_size\": 100,\n \"page_id\": 0\n }'\n"})}),(0,r.jsx)(n.h5,{id:"example-successful-response-5",children:"Example successful response"}),(0,r.jsx)(n.p,{children:"HTTP code: 200"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-json",children:'{\n "numberOfShards": 4,\n "shards": {\n "0": "127.0.0.1:7934",\n "1": "127.0.0.1:7934",\n "2": "127.0.0.1:7934",\n "3": "127.0.0.1:7934"\n }\n}\n'})})]}),"\n",(0,r.jsx)(n.hr,{}),"\n",(0,r.jsxs)(s,{children:[(0,r.jsxs)("summary",{children:[(0,r.jsx)("code",{children:"POST"})," ",(0,r.jsx)("code",{children:(0,r.jsx)("b",{children:"uber.cadence.admin.v1.AdminAPIDescribeWorkflowExecution"})})]}),(0,r.jsx)(n.h4,{id:"describe-internal-information-of-workflow-execution",children:"Describe internal information of workflow execution"}),(0,r.jsx)(n.h5,{id:"headers-6",children:"Headers"}),(0,r.jsxs)(n.table,{children:[(0,r.jsx)(n.thead,{children:(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.th,{children:"name"}),(0,r.jsx)(n.th,{children:"example"})]})}),(0,r.jsxs)(n.tbody,{children:[(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"context-ttl-ms"}),(0,r.jsx)(n.td,{children:"2000"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-caller"}),(0,r.jsx)(n.td,{children:"curl-client"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-service"}),(0,r.jsx)(n.td,{children:"cadence-frontend"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-encoding"}),(0,r.jsx)(n.td,{children:"json"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-procedure"}),(0,r.jsx)(n.td,{children:"uber.cadence.admin.v1.AdminAPIDescribeWorkflowExecution"})]})]})]}),(0,r.jsx)(n.h5,{id:"example-payload-6",children:"Example payload"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-json",children:'{\n "domain": "sample-domain",\n "workflow_execution": {\n "workflow_id": "sample-workflow-id",\n "run_id": "cc09d5dd-b2fa-46d8-b426-54c96b12d18f"\n }\n}\n'})}),(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"run_id"})," is optional and allows to describe a specific run."]}),(0,r.jsx)(n.h5,{id:"example-curl-6",children:"Example cURL"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-bash",children:"curl -X POST http://0.0.0.0:8800 \\\n -H 'context-ttl-ms: 2000' \\\n -H 'rpc-caller: curl-client' \\\n -H 'rpc-service: cadence-frontend' \\\n -H 'rpc-encoding: json' \\\n -H 'rpc-procedure: uber.cadence.admin.v1.AdminAPI::DescribeWorkflowExecution' \\\n -d \\\n '{\n \"domain\": \"sample-domain\",\n \"workflow_execution\": {\n \"workflow_id\": \"sample-workflow-id\",\n \"run_id\": \"cc09d5dd-b2fa-46d8-b426-54c96b12d18f\"\n }\n }' | tr -d '\\'\n"})}),(0,r.jsx)(n.h5,{id:"example-successful-response-6",children:"Example successful response"}),(0,r.jsx)(n.p,{children:"HTTP code: 200"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-json",children:'{\n "shardId": 3,\n "historyAddr": "127.0.0.1:7934",\n "mutableStateInDatabase": {\n "ActivityInfos": {},\n "TimerInfos": {},\n "ChildExecutionInfos": {},\n "RequestCancelInfos": {},\n "SignalInfos": {},\n "SignalRequestedIDs": {},\n "ExecutionInfo": {\n "DomainID": "d7aff879-f524-43a8-b340-5a223a69d75b",\n "WorkflowID": "sample-workflow-id",\n "RunID": "cc09d5dd-b2fa-46d8-b426-54c96b12d18f",\n "FirstExecutionRunID": "cc09d5dd-b2fa-46d8-b426-54c96b12d18f",\n "ParentDomainID": "",\n "ParentWorkflowID": "",\n "ParentRunID": "",\n "InitiatedID": -7,\n "CompletionEventBatchID": 3,\n "CompletionEvent": null,\n "TaskList": "sample-task-list",\n "WorkflowTypeName": "sample-workflow-type",\n "WorkflowTimeout": 11,\n "DecisionStartToCloseTimeout": 10,\n "ExecutionContext": null,\n "State": 2,\n "CloseStatus": 6,\n "LastFirstEventID": 3,\n "LastEventTaskID": 8388614,\n "NextEventID": 4,\n "LastProcessedEvent": -23,\n "StartTimestamp": "2023-09-08T05:13:04.24Z",\n "LastUpdatedTimestamp": "2023-09-08T05:13:15.247Z",\n "CreateRequestID": "8049b932-6c2f-415a-9bb2-241dcf4cfc9c",\n "SignalCount": 0,\n "DecisionVersion": 0,\n "DecisionScheduleID": 2,\n "DecisionStartedID": -23,\n "DecisionRequestID": "emptyUuid",\n "DecisionTimeout": 10,\n "DecisionAttempt": 0,\n "DecisionStartedTimestamp": 0,\n "DecisionScheduledTimestamp": 1694149984240504000,\n "DecisionOriginalScheduledTimestamp": 1694149984240503000,\n "CancelRequested": false,\n "CancelRequestID": "",\n "StickyTaskList": "",\n "StickyScheduleToStartTimeout": 0,\n "ClientLibraryVersion": "",\n "ClientFeatureVersion": "",\n "ClientImpl": "",\n "AutoResetPoints": {},\n "Memo": null,\n "SearchAttributes": null,\n "PartitionConfig": null,\n "Attempt": 0,\n "HasRetryPolicy": false,\n "InitialInterval": 0,\n "BackoffCoefficient": 0,\n "MaximumInterval": 0,\n "ExpirationTime": "0001-01-01T00:00:00Z",\n "MaximumAttempts": 0,\n "NonRetriableErrors": null,\n "BranchToken": null,\n "CronSchedule": "",\n "IsCron": false,\n "ExpirationSeconds": 0\n },\n "ExecutionStats": null,\n "BufferedEvents": [],\n "VersionHistories": {\n "CurrentVersionHistoryIndex": 0,\n "Histories": [\n {\n "BranchToken": "WQsACgAAACRjYzA5ZDVkZC1iMmZhLTQ2ZDgtYjQyNi01NGM5NmIxMmQxOGYLABQAAAAkYWM5YmIwMmUtMjllYy00YWEyLTlkZGUtZWQ0YWU1NWRhMjlhDwAeDAAAAAAA",\n "Items": [\n {\n "EventID": 3,\n "Version": 0\n }\n ]\n }\n ]\n },\n "ReplicationState": null,\n "Checksum": {\n "Version": 0,\n "Flavor": 0,\n "Value": null\n }\n }\n}\n'})})]}),"\n",(0,r.jsx)(n.hr,{}),"\n",(0,r.jsx)(n.h3,{id:"domain-api",children:"Domain API"}),"\n",(0,r.jsx)(n.hr,{}),"\n",(0,r.jsxs)(s,{children:[(0,r.jsxs)("summary",{children:[(0,r.jsx)("code",{children:"POST"})," ",(0,r.jsx)("code",{children:(0,r.jsx)("b",{children:"uber.cadence.api.v1.DomainAPIDescribeDomain"})})]}),(0,r.jsx)(n.h4,{id:"describe-existing-workflow-domain",children:"Describe existing workflow domain"}),(0,r.jsx)(n.h5,{id:"headers-7",children:"Headers"}),(0,r.jsxs)(n.table,{children:[(0,r.jsx)(n.thead,{children:(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.th,{children:"name"}),(0,r.jsx)(n.th,{children:"example"})]})}),(0,r.jsxs)(n.tbody,{children:[(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"context-ttl-ms"}),(0,r.jsx)(n.td,{children:"2000"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-caller"}),(0,r.jsx)(n.td,{children:"curl-client"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-service"}),(0,r.jsx)(n.td,{children:"cadence-frontend"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-encoding"}),(0,r.jsx)(n.td,{children:"json"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-procedure"}),(0,r.jsx)(n.td,{children:"uber.cadence.api.v1.DomainAPIDescribeDomain"})]})]})]}),(0,r.jsx)(n.h5,{id:"example-payload-7",children:"Example payload"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-json",children:'{\n "name": "sample-domain",\n "uuid": "d7aff879-f524-43a8-b340-5a223a69d75b"\n}\n'})}),(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"uuid"})," of the domain is optional."]}),(0,r.jsx)(n.h5,{id:"example-curl-7",children:"Example cURL"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-bash",children:"curl -X POST http://0.0.0.0:8800 \\\n -H 'context-ttl-ms: 2000' \\\n -H 'rpc-caller: curl-client' \\\n -H 'rpc-service: cadence-frontend' \\\n -H 'rpc-encoding: json' \\\n -H 'rpc-procedure: uber.cadence.api.v1.DomainAPI::DescribeDomain' \\\n -d \\\n '{\n \"name\": \"sample-domain\"\n }'\n"})}),(0,r.jsx)(n.h5,{id:"example-successful-response-7",children:"Example successful response"}),(0,r.jsx)(n.p,{children:"HTTP code: 200"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-json",children:'{\n "domain": {\n "id": "d7aff879-f524-43a8-b340-5a223a69d75b",\n "name": "sample-domain",\n "status": "DOMAIN_STATUS_REGISTERED",\n "data": {},\n "workflowExecutionRetentionPeriod": "259200s",\n "badBinaries": {\n "binaries": {}\n },\n "historyArchivalStatus": "ARCHIVAL_STATUS_ENABLED",\n "historyArchivalUri": "file:///tmp/cadence_archival/development",\n "visibilityArchivalStatus": "ARCHIVAL_STATUS_ENABLED",\n "visibilityArchivalUri": "file:///tmp/cadence_vis_archival/development",\n "activeClusterName": "cluster0",\n "clusters": [\n {\n "clusterName": "cluster0"\n }\n ],\n "isGlobalDomain": true,\n "isolationGroups": {}\n }\n}\n'})})]}),"\n",(0,r.jsx)(n.hr,{}),"\n",(0,r.jsxs)(s,{children:[(0,r.jsxs)("summary",{children:[(0,r.jsx)("code",{children:"POST"})," ",(0,r.jsx)("code",{children:(0,r.jsx)("b",{children:"uber.cadence.api.v1.DomainAPIListDomains"})})]}),(0,r.jsx)(n.h4,{id:"list-all-domains-in-the-cluster",children:"List all domains in the cluster"}),(0,r.jsx)(n.h5,{id:"headers-8",children:"Headers"}),(0,r.jsxs)(n.table,{children:[(0,r.jsx)(n.thead,{children:(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.th,{children:"name"}),(0,r.jsx)(n.th,{children:"example"})]})}),(0,r.jsxs)(n.tbody,{children:[(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"context-ttl-ms"}),(0,r.jsx)(n.td,{children:"2000"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-caller"}),(0,r.jsx)(n.td,{children:"curl-client"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-service"}),(0,r.jsx)(n.td,{children:"cadence-frontend"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-encoding"}),(0,r.jsx)(n.td,{children:"json"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-procedure"}),(0,r.jsx)(n.td,{children:"uber.cadence.api.v1.DomainAPIListDomains"})]})]})]}),(0,r.jsx)(n.h5,{id:"example-payload-8",children:"Example payload"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-json",children:'{\n "page_size": 100\n}\n'})}),(0,r.jsx)(n.h5,{id:"example-curl-8",children:"Example cURL"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-bash",children:"curl -X POST http://0.0.0.0:8800 \\\n -H 'context-ttl-ms: 2000' \\\n -H 'rpc-caller: curl-client' \\\n -H 'rpc-service: cadence-frontend' \\\n -H 'rpc-encoding: json' \\\n -H 'rpc-procedure: uber.cadence.api.v1.DomainAPI::ListDomains' \\\n -d \\\n '{\n \"page_size\": 100\n }'\n"})}),(0,r.jsx)(n.h5,{id:"example-successful-response-8",children:"Example successful response"}),(0,r.jsx)(n.p,{children:"HTTP code: 200"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-json",children:'{\n "domains": [\n {\n "id": "3116607e-419b-4783-85fc-47726a4c3fe9",\n "name": "cadence-batcher",\n "status": "DOMAIN_STATUS_REGISTERED",\n "description": "Cadence internal system domain",\n "data": {},\n "workflowExecutionRetentionPeriod": "604800s",\n "badBinaries": {\n "binaries": {}\n },\n "historyArchivalStatus": "ARCHIVAL_STATUS_DISABLED",\n "visibilityArchivalStatus": "ARCHIVAL_STATUS_DISABLED",\n "activeClusterName": "cluster0",\n "clusters": [\n {\n "clusterName": "cluster0"\n }\n ],\n "failoverVersion": "-24",\n "isolationGroups": {}\n },\n {\n "id": "59c51119-1b41-4a28-986d-d6e377716f82",\n "name": "cadence-shadower",\n "status": "DOMAIN_STATUS_REGISTERED",\n "description": "Cadence internal system domain",\n "data": {},\n "workflowExecutionRetentionPeriod": "604800s",\n "badBinaries": {\n "binaries": {}\n },\n "historyArchivalStatus": "ARCHIVAL_STATUS_DISABLED",\n "visibilityArchivalStatus": "ARCHIVAL_STATUS_DISABLED",\n "activeClusterName": "cluster0",\n "clusters": [\n {\n "clusterName": "cluster0"\n }\n ],\n "failoverVersion": "-24",\n "isolationGroups": {}\n },\n {\n "id": "32049b68-7872-4094-8e63-d0dd59896a83",\n "name": "cadence-system",\n "status": "DOMAIN_STATUS_REGISTERED",\n "description": "cadence system workflow domain",\n "ownerEmail": "cadence-dev-group@uber.com",\n "data": {},\n "workflowExecutionRetentionPeriod": "259200s",\n "badBinaries": {\n "binaries": {}\n },\n "historyArchivalStatus": "ARCHIVAL_STATUS_DISABLED",\n "visibilityArchivalStatus": "ARCHIVAL_STATUS_DISABLED",\n "activeClusterName": "cluster0",\n "clusters": [\n {\n "clusterName": "cluster0"\n }\n ],\n "failoverVersion": "-24",\n "isolationGroups": {}\n },\n {\n "id": "d7aff879-f524-43a8-b340-5a223a69d75b",\n "name": "sample-domain",\n "status": "DOMAIN_STATUS_REGISTERED",\n "data": {},\n "workflowExecutionRetentionPeriod": "259200s",\n "badBinaries": {\n "binaries": {}\n },\n "historyArchivalStatus": "ARCHIVAL_STATUS_ENABLED",\n "historyArchivalUri": "file:///tmp/cadence_archival/development",\n "visibilityArchivalStatus": "ARCHIVAL_STATUS_ENABLED",\n "visibilityArchivalUri": "file:///tmp/cadence_vis_archival/development",\n "activeClusterName": "cluster0",\n "clusters": [\n {\n "clusterName": "cluster0"\n }\n ],\n "isGlobalDomain": true,\n "isolationGroups": {}\n }\n ],\n "nextPageToken": ""\n}\n'})})]}),"\n",(0,r.jsx)(n.hr,{}),"\n",(0,r.jsx)(n.h3,{id:"meta-api",children:"Meta API"}),"\n",(0,r.jsx)(n.hr,{}),"\n",(0,r.jsxs)(s,{children:[(0,r.jsxs)("summary",{children:[(0,r.jsx)("code",{children:"POST"})," ",(0,r.jsx)("code",{children:(0,r.jsx)("b",{children:"uber.cadence.api.v1.MetaAPIHealth"})})]}),(0,r.jsx)(n.h4,{id:"health-check",children:"Health check"}),(0,r.jsx)(n.h5,{id:"headers-9",children:"Headers"}),(0,r.jsxs)(n.table,{children:[(0,r.jsx)(n.thead,{children:(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.th,{children:"name"}),(0,r.jsx)(n.th,{children:"example"})]})}),(0,r.jsxs)(n.tbody,{children:[(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"context-ttl-ms"}),(0,r.jsx)(n.td,{children:"2000"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-caller"}),(0,r.jsx)(n.td,{children:"curl-client"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-service"}),(0,r.jsx)(n.td,{children:"cadence-frontend"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-encoding"}),(0,r.jsx)(n.td,{children:"json"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-procedure"}),(0,r.jsx)(n.td,{children:"uber.cadence.api.v1.MetaAPIHealth"})]})]})]}),(0,r.jsx)(n.h5,{id:"example-payload-9",children:"Example payload"}),(0,r.jsx)(n.p,{children:"None"}),(0,r.jsx)(n.h5,{id:"example-curl-9",children:"Example cURL"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-bash",children:"curl -X POST http://0.0.0.0:8800 \\\n -H 'context-ttl-ms: 2000' \\\n -H 'rpc-caller: curl-client' \\\n -H 'rpc-service: cadence-frontend' \\\n -H 'rpc-encoding: json' \\\n -H 'rpc-procedure: uber.cadence.api.v1.MetaAPI::Health'\n"})}),(0,r.jsx)(n.h5,{id:"example-successful-response-9",children:"Example successful response"}),(0,r.jsx)(n.p,{children:"HTTP code: 200"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-json",children:'{\n "ok": true,\n "message": "OK"\n}\n'})})]}),"\n",(0,r.jsx)(n.hr,{}),"\n",(0,r.jsx)(n.h3,{id:"visibility-api",children:"Visibility API"}),"\n",(0,r.jsx)(n.hr,{}),"\n",(0,r.jsxs)(s,{children:[(0,r.jsxs)("summary",{children:[(0,r.jsx)("code",{children:"POST"})," ",(0,r.jsx)("code",{children:(0,r.jsx)("b",{children:"uber.cadence.api.v1.VisibilityAPIGetSearchAttributes"})})]}),(0,r.jsx)(n.h4,{id:"get-search-attributes",children:"Get search attributes"}),(0,r.jsx)(n.h5,{id:"headers-10",children:"Headers"}),(0,r.jsxs)(n.table,{children:[(0,r.jsx)(n.thead,{children:(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.th,{children:"name"}),(0,r.jsx)(n.th,{children:"example"})]})}),(0,r.jsxs)(n.tbody,{children:[(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"context-ttl-ms"}),(0,r.jsx)(n.td,{children:"2000"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-caller"}),(0,r.jsx)(n.td,{children:"curl-client"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-service"}),(0,r.jsx)(n.td,{children:"cadence-frontend"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-encoding"}),(0,r.jsx)(n.td,{children:"json"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-procedure"}),(0,r.jsx)(n.td,{children:"uber.cadence.api.v1.VisibilityAPIGetSearchAttributes"})]})]})]}),(0,r.jsx)(n.h5,{id:"example-payload-10",children:"Example payload"}),(0,r.jsx)(n.p,{children:"None"}),(0,r.jsx)(n.h5,{id:"example-curl-10",children:"Example cURL"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-bash",children:"curl -X POST http://0.0.0.0:8800 \\\n -H 'context-ttl-ms: 2000' \\\n -H 'rpc-caller: curl-client' \\\n -H 'rpc-service: cadence-frontend' \\\n -H 'rpc-encoding: json' \\\n -H 'rpc-procedure: uber.cadence.api.v1.VisibilityAPI::GetSearchAttributes'\n"})}),(0,r.jsx)(n.h5,{id:"example-successful-response-10",children:"Example successful response"}),(0,r.jsx)(n.p,{children:"HTTP code: 200"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-json",children:'{\n "keys": {\n "BinaryChecksums": "INDEXED_VALUE_TYPE_KEYWORD",\n "CadenceChangeVersion": "INDEXED_VALUE_TYPE_KEYWORD",\n "CloseStatus": "INDEXED_VALUE_TYPE_INT",\n "CloseTime": "INDEXED_VALUE_TYPE_INT",\n "CustomBoolField": "INDEXED_VALUE_TYPE_BOOL",\n "CustomDatetimeField": "INDEXED_VALUE_TYPE_DATETIME",\n "CustomDomain": "INDEXED_VALUE_TYPE_KEYWORD",\n "CustomDoubleField": "INDEXED_VALUE_TYPE_DOUBLE",\n "CustomIntField": "INDEXED_VALUE_TYPE_INT",\n "CustomKeywordField": "INDEXED_VALUE_TYPE_KEYWORD",\n "CustomStringField": "INDEXED_VALUE_TYPE_STRING",\n "DomainID": "INDEXED_VALUE_TYPE_KEYWORD",\n "ExecutionTime": "INDEXED_VALUE_TYPE_INT",\n "HistoryLength": "INDEXED_VALUE_TYPE_INT",\n "IsCron": "INDEXED_VALUE_TYPE_KEYWORD",\n "NewKey": "INDEXED_VALUE_TYPE_KEYWORD",\n "NumClusters": "INDEXED_VALUE_TYPE_INT",\n "Operator": "INDEXED_VALUE_TYPE_KEYWORD",\n "Passed": "INDEXED_VALUE_TYPE_BOOL",\n "RolloutID": "INDEXED_VALUE_TYPE_KEYWORD",\n "RunID": "INDEXED_VALUE_TYPE_KEYWORD",\n "ShardID": "INDEXED_VALUE_TYPE_INT",\n "StartTime": "INDEXED_VALUE_TYPE_INT",\n "TaskList": "INDEXED_VALUE_TYPE_KEYWORD",\n "TestNewKey": "INDEXED_VALUE_TYPE_STRING",\n "UpdateTime": "INDEXED_VALUE_TYPE_INT",\n "WorkflowID": "INDEXED_VALUE_TYPE_KEYWORD",\n "WorkflowType": "INDEXED_VALUE_TYPE_KEYWORD",\n "addon": "INDEXED_VALUE_TYPE_KEYWORD",\n "addon-type": "INDEXED_VALUE_TYPE_KEYWORD",\n "environment": "INDEXED_VALUE_TYPE_KEYWORD",\n "project": "INDEXED_VALUE_TYPE_KEYWORD",\n "service": "INDEXED_VALUE_TYPE_KEYWORD",\n "user": "INDEXED_VALUE_TYPE_KEYWORD"\n }\n}\n'})})]}),"\n",(0,r.jsx)(n.hr,{}),"\n",(0,r.jsxs)(s,{children:[(0,r.jsxs)("summary",{children:[(0,r.jsx)("code",{children:"POST"})," ",(0,r.jsx)("code",{children:(0,r.jsx)("b",{children:"uber.cadence.api.v1.VisibilityAPIListClosedWorkflowExecutions"})})]}),(0,r.jsx)(n.h4,{id:"list-closed-workflow-executions-in-a-domain",children:"List closed workflow executions in a domain"}),(0,r.jsx)(n.h5,{id:"headers-11",children:"Headers"}),(0,r.jsxs)(n.table,{children:[(0,r.jsx)(n.thead,{children:(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.th,{children:"name"}),(0,r.jsx)(n.th,{children:"example"})]})}),(0,r.jsxs)(n.tbody,{children:[(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"context-ttl-ms"}),(0,r.jsx)(n.td,{children:"2000"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-caller"}),(0,r.jsx)(n.td,{children:"curl-client"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-service"}),(0,r.jsx)(n.td,{children:"cadence-frontend"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-encoding"}),(0,r.jsx)(n.td,{children:"json"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-procedure"}),(0,r.jsx)(n.td,{children:"uber.cadence.api.v1.VisibilityAPIListClosedWorkflowExecutions"})]})]})]}),(0,r.jsx)(n.h5,{id:"example-payloads",children:"Example payloads"}),(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"startTimeFilter"})," is required while ",(0,r.jsx)(n.code,{children:"executionFilter"})," and ",(0,r.jsx)(n.code,{children:"typeFilter"})," are optional."]}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-json",children:'{\n "domain": "sample-domain",\n "start_time_filter": {\n "earliest_time": "2023-01-01T00:00:00Z",\n "latest_time": "2023-12-31T00:00:00Z"\n }\n}\n'})}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-json",children:'{\n "domain": "sample-domain",\n "start_time_filter": {\n "earliest_time": "2023-01-01T00:00:00Z",\n "latest_time": "2023-12-31T00:00:00Z"\n },\n "execution_filter": {\n "workflow_id": "sample-workflow-id",\n "run_id": "71c3d47b-454a-4315-97c7-15355140094b"\n }\n}\n'})}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-json",children:'{\n "domain": "sample-domain",\n "start_time_filter": {\n "earliest_time": "2023-01-01T00:00:00Z",\n "latest_time": "2023-12-31T00:00:00Z"\n },\n "type_filter": {\n "name": "sample-workflow-type"\n }\n}\n'})}),(0,r.jsx)(n.h5,{id:"example-curl-11",children:"Example cURL"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-bash",children:'curl -X POST http://0.0.0.0:8800 \\\n -H \'context-ttl-ms: 2000\' \\\n -H \'rpc-caller: curl-client\' \\\n -H \'rpc-service: cadence-frontend\' \\\n -H \'rpc-encoding: json\' \\\n -H \'rpc-procedure: uber.cadence.api.v1.VisibilityAPI::ListClosedWorkflowExecutions\' \\\n -d \\\n \'{\n "domain": "sample-domain",\n "start_time_filter": {\n "earliest_time": "2023-01-01T00:00:00Z",\n "latest_time": "2023-12-31T00:00:00Z"\n }\n }\'\n'})}),(0,r.jsx)(n.h5,{id:"example-successful-response-11",children:"Example successful response"}),(0,r.jsx)(n.p,{children:"HTTP code: 200"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-json",children:'{\n "executions": [\n {\n "workflowExecution": {\n "workflowId": "sample-workflow-id",\n "runId": "71c3d47b-454a-4315-97c7-15355140094b"\n },\n "type": {\n "name": "sample-workflow-type"\n },\n "startTime": "2023-09-08T06:31:18.778Z",\n "closeTime": "2023-09-08T06:32:18.782Z",\n "closeStatus": "WORKFLOW_EXECUTION_CLOSE_STATUS_TIMED_OUT",\n "historyLength": "5",\n "executionTime": "2023-09-08T06:31:18.778Z",\n "memo": {},\n "searchAttributes": {\n "indexedFields": {}\n },\n "taskList": "sample-task-list"\n }\n ],\n "nextPageToken": ""\n}\n'})})]}),"\n",(0,r.jsx)(n.hr,{}),"\n",(0,r.jsxs)(s,{children:[(0,r.jsxs)("summary",{children:[(0,r.jsx)("code",{children:"POST"})," ",(0,r.jsx)("code",{children:(0,r.jsx)("b",{children:"uber.cadence.api.v1.VisibilityAPIListOpenWorkflowExecutions"})})]}),(0,r.jsx)(n.h4,{id:"list-open-workflow-executions-in-a-domain",children:"List open workflow executions in a domain"}),(0,r.jsx)(n.h5,{id:"headers-12",children:"Headers"}),(0,r.jsxs)(n.table,{children:[(0,r.jsx)(n.thead,{children:(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.th,{children:"name"}),(0,r.jsx)(n.th,{children:"example"})]})}),(0,r.jsxs)(n.tbody,{children:[(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"context-ttl-ms"}),(0,r.jsx)(n.td,{children:"2000"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-caller"}),(0,r.jsx)(n.td,{children:"curl-client"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-service"}),(0,r.jsx)(n.td,{children:"cadence-frontend"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-encoding"}),(0,r.jsx)(n.td,{children:"json"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-procedure"}),(0,r.jsx)(n.td,{children:"uber.cadence.api.v1.VisibilityAPIListOpenWorkflowExecutions"})]})]})]}),(0,r.jsx)(n.h5,{id:"example-payloads-1",children:"Example payloads"}),(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"startTimeFilter"})," is required while ",(0,r.jsx)(n.code,{children:"executionFilter"})," and ",(0,r.jsx)(n.code,{children:"typeFilter"})," are optional."]}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-json",children:'{\n "domain": "sample-domain",\n "start_time_filter": {\n "earliest_time": "2023-01-01T00:00:00Z",\n "latest_time": "2023-12-31T00:00:00Z"\n }\n}\n'})}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-json",children:'{\n "domain": "sample-domain",\n "start_time_filter": {\n "earliest_time": "2023-01-01T00:00:00Z",\n "latest_time": "2023-12-31T00:00:00Z"\n },\n "execution_filter": {\n "workflow_id": "sample-workflow-id",\n "run_id": "71c3d47b-454a-4315-97c7-15355140094b"\n }\n}\n'})}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-json",children:'{\n "domain": "sample-domain",\n "start_time_filter": {\n "earliest_time": "2023-01-01T00:00:00Z",\n "latest_time": "2023-12-31T00:00:00Z"\n },\n "type_filter": {\n "name": "sample-workflow-type"\n }\n}\n'})}),(0,r.jsx)(n.h5,{id:"example-curl-12",children:"Example cURL"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-bash",children:'curl -X POST http://0.0.0.0:8800 \\\n -H \'context-ttl-ms: 2000\' \\\n -H \'rpc-caller: curl-client\' \\\n -H \'rpc-service: cadence-frontend\' \\\n -H \'rpc-encoding: json\' \\\n -H \'rpc-procedure: uber.cadence.api.v1.VisibilityAPI::ListOpenWorkflowExecutions\' \\\n -d \\\n \'{\n "domain": "sample-domain",\n "start_time_filter": {\n "earliest_time": "2023-01-01T00:00:00Z",\n "latest_time": "2023-12-31T00:00:00Z"\n }\n }\'\n'})}),(0,r.jsx)(n.h5,{id:"example-successful-response-12",children:"Example successful response"}),(0,r.jsx)(n.p,{children:"HTTP code: 200"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-json",children:'{\n "executions": [\n {\n "workflowExecution": {\n "workflowId": "sample-workflow-id",\n "runId": "5dbabeeb-82a2-41ed-bf55-dc732a4d46ce"\n },\n "type": {\n "name": "sample-workflow-type"\n },\n "startTime": "2023-09-12T02:17:46.596Z",\n "executionTime": "2023-09-12T02:17:46.596Z",\n "memo": {},\n "searchAttributes": {\n "indexedFields": {}\n },\n "taskList": "sample-task-list"\n }\n ],\n "nextPageToken": ""\n}\n'})})]}),"\n",(0,r.jsx)(n.hr,{}),"\n",(0,r.jsx)(n.h3,{id:"workflow-api",children:"Workflow API"}),"\n",(0,r.jsx)(n.hr,{}),"\n",(0,r.jsxs)(s,{children:[(0,r.jsxs)("summary",{children:[(0,r.jsx)("code",{children:"POST"})," ",(0,r.jsx)("code",{children:(0,r.jsx)("b",{children:"uber.cadence.api.v1.WorkflowAPIDescribeTaskList"})})]}),(0,r.jsx)(n.h4,{id:"describe-pollers-info-of-tasklist",children:"Describe pollers info of tasklist"}),(0,r.jsx)(n.h5,{id:"headers-13",children:"Headers"}),(0,r.jsxs)(n.table,{children:[(0,r.jsx)(n.thead,{children:(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.th,{children:"name"}),(0,r.jsx)(n.th,{children:"example"})]})}),(0,r.jsxs)(n.tbody,{children:[(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"context-ttl-ms"}),(0,r.jsx)(n.td,{children:"2000"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-caller"}),(0,r.jsx)(n.td,{children:"curl-client"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-service"}),(0,r.jsx)(n.td,{children:"cadence-frontend"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-encoding"}),(0,r.jsx)(n.td,{children:"json"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-procedure"}),(0,r.jsx)(n.td,{children:"uber.cadence.api.v1.WorkflowAPIDescribeTaskList"})]})]})]}),(0,r.jsx)(n.h5,{id:"example-payload-11",children:"Example payload"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-json",children:'{\n "domain": "sample-domain",\n "task_list": {\n "name": "sample-task-list",\n "kind": 1\n },\n "task_list_type": 1,\n "include_task_list_status": true\n}\n'})}),(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"task_list"})," kind is optional."]}),(0,r.jsx)(n.p,{children:"Task list kinds"}),(0,r.jsxs)(n.table,{children:[(0,r.jsx)(n.thead,{children:(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.th,{children:"type"}),(0,r.jsx)(n.th,{children:"value"})]})}),(0,r.jsxs)(n.tbody,{children:[(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"TaskListKindNormal"}),(0,r.jsx)(n.td,{children:"1"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"TaskListKindSticky"}),(0,r.jsx)(n.td,{children:"2"})]})]})]}),(0,r.jsx)(n.p,{children:"Task list types"}),(0,r.jsxs)(n.table,{children:[(0,r.jsx)(n.thead,{children:(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.th,{children:"type"}),(0,r.jsx)(n.th,{children:"value"})]})}),(0,r.jsxs)(n.tbody,{children:[(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"TaskListTypeDecision"}),(0,r.jsx)(n.td,{children:"1"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"TaskListTypeActivity"}),(0,r.jsx)(n.td,{children:"2"})]})]})]}),(0,r.jsx)(n.h5,{id:"example-curl-13",children:"Example cURL"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-bash",children:'curl -X POST http://0.0.0.0:8800 \\\n -H \'context-ttl-ms: 2000\' \\\n -H \'rpc-caller: curl-client\' \\\n -H \'rpc-service: cadence-frontend\' \\\n -H \'rpc-encoding: json\' \\\n -H \'rpc-procedure: uber.cadence.api.v1.WorkflowAPI::DescribeTaskList\' \\\n -d \\\n \'{\n "domain": "sample-domain",\n "task_list": {\n "name": "sample-task-list",\n "kind": 1\n },\n "task_list_type": 1,\n "include_task_list_status": true\n }\'\n'})}),(0,r.jsx)(n.h5,{id:"example-successful-response-13",children:"Example successful response"}),(0,r.jsx)(n.p,{children:"HTTP code: 200"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-json",children:'{\n "taskListStatus": {\n "readLevel": "200000",\n "ratePerSecond": 100000,\n "taskIdBlock": {\n "startId": "200001",\n "endId": "300000"\n }\n }\n}\n'})})]}),"\n",(0,r.jsx)(n.hr,{}),"\n",(0,r.jsxs)(s,{children:[(0,r.jsxs)("summary",{children:[(0,r.jsx)("code",{children:"POST"})," ",(0,r.jsx)("code",{children:(0,r.jsx)("b",{children:"uber.cadence.api.v1.WorkflowAPIDescribeWorkflowExecution"})})]}),(0,r.jsx)(n.h4,{id:"describe-a-workflow-execution",children:"Describe a workflow execution"}),(0,r.jsx)(n.h5,{id:"headers-14",children:"Headers"}),(0,r.jsxs)(n.table,{children:[(0,r.jsx)(n.thead,{children:(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.th,{children:"name"}),(0,r.jsx)(n.th,{children:"example"})]})}),(0,r.jsxs)(n.tbody,{children:[(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"context-ttl-ms"}),(0,r.jsx)(n.td,{children:"2000"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-caller"}),(0,r.jsx)(n.td,{children:"curl-client"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-service"}),(0,r.jsx)(n.td,{children:"cadence-frontend"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-encoding"}),(0,r.jsx)(n.td,{children:"json"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-procedure"}),(0,r.jsx)(n.td,{children:"uber.cadence.api.v1.WorkflowAPIDescribeWorkflowExecution"})]})]})]}),(0,r.jsx)(n.h5,{id:"example-payload-12",children:"Example payload"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-json",children:'{\n "domain": "sample-domain",\n "workflow_execution": {\n "workflow_id": "sample-workflow-id",\n "run_id": "5dbabeeb-82a2-41ed-bf55-dc732a4d46ce"\n }\n}\n'})}),(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"run_id"})," is optional and allows to describe a specific run."]}),(0,r.jsx)(n.h5,{id:"example-curl-14",children:"Example cURL"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-bash",children:'curl -X POST http://0.0.0.0:8800 \\\n -H \'context-ttl-ms: 2000\' \\\n -H \'rpc-caller: curl-client\' \\\n -H \'rpc-service: cadence-frontend\' \\\n -H \'rpc-encoding: json\' \\\n -H \'rpc-procedure: uber.cadence.api.v1.WorkflowAPI::DescribeWorkflowExecution\' \\\n -d \\\n \'{\n "domain": "sample-domain",\n "workflow_execution": {\n "workflow_id": "sample-workflow-id",\n "run_id": "5dbabeeb-82a2-41ed-bf55-dc732a4d46ce"\n }\n }\'\n'})}),(0,r.jsx)(n.h5,{id:"example-successful-response-14",children:"Example successful response"}),(0,r.jsx)(n.p,{children:"HTTP code: 200"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-json",children:'{\n "executionConfiguration": {\n "taskList": {\n "name": "sample-task-list"\n },\n "executionStartToCloseTimeout": "11s",\n "taskStartToCloseTimeout": "10s"\n },\n "workflowExecutionInfo": {\n "workflowExecution": {\n "workflowId": "sample-workflow-id",\n "runId": "5dbabeeb-82a2-41ed-bf55-dc732a4d46ce"\n },\n "type": {\n "name": "sample-workflow-type"\n },\n "startTime": "2023-09-12T02:17:46.596Z",\n "closeTime": "2023-09-12T02:17:57.602707Z",\n "closeStatus": "WORKFLOW_EXECUTION_CLOSE_STATUS_TIMED_OUT",\n "historyLength": "3",\n "executionTime": "2023-09-12T02:17:46.596Z",\n "memo": {},\n "searchAttributes": {},\n "autoResetPoints": {}\n },\n "pendingDecision": {\n "state": "PENDING_DECISION_STATE_SCHEDULED",\n "scheduledTime": "2023-09-12T02:17:46.596982Z",\n "originalScheduledTime": "2023-09-12T02:17:46.596982Z"\n }\n}\n'})})]}),"\n",(0,r.jsx)(n.hr,{}),"\n",(0,r.jsxs)(s,{children:[(0,r.jsxs)("summary",{children:[(0,r.jsx)("code",{children:"POST"})," ",(0,r.jsx)("code",{children:(0,r.jsx)("b",{children:"uber.cadence.api.v1.WorkflowAPIGetClusterInfo"})})]}),(0,r.jsx)(n.h4,{id:"get-supported-client-versions-for-the-cluster",children:"Get supported client versions for the cluster"}),(0,r.jsx)(n.h5,{id:"headers-15",children:"Headers"}),(0,r.jsxs)(n.table,{children:[(0,r.jsx)(n.thead,{children:(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.th,{children:"name"}),(0,r.jsx)(n.th,{children:"example"})]})}),(0,r.jsxs)(n.tbody,{children:[(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"context-ttl-ms"}),(0,r.jsx)(n.td,{children:"2000"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-caller"}),(0,r.jsx)(n.td,{children:"curl-client"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-service"}),(0,r.jsx)(n.td,{children:"cadence-frontend"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-encoding"}),(0,r.jsx)(n.td,{children:"json"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-procedure"}),(0,r.jsx)(n.td,{children:"uber.cadence.api.v1.WorkflowAPIGetClusterInfo"})]})]})]}),(0,r.jsx)(n.h5,{id:"example-payload-13",children:"Example payload"}),(0,r.jsx)(n.p,{children:"None"}),(0,r.jsx)(n.h5,{id:"example-curl-15",children:"Example cURL"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-bash",children:"curl -X POST http://0.0.0.0:8800 \\\n -H 'context-ttl-ms: 2000' \\\n -H 'rpc-caller: curl-client' \\\n -H 'rpc-service: cadence-frontend' \\\n -H 'rpc-encoding: json' \\\n -H 'rpc-procedure: uber.cadence.api.v1.WorkflowAPI::GetClusterInfo'\n"})}),(0,r.jsx)(n.h5,{id:"example-successful-response-15",children:"Example successful response"}),(0,r.jsx)(n.p,{children:"HTTP code: 200"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-json",children:'{\n "supportedClientVersions": {\n "goSdk": "1.7.0",\n "javaSdk": "1.5.0"\n }\n}\n'})})]}),"\n",(0,r.jsx)(n.hr,{}),"\n",(0,r.jsxs)(s,{children:[(0,r.jsxs)("summary",{children:[(0,r.jsx)("code",{children:"POST"})," ",(0,r.jsx)("code",{children:(0,r.jsx)("b",{children:"uber.cadence.api.v1.WorkflowAPIGetTaskListsByDomain"})})]}),(0,r.jsx)(n.h4,{id:"get-the-task-lists-in-a-domain",children:"Get the task lists in a domain"}),(0,r.jsx)(n.h5,{id:"headers-16",children:"Headers"}),(0,r.jsxs)(n.table,{children:[(0,r.jsx)(n.thead,{children:(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.th,{children:"name"}),(0,r.jsx)(n.th,{children:"example"})]})}),(0,r.jsxs)(n.tbody,{children:[(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"context-ttl-ms"}),(0,r.jsx)(n.td,{children:"2000"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-caller"}),(0,r.jsx)(n.td,{children:"curl-client"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-service"}),(0,r.jsx)(n.td,{children:"cadence-frontend"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-encoding"}),(0,r.jsx)(n.td,{children:"json"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-procedure"}),(0,r.jsx)(n.td,{children:"uber.cadence.api.v1.WorkflowAPIGetTaskListsByDomain"})]})]})]}),(0,r.jsx)(n.h5,{id:"example-payload-14",children:"Example payload"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-json",children:'{\n "domain": "sample-domain"\n}\n'})}),(0,r.jsx)(n.h5,{id:"example-curl-16",children:"Example cURL"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-bash",children:"curl -X POST http://0.0.0.0:8800 \\\n -H 'context-ttl-ms: 2000' \\\n -H 'rpc-caller: curl-client' \\\n -H 'rpc-service: cadence-frontend' \\\n -H 'rpc-encoding: json' \\\n -H 'rpc-procedure: uber.cadence.api.v1.WorkflowAPI::GetTaskListsByDomain' \\\n -d \\\n '{\n \"domain\": \"sample-domain\"\n }'\n"})}),(0,r.jsx)(n.h5,{id:"example-successful-response-16",children:"Example successful response"}),(0,r.jsx)(n.p,{children:"HTTP code: 200"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-json",children:'{\n "decisionTaskListMap": {},\n "activityTaskListMap": {}\n}\n'})})]}),"\n",(0,r.jsx)(n.hr,{}),"\n",(0,r.jsxs)(s,{children:[(0,r.jsxs)("summary",{children:[(0,r.jsx)("code",{children:"POST"})," ",(0,r.jsx)("code",{children:(0,r.jsx)("b",{children:"uber.cadence.api.v1.WorkflowAPIGetWorkflowExecutionHistory"})})]}),(0,r.jsx)(n.h4,{id:"get-the-history-of-workflow-executions",children:"Get the history of workflow executions"}),(0,r.jsx)(n.h5,{id:"headers-17",children:"Headers"}),(0,r.jsxs)(n.table,{children:[(0,r.jsx)(n.thead,{children:(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.th,{children:"name"}),(0,r.jsx)(n.th,{children:"example"})]})}),(0,r.jsxs)(n.tbody,{children:[(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"context-ttl-ms"}),(0,r.jsx)(n.td,{children:"2000"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-caller"}),(0,r.jsx)(n.td,{children:"curl-client"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-service"}),(0,r.jsx)(n.td,{children:"cadence-frontend"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-encoding"}),(0,r.jsx)(n.td,{children:"json"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-procedure"}),(0,r.jsx)(n.td,{children:"uber.cadence.api.v1.WorkflowAPIGetWorkflowExecutionHistory"})]})]})]}),(0,r.jsx)(n.h5,{id:"example-payload-15",children:"Example payload"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-json",children:'{\n "domain": "sample-domain",\n "workflow_execution": {\n "workflow_id": "sample-workflow-id"\n }\n}\n'})}),(0,r.jsx)(n.h5,{id:"example-curl-17",children:"Example cURL"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-bash",children:"curl -X POST http://0.0.0.0:8800 \\\n -H 'context-ttl-ms: 2000' \\\n -H 'rpc-caller: curl-client' \\\n -H 'rpc-service: cadence-frontend' \\\n -H 'rpc-encoding: json' \\\n -H 'rpc-procedure: uber.cadence.api.v1.WorkflowAPI::GetWorkflowExecutionHistory' \\\n -d \\\n '{\n \"domain\": \"sample-domain\",\n \"workflow_execution\": {\n \"workflow_id\": \"sample-workflow-id\"\n }\n }'\n"})}),(0,r.jsx)(n.h5,{id:"example-successful-response-17",children:"Example successful response"}),(0,r.jsx)(n.p,{children:"HTTP code: 200"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-json",children:'{\n "history": {\n "events": [\n {\n "eventId": "1",\n "eventTime": "2023-09-12T05:34:46.107550Z",\n "taskId": "9437321",\n "workflowExecutionStartedEventAttributes": {\n "workflowType": {\n "name": "sample-workflow-type"\n },\n "taskList": {\n "name": "sample-task-list"\n },\n "input": {\n "data": "IkN1cmwhIg=="\n },\n "executionStartToCloseTimeout": "61s",\n "taskStartToCloseTimeout": "60s",\n "originalExecutionRunId": "fd7c2283-79dd-458c-8306-e2d1d8217613",\n "identity": "client-name-visible-in-history",\n "firstExecutionRunId": "fd7c2283-79dd-458c-8306-e2d1d8217613",\n "firstDecisionTaskBackoff": "0s"\n }\n },\n {\n "eventId": "2",\n "eventTime": "2023-09-12T05:34:46.107565Z",\n "taskId": "9437322",\n "decisionTaskScheduledEventAttributes": {\n "taskList": {\n "name": "sample-task-list"\n },\n "startToCloseTimeout": "60s"\n }\n },\n {\n "eventId": "3",\n "eventTime": "2023-09-12T05:34:59.184511Z",\n "taskId": "9437330",\n "workflowExecutionCancelRequestedEventAttributes": {\n "cause": "dummy",\n "identity": "client-name-visible-in-history"\n }\n },\n {\n "eventId": "4",\n "eventTime": "2023-09-12T05:35:47.112156Z",\n "taskId": "9437332",\n "workflowExecutionTimedOutEventAttributes": {\n "timeoutType": "TIMEOUT_TYPE_START_TO_CLOSE"\n }\n }\n ]\n }\n}\n'})})]}),"\n",(0,r.jsx)(n.hr,{}),"\n",(0,r.jsxs)(s,{children:[(0,r.jsxs)("summary",{children:[(0,r.jsx)("code",{children:"POST"})," ",(0,r.jsx)("code",{children:(0,r.jsx)("b",{children:"uber.cadence.api.v1.WorkflowAPIListTaskListPartitions"})})]}),(0,r.jsx)(n.h4,{id:"list-all-the-task-list-partitions-and-the-hostname-for-partitions",children:"List all the task list partitions and the hostname for partitions"}),(0,r.jsx)(n.h5,{id:"headers-18",children:"Headers"}),(0,r.jsxs)(n.table,{children:[(0,r.jsx)(n.thead,{children:(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.th,{children:"name"}),(0,r.jsx)(n.th,{children:"example"})]})}),(0,r.jsxs)(n.tbody,{children:[(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"context-ttl-ms"}),(0,r.jsx)(n.td,{children:"2000"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-caller"}),(0,r.jsx)(n.td,{children:"curl-client"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-service"}),(0,r.jsx)(n.td,{children:"cadence-frontend"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-encoding"}),(0,r.jsx)(n.td,{children:"json"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-procedure"}),(0,r.jsx)(n.td,{children:"uber.cadence.api.v1.WorkflowAPIListTaskListPartitions"})]})]})]}),(0,r.jsx)(n.h5,{id:"example-payload-16",children:"Example payload"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-json",children:'{\n "domain": "sample-domain",\n "task_list": {\n "name": "sample-task-list"\n }\n}\n'})}),(0,r.jsx)(n.h5,{id:"example-curl-18",children:"Example cURL"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-bash",children:"curl -X POST http://0.0.0.0:8800 \\\n -H 'context-ttl-ms: 2000' \\\n -H 'rpc-caller: curl-client' \\\n -H 'rpc-service: cadence-frontend' \\\n -H 'rpc-encoding: json' \\\n -H 'rpc-procedure: uber.cadence.api.v1.WorkflowAPI::ListTaskListPartitions' \\\n -d \\\n '{\n \"domain\": \"sample-domain\",\n \"task_list\": {\n \"name\": \"sample-task-list\"\n }\n }'\n"})}),(0,r.jsx)(n.h5,{id:"example-successful-response-18",children:"Example successful response"}),(0,r.jsx)(n.p,{children:"HTTP code: 200"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-json",children:'{\n "activityTaskListPartitions": [\n {\n "key": "sample-task-list",\n "ownerHostName": "127.0.0.1:7935"\n }\n ],\n "decisionTaskListPartitions": [\n {\n "key": "sample-task-list",\n "ownerHostName": "127.0.0.1:7935"\n }\n ]\n}\n'})})]}),"\n",(0,r.jsx)(n.hr,{}),"\n",(0,r.jsxs)(s,{children:[(0,r.jsxs)("summary",{children:[(0,r.jsx)("code",{children:"POST"})," ",(0,r.jsx)("code",{children:(0,r.jsx)("b",{children:"uber.cadence.api.v1.WorkflowAPIRefreshWorkflowTasks"})})]}),(0,r.jsx)(n.h4,{id:"refresh-all-the-tasks-of-a-workflow",children:"Refresh all the tasks of a workflow"}),(0,r.jsx)(n.h5,{id:"headers-19",children:"Headers"}),(0,r.jsxs)(n.table,{children:[(0,r.jsx)(n.thead,{children:(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.th,{children:"name"}),(0,r.jsx)(n.th,{children:"example"})]})}),(0,r.jsxs)(n.tbody,{children:[(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"context-ttl-ms"}),(0,r.jsx)(n.td,{children:"2000"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-caller"}),(0,r.jsx)(n.td,{children:"curl-client"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-service"}),(0,r.jsx)(n.td,{children:"cadence-frontend"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-encoding"}),(0,r.jsx)(n.td,{children:"json"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-procedure"}),(0,r.jsx)(n.td,{children:"uber.cadence.api.v1.WorkflowAPIRefreshWorkflowTasks"})]})]})]}),(0,r.jsx)(n.h5,{id:"example-payload-17",children:"Example payload"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-json",children:'{\n "domain": "sample-domain",\n "workflow_execution": {\n "workflow_id": "sample-workflow-id",\n "run_id": "b7973fb8-2229-4fe7-ad70-c919c1ae8774"\n }\n}\n'})}),(0,r.jsx)(n.h5,{id:"example-curl-19",children:"Example cURL"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-bash",children:'curl -X POST http://0.0.0.0:8800 \\\n -H \'context-ttl-ms: 2000\' \\\n -H \'rpc-caller: curl-client\' \\\n -H \'rpc-service: cadence-frontend\' \\\n -H \'rpc-encoding: json\' \\\n -H \'rpc-procedure: uber.cadence.api.v1.WorkflowAPI::RefreshWorkflowTasks\' \\\n -d \\\n \'{\n "domain": "sample-domain",\n "workflow_execution": {\n "workflow_id": "sample-workflow-id",\n "run_id": "b7973fb8-2229-4fe7-ad70-c919c1ae8774"\n }\n }\'\n'})}),(0,r.jsx)(n.h5,{id:"example-successful-response-19",children:"Example successful response"}),(0,r.jsx)(n.p,{children:"HTTP code: 200"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-json",children:"{}\n"})})]}),"\n",(0,r.jsx)(n.hr,{}),"\n",(0,r.jsxs)(s,{children:[(0,r.jsxs)("summary",{children:[(0,r.jsx)("code",{children:"POST"})," ",(0,r.jsx)("code",{children:(0,r.jsx)("b",{children:"uber.cadence.api.v1.WorkflowAPIRequestCancelWorkflowExecution"})})]}),(0,r.jsx)(n.h4,{id:"cancel-a-workflow-execution",children:"Cancel a workflow execution"}),(0,r.jsx)(n.h5,{id:"headers-20",children:"Headers"}),(0,r.jsxs)(n.table,{children:[(0,r.jsx)(n.thead,{children:(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.th,{children:"name"}),(0,r.jsx)(n.th,{children:"example"})]})}),(0,r.jsxs)(n.tbody,{children:[(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"context-ttl-ms"}),(0,r.jsx)(n.td,{children:"2000"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-caller"}),(0,r.jsx)(n.td,{children:"curl-client"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-service"}),(0,r.jsx)(n.td,{children:"cadence-frontend"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-encoding"}),(0,r.jsx)(n.td,{children:"json"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-procedure"}),(0,r.jsx)(n.td,{children:"uber.cadence.api.v1.WorkflowAPIRequestCancelWorkflowExecution"})]})]})]}),(0,r.jsx)(n.h5,{id:"example-payload-18",children:"Example payload"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-json",children:'{\n "domain": "sample-domain",\n "workflow_execution": {\n "workflow_id": "sample-workflow-id",\n "run_id": "b7973fb8-2229-4fe7-ad70-c919c1ae8774"\n },\n "request_id": "8049B932-6C2F-415A-9BB2-241DCF4CFC9C",\n "cause": "dummy",\n "identity": "client-name-visible-in-history",\n "first_execution_run_id": "b7973fb8-2229-4fe7-ad70-c919c1ae8774"\n}\n'})}),(0,r.jsx)(n.h5,{id:"example-curl-20",children:"Example cURL"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-bash",children:'curl -X POST http://0.0.0.0:8800 \\\n -H \'context-ttl-ms: 2000\' \\\n -H \'rpc-caller: curl-client\' \\\n -H \'rpc-service: cadence-frontend\' \\\n -H \'rpc-encoding: json\' \\\n -H \'rpc-procedure: uber.cadence.api.v1.WorkflowAPI::RequestCancelWorkflowExecution\' \\\n -d \\\n \'{\n "domain": "sample-domain",\n "workflow_execution": {\n "workflow_id": "sample-workflow-id",\n "run_id": "fd7c2283-79dd-458c-8306-e2d1d8217613"\n },\n "request_id": "8049B932-6C2F-415A-9BB2-241DCF4CFC9C",\n "cause": "dummy",\n "identity": "client-name-visible-in-history",\n "first_execution_run_id": "fd7c2283-79dd-458c-8306-e2d1d8217613"\n }\'\n'})}),(0,r.jsx)(n.h5,{id:"example-successful-response-20",children:"Example successful response"}),(0,r.jsx)(n.p,{children:"HTTP code: 200"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-json",children:"{}\n"})})]}),"\n",(0,r.jsx)(n.hr,{}),"\n",(0,r.jsxs)(s,{children:[(0,r.jsxs)("summary",{children:[(0,r.jsx)("code",{children:"POST"})," ",(0,r.jsx)("code",{children:(0,r.jsx)("b",{children:"uber.cadence.api.v1.WorkflowAPIRestartWorkflowExecution"})})]}),(0,r.jsx)(n.h4,{id:"restart-a-previous-workflow-execution",children:"Restart a previous workflow execution"}),(0,r.jsx)(n.h5,{id:"headers-21",children:"Headers"}),(0,r.jsxs)(n.table,{children:[(0,r.jsx)(n.thead,{children:(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.th,{children:"name"}),(0,r.jsx)(n.th,{children:"example"})]})}),(0,r.jsxs)(n.tbody,{children:[(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"context-ttl-ms"}),(0,r.jsx)(n.td,{children:"2000"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-caller"}),(0,r.jsx)(n.td,{children:"curl-client"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-service"}),(0,r.jsx)(n.td,{children:"cadence-frontend"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-encoding"}),(0,r.jsx)(n.td,{children:"json"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-procedure"}),(0,r.jsx)(n.td,{children:"uber.cadence.api.v1.WorkflowAPIRestartWorkflowExecution"})]})]})]}),(0,r.jsx)(n.h5,{id:"example-payload-19",children:"Example payload"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-json",children:'{\n "domain": "sample-domain",\n "workflow_execution": {\n "workflow_id": "sample-workflow-id",\n "run_id": "0f95ad5b-03bc-4c6b-8cf0-1f3ea08eb86a"\n },\n "identity": "client-name-visible-in-history",\n "reason": "dummy"\n}\n'})}),(0,r.jsx)(n.h5,{id:"example-curl-21",children:"Example cURL"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-bash",children:'curl -X POST http://0.0.0.0:8800 \\\n -H \'context-ttl-ms: 2000\' \\\n -H \'rpc-caller: curl-client\' \\\n -H \'rpc-service: cadence-frontend\' \\\n -H \'rpc-encoding: json\' \\\n -H \'rpc-procedure: uber.cadence.api.v1.WorkflowAPI::RestartWorkflowExecution\' \\\n -d \\\n \'{\n "domain": "sample-domain",\n "workflow_execution": {\n "workflow_id": "sample-workflow-id",\n "run_id": "0f95ad5b-03bc-4c6b-8cf0-1f3ea08eb86a"\n },\n "identity": "client-name-visible-in-history",\n "reason": "dummy"\n }\'\n'})}),(0,r.jsx)(n.h5,{id:"example-successful-response-21",children:"Example successful response"}),(0,r.jsx)(n.p,{children:"HTTP code: 200"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-json",children:'{\n "runId": "82914458-3221-42b4-ae54-2e66dff864f7"\n}\n'})})]}),"\n",(0,r.jsx)(n.hr,{}),"\n",(0,r.jsxs)(s,{children:[(0,r.jsxs)("summary",{children:[(0,r.jsx)("code",{children:"POST"})," ",(0,r.jsx)("code",{children:(0,r.jsx)("b",{children:"uber.cadence.api.v1.WorkflowAPISignalWithStartWorkflowExecution"})})]}),(0,r.jsx)(n.h4,{id:"signal-the-current-open-workflow-if-exists-or-attempt-to-start-a-new-run-based-on-idresuepolicy-and-signals-it",children:"Signal the current open workflow if exists, or attempt to start a new run based on IDResuePolicy and signals it"}),(0,r.jsx)(n.h5,{id:"headers-22",children:"Headers"}),(0,r.jsxs)(n.table,{children:[(0,r.jsx)(n.thead,{children:(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.th,{children:"name"}),(0,r.jsx)(n.th,{children:"example"})]})}),(0,r.jsxs)(n.tbody,{children:[(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"context-ttl-ms"}),(0,r.jsx)(n.td,{children:"2000"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-caller"}),(0,r.jsx)(n.td,{children:"curl-client"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-service"}),(0,r.jsx)(n.td,{children:"cadence-frontend"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-encoding"}),(0,r.jsx)(n.td,{children:"json"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-procedure"}),(0,r.jsx)(n.td,{children:"uber.cadence.api.v1.WorkflowAPISignalWithStartWorkflowExecution"})]})]})]}),(0,r.jsx)(n.h5,{id:"example-payload-20",children:"Example payload"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-json",children:'{\n "start_request": {\n "domain": "sample-domain",\n "workflow_id": "sample-workflow-id",\n "execution_start_to_close_timeout": "61s",\n "task_start_to_close_timeout": "60s",\n "workflow_type": {\n "name": "sample-workflow-type"\n },\n "task_list": {\n "name": "sample-task-list"\n },\n "identity": "client-name-visible-in-history",\n "request_id": "8049B932-6C2F-415A-9BB2-241DCF4CFC9C",\n "input": {\n "data": "IkN1cmwhIg=="\n }\n },\n "signal_name": "channelA",\n "signal_input": {\n "data": "MTA="\n }\n}\n'})}),(0,r.jsx)(n.h5,{id:"example-curl-22",children:"Example cURL"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-bash",children:'curl -X POST http://0.0.0.0:8800 \\\n -H \'context-ttl-ms: 2000\' \\\n -H \'rpc-caller: curl-client\' \\\n -H \'rpc-service: cadence-frontend\' \\\n -H \'rpc-encoding: json\' \\\n -H \'rpc-procedure: uber.cadence.api.v1.WorkflowAPI::SignalWithStartWorkflowExecution\' \\\n -d \\\n \'{\n "start_request": {\n "domain": "sample-domain",\n "workflow_id": "sample-workflow-id",\n "execution_start_to_close_timeout": "61s",\n "task_start_to_close_timeout": "60s",\n "workflow_type": {\n "name": "sample-workflow-type"\n },\n "task_list": {\n "name": "sample-task-list"\n },\n "identity": "client-name-visible-in-history",\n "request_id": "8049B932-6C2F-415A-9BB2-241DCF4CFC9C",\n "input": {\n "data": "IkN1cmwhIg=="\n }\n },\n "signal_name": "channelA",\n "signal_input": {\n "data": "MTA="\n }\n }\'\n'})}),(0,r.jsx)(n.h5,{id:"example-successful-response-22",children:"Example successful response"}),(0,r.jsx)(n.p,{children:"HTTP code: 200"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-json",children:'{\n "runId": "cc09d5dd-b2fa-46d8-b426-54c96b12d18f"\n}\n'})})]}),"\n",(0,r.jsx)(n.hr,{}),"\n",(0,r.jsxs)(s,{children:[(0,r.jsxs)("summary",{children:[(0,r.jsx)("code",{children:"POST"})," ",(0,r.jsx)("code",{children:(0,r.jsx)("b",{children:"uber.cadence.api.v1.WorkflowAPISignalWorkflowExecution"})})]}),(0,r.jsx)(n.h4,{id:"signal-a-workflow-execution",children:"Signal a workflow execution"}),(0,r.jsx)(n.h5,{id:"headers-23",children:"Headers"}),(0,r.jsxs)(n.table,{children:[(0,r.jsx)(n.thead,{children:(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.th,{children:"name"}),(0,r.jsx)(n.th,{children:"example"})]})}),(0,r.jsxs)(n.tbody,{children:[(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"context-ttl-ms"}),(0,r.jsx)(n.td,{children:"2000"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-caller"}),(0,r.jsx)(n.td,{children:"curl-client"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-service"}),(0,r.jsx)(n.td,{children:"cadence-frontend"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-encoding"}),(0,r.jsx)(n.td,{children:"json"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-procedure"}),(0,r.jsx)(n.td,{children:"uber.cadence.api.v1.WorkflowAPISignalWorkflowExecution"})]})]})]}),(0,r.jsx)(n.h5,{id:"example-payload-21",children:"Example payload"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-json",children:'{\n "domain": "sample-domain",\n "workflow_execution": {\n "workflow_id": "sample-workflow-id",\n "run_id": "cc09d5dd-b2fa-46d8-b426-54c96b12d18f"\n },\n "signal_name": "channelA",\n "signal_input": {\n "data": "MTA="\n }\n}\n'})}),(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"run_id"})," is optional and allows to signal a specific run."]}),(0,r.jsx)(n.h5,{id:"example-curl-23",children:"Example cURL"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-bash",children:'curl -X POST http://0.0.0.0:8800 \\\n -H \'context-ttl-ms: 2000\' \\\n -H \'rpc-caller: curl-client\' \\\n -H \'rpc-service: cadence-frontend\' \\\n -H \'rpc-encoding: json\' \\\n -H \'rpc-procedure: uber.cadence.api.v1.WorkflowAPI::SignalWorkflowExecution\' \\\n -d \\\n \'{\n "domain": "sample-domain",\n "workflow_execution": {\n "workflow_id": "sample-workflow-id"\n },\n "signal_name": "channelA",\n "signal_input": {\n "data": "MTA="\n }\n }\'\n'})}),(0,r.jsx)(n.h5,{id:"example-successful-response-23",children:"Example successful response"}),(0,r.jsx)(n.p,{children:"HTTP code: 200"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-json",children:"{}\n"})})]}),"\n",(0,r.jsx)(n.hr,{}),"\n",(0,r.jsxs)(s,{children:[(0,r.jsxs)("summary",{children:[(0,r.jsx)("code",{children:"POST"})," ",(0,r.jsx)("code",{children:(0,r.jsx)("b",{children:"uber.cadence.api.v1.WorkflowAPIStartWorkflowExecution"})})]}),(0,r.jsx)(n.h4,{id:"start-a-new-workflow-execution",children:"Start a new workflow execution"}),(0,r.jsx)(n.h5,{id:"headers-24",children:"Headers"}),(0,r.jsxs)(n.table,{children:[(0,r.jsx)(n.thead,{children:(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.th,{children:"name"}),(0,r.jsx)(n.th,{children:"example"})]})}),(0,r.jsxs)(n.tbody,{children:[(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"context-ttl-ms"}),(0,r.jsx)(n.td,{children:"2000"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-caller"}),(0,r.jsx)(n.td,{children:"curl-client"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-service"}),(0,r.jsx)(n.td,{children:"cadence-frontend"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-encoding"}),(0,r.jsx)(n.td,{children:"json"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-procedure"}),(0,r.jsx)(n.td,{children:"uber.cadence.api.v1.WorkflowAPIStartWorkflowExecution"})]})]})]}),(0,r.jsx)(n.h5,{id:"example-payload-22",children:"Example payload"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-json",children:'{\n "domain": "sample-domain",\n "workflow_id": "sample-workflow-id",\n "execution_start_to_close_timeout": "61s",\n "task_start_to_close_timeout": "60s",\n "workflow_type": {\n "name": "sample-workflow-type"\n },\n "task_list": {\n "name": "sample-task-list"\n },\n "identity": "client-name-visible-in-history",\n "request_id": "8049B932-6C2F-415A-9BB2-241DCF4CFC9C",\n "input": {\n "data": "IkN1cmwhIg=="\n }\n}\n'})}),(0,r.jsx)(n.h5,{id:"example-curl-24",children:"Example cURL"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-bash",children:'curl -X POST http://0.0.0.0:8800 \\\n -H \'context-ttl-ms: 2000\' \\\n -H \'rpc-caller: curl-client\' \\\n -H \'rpc-service: cadence-frontend\' \\\n -H \'rpc-encoding: json\' \\\n -H \'rpc-procedure: uber.cadence.api.v1.WorkflowAPI::StartWorkflowExecution\' \\\n -d \\\n \'{\n "domain": "sample-domain",\n "workflow_id": "sample-workflow-id",\n "execution_start_to_close_timeout": "61s",\n "task_start_to_close_timeout": "60s",\n "workflow_type": {\n "name": "sample-workflow-type"\n },\n "task_list": {\n "name": "sample-task-list"\n },\n "identity": "client-name-visible-in-history",\n "request_id": "8049B932-6C2F-415A-9BB2-241DCF4CFC9C",\n "input": {\n "data": "IkN1cmwhIg=="\n }\n }\'\n'})}),(0,r.jsx)(n.h5,{id:"example-successful-response-24",children:"Example successful response"}),(0,r.jsx)(n.p,{children:"HTTP code: 200"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-json",children:'{\n "runId": "cc09d5dd-b2fa-46d8-b426-54c96b12d18f"\n}\n'})})]}),"\n",(0,r.jsx)(n.hr,{}),"\n",(0,r.jsxs)(s,{children:[(0,r.jsxs)("summary",{children:[(0,r.jsx)("code",{children:"POST"})," ",(0,r.jsx)("code",{children:(0,r.jsx)("b",{children:"uber.cadence.api.v1.WorkflowAPITerminateWorkflowExecution"})})]}),(0,r.jsx)(n.h4,{id:"terminate-a-new-workflow-execution",children:"Terminate a new workflow execution"}),(0,r.jsx)(n.h5,{id:"headers-25",children:"Headers"}),(0,r.jsxs)(n.table,{children:[(0,r.jsx)(n.thead,{children:(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.th,{children:"name"}),(0,r.jsx)(n.th,{children:"example"})]})}),(0,r.jsxs)(n.tbody,{children:[(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"context-ttl-ms"}),(0,r.jsx)(n.td,{children:"2000"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-caller"}),(0,r.jsx)(n.td,{children:"curl-client"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-service"}),(0,r.jsx)(n.td,{children:"cadence-frontend"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-encoding"}),(0,r.jsx)(n.td,{children:"json"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"rpc-procedure"}),(0,r.jsx)(n.td,{children:"uber.cadence.api.v1.WorkflowAPITerminateWorkflowExecution"})]})]})]}),(0,r.jsx)(n.h5,{id:"example-payloads-2",children:"Example payloads"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-json",children:'{\n "domain": "sample-domain",\n "workflow_execution": {\n "workflow_id": "sample-workflow-id"\n }\n}\n'})}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-json",children:'{\n "domain": "sample-domain",\n "workflow_execution": {\n "workflow_id": "sample-workflow-id",\n "run_id": "0f95ad5b-03bc-4c6b-8cf0-1f3ea08eb86a"\n },\n "reason": "dummy",\n "identity": "client-name-visible-in-history",\n "first_execution_run_id": "0f95ad5b-03bc-4c6b-8cf0-1f3ea08eb86a"\n}\n'})}),(0,r.jsx)(n.h5,{id:"example-curl-25",children:"Example cURL"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-bash",children:"curl -X POST http://0.0.0.0:8800 \\\n -H 'context-ttl-ms: 2000' \\\n -H 'rpc-caller: curl-client' \\\n -H 'rpc-service: cadence-frontend' \\\n -H 'rpc-encoding: json' \\\n -H 'rpc-procedure: uber.cadence.api.v1.WorkflowAPI::TerminateWorkflowExecution' \\\n -d \\\n '{\n \"domain\": \"sample-domain\",\n \"workflow_execution\": {\n \"workflow_id\": \"sample-workflow-id\"\n }\n }'\n"})}),(0,r.jsx)(n.h5,{id:"example-successful-response-25",children:"Example successful response"}),(0,r.jsx)(n.p,{children:"HTTP code: 200"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-json",children:"{}\n"})})]}),"\n",(0,r.jsx)(n.hr,{})]})}function h(e={}){const{wrapper:n}={...(0,c.R)(),...e.components};return n?(0,r.jsx)(n,{...e,children:(0,r.jsx)(o,{...e})}):o(e)}},8453:(e,n,s)=>{s.d(n,{R:()=>d,x:()=>i});var l=s(6540);const r={},c=l.createContext(r);function d(e){const n=l.useContext(c);return l.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function i(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:d(e.components),l.createElement(c.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/cdada9ee.5251b911.js b/assets/js/cdada9ee.5251b911.js new file mode 100644 index 000000000..2c25ed6a2 --- /dev/null +++ b/assets/js/cdada9ee.5251b911.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[1249],{1176:(e,t,o)=>{o.r(t),o.d(t,{assets:()=>a,contentTitle:()=>c,default:()=>h,frontMatter:()=>r,metadata:()=>i,toc:()=>l});const i=JSON.parse('{"id":"concepts/topology","title":"Deployment topology","description":"Overview","source":"@site/docs/03-concepts/05-topology.md","sourceDirName":"03-concepts","slug":"/concepts/topology","permalink":"/Cadence-Docs/docs/concepts/topology","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/03-concepts/05-topology.md","tags":[],"version":"current","sidebarPosition":5,"frontMatter":{"layout":"default","title":"Deployment topology","permalink":"/docs/concepts/topology"},"sidebar":"docsSidebar","previous":{"title":"Synchronous query","permalink":"/Cadence-Docs/docs/concepts/queries"},"next":{"title":"Task lists","permalink":"/Cadence-Docs/docs/concepts/task-lists"}}');var n=o(4848),s=o(8453);const r={layout:"default",title:"Deployment topology",permalink:"/docs/concepts/topology"},c="Deployment topology",a={},l=[{value:"Overview",id:"overview",level:2},{value:"Cadence Service",id:"cadence-service",level:2},{value:"Workflow Worker",id:"workflow-worker",level:2},{value:"Activity Worker",id:"activity-worker",level:2},{value:"External Clients",id:"external-clients",level:2}];function d(e){const t={a:"a",code:"code",em:"em",h1:"h1",h2:"h2",header:"header",img:"img",li:"li",p:"p",ul:"ul",...(0,s.R)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(t.header,{children:(0,n.jsx)(t.h1,{id:"deployment-topology",children:"Deployment topology"})}),"\n",(0,n.jsx)(t.h2,{id:"overview",children:"Overview"}),"\n",(0,n.jsx)(t.p,{children:"Cadence is a highly scalable fault-oblivious stateful code platform. The fault-oblivious code is a next level of abstraction over commonly used techniques to achieve fault tolerance and durability."}),"\n",(0,n.jsx)(t.p,{children:"A common Cadence-based application consists of a Cadence service, workflow and activity_workers, and external clients.\nNote that both types of workers as well as external clients are roles and can be collocated in a single application process if necessary."}),"\n",(0,n.jsx)(t.h2,{id:"cadence-service",children:"Cadence Service"}),"\n",(0,n.jsx)(t.p,{children:(0,n.jsx)(t.img,{src:"https://user-images.githubusercontent.com/14902200/160308507-2854a98a-0582-4748-87e4-e0695d3b6e86.jpg",alt:"Cadence Architecture"})}),"\n",(0,n.jsxs)(t.p,{children:["At the core of Cadence is a highly scalable multitentant service. The service exposes all of its functionality through a strongly typed ",(0,n.jsx)(t.a,{href:"https://github.com/cadence-workflow/cadence-idl/tree/master/proto/cadence-workflow/cadence/api/v1",children:"gRPC API"}),". A Cadence cluster include multiple services, each of which may run on multiple nodes for scalability and reliablity:"]}),"\n",(0,n.jsxs)(t.ul,{children:["\n",(0,n.jsx)(t.li,{children:"Front End: which is a stateless service used to handle incoming requests from Workers. It is expected that an external load balancing mechanism is used to distribute load between Front End instances."}),"\n",(0,n.jsx)(t.li,{children:"History Service: where the core logic of orchestrating workflow steps and activities is implemented"}),"\n",(0,n.jsx)(t.li,{children:"Matching Service: matches workflow/activity tasks that need to be executed to workflow/activity workers that are able to execute them. Matching is assigned task for execution by the history service"}),"\n",(0,n.jsx)(t.li,{children:"Internal Worker Service: implements Cadence workflows and activities for internal requirements such as archiving"}),"\n",(0,n.jsx)(t.li,{children:"Workers: are effectively the client apps for Cadence. This is where user created workflow and activity logic is executed"}),"\n"]}),"\n",(0,n.jsxs)(t.p,{children:["Internally it depends on a persistent store. Currently, Apache Cassandra, MySQL, PostgreSQL, CockroachDB (",(0,n.jsx)(t.a,{href:"https://www.cockroachlabs.com/docs/stable/postgresql-compatibility.html",children:"PostgreSQL compatible"}),") and TiDB (",(0,n.jsx)(t.a,{href:"https://docs.pingcap.com/tidb/dev/mysql-compatibility",children:"MySQL compatible"}),") stores are supported out of the box. For listing workflows using complex predicates, ElasticSearch and OpenSearch cluster can be used."]}),"\n",(0,n.jsx)(t.p,{children:"Cadence service is responsible for keeping workflow state and associated durable timers. It maintains internal queues (called task_lists) which are used to dispatch tasks to external workers."}),"\n",(0,n.jsx)(t.p,{children:"Cadence service is multitentant. Therefore it is expected that multiple pools of workers implementing different use cases connect to the same service instance. For example, at Uber a single service is used by more than a hundred applications. At the same time some external customers deploy an instance of Cadence service per application. For local development, a local Cadence service instance configured through docker-compose is used."}),"\n",(0,n.jsx)(t.p,{children:(0,n.jsx)(t.img,{src:"https://user-images.githubusercontent.com/14902200/160308592-400e11bc-0b21-4dd1-b568-8ac59005e6b7.svg",alt:"Cadence Overview"})}),"\n",(0,n.jsx)(t.h2,{id:"workflow-worker",children:"Workflow Worker"}),"\n",(0,n.jsxs)(t.p,{children:["Cadence reuses terminology from ",(0,n.jsx)(t.em,{children:"workflow automation"})," domain. So fault-oblivious stateful code is called workflow."]}),"\n",(0,n.jsxs)(t.p,{children:["The Cadence service does not execute workflow code directly. The workflow code is hosted by an external (from the service point of view) workflow_worker process. These processes receive ",(0,n.jsx)(t.em,{children:"decision_tasks"})," that contain events that the workflow is expected to handle from the Cadence service, delivers them to the workflow code, and communicates workflow ",(0,n.jsx)(t.em,{children:"decisions"})," back to the service."]}),"\n",(0,n.jsx)(t.p,{children:"As workflow code is external to the service, it can be implemented in any language that can talk service Thrift API. Currently Java and Go clients are production ready. While Python and C# clients are under development. Let us know if you are interested in contributing a client in your preferred language."}),"\n",(0,n.jsx)(t.p,{children:"The Cadence service API doesn't impose any specific workflow definition language. So a specific worker can be implemented to execute practically any existing workflow specification. The model the Cadence team chose to support out of the box is based on the idea of durable function. Durable functions are as close as possible to application business logic with minimal plumbing required."}),"\n",(0,n.jsx)(t.h2,{id:"activity-worker",children:"Activity Worker"}),"\n",(0,n.jsx)(t.p,{children:"Workflow fault-oblivious code is immune to infrastructure failures. But it has to communicate with the imperfect external world where failures are common. All communication to the external world is done through activities. Activities are pieces of code that can perform any application-specific action like calling a service, updating a database record, or downloading a file from Amazon S3. Cadence activities are very feature-rich compared to queuing systems. Example features are task routing to specific processes, infinite retries, heartbeats, and unlimited execution time."}),"\n",(0,n.jsxs)(t.p,{children:["Activities are hosted by ",(0,n.jsx)(t.em,{children:"activity_worker"})," processes that receive ",(0,n.jsx)(t.em,{children:"activity_tasks"})," from the Cadence service, invoke correspondent activity implementations and report back task completion statuses."]}),"\n",(0,n.jsx)(t.h2,{id:"external-clients",children:"External Clients"}),"\n",(0,n.jsxs)(t.p,{children:["Workflow and activity_workers host workflow and activity code. But to create a workflow instance (an execution in Cadence terminology) the ",(0,n.jsx)(t.code,{children:"StartWorkflowExecution"})," Cadence service API call should be used. Usually, workflows are started by outside entities like UIs, microservices or CLIs."]}),"\n",(0,n.jsx)(t.p,{children:"These entities can also:"}),"\n",(0,n.jsxs)(t.ul,{children:["\n",(0,n.jsx)(t.li,{children:"notify workflows about asynchronous external events in the form of signals"}),"\n",(0,n.jsx)(t.li,{children:"synchronously query workflow state"}),"\n",(0,n.jsx)(t.li,{children:"synchronously wait for a workflow completion"}),"\n",(0,n.jsx)(t.li,{children:"cancel, terminate, restart, and reset workflows"}),"\n",(0,n.jsx)(t.li,{children:"search for specific workflows using list API"}),"\n"]})]})}function h(e={}){const{wrapper:t}={...(0,s.R)(),...e.components};return t?(0,n.jsx)(t,{...e,children:(0,n.jsx)(d,{...e})}):d(e)}},8453:(e,t,o)=>{o.d(t,{R:()=>r,x:()=>c});var i=o(6540);const n={},s=i.createContext(n);function r(e){const t=i.useContext(s);return i.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function c(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(n):e.components||n:r(e.components),i.createElement(s.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/cdada9ee.d2a78d8f.js b/assets/js/cdada9ee.d2a78d8f.js deleted file mode 100644 index eb835445b..000000000 --- a/assets/js/cdada9ee.d2a78d8f.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[1249],{1176:(e,t,o)=>{o.r(t),o.d(t,{assets:()=>a,contentTitle:()=>c,default:()=>h,frontMatter:()=>r,metadata:()=>i,toc:()=>l});const i=JSON.parse('{"id":"concepts/topology","title":"Deployment topology","description":"Overview","source":"@site/docs/03-concepts/05-topology.md","sourceDirName":"03-concepts","slug":"/concepts/topology","permalink":"/docs/concepts/topology","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/03-concepts/05-topology.md","tags":[],"version":"current","sidebarPosition":5,"frontMatter":{"layout":"default","title":"Deployment topology","permalink":"/docs/concepts/topology"},"sidebar":"docsSidebar","previous":{"title":"Synchronous query","permalink":"/docs/concepts/queries"},"next":{"title":"Task lists","permalink":"/docs/concepts/task-lists"}}');var n=o(4848),s=o(8453);const r={layout:"default",title:"Deployment topology",permalink:"/docs/concepts/topology"},c="Deployment topology",a={},l=[{value:"Overview",id:"overview",level:2},{value:"Cadence Service",id:"cadence-service",level:2},{value:"Workflow Worker",id:"workflow-worker",level:2},{value:"Activity Worker",id:"activity-worker",level:2},{value:"External Clients",id:"external-clients",level:2}];function d(e){const t={a:"a",code:"code",em:"em",h1:"h1",h2:"h2",header:"header",img:"img",li:"li",p:"p",ul:"ul",...(0,s.R)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(t.header,{children:(0,n.jsx)(t.h1,{id:"deployment-topology",children:"Deployment topology"})}),"\n",(0,n.jsx)(t.h2,{id:"overview",children:"Overview"}),"\n",(0,n.jsx)(t.p,{children:"Cadence is a highly scalable fault-oblivious stateful code platform. The fault-oblivious code is a next level of abstraction over commonly used techniques to achieve fault tolerance and durability."}),"\n",(0,n.jsx)(t.p,{children:"A common Cadence-based application consists of a Cadence service, workflow and activity_workers, and external clients.\nNote that both types of workers as well as external clients are roles and can be collocated in a single application process if necessary."}),"\n",(0,n.jsx)(t.h2,{id:"cadence-service",children:"Cadence Service"}),"\n",(0,n.jsx)(t.p,{children:(0,n.jsx)(t.img,{src:"https://user-images.githubusercontent.com/14902200/160308507-2854a98a-0582-4748-87e4-e0695d3b6e86.jpg",alt:"Cadence Architecture"})}),"\n",(0,n.jsxs)(t.p,{children:["At the core of Cadence is a highly scalable multitentant service. The service exposes all of its functionality through a strongly typed ",(0,n.jsx)(t.a,{href:"https://github.com/cadence-workflow/cadence-idl/tree/master/proto/cadence-workflow/cadence/api/v1",children:"gRPC API"}),". A Cadence cluster include multiple services, each of which may run on multiple nodes for scalability and reliablity:"]}),"\n",(0,n.jsxs)(t.ul,{children:["\n",(0,n.jsx)(t.li,{children:"Front End: which is a stateless service used to handle incoming requests from Workers. It is expected that an external load balancing mechanism is used to distribute load between Front End instances."}),"\n",(0,n.jsx)(t.li,{children:"History Service: where the core logic of orchestrating workflow steps and activities is implemented"}),"\n",(0,n.jsx)(t.li,{children:"Matching Service: matches workflow/activity tasks that need to be executed to workflow/activity workers that are able to execute them. Matching is assigned task for execution by the history service"}),"\n",(0,n.jsx)(t.li,{children:"Internal Worker Service: implements Cadence workflows and activities for internal requirements such as archiving"}),"\n",(0,n.jsx)(t.li,{children:"Workers: are effectively the client apps for Cadence. This is where user created workflow and activity logic is executed"}),"\n"]}),"\n",(0,n.jsxs)(t.p,{children:["Internally it depends on a persistent store. Currently, Apache Cassandra, MySQL, PostgreSQL, CockroachDB (",(0,n.jsx)(t.a,{href:"https://www.cockroachlabs.com/docs/stable/postgresql-compatibility.html",children:"PostgreSQL compatible"}),") and TiDB (",(0,n.jsx)(t.a,{href:"https://docs.pingcap.com/tidb/dev/mysql-compatibility",children:"MySQL compatible"}),") stores are supported out of the box. For listing workflows using complex predicates, ElasticSearch and OpenSearch cluster can be used."]}),"\n",(0,n.jsx)(t.p,{children:"Cadence service is responsible for keeping workflow state and associated durable timers. It maintains internal queues (called task_lists) which are used to dispatch tasks to external workers."}),"\n",(0,n.jsx)(t.p,{children:"Cadence service is multitentant. Therefore it is expected that multiple pools of workers implementing different use cases connect to the same service instance. For example, at Uber a single service is used by more than a hundred applications. At the same time some external customers deploy an instance of Cadence service per application. For local development, a local Cadence service instance configured through docker-compose is used."}),"\n",(0,n.jsx)(t.p,{children:(0,n.jsx)(t.img,{src:"https://user-images.githubusercontent.com/14902200/160308592-400e11bc-0b21-4dd1-b568-8ac59005e6b7.svg",alt:"Cadence Overview"})}),"\n",(0,n.jsx)(t.h2,{id:"workflow-worker",children:"Workflow Worker"}),"\n",(0,n.jsxs)(t.p,{children:["Cadence reuses terminology from ",(0,n.jsx)(t.em,{children:"workflow automation"})," domain. So fault-oblivious stateful code is called workflow."]}),"\n",(0,n.jsxs)(t.p,{children:["The Cadence service does not execute workflow code directly. The workflow code is hosted by an external (from the service point of view) workflow_worker process. These processes receive ",(0,n.jsx)(t.em,{children:"decision_tasks"})," that contain events that the workflow is expected to handle from the Cadence service, delivers them to the workflow code, and communicates workflow ",(0,n.jsx)(t.em,{children:"decisions"})," back to the service."]}),"\n",(0,n.jsx)(t.p,{children:"As workflow code is external to the service, it can be implemented in any language that can talk service Thrift API. Currently Java and Go clients are production ready. While Python and C# clients are under development. Let us know if you are interested in contributing a client in your preferred language."}),"\n",(0,n.jsx)(t.p,{children:"The Cadence service API doesn't impose any specific workflow definition language. So a specific worker can be implemented to execute practically any existing workflow specification. The model the Cadence team chose to support out of the box is based on the idea of durable function. Durable functions are as close as possible to application business logic with minimal plumbing required."}),"\n",(0,n.jsx)(t.h2,{id:"activity-worker",children:"Activity Worker"}),"\n",(0,n.jsx)(t.p,{children:"Workflow fault-oblivious code is immune to infrastructure failures. But it has to communicate with the imperfect external world where failures are common. All communication to the external world is done through activities. Activities are pieces of code that can perform any application-specific action like calling a service, updating a database record, or downloading a file from Amazon S3. Cadence activities are very feature-rich compared to queuing systems. Example features are task routing to specific processes, infinite retries, heartbeats, and unlimited execution time."}),"\n",(0,n.jsxs)(t.p,{children:["Activities are hosted by ",(0,n.jsx)(t.em,{children:"activity_worker"})," processes that receive ",(0,n.jsx)(t.em,{children:"activity_tasks"})," from the Cadence service, invoke correspondent activity implementations and report back task completion statuses."]}),"\n",(0,n.jsx)(t.h2,{id:"external-clients",children:"External Clients"}),"\n",(0,n.jsxs)(t.p,{children:["Workflow and activity_workers host workflow and activity code. But to create a workflow instance (an execution in Cadence terminology) the ",(0,n.jsx)(t.code,{children:"StartWorkflowExecution"})," Cadence service API call should be used. Usually, workflows are started by outside entities like UIs, microservices or CLIs."]}),"\n",(0,n.jsx)(t.p,{children:"These entities can also:"}),"\n",(0,n.jsxs)(t.ul,{children:["\n",(0,n.jsx)(t.li,{children:"notify workflows about asynchronous external events in the form of signals"}),"\n",(0,n.jsx)(t.li,{children:"synchronously query workflow state"}),"\n",(0,n.jsx)(t.li,{children:"synchronously wait for a workflow completion"}),"\n",(0,n.jsx)(t.li,{children:"cancel, terminate, restart, and reset workflows"}),"\n",(0,n.jsx)(t.li,{children:"search for specific workflows using list API"}),"\n"]})]})}function h(e={}){const{wrapper:t}={...(0,s.R)(),...e.components};return t?(0,n.jsx)(t,{...e,children:(0,n.jsx)(d,{...e})}):d(e)}},8453:(e,t,o)=>{o.d(t,{R:()=>r,x:()=>c});var i=o(6540);const n={},s=i.createContext(n);function r(e){const t=i.useContext(s);return i.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function c(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(n):e.components||n:r(e.components),i.createElement(s.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/cdf6e634.2e392cc2.js b/assets/js/cdf6e634.2e392cc2.js new file mode 100644 index 000000000..b0900396e --- /dev/null +++ b/assets/js/cdf6e634.2e392cc2.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[3334],{8752:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>c,contentTitle:()=>r,default:()=>u,frontMatter:()=>i,metadata:()=>a,toc:()=>l});var a=n(6398),o=n(4848),s=n(8453);const i={title:"Cadence Community Spotlight Update - June 2023",date:new Date("2023-06-30T00:00:00.000Z"),authors:"sharanf",tags:["community-spotlight","release"]},r=void 0,c={authorsImageUrls:[void 0]},l=[{value:"Cadence Release 1.0",id:"cadence-release-10",level:2}];function d(e){const t={a:"a",h2:"h2",p:"p",...(0,s.R)(),...e.components};return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsx)(t.p,{children:"We've had a short break but now we are back. Welcome to the latest of our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!"}),"\n",(0,o.jsx)(t.p,{children:"Please see below for a roundup of the highlights:"}),"\n",(0,o.jsx)(t.h2,{id:"cadence-release-10",children:"Cadence Release 1.0"}),"\n",(0,o.jsxs)(t.p,{children:["Just in case you missed it - at the end of April ",(0,o.jsx)(t.a,{href:"https://github.com/cadence-workflow/cadence/releases/tag/v1.0.0",children:"Cadence v1.0"})," was officially released. This release is a significant milestone for the project and the community. It indicates that we are confident in the stability of the code that we can recommend it and promote it widely to more users. Kudos to everyone that worked together to make this release happen."]}),"\n",(0,o.jsxs)(t.p,{children:["And the Uber team also gave Cadence a writeup on the ",(0,o.jsx)(t.a,{href:"https://www.uber.com/en-SE/blog/announcing-cadence/",children:"Uber Engineering Blog"})," so please take a look."]})]})}function u(e={}){const{wrapper:t}={...(0,s.R)(),...e.components};return t?(0,o.jsx)(t,{...e,children:(0,o.jsx)(d,{...e})}):d(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>i,x:()=>r});var a=n(6540);const o={},s=a.createContext(o);function i(e){const t=a.useContext(s);return a.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function r(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:i(e.components),a.createElement(s.Provider,{value:t},e.children)}},6398:e=>{e.exports=JSON.parse('{"permalink":"/Cadence-Docs/blog/2023/06/30/community-spotlight-june-2023","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2023-06-30-community-spotlight-june-2023.md","source":"@site/blog/2023-06-30-community-spotlight-june-2023.md","title":"Cadence Community Spotlight Update - June 2023","description":"We\'ve had a short break but now we are back. Welcome to the latest of our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!","date":"2023-06-30T00:00:00.000Z","tags":[{"inline":false,"label":"Community Spotlight","permalink":"/Cadence-Docs/blog/tags/community-spotlights","description":"Community Spotlight tag description"},{"inline":false,"label":"Releases","permalink":"/Cadence-Docs/blog/tags/releases","description":"Releases tag description"}],"readingTime":2.725,"hasTruncateMarker":true,"authors":[{"name":"Sharan Foga","title":"Director of Operations & Customer Success @ Encube Technologies","url":"https://www.linkedin.com/in/sfoga/","page":{"permalink":"/Cadence-Docs/blog/authors/sharanf"},"socials":{"linkedin":"https://www.linkedin.com/in/sfoga/","github":"https://github.com/sharanf"},"imageURL":"https://github.com/sharanf.png","key":"sharanf"}],"frontMatter":{"title":"Cadence Community Spotlight Update - June 2023","date":"2023-06-30T00:00:00.000Z","authors":"sharanf","tags":["community-spotlight","release"]},"unlisted":false,"prevItem":{"title":"Understanding components of Cadence application","permalink":"/Cadence-Docs/blog/2023/06/28/components-of-cadence-application-setup"},"nextItem":{"title":"2023 Cadence Community Survey Results","permalink":"/Cadence-Docs/blog/2023/06/08/2023-06-08-survey-results/survey-results"}}')}}]); \ No newline at end of file diff --git a/assets/js/cdf6e634.4c655d2a.js b/assets/js/cdf6e634.4c655d2a.js deleted file mode 100644 index e75960326..000000000 --- a/assets/js/cdf6e634.4c655d2a.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[3334],{8752:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>l,contentTitle:()=>r,default:()=>h,frontMatter:()=>i,metadata:()=>a,toc:()=>c});var a=n(6398),o=n(4848),s=n(8453);const i={title:"Cadence Community Spotlight Update - June 2023",date:new Date("2023-06-30T00:00:00.000Z"),authors:"sharanf",tags:["community-spotlight","release"]},r=void 0,l={authorsImageUrls:[void 0]},c=[{value:"Cadence Release 1.0",id:"cadence-release-10",level:2}];function u(e){const t={a:"a",h2:"h2",p:"p",...(0,s.R)(),...e.components};return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsx)(t.p,{children:"We've had a short break but now we are back. Welcome to the latest of our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!"}),"\n",(0,o.jsx)(t.p,{children:"Please see below for a roundup of the highlights:"}),"\n",(0,o.jsx)(t.h2,{id:"cadence-release-10",children:"Cadence Release 1.0"}),"\n",(0,o.jsxs)(t.p,{children:["Just in case you missed it - at the end of April ",(0,o.jsx)(t.a,{href:"https://github.com/cadence-workflow/cadence/releases/tag/v1.0.0",children:"Cadence v1.0"})," was officially released. This release is a significant milestone for the project and the community. It indicates that we are confident in the stability of the code that we can recommend it and promote it widely to more users. Kudos to everyone that worked together to make this release happen."]}),"\n",(0,o.jsxs)(t.p,{children:["And the Uber team also gave Cadence a writeup on the ",(0,o.jsx)(t.a,{href:"https://www.uber.com/en-SE/blog/announcing-cadence/",children:"Uber Engineering Blog"})," so please take a look."]})]})}function h(e={}){const{wrapper:t}={...(0,s.R)(),...e.components};return t?(0,o.jsx)(t,{...e,children:(0,o.jsx)(u,{...e})}):u(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>i,x:()=>r});var a=n(6540);const o={},s=a.createContext(o);function i(e){const t=a.useContext(s);return a.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function r(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:i(e.components),a.createElement(s.Provider,{value:t},e.children)}},6398:e=>{e.exports=JSON.parse('{"permalink":"/blog/2023/06/30/community-spotlight-june-2023","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2023-06-30-community-spotlight-june-2023.md","source":"@site/blog/2023-06-30-community-spotlight-june-2023.md","title":"Cadence Community Spotlight Update - June 2023","description":"We\'ve had a short break but now we are back. Welcome to the latest of our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!","date":"2023-06-30T00:00:00.000Z","tags":[{"inline":false,"label":"Community Spotlight","permalink":"/blog/tags/community-spotlights","description":"Community Spotlight tag description"},{"inline":false,"label":"Releases","permalink":"/blog/tags/releases","description":"Releases tag description"}],"readingTime":2.725,"hasTruncateMarker":true,"authors":[{"name":"Sharan Foga","title":"Director of Operations & Customer Success @ Encube Technologies","url":"https://www.linkedin.com/in/sfoga/","page":{"permalink":"/blog/authors/sharanf"},"socials":{"linkedin":"https://www.linkedin.com/in/sfoga/","github":"https://github.com/sharanf"},"imageURL":"https://github.com/sharanf.png","key":"sharanf"}],"frontMatter":{"title":"Cadence Community Spotlight Update - June 2023","date":"2023-06-30T00:00:00.000Z","authors":"sharanf","tags":["community-spotlight","release"]},"unlisted":false,"prevItem":{"title":"Understanding components of Cadence application","permalink":"/blog/2023/06/28/components-of-cadence-application-setup"},"nextItem":{"title":"2023 Cadence Community Survey Results","permalink":"/blog/2023/06/08/2023-06-08-survey-results/survey-results"}}')}}]); \ No newline at end of file diff --git a/assets/js/cfb807c8.ef4959bc.js b/assets/js/cfb807c8.5d3e3ac1.js similarity index 66% rename from assets/js/cfb807c8.ef4959bc.js rename to assets/js/cfb807c8.5d3e3ac1.js index cbe32121c..36c742c9e 100644 --- a/assets/js/cfb807c8.ef4959bc.js +++ b/assets/js/cfb807c8.5d3e3ac1.js @@ -1 +1 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[9308],{8935:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>c,contentTitle:()=>r,default:()=>h,frontMatter:()=>s,metadata:()=>o,toc:()=>l});var o=n(1606),i=n(4848),a=n(8453);const s={title:"Cadence Community Spotlight Update - July 2022",date:new Date("2022-07-31T00:00:00.000Z"),authors:"sharanf",tags:["community-spotlight"]},r=void 0,c={authorsImageUrls:[void 0]},l=[{value:"Flying Drones with Cadence",id:"flying-drones-with-cadence",level:2},{value:"GitHub Statistics",id:"github-statistics",level:2}];function u(e){const t={a:"a",h2:"h2",p:"p",...(0,a.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(t.p,{children:"Here\u2019s our monthly Community Spotlight update that gives you news from in and around the Cadence community!"}),"\n",(0,i.jsx)(t.p,{children:"Please see below for a roundup of the highlights:"}),"\n",(0,i.jsx)(t.h2,{id:"flying-drones-with-cadence",children:"Flying Drones with Cadence"}),"\n",(0,i.jsxs)(t.p,{children:["Community member ",(0,i.jsx)(t.a,{href:"https://www.linkedin.com/in/paul-brebner-0a547b4/",children:"Paul Brebner"})," has released ",(0,i.jsx)(t.a,{href:"https://www.instaclustr.com/blog/spinning-your-drones-with-cadence-and-apache-kafka-how-many-drones-can-we-fly/",children:"another blog"})," in the series of using Cadence to manage a drone delivery service. You can see a ",(0,i.jsx)(t.a,{href:"https://www.youtube.com/watch?v=YgQeFSqzprk",children:"simulated view of it in action"})]}),"\n",(0,i.jsx)(t.p,{children:"Don\u2019t forget to try out the code yourself and remember if you have used Cadence to do something interesting then please let us know so we can feature it in our next update."}),"\n",(0,i.jsx)(t.h2,{id:"github-statistics",children:"GitHub Statistics"}),"\n",(0,i.jsxs)(t.p,{children:["During July the main Cadence branch had 28 pull requests (PRs) merged. There were 214 files changed by 11 different authors. You can find more details ",(0,i.jsx)(t.a,{href:"https://github.com/cadence-workflow/cadence/pulse/monthly",children:"here"})]}),"\n",(0,i.jsxs)(t.p,{children:["The Cadence documentation repository was not as busy with only 2 PRs merged in July, 5 commits and 3 authors active. More details can be found ",(0,i.jsx)(t.a,{href:"https://github.com/cadence-workflow/Cadence-Docs/pulse/monthly",children:"here"})]})]})}function h(e={}){const{wrapper:t}={...(0,a.R)(),...e.components};return t?(0,i.jsx)(t,{...e,children:(0,i.jsx)(u,{...e})}):u(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>s,x:()=>r});var o=n(6540);const i={},a=o.createContext(i);function s(e){const t=o.useContext(a);return o.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function r(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:s(e.components),o.createElement(a.Provider,{value:t},e.children)}},1606:e=>{e.exports=JSON.parse('{"permalink":"/blog/2022/07/31/community-spotlight-update-july-2022","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2022-07-31-community-spotlight-update-july-2022.md","source":"@site/blog/2022-07-31-community-spotlight-update-july-2022.md","title":"Cadence Community Spotlight Update - July 2022","description":"Here\u2019s our monthly Community Spotlight update that gives you news from in and around the Cadence community!","date":"2022-07-31T00:00:00.000Z","tags":[{"inline":false,"label":"Community Spotlight","permalink":"/blog/tags/community-spotlights","description":"Community Spotlight tag description"}],"readingTime":1.885,"hasTruncateMarker":true,"authors":[{"name":"Sharan Foga","title":"Director of Operations & Customer Success @ Encube Technologies","url":"https://www.linkedin.com/in/sfoga/","page":{"permalink":"/blog/authors/sharanf"},"socials":{"linkedin":"https://www.linkedin.com/in/sfoga/","github":"https://github.com/sharanf"},"imageURL":"https://github.com/sharanf.png","key":"sharanf"}],"frontMatter":{"title":"Cadence Community Spotlight Update - July 2022","date":"2022-07-31T00:00:00.000Z","authors":"sharanf","tags":["community-spotlight"]},"unlisted":false,"prevItem":{"title":"Cadence Community Spotlight Update - August 2022","permalink":"/blog/2022/08/31/community-spotlight-august-2022"},"nextItem":{"title":"Cadence Community Spotlight Update - June 2022","permalink":"/blog/2022/06/30/community-spotlight-update-june-2022"}}')}}]); \ No newline at end of file +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[9308],{8935:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>c,contentTitle:()=>r,default:()=>h,frontMatter:()=>s,metadata:()=>o,toc:()=>l});var o=n(1606),i=n(4848),a=n(8453);const s={title:"Cadence Community Spotlight Update - July 2022",date:new Date("2022-07-31T00:00:00.000Z"),authors:"sharanf",tags:["community-spotlight"]},r=void 0,c={authorsImageUrls:[void 0]},l=[{value:"Flying Drones with Cadence",id:"flying-drones-with-cadence",level:2},{value:"GitHub Statistics",id:"github-statistics",level:2}];function u(e){const t={a:"a",h2:"h2",p:"p",...(0,a.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(t.p,{children:"Here\u2019s our monthly Community Spotlight update that gives you news from in and around the Cadence community!"}),"\n",(0,i.jsx)(t.p,{children:"Please see below for a roundup of the highlights:"}),"\n",(0,i.jsx)(t.h2,{id:"flying-drones-with-cadence",children:"Flying Drones with Cadence"}),"\n",(0,i.jsxs)(t.p,{children:["Community member ",(0,i.jsx)(t.a,{href:"https://www.linkedin.com/in/paul-brebner-0a547b4/",children:"Paul Brebner"})," has released ",(0,i.jsx)(t.a,{href:"https://www.instaclustr.com/blog/spinning-your-drones-with-cadence-and-apache-kafka-how-many-drones-can-we-fly/",children:"another blog"})," in the series of using Cadence to manage a drone delivery service. You can see a ",(0,i.jsx)(t.a,{href:"https://www.youtube.com/watch?v=YgQeFSqzprk",children:"simulated view of it in action"})]}),"\n",(0,i.jsx)(t.p,{children:"Don\u2019t forget to try out the code yourself and remember if you have used Cadence to do something interesting then please let us know so we can feature it in our next update."}),"\n",(0,i.jsx)(t.h2,{id:"github-statistics",children:"GitHub Statistics"}),"\n",(0,i.jsxs)(t.p,{children:["During July the main Cadence branch had 28 pull requests (PRs) merged. There were 214 files changed by 11 different authors. You can find more details ",(0,i.jsx)(t.a,{href:"https://github.com/cadence-workflow/cadence/pulse/monthly",children:"here"})]}),"\n",(0,i.jsxs)(t.p,{children:["The Cadence documentation repository was not as busy with only 2 PRs merged in July, 5 commits and 3 authors active. More details can be found ",(0,i.jsx)(t.a,{href:"https://github.com/cadence-workflow/Cadence-Docs/pulse/monthly",children:"here"})]})]})}function h(e={}){const{wrapper:t}={...(0,a.R)(),...e.components};return t?(0,i.jsx)(t,{...e,children:(0,i.jsx)(u,{...e})}):u(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>s,x:()=>r});var o=n(6540);const i={},a=o.createContext(i);function s(e){const t=o.useContext(a);return o.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function r(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:s(e.components),o.createElement(a.Provider,{value:t},e.children)}},1606:e=>{e.exports=JSON.parse('{"permalink":"/Cadence-Docs/blog/2022/07/31/community-spotlight-update-july-2022","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2022-07-31-community-spotlight-update-july-2022.md","source":"@site/blog/2022-07-31-community-spotlight-update-july-2022.md","title":"Cadence Community Spotlight Update - July 2022","description":"Here\u2019s our monthly Community Spotlight update that gives you news from in and around the Cadence community!","date":"2022-07-31T00:00:00.000Z","tags":[{"inline":false,"label":"Community Spotlight","permalink":"/Cadence-Docs/blog/tags/community-spotlights","description":"Community Spotlight tag description"}],"readingTime":1.885,"hasTruncateMarker":true,"authors":[{"name":"Sharan Foga","title":"Director of Operations & Customer Success @ Encube Technologies","url":"https://www.linkedin.com/in/sfoga/","page":{"permalink":"/Cadence-Docs/blog/authors/sharanf"},"socials":{"linkedin":"https://www.linkedin.com/in/sfoga/","github":"https://github.com/sharanf"},"imageURL":"https://github.com/sharanf.png","key":"sharanf"}],"frontMatter":{"title":"Cadence Community Spotlight Update - July 2022","date":"2022-07-31T00:00:00.000Z","authors":"sharanf","tags":["community-spotlight"]},"unlisted":false,"prevItem":{"title":"Cadence Community Spotlight Update - August 2022","permalink":"/Cadence-Docs/blog/2022/08/31/community-spotlight-august-2022"},"nextItem":{"title":"Cadence Community Spotlight Update - June 2022","permalink":"/Cadence-Docs/blog/2022/06/30/community-spotlight-update-june-2022"}}')}}]); \ No newline at end of file diff --git a/assets/js/cfd61dd5.65104469.js b/assets/js/cfd61dd5.65104469.js deleted file mode 100644 index 61c29a7d4..000000000 --- a/assets/js/cfd61dd5.65104469.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[3044],{7237:(e,t,s)=>{s.r(t),s.d(t,{assets:()=>c,contentTitle:()=>r,default:()=>u,frontMatter:()=>a,metadata:()=>o,toc:()=>l});const o=JSON.parse('{"id":"use-cases/index","title":"Introduction","description":"As Cadence developers, we face a difficult non-technical problem: How to position and describe the Cadence platform.","source":"@site/docs/02-use-cases/index.md","sourceDirName":"02-use-cases","slug":"/use-cases/","permalink":"/docs/use-cases/","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/02-use-cases/index.md","tags":[],"version":"current","frontMatter":{"layout":"default","title":"Introduction","permalink":"/docs/use-cases/"},"sidebar":"docsSidebar","previous":{"title":"Video Tutorials","permalink":"/docs/get-started/video-tutorials"},"next":{"title":"Periodic execution","permalink":"/docs/use-cases/periodic-execution"}}');var n=s(4848),i=s(8453);const a={layout:"default",title:"Introduction",permalink:"/docs/use-cases/"},r="Use cases",c={},l=[];function d(e){const t={a:"a",em:"em",h1:"h1",header:"header",p:"p",strong:"strong",...(0,i.R)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(t.header,{children:(0,n.jsx)(t.h1,{id:"use-cases",children:"Use cases"})}),"\n",(0,n.jsx)(t.p,{children:"As Cadence developers, we face a difficult non-technical problem: How to position and describe the Cadence platform."}),"\n",(0,n.jsxs)(t.p,{children:["We call it ",(0,n.jsx)(t.em,{children:"workflow"}),'. But when most people hear the word "workflow" they think about ',(0,n.jsx)(t.a,{href:"https://en.wikipedia.org/wiki/Low-code_development_platform",children:"low-code"})," and UIs. While these might be useful for non technical users, they frequently bring more pain than value to software engineers. Most UIs and low-code ",(0,n.jsx)(t.a,{href:"https://en.wikipedia.org/wiki/Domain-specific_language",children:"DSLs"}),' are awesome for "hello world" demo applications, but any diagram with 100+ elements or a few thousand lines of JSON DSL is completely impractical. So positioning Cadence as a workflow is not ideal as it turns away developers that would enjoy its code-only approach.']}),"\n",(0,n.jsxs)(t.p,{children:["We call it ",(0,n.jsx)(t.em,{children:"orchestrator"}),". But this term is ",(0,n.jsx)(t.a,{href:"https://en.wikipedia.org/wiki/Orchestration_(computing)",children:"pretty narrow"})," and turns away customers that want to implement business process automation solutions."]}),"\n",(0,n.jsxs)(t.p,{children:["We call it ",(0,n.jsx)(t.em,{children:"durable function"})," platform. It is technically a correct term. But most developers outside of the Microsoft ecosystem have never heard of ",(0,n.jsx)(t.a,{href:"https://docs.microsoft.com/en-us/azure/azure-functions/durable/durable-functions-overview",children:"Durable Functions"}),"."]}),"\n",(0,n.jsxs)(t.p,{children:["We believe that problem in naming comes from the fact that Cadence is indeed a ",(0,n.jsx)(t.strong,{children:"new way to write distributed applications"}),". It is generic enough that it can be applied to practically any use case that goes beyond a single request reply. It can be used to build applications that are in traditional areas of workflow or orchestration platforms. But it is also huge ",(0,n.jsx)(t.em,{children:"developer productivity"})," boost for multiple use cases that traditionally rely on databases and/or task queues."]}),"\n",(0,n.jsx)(t.p,{children:"This section represents a far from complete list of use cases where Cadence is a good fit. All of them have been used by real production services inside and outside of Uber."}),"\n",(0,n.jsx)(t.p,{children:"Don't think of this list as exhaustive. It is common to employ multiple use types in a single application. For example, an operational management use case might need periodic execution, service orchestration, polling, event driven, as well as interactive parts."})]})}function u(e={}){const{wrapper:t}={...(0,i.R)(),...e.components};return t?(0,n.jsx)(t,{...e,children:(0,n.jsx)(d,{...e})}):d(e)}},8453:(e,t,s)=>{s.d(t,{R:()=>a,x:()=>r});var o=s(6540);const n={},i=o.createContext(n);function a(e){const t=o.useContext(i);return o.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function r(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(n):e.components||n:a(e.components),o.createElement(i.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/cfd61dd5.c7194c80.js b/assets/js/cfd61dd5.c7194c80.js new file mode 100644 index 000000000..412c3f3b8 --- /dev/null +++ b/assets/js/cfd61dd5.c7194c80.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[3044],{7237:(e,t,s)=>{s.r(t),s.d(t,{assets:()=>c,contentTitle:()=>r,default:()=>u,frontMatter:()=>i,metadata:()=>o,toc:()=>l});const o=JSON.parse('{"id":"use-cases/index","title":"Introduction","description":"As Cadence developers, we face a difficult non-technical problem: How to position and describe the Cadence platform.","source":"@site/docs/02-use-cases/index.md","sourceDirName":"02-use-cases","slug":"/use-cases/","permalink":"/Cadence-Docs/docs/use-cases/","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/02-use-cases/index.md","tags":[],"version":"current","frontMatter":{"layout":"default","title":"Introduction","permalink":"/docs/use-cases/"},"sidebar":"docsSidebar","previous":{"title":"Video Tutorials","permalink":"/Cadence-Docs/docs/get-started/video-tutorials"},"next":{"title":"Periodic execution","permalink":"/Cadence-Docs/docs/use-cases/periodic-execution"}}');var n=s(4848),a=s(8453);const i={layout:"default",title:"Introduction",permalink:"/docs/use-cases/"},r="Use cases",c={},l=[];function d(e){const t={a:"a",em:"em",h1:"h1",header:"header",p:"p",strong:"strong",...(0,a.R)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(t.header,{children:(0,n.jsx)(t.h1,{id:"use-cases",children:"Use cases"})}),"\n",(0,n.jsx)(t.p,{children:"As Cadence developers, we face a difficult non-technical problem: How to position and describe the Cadence platform."}),"\n",(0,n.jsxs)(t.p,{children:["We call it ",(0,n.jsx)(t.em,{children:"workflow"}),'. But when most people hear the word "workflow" they think about ',(0,n.jsx)(t.a,{href:"https://en.wikipedia.org/wiki/Low-code_development_platform",children:"low-code"})," and UIs. While these might be useful for non technical users, they frequently bring more pain than value to software engineers. Most UIs and low-code ",(0,n.jsx)(t.a,{href:"https://en.wikipedia.org/wiki/Domain-specific_language",children:"DSLs"}),' are awesome for "hello world" demo applications, but any diagram with 100+ elements or a few thousand lines of JSON DSL is completely impractical. So positioning Cadence as a workflow is not ideal as it turns away developers that would enjoy its code-only approach.']}),"\n",(0,n.jsxs)(t.p,{children:["We call it ",(0,n.jsx)(t.em,{children:"orchestrator"}),". But this term is ",(0,n.jsx)(t.a,{href:"https://en.wikipedia.org/wiki/Orchestration_(computing)",children:"pretty narrow"})," and turns away customers that want to implement business process automation solutions."]}),"\n",(0,n.jsxs)(t.p,{children:["We call it ",(0,n.jsx)(t.em,{children:"durable function"})," platform. It is technically a correct term. But most developers outside of the Microsoft ecosystem have never heard of ",(0,n.jsx)(t.a,{href:"https://docs.microsoft.com/en-us/azure/azure-functions/durable/durable-functions-overview",children:"Durable Functions"}),"."]}),"\n",(0,n.jsxs)(t.p,{children:["We believe that problem in naming comes from the fact that Cadence is indeed a ",(0,n.jsx)(t.strong,{children:"new way to write distributed applications"}),". It is generic enough that it can be applied to practically any use case that goes beyond a single request reply. It can be used to build applications that are in traditional areas of workflow or orchestration platforms. But it is also huge ",(0,n.jsx)(t.em,{children:"developer productivity"})," boost for multiple use cases that traditionally rely on databases and/or task queues."]}),"\n",(0,n.jsx)(t.p,{children:"This section represents a far from complete list of use cases where Cadence is a good fit. All of them have been used by real production services inside and outside of Uber."}),"\n",(0,n.jsx)(t.p,{children:"Don't think of this list as exhaustive. It is common to employ multiple use types in a single application. For example, an operational management use case might need periodic execution, service orchestration, polling, event driven, as well as interactive parts."})]})}function u(e={}){const{wrapper:t}={...(0,a.R)(),...e.components};return t?(0,n.jsx)(t,{...e,children:(0,n.jsx)(d,{...e})}):d(e)}},8453:(e,t,s)=>{s.d(t,{R:()=>i,x:()=>r});var o=s(6540);const n={},a=o.createContext(n);function i(e){const t=o.useContext(a);return o.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function r(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(n):e.components||n:i(e.components),o.createElement(a.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/d0ac2d40.6e91bc5b.js b/assets/js/d0ac2d40.6e91bc5b.js deleted file mode 100644 index 42976dbf2..000000000 --- a/assets/js/d0ac2d40.6e91bc5b.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[6401],{9878:(e,t,i)=>{i.r(t),i.d(t,{assets:()=>s,contentTitle:()=>o,default:()=>u,frontMatter:()=>r,metadata:()=>n,toc:()=>l});const n=JSON.parse('{"id":"java-client/activity-interface","title":"Activity interface","description":"An is a manifestation of a particular in the business logic.","source":"@site/docs/04-java-client/05-activity-interface.md","sourceDirName":"04-java-client","slug":"/java-client/activity-interface","permalink":"/docs/java-client/activity-interface","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/04-java-client/05-activity-interface.md","tags":[],"version":"current","sidebarPosition":5,"frontMatter":{"layout":"default","title":"Activity interface","permalink":"/docs/java-client/activity-interface"},"sidebar":"docsSidebar","previous":{"title":"Starting workflows","permalink":"/docs/java-client/starting-workflow-executions"},"next":{"title":"Versioning","permalink":"/docs/java-client/versioning"}}');var a=i(4848),c=i(8453);const r={layout:"default",title:"Activity interface",permalink:"/docs/java-client/activity-interface"},o="Activity interface",s={},l=[];function d(e){const t={a:"a",code:"code",h1:"h1",header:"header",p:"p",pre:"pre",...(0,c.R)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(t.header,{children:(0,a.jsx)(t.h1,{id:"activity-interface",children:"Activity interface"})}),"\n",(0,a.jsx)(t.p,{children:"An activity is a manifestation of a particular task in the business logic."}),"\n",(0,a.jsxs)(t.p,{children:["Activities are defined as methods of a plain Java interface. Each method defines a single activity type. A single\nworkflow can use more than one activity interface and call more than one activity method from the same interface.\nThe only requirement is that activity method arguments and return values are serializable to a byte array using the provided\n",(0,a.jsx)(t.a,{href:"https://static.javadoc.io/com.uber.cadence/cadence-client/2.4.1/index.html?com/cadence-workflow/cadence/converter/DataConverter.html",children:"DataConverter"}),"\ninterface. The default implementation uses a JSON serializer, but an alternative implementation can be easily configured."]}),"\n",(0,a.jsx)(t.p,{children:"Following is an example of an interface that defines four activities:"}),"\n",(0,a.jsx)(t.pre,{children:(0,a.jsx)(t.code,{className:"language-java",children:"public interface FileProcessingActivities {\n\n void upload(String bucketName, String localName, String targetName);\n\n String download(String bucketName, String remoteName);\n\n @ActivityMethod(scheduleToCloseTimeoutSeconds = 2)\n String processFile(String localName);\n\n void deleteLocalFile(String fileName);\n}\n\n"})}),"\n",(0,a.jsx)(t.p,{children:"We recommend to use a single value type argument for activity methods. In this way, adding new arguments as fields\nto the value type is a backwards-compatible change."}),"\n",(0,a.jsx)(t.p,{children:"An optional @ActivityMethod annotation can be used to specify activity options like timeouts or a task_list. Required options\nthat are not specified through the annotation must be specified at runtime."})]})}function u(e={}){const{wrapper:t}={...(0,c.R)(),...e.components};return t?(0,a.jsx)(t,{...e,children:(0,a.jsx)(d,{...e})}):d(e)}},8453:(e,t,i)=>{i.d(t,{R:()=>r,x:()=>o});var n=i(6540);const a={},c=n.createContext(a);function r(e){const t=n.useContext(c);return n.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function o(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:r(e.components),n.createElement(c.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/d0ac2d40.a5968188.js b/assets/js/d0ac2d40.a5968188.js new file mode 100644 index 000000000..3ce7d2d8a --- /dev/null +++ b/assets/js/d0ac2d40.a5968188.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[6401],{9878:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>s,contentTitle:()=>o,default:()=>u,frontMatter:()=>r,metadata:()=>i,toc:()=>l});const i=JSON.parse('{"id":"java-client/activity-interface","title":"Activity interface","description":"An is a manifestation of a particular in the business logic.","source":"@site/docs/04-java-client/05-activity-interface.md","sourceDirName":"04-java-client","slug":"/java-client/activity-interface","permalink":"/Cadence-Docs/docs/java-client/activity-interface","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/04-java-client/05-activity-interface.md","tags":[],"version":"current","sidebarPosition":5,"frontMatter":{"layout":"default","title":"Activity interface","permalink":"/docs/java-client/activity-interface"},"sidebar":"docsSidebar","previous":{"title":"Starting workflows","permalink":"/Cadence-Docs/docs/java-client/starting-workflow-executions"},"next":{"title":"Versioning","permalink":"/Cadence-Docs/docs/java-client/versioning"}}');var a=n(4848),c=n(8453);const r={layout:"default",title:"Activity interface",permalink:"/docs/java-client/activity-interface"},o="Activity interface",s={},l=[];function d(e){const t={a:"a",code:"code",h1:"h1",header:"header",p:"p",pre:"pre",...(0,c.R)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(t.header,{children:(0,a.jsx)(t.h1,{id:"activity-interface",children:"Activity interface"})}),"\n",(0,a.jsx)(t.p,{children:"An activity is a manifestation of a particular task in the business logic."}),"\n",(0,a.jsxs)(t.p,{children:["Activities are defined as methods of a plain Java interface. Each method defines a single activity type. A single\nworkflow can use more than one activity interface and call more than one activity method from the same interface.\nThe only requirement is that activity method arguments and return values are serializable to a byte array using the provided\n",(0,a.jsx)(t.a,{href:"https://static.javadoc.io/com.uber.cadence/cadence-client/2.4.1/index.html?com/cadence-workflow/cadence/converter/DataConverter.html",children:"DataConverter"}),"\ninterface. The default implementation uses a JSON serializer, but an alternative implementation can be easily configured."]}),"\n",(0,a.jsx)(t.p,{children:"Following is an example of an interface that defines four activities:"}),"\n",(0,a.jsx)(t.pre,{children:(0,a.jsx)(t.code,{className:"language-java",children:"public interface FileProcessingActivities {\n\n void upload(String bucketName, String localName, String targetName);\n\n String download(String bucketName, String remoteName);\n\n @ActivityMethod(scheduleToCloseTimeoutSeconds = 2)\n String processFile(String localName);\n\n void deleteLocalFile(String fileName);\n}\n\n"})}),"\n",(0,a.jsx)(t.p,{children:"We recommend to use a single value type argument for activity methods. In this way, adding new arguments as fields\nto the value type is a backwards-compatible change."}),"\n",(0,a.jsx)(t.p,{children:"An optional @ActivityMethod annotation can be used to specify activity options like timeouts or a task_list. Required options\nthat are not specified through the annotation must be specified at runtime."})]})}function u(e={}){const{wrapper:t}={...(0,c.R)(),...e.components};return t?(0,a.jsx)(t,{...e,children:(0,a.jsx)(d,{...e})}):d(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>r,x:()=>o});var i=n(6540);const a={},c=i.createContext(a);function r(e){const t=i.useContext(c);return i.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function o(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:r(e.components),i.createElement(c.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/d0bf664b.3a3af1d5.js b/assets/js/d0bf664b.3a3af1d5.js deleted file mode 100644 index e088ad4bb..000000000 --- a/assets/js/d0bf664b.3a3af1d5.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[4177],{1285:t=>{t.exports=JSON.parse('{"tag":{"label":"Community Spotlight","permalink":"/blog/tags/community-spotlights","description":"Community Spotlight tag description","allTagsPath":"/blog/tags","count":20,"unlisted":false},"listMetadata":{"permalink":"/blog/tags/community-spotlights/page/2","page":2,"postsPerPage":10,"totalPages":2,"totalCount":20,"previousPage":"/blog/tags/community-spotlights","blogDescription":"The latest news and updates from the Cadence team","blogTitle":"Cadence Blog"}}')}}]); \ No newline at end of file diff --git a/assets/js/d2436a2b.d6e0255e.js b/assets/js/d2436a2b.d6e0255e.js deleted file mode 100644 index 7426a541b..000000000 --- a/assets/js/d2436a2b.d6e0255e.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[837],{9112:e=>{e.exports=JSON.parse('{"version":{"pluginId":"community","version":"current","label":"Next","banner":null,"badge":false,"noIndex":false,"className":"docs-version-current","isLast":true,"docsSidebars":{"community":[{"type":"link","label":"Support","href":"/community/support","docId":"support","unlisted":false},{"type":"link","label":"Team","href":"/community/team","docId":"team","unlisted":false},{"type":"link","label":"Chat with us on Slack","href":"http://t.uber.com/cadence-slack"}]},"docs":{"contributing":{"id":"contributing","title":"Contributing","description":""},"resources":{"id":"resources","title":"Resources","description":"Cadence documentation"},"support":{"id":"support","title":"Support","description":"On this page we\'ve listed some Cadence-related communities that you can be a part of.","sidebar":"community"},"team":{"id":"team","title":"Team","description":"Core Team","sidebar":"community"}}}}')}}]); \ No newline at end of file diff --git a/assets/js/d27d92a2.fa23e5d9.js b/assets/js/d27d92a2.e180642c.js similarity index 74% rename from assets/js/d27d92a2.fa23e5d9.js rename to assets/js/d27d92a2.e180642c.js index ee72dcf8f..83e72c94f 100644 --- a/assets/js/d27d92a2.fa23e5d9.js +++ b/assets/js/d27d92a2.e180642c.js @@ -1 +1 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[3060],{3592:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>c,contentTitle:()=>r,default:()=>h,frontMatter:()=>s,metadata:()=>a,toc:()=>l});var a=t(1606),i=t(4848),o=t(8453);const s={title:"Cadence Community Spotlight Update - July 2022",date:new Date("2022-07-31T00:00:00.000Z"),authors:"sharanf",tags:["community-spotlight"]},r=void 0,c={authorsImageUrls:[void 0]},l=[{value:"Flying Drones with Cadence",id:"flying-drones-with-cadence",level:2},{value:"GitHub Statistics",id:"github-statistics",level:2},{value:"Cadence Roadmap",id:"cadence-roadmap",level:2},{value:"Cadence in the News!",id:"cadence-in-the-news",level:2},{value:"Upcoming Events",id:"upcoming-events",level:2}];function d(e){const n={a:"a",h2:"h2",li:"li",p:"p",ul:"ul",...(0,o.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.p,{children:"Here\u2019s our monthly Community Spotlight update that gives you news from in and around the Cadence community!"}),"\n",(0,i.jsx)(n.p,{children:"Please see below for a roundup of the highlights:"}),"\n",(0,i.jsx)(n.h2,{id:"flying-drones-with-cadence",children:"Flying Drones with Cadence"}),"\n",(0,i.jsxs)(n.p,{children:["Community member ",(0,i.jsx)(n.a,{href:"https://www.linkedin.com/in/paul-brebner-0a547b4/",children:"Paul Brebner"})," has released ",(0,i.jsx)(n.a,{href:"https://www.instaclustr.com/blog/spinning-your-drones-with-cadence-and-apache-kafka-how-many-drones-can-we-fly/",children:"another blog"})," in the series of using Cadence to manage a drone delivery service. You can see a ",(0,i.jsx)(n.a,{href:"https://www.youtube.com/watch?v=YgQeFSqzprk",children:"simulated view of it in action"})]}),"\n",(0,i.jsx)(n.p,{children:"Don\u2019t forget to try out the code yourself and remember if you have used Cadence to do something interesting then please let us know so we can feature it in our next update."}),"\n",(0,i.jsx)(n.h2,{id:"github-statistics",children:"GitHub Statistics"}),"\n",(0,i.jsxs)(n.p,{children:["During July the main Cadence branch had 28 pull requests (PRs) merged. There were 214 files changed by 11 different authors. You can find more details ",(0,i.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence/pulse/monthly",children:"here"})]}),"\n",(0,i.jsxs)(n.p,{children:["The Cadence documentation repository was not as busy with only 2 PRs merged in July, 5 commits and 3 authors active. More details can be found ",(0,i.jsx)(n.a,{href:"https://github.com/cadence-workflow/Cadence-Docs/pulse/monthly",children:"here"})]}),"\n",(0,i.jsx)(n.h2,{id:"cadence-roadmap",children:"Cadence Roadmap"}),"\n",(0,i.jsx)(n.p,{children:"The Cadence Core team has been busy this month looking at the various community feedback for potential improvements and features for Cadence. Planning is already in place for a development roadmap and it is still a little too early to say what will be included so please watch out for future updates. All I know is that it\u2019s going to be exciting!"}),"\n",(0,i.jsx)(n.h2,{id:"cadence-in-the-news",children:"Cadence in the News!"}),"\n",(0,i.jsx)(n.p,{children:"Below are a selection of Cadence related articles, blogs and whitepapers. Please take a look and feel free to share via your own social media channels."}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://www.instaclustr.com/blog/migrate-to-cadence-from-temporal/",children:"Migrate to Cadence From Temporal"})}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://www.instaclustr.com/blog/spinning-your-drones-with-cadence-and-apache-kafka-how-many-drones-can-we-fly/",children:"Spinning Your Drones With Cadence and Apache Kafka\xae: How Many Drones Can We Fly?"})}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.h2,{id:"upcoming-events",children:"Upcoming Events"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://calendar.google.com/calendar/u/0/embed?src=e6r40gp3c2r01054id7e99dlac@group.calendar.google.com&ctz=America/Los_Angeles",children:"Cadence Technical Office Hours - 29th August 2022 @ 9am PT"})}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://info.instaclustr.com/webinar-cadence-fundamentals-event-sourcing/",children:"Webinar: Cadence Fundamentals: Event Sourcing - Two sessions one on 16th and one on 18th August 2022\n"})}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://info.instaclustr.com/webinar-emea-building-cadence-workflow.html",children:"Webinar: Building Your First Cadence Workflow with Java and Go - 1st September 2022"})}),"\n"]}),"\n"]}),"\n",(0,i.jsxs)(n.p,{children:["If you have any news or topics you'd like us to include in our next update then please join our ",(0,i.jsx)(n.a,{href:"http://t.uber.com/cadence-slack",children:"Slack"}),"#community channel."]}),"\n",(0,i.jsxs)(n.p,{children:["Please remember that this update is for you - so if you have any comments or feedback that could help us improve it then please share it with us in the #community ",(0,i.jsx)(n.a,{href:"http://t.uber.com/cadence-slack",children:"Slack"})," channel."]})]})}function h(e={}){const{wrapper:n}={...(0,o.R)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(d,{...e})}):d(e)}},8453:(e,n,t)=>{t.d(n,{R:()=>s,x:()=>r});var a=t(6540);const i={},o=a.createContext(i);function s(e){const n=a.useContext(o);return a.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function r(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:s(e.components),a.createElement(o.Provider,{value:n},e.children)}},1606:e=>{e.exports=JSON.parse('{"permalink":"/blog/2022/07/31/community-spotlight-update-july-2022","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2022-07-31-community-spotlight-update-july-2022.md","source":"@site/blog/2022-07-31-community-spotlight-update-july-2022.md","title":"Cadence Community Spotlight Update - July 2022","description":"Here\u2019s our monthly Community Spotlight update that gives you news from in and around the Cadence community!","date":"2022-07-31T00:00:00.000Z","tags":[{"inline":false,"label":"Community Spotlight","permalink":"/blog/tags/community-spotlights","description":"Community Spotlight tag description"}],"readingTime":1.885,"hasTruncateMarker":true,"authors":[{"name":"Sharan Foga","title":"Director of Operations & Customer Success @ Encube Technologies","url":"https://www.linkedin.com/in/sfoga/","page":{"permalink":"/blog/authors/sharanf"},"socials":{"linkedin":"https://www.linkedin.com/in/sfoga/","github":"https://github.com/sharanf"},"imageURL":"https://github.com/sharanf.png","key":"sharanf"}],"frontMatter":{"title":"Cadence Community Spotlight Update - July 2022","date":"2022-07-31T00:00:00.000Z","authors":"sharanf","tags":["community-spotlight"]},"unlisted":false,"prevItem":{"title":"Cadence Community Spotlight Update - August 2022","permalink":"/blog/2022/08/31/community-spotlight-august-2022"},"nextItem":{"title":"Cadence Community Spotlight Update - June 2022","permalink":"/blog/2022/06/30/community-spotlight-update-june-2022"}}')}}]); \ No newline at end of file +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[3060],{3592:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>r,contentTitle:()=>c,default:()=>h,frontMatter:()=>s,metadata:()=>a,toc:()=>l});var a=t(1606),i=t(4848),o=t(8453);const s={title:"Cadence Community Spotlight Update - July 2022",date:new Date("2022-07-31T00:00:00.000Z"),authors:"sharanf",tags:["community-spotlight"]},c=void 0,r={authorsImageUrls:[void 0]},l=[{value:"Flying Drones with Cadence",id:"flying-drones-with-cadence",level:2},{value:"GitHub Statistics",id:"github-statistics",level:2},{value:"Cadence Roadmap",id:"cadence-roadmap",level:2},{value:"Cadence in the News!",id:"cadence-in-the-news",level:2},{value:"Upcoming Events",id:"upcoming-events",level:2}];function d(e){const n={a:"a",h2:"h2",li:"li",p:"p",ul:"ul",...(0,o.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.p,{children:"Here\u2019s our monthly Community Spotlight update that gives you news from in and around the Cadence community!"}),"\n",(0,i.jsx)(n.p,{children:"Please see below for a roundup of the highlights:"}),"\n",(0,i.jsx)(n.h2,{id:"flying-drones-with-cadence",children:"Flying Drones with Cadence"}),"\n",(0,i.jsxs)(n.p,{children:["Community member ",(0,i.jsx)(n.a,{href:"https://www.linkedin.com/in/paul-brebner-0a547b4/",children:"Paul Brebner"})," has released ",(0,i.jsx)(n.a,{href:"https://www.instaclustr.com/blog/spinning-your-drones-with-cadence-and-apache-kafka-how-many-drones-can-we-fly/",children:"another blog"})," in the series of using Cadence to manage a drone delivery service. You can see a ",(0,i.jsx)(n.a,{href:"https://www.youtube.com/watch?v=YgQeFSqzprk",children:"simulated view of it in action"})]}),"\n",(0,i.jsx)(n.p,{children:"Don\u2019t forget to try out the code yourself and remember if you have used Cadence to do something interesting then please let us know so we can feature it in our next update."}),"\n",(0,i.jsx)(n.h2,{id:"github-statistics",children:"GitHub Statistics"}),"\n",(0,i.jsxs)(n.p,{children:["During July the main Cadence branch had 28 pull requests (PRs) merged. There were 214 files changed by 11 different authors. You can find more details ",(0,i.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence/pulse/monthly",children:"here"})]}),"\n",(0,i.jsxs)(n.p,{children:["The Cadence documentation repository was not as busy with only 2 PRs merged in July, 5 commits and 3 authors active. More details can be found ",(0,i.jsx)(n.a,{href:"https://github.com/cadence-workflow/Cadence-Docs/pulse/monthly",children:"here"})]}),"\n",(0,i.jsx)(n.h2,{id:"cadence-roadmap",children:"Cadence Roadmap"}),"\n",(0,i.jsx)(n.p,{children:"The Cadence Core team has been busy this month looking at the various community feedback for potential improvements and features for Cadence. Planning is already in place for a development roadmap and it is still a little too early to say what will be included so please watch out for future updates. All I know is that it\u2019s going to be exciting!"}),"\n",(0,i.jsx)(n.h2,{id:"cadence-in-the-news",children:"Cadence in the News!"}),"\n",(0,i.jsx)(n.p,{children:"Below are a selection of Cadence related articles, blogs and whitepapers. Please take a look and feel free to share via your own social media channels."}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://www.instaclustr.com/blog/migrate-to-cadence-from-temporal/",children:"Migrate to Cadence From Temporal"})}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://www.instaclustr.com/blog/spinning-your-drones-with-cadence-and-apache-kafka-how-many-drones-can-we-fly/",children:"Spinning Your Drones With Cadence and Apache Kafka\xae: How Many Drones Can We Fly?"})}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.h2,{id:"upcoming-events",children:"Upcoming Events"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://calendar.google.com/calendar/u/0/embed?src=e6r40gp3c2r01054id7e99dlac@group.calendar.google.com&ctz=America/Los_Angeles",children:"Cadence Technical Office Hours - 29th August 2022 @ 9am PT"})}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://info.instaclustr.com/webinar-cadence-fundamentals-event-sourcing/",children:"Webinar: Cadence Fundamentals: Event Sourcing - Two sessions one on 16th and one on 18th August 2022\n"})}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://info.instaclustr.com/webinar-emea-building-cadence-workflow.html",children:"Webinar: Building Your First Cadence Workflow with Java and Go - 1st September 2022"})}),"\n"]}),"\n"]}),"\n",(0,i.jsxs)(n.p,{children:["If you have any news or topics you'd like us to include in our next update then please join our ",(0,i.jsx)(n.a,{href:"http://t.uber.com/cadence-slack",children:"Slack"}),"#community channel."]}),"\n",(0,i.jsxs)(n.p,{children:["Please remember that this update is for you - so if you have any comments or feedback that could help us improve it then please share it with us in the #community ",(0,i.jsx)(n.a,{href:"http://t.uber.com/cadence-slack",children:"Slack"})," channel."]})]})}function h(e={}){const{wrapper:n}={...(0,o.R)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(d,{...e})}):d(e)}},8453:(e,n,t)=>{t.d(n,{R:()=>s,x:()=>c});var a=t(6540);const i={},o=a.createContext(i);function s(e){const n=a.useContext(o);return a.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function c(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:s(e.components),a.createElement(o.Provider,{value:n},e.children)}},1606:e=>{e.exports=JSON.parse('{"permalink":"/Cadence-Docs/blog/2022/07/31/community-spotlight-update-july-2022","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2022-07-31-community-spotlight-update-july-2022.md","source":"@site/blog/2022-07-31-community-spotlight-update-july-2022.md","title":"Cadence Community Spotlight Update - July 2022","description":"Here\u2019s our monthly Community Spotlight update that gives you news from in and around the Cadence community!","date":"2022-07-31T00:00:00.000Z","tags":[{"inline":false,"label":"Community Spotlight","permalink":"/Cadence-Docs/blog/tags/community-spotlights","description":"Community Spotlight tag description"}],"readingTime":1.885,"hasTruncateMarker":true,"authors":[{"name":"Sharan Foga","title":"Director of Operations & Customer Success @ Encube Technologies","url":"https://www.linkedin.com/in/sfoga/","page":{"permalink":"/Cadence-Docs/blog/authors/sharanf"},"socials":{"linkedin":"https://www.linkedin.com/in/sfoga/","github":"https://github.com/sharanf"},"imageURL":"https://github.com/sharanf.png","key":"sharanf"}],"frontMatter":{"title":"Cadence Community Spotlight Update - July 2022","date":"2022-07-31T00:00:00.000Z","authors":"sharanf","tags":["community-spotlight"]},"unlisted":false,"prevItem":{"title":"Cadence Community Spotlight Update - August 2022","permalink":"/Cadence-Docs/blog/2022/08/31/community-spotlight-august-2022"},"nextItem":{"title":"Cadence Community Spotlight Update - June 2022","permalink":"/Cadence-Docs/blog/2022/06/30/community-spotlight-update-june-2022"}}')}}]); \ No newline at end of file diff --git a/assets/js/d280f29d.c4924f81.js b/assets/js/d280f29d.c4924f81.js new file mode 100644 index 000000000..801e7a163 --- /dev/null +++ b/assets/js/d280f29d.c4924f81.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[4881],{1892:(n,e,t)=>{t.r(e),t.d(e,{assets:()=>l,contentTitle:()=>r,default:()=>h,frontMatter:()=>s,metadata:()=>a,toc:()=>c});const a=JSON.parse('{"id":"go-client/signals","title":"Signals","description":"Signalsworkflow:. Previously, you had","source":"@site/docs/05-go-client/08-signals.md","sourceDirName":"05-go-client","slug":"/go-client/signals","permalink":"/Cadence-Docs/docs/go-client/signals","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/05-go-client/08-signals.md","tags":[],"version":"current","sidebarPosition":8,"frontMatter":{"layout":"default","title":"Signals","permalink":"/docs/go-client/signals"},"sidebar":"docsSidebar","previous":{"title":"Error handling","permalink":"/Cadence-Docs/docs/go-client/error-handling"},"next":{"title":"Continue as new","permalink":"/Cadence-Docs/docs/go-client/continue-as-new"}}');var o=t(4848),i=t(8453);const s={layout:"default",title:"Signals",permalink:"/docs/go-client/signals"},r="Signals",l={},c=[{value:"SignalWithStart",id:"signalwithstart",level:2}];function d(n){const e={a:"a",code:"code",h1:"h1",h2:"h2",header:"header",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,i.R)(),...n.components};return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsx)(e.header,{children:(0,o.jsx)(e.h1,{id:"signals",children:"Signals"})}),"\n",(0,o.jsx)(e.p,{children:"Signals provide a mechanism to send data directly to a running workflow. Previously, you had\ntwo options for passing data to the workflow implementation:"}),"\n",(0,o.jsxs)(e.ul,{children:["\n",(0,o.jsx)(e.li,{children:"Via start parameters"}),"\n",(0,o.jsx)(e.li,{children:"As return values from activities"}),"\n"]}),"\n",(0,o.jsx)(e.p,{children:"With start parameters, we could only pass in values before workflow_execution began."}),"\n",(0,o.jsx)(e.p,{children:"Return values from activities allowed us to pass information to a running workflow, but this\napproach comes with its own complications. One major drawback is reliance on polling. This means\nthat the data needs to be stored in a third-party location until it's ready to be picked up by\nthe activity. Further, the lifecycle of this activity requires management, and the activity\nrequires manual restart if it fails before acquiring the data."}),"\n",(0,o.jsx)(e.p,{children:"Signals, on the other hand, provide a fully asynchronous and durable mechanism for providing data to\na running workflow. When a signal is received for a running workflow, Cadence persists the event\nand the payload in the workflow history. The workflow can then process the signal at any time\nafterwards without the risk of losing the information. The workflow also has the option to stop\nexecution by blocking on a signal channel."}),"\n",(0,o.jsx)(e.pre,{children:(0,o.jsx)(e.code,{className:"language-go",children:'var signalVal string\nsignalChan := workflow.GetSignalChannel(ctx, signalName)\n\ns := workflow.NewSelector(ctx)\ns.AddReceive(signalChan, func(c workflow.Channel, more bool) {\n c.Receive(ctx, &signalVal)\n workflow.GetLogger(ctx).Info("Received signal!", zap.String("signal", signalName), zap.String("value", signalVal))\n})\ns.Select(ctx)\n\nif len(signalVal) > 0 && signalVal != "SOME_VALUE" {\n return errors.New("signalVal")\n}\n'})}),"\n",(0,o.jsxs)(e.p,{children:["In the example above, the workflow code uses ",(0,o.jsx)(e.strong,{children:"workflow.GetSignalChannel"})," to open a\n",(0,o.jsx)(e.strong,{children:"workflow.Channel"})," for the named signal. We then use a ",(0,o.jsx)(e.strong,{children:"workflow.Selector"})," to wait on this\nchannel and process the payload received with the signal."]}),"\n",(0,o.jsx)(e.h2,{id:"signalwithstart",children:"SignalWithStart"}),"\n",(0,o.jsxs)(e.p,{children:["You may not know if a workflow is running and can accept a signal. The\n",(0,o.jsx)(e.a,{href:"https://godoc.org/go.uber.org/cadence/client#Client",children:"client.SignalWithStartWorkflow"})," API\nallows you to send a signal to the current workflow instance if one exists or to create a new\nrun and then send the signal. ",(0,o.jsx)(e.code,{children:"SignalWithStartWorkflow"})," therefore doesn't take a run_ID as a\nparameter."]})]})}function h(n={}){const{wrapper:e}={...(0,i.R)(),...n.components};return e?(0,o.jsx)(e,{...n,children:(0,o.jsx)(d,{...n})}):d(n)}},8453:(n,e,t)=>{t.d(e,{R:()=>s,x:()=>r});var a=t(6540);const o={},i=a.createContext(o);function s(n){const e=a.useContext(i);return a.useMemo((function(){return"function"==typeof n?n(e):{...e,...n}}),[e,n])}function r(n){let e;return e=n.disableParentContext?"function"==typeof n.components?n.components(o):n.components||o:s(n.components),a.createElement(i.Provider,{value:e},n.children)}}}]); \ No newline at end of file diff --git a/assets/js/d280f29d.cd209164.js b/assets/js/d280f29d.cd209164.js deleted file mode 100644 index f42356e8c..000000000 --- a/assets/js/d280f29d.cd209164.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[4881],{1892:(n,e,t)=>{t.r(e),t.d(e,{assets:()=>l,contentTitle:()=>r,default:()=>h,frontMatter:()=>s,metadata:()=>a,toc:()=>c});const a=JSON.parse('{"id":"go-client/signals","title":"Signals","description":"Signalsworkflow:. Previously, you had","source":"@site/docs/05-go-client/08-signals.md","sourceDirName":"05-go-client","slug":"/go-client/signals","permalink":"/docs/go-client/signals","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/05-go-client/08-signals.md","tags":[],"version":"current","sidebarPosition":8,"frontMatter":{"layout":"default","title":"Signals","permalink":"/docs/go-client/signals"},"sidebar":"docsSidebar","previous":{"title":"Error handling","permalink":"/docs/go-client/error-handling"},"next":{"title":"Continue as new","permalink":"/docs/go-client/continue-as-new"}}');var o=t(4848),i=t(8453);const s={layout:"default",title:"Signals",permalink:"/docs/go-client/signals"},r="Signals",l={},c=[{value:"SignalWithStart",id:"signalwithstart",level:2}];function d(n){const e={a:"a",code:"code",h1:"h1",h2:"h2",header:"header",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,i.R)(),...n.components};return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsx)(e.header,{children:(0,o.jsx)(e.h1,{id:"signals",children:"Signals"})}),"\n",(0,o.jsx)(e.p,{children:"Signals provide a mechanism to send data directly to a running workflow. Previously, you had\ntwo options for passing data to the workflow implementation:"}),"\n",(0,o.jsxs)(e.ul,{children:["\n",(0,o.jsx)(e.li,{children:"Via start parameters"}),"\n",(0,o.jsx)(e.li,{children:"As return values from activities"}),"\n"]}),"\n",(0,o.jsx)(e.p,{children:"With start parameters, we could only pass in values before workflow_execution began."}),"\n",(0,o.jsx)(e.p,{children:"Return values from activities allowed us to pass information to a running workflow, but this\napproach comes with its own complications. One major drawback is reliance on polling. This means\nthat the data needs to be stored in a third-party location until it's ready to be picked up by\nthe activity. Further, the lifecycle of this activity requires management, and the activity\nrequires manual restart if it fails before acquiring the data."}),"\n",(0,o.jsx)(e.p,{children:"Signals, on the other hand, provide a fully asynchronous and durable mechanism for providing data to\na running workflow. When a signal is received for a running workflow, Cadence persists the event\nand the payload in the workflow history. The workflow can then process the signal at any time\nafterwards without the risk of losing the information. The workflow also has the option to stop\nexecution by blocking on a signal channel."}),"\n",(0,o.jsx)(e.pre,{children:(0,o.jsx)(e.code,{className:"language-go",children:'var signalVal string\nsignalChan := workflow.GetSignalChannel(ctx, signalName)\n\ns := workflow.NewSelector(ctx)\ns.AddReceive(signalChan, func(c workflow.Channel, more bool) {\n c.Receive(ctx, &signalVal)\n workflow.GetLogger(ctx).Info("Received signal!", zap.String("signal", signalName), zap.String("value", signalVal))\n})\ns.Select(ctx)\n\nif len(signalVal) > 0 && signalVal != "SOME_VALUE" {\n return errors.New("signalVal")\n}\n'})}),"\n",(0,o.jsxs)(e.p,{children:["In the example above, the workflow code uses ",(0,o.jsx)(e.strong,{children:"workflow.GetSignalChannel"})," to open a\n",(0,o.jsx)(e.strong,{children:"workflow.Channel"})," for the named signal. We then use a ",(0,o.jsx)(e.strong,{children:"workflow.Selector"})," to wait on this\nchannel and process the payload received with the signal."]}),"\n",(0,o.jsx)(e.h2,{id:"signalwithstart",children:"SignalWithStart"}),"\n",(0,o.jsxs)(e.p,{children:["You may not know if a workflow is running and can accept a signal. The\n",(0,o.jsx)(e.a,{href:"https://godoc.org/go.uber.org/cadence/client#Client",children:"client.SignalWithStartWorkflow"})," API\nallows you to send a signal to the current workflow instance if one exists or to create a new\nrun and then send the signal. ",(0,o.jsx)(e.code,{children:"SignalWithStartWorkflow"})," therefore doesn't take a run_ID as a\nparameter."]})]})}function h(n={}){const{wrapper:e}={...(0,i.R)(),...n.components};return e?(0,o.jsx)(e,{...n,children:(0,o.jsx)(d,{...n})}):d(n)}},8453:(n,e,t)=>{t.d(e,{R:()=>s,x:()=>r});var a=t(6540);const o={},i=a.createContext(o);function s(n){const e=a.useContext(i);return a.useMemo((function(){return"function"==typeof n?n(e):{...e,...n}}),[e,n])}function r(n){let e;return e=n.disableParentContext?"function"==typeof n.components?n.components(o):n.components||o:s(n.components),a.createElement(i.Provider,{value:e},n.children)}}}]); \ No newline at end of file diff --git a/assets/js/d33895f8.aa403fb7.js b/assets/js/d33895f8.558861c1.js similarity index 79% rename from assets/js/d33895f8.aa403fb7.js rename to assets/js/d33895f8.558861c1.js index 796ff111f..cb55a5844 100644 --- a/assets/js/d33895f8.aa403fb7.js +++ b/assets/js/d33895f8.558861c1.js @@ -1 +1 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[7125],{4669:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>c,contentTitle:()=>o,default:()=>h,frontMatter:()=>r,metadata:()=>a,toc:()=>l});var a=t(375),s=t(4848),i=t(8453);const r={title:"Announcement: Cadence Helm Charts v0 Release",date:new Date("2024-10-01T00:00:00.000Z"),authors:"taylanisikdemir",tags:["announcement"]},o=void 0,c={authorsImageUrls:[void 0]},l=[{value:"Introducing Cadence Kubernetes Helm Chart v0",id:"introducing-cadence-kubernetes-helm-chart-v0",level:2},{value:"How to Get Started",id:"how-to-get-started",level:2},{value:"Current State of the Chart",id:"current-state-of-the-chart",level:2},{value:"Next Steps",id:"next-steps",level:2}];function d(e){const n={a:"a",code:"code",h2:"h2",li:"li",p:"p",pre:"pre",ul:"ul",...(0,i.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsxs)(n.p,{children:["We\u2019ve heard your feedback: deploying Cadence has been a challenge, especially with limited documentation on operational aspects. So far, we\u2019ve only provided a few ",(0,s.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence/tree/master/docker",children:"docker compose files"})," to help you get started on a development machine. However, deploying and managing Cadence at scale requires a deep understanding of underlying services, configurations and their dependencies."]}),"\n",(0,s.jsx)(n.p,{children:"To address these challenges, we\u2019re launching several initiatives to make it easier to deploy and operate Cadence clusters. These include deployment specs for common scenarios, monitoring dashboards, alerts, runbooks, and more comprehensive documentation."}),"\n",(0,s.jsx)(n.h2,{id:"introducing-cadence-kubernetes-helm-chart-v0",children:"Introducing Cadence Kubernetes Helm Chart v0"}),"\n",(0,s.jsxs)(n.p,{children:["Today, we are happy to announce the release of ",(0,s.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence-charts",children:"Cadence Kubernetes Helm Chart v0"}),". This will be the starting point for standardizing Cadence deployments on Kubernetes. We chose Kubernetes because it's the leading compute platform, but Cadence remains flexible and can run on any infrastructure."]}),"\n",(0,s.jsx)(n.h2,{id:"how-to-get-started",children:"How to Get Started"}),"\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.a,{href:"https://helm.sh",children:"Helm"})," must be installed to use the charts. Please refer to Helm's ",(0,s.jsx)(n.a,{href:"https://helm.sh/docs",children:"documentation"})," to get started."]}),"\n",(0,s.jsx)(n.p,{children:"Once Helm has been set up correctly, add the repo as follows:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"helm repo add cadence https://uber.github.io/cadence-charts\n"})}),"\n",(0,s.jsxs)(n.p,{children:["If you had already added this repo earlier, run ",(0,s.jsx)(n.code,{children:"helm repo update"})," to retrieve the latest versions of the packages. You can then run ",(0,s.jsx)(n.code,{children:"helm search repo cadence"})," to see the charts."]}),"\n",(0,s.jsx)(n.p,{children:"To install the cadence chart:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"helm install my-cadence cadence/cadence\n"})}),"\n",(0,s.jsx)(n.p,{children:"To uninstall the chart:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"helm delete my-cadence\n"})}),"\n",(0,s.jsxs)(n.p,{children:["See ",(0,s.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence-charts/blob/main/CONTRIBUTING.md",children:"CONTRIBUTING.md"})," for details on how to validate the deployment by running sample workflows."]}),"\n",(0,s.jsx)(n.h2,{id:"current-state-of-the-chart",children:"Current State of the Chart"}),"\n",(0,s.jsx)(n.p,{children:"There were a few community-created Cadence Helm charts but they were not actively maintained and had a few glitches that Cadence team @Uber wasn't able to provide support for. With the introduction of the new official Cadence Helm chart, our team is committed to provide support and evolve it with input from community."}),"\n",(0,s.jsx)(n.p,{children:"The v0 chart contains only the basics at the moment:"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:"Cadence backend services as separate deployments: frontend, history, matching, worker."}),"\n",(0,s.jsx)(n.li,{children:"Customizable replica counts and resource limitations."}),"\n",(0,s.jsx)(n.li,{children:"Customizable dynamic config as a configmap."}),"\n",(0,s.jsx)(n.li,{children:"A single instance ephemeral Cassandra container. This is included so that no external dependency is required to get started. Ideally you should have your own external (hosted or managed) DB instance that you can specify in values.yaml."}),"\n",(0,s.jsxs)(n.li,{children:["The chart comes with ",(0,s.jsx)(n.code,{children:"cadence:master-auto-setup"})," as the default image and capable of setting up Cassandra DB schema on first installation."]}),"\n"]}),"\n",(0,s.jsx)(n.p,{children:"What is (obviously) missing:"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:"Support for advanced visibility stores like Elasticsearch or Pinot."}),"\n",(0,s.jsx)(n.li,{children:"Support for persistent plugins configurations besides Cassandra."}),"\n",(0,s.jsx)(n.li,{children:"Support for fully customizable service config via values.yaml."}),"\n",(0,s.jsx)(n.li,{children:"Metrics integration with Prometheus (and more out of the box prometheus dashboards)"}),"\n",(0,s.jsx)(n.li,{children:"Custom annotations/lables/tolerations etc."}),"\n",(0,s.jsx)(n.li,{children:"Support for ingress"}),"\n"]}),"\n",(0,s.jsx)(n.h2,{id:"next-steps",children:"Next Steps"}),"\n",(0,s.jsxs)(n.p,{children:["Since this is an early release, we would love to hear from you. Feel free to start ",(0,s.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence-charts/discussions",children:"discussions"})," or report ",(0,s.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence-charts/issues",children:"issues"}),"."]}),"\n",(0,s.jsxs)(n.p,{children:["Also check out the ",(0,s.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence-charts/blob/main/CONTRIBUTING.md",children:"contribution guideline"})," if you are interested to contribute. Don't hesitate to send a PR and ping us over slack if we miss it."]}),"\n",(0,s.jsxs)(n.p,{children:["P.S. Huge thanks to our summer intern ",(0,s.jsx)(n.a,{href:"https://github.com/nikitab7",children:"Nikita Bhardwaj"})," for kickstarting the Cadence Helm charts initiative."]})]})}function h(e={}){const{wrapper:n}={...(0,i.R)(),...e.components};return n?(0,s.jsx)(n,{...e,children:(0,s.jsx)(d,{...e})}):d(e)}},8453:(e,n,t)=>{t.d(n,{R:()=>r,x:()=>o});var a=t(6540);const s={},i=a.createContext(s);function r(e){const n=a.useContext(i);return a.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function o(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:r(e.components),a.createElement(i.Provider,{value:n},e.children)}},375:e=>{e.exports=JSON.parse('{"permalink":"/blog/2024/10/01/announcing-cadence-helm-charts-v0","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2024-10-01-announcing-cadence-helm-charts-v0.md","source":"@site/blog/2024-10-01-announcing-cadence-helm-charts-v0.md","title":"Announcement: Cadence Helm Charts v0 Release","description":"We\u2019ve heard your feedback: deploying Cadence has been a challenge, especially with limited documentation on operational aspects. So far, we\u2019ve only provided a few docker compose files to help you get started on a development machine. However, deploying and managing Cadence at scale requires a deep understanding of underlying services, configurations and their dependencies.","date":"2024-10-01T00:00:00.000Z","tags":[{"inline":false,"label":"Announcement","permalink":"/blog/tags/announcements","description":"Announcement tag description"}],"readingTime":2.6,"hasTruncateMarker":true,"authors":[{"name":"Taylan Isikdemir","title":"Sr. Staff Software Engineer @ Uber","url":"https://www.linkedin.com/in/taylan-isikdemir","page":{"permalink":"/blog/authors/taylanisikdemir"},"socials":{"linkedin":"https://www.linkedin.com/in/taylan-isikdemir","github":"https://github.com/taylanisikdemir"},"imageURL":"https://github.com/taylanisikdemir.png","key":"taylanisikdemir"}],"frontMatter":{"title":"Announcement: Cadence Helm Charts v0 Release","date":"2024-10-01T00:00:00.000Z","authors":"taylanisikdemir","tags":["announcement"]},"unlisted":false,"prevItem":{"title":"Zonal Isolation for Cadence Workflows","permalink":"/blog/zonal-isolation-v1/zonal-isolation-v1"},"nextItem":{"title":"Minimizing blast radius in Cadence: Introducing Workflow ID-based Rate Limits","permalink":"/blog/2024/09/05/workflow-specific-rate-limits"}}')}}]); \ No newline at end of file +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[7125],{4669:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>c,contentTitle:()=>o,default:()=>h,frontMatter:()=>r,metadata:()=>a,toc:()=>l});var a=t(375),s=t(4848),i=t(8453);const r={title:"Announcement: Cadence Helm Charts v0 Release",date:new Date("2024-10-01T00:00:00.000Z"),authors:"taylanisikdemir",tags:["announcement"]},o=void 0,c={authorsImageUrls:[void 0]},l=[{value:"Introducing Cadence Kubernetes Helm Chart v0",id:"introducing-cadence-kubernetes-helm-chart-v0",level:2},{value:"How to Get Started",id:"how-to-get-started",level:2},{value:"Current State of the Chart",id:"current-state-of-the-chart",level:2},{value:"Next Steps",id:"next-steps",level:2}];function d(e){const n={a:"a",code:"code",h2:"h2",li:"li",p:"p",pre:"pre",ul:"ul",...(0,i.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsxs)(n.p,{children:["We\u2019ve heard your feedback: deploying Cadence has been a challenge, especially with limited documentation on operational aspects. So far, we\u2019ve only provided a few ",(0,s.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence/tree/master/docker",children:"docker compose files"})," to help you get started on a development machine. However, deploying and managing Cadence at scale requires a deep understanding of underlying services, configurations and their dependencies."]}),"\n",(0,s.jsx)(n.p,{children:"To address these challenges, we\u2019re launching several initiatives to make it easier to deploy and operate Cadence clusters. These include deployment specs for common scenarios, monitoring dashboards, alerts, runbooks, and more comprehensive documentation."}),"\n",(0,s.jsx)(n.h2,{id:"introducing-cadence-kubernetes-helm-chart-v0",children:"Introducing Cadence Kubernetes Helm Chart v0"}),"\n",(0,s.jsxs)(n.p,{children:["Today, we are happy to announce the release of ",(0,s.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence-charts",children:"Cadence Kubernetes Helm Chart v0"}),". This will be the starting point for standardizing Cadence deployments on Kubernetes. We chose Kubernetes because it's the leading compute platform, but Cadence remains flexible and can run on any infrastructure."]}),"\n",(0,s.jsx)(n.h2,{id:"how-to-get-started",children:"How to Get Started"}),"\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.a,{href:"https://helm.sh",children:"Helm"})," must be installed to use the charts. Please refer to Helm's ",(0,s.jsx)(n.a,{href:"https://helm.sh/docs",children:"documentation"})," to get started."]}),"\n",(0,s.jsx)(n.p,{children:"Once Helm has been set up correctly, add the repo as follows:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"helm repo add cadence https://uber.github.io/cadence-charts\n"})}),"\n",(0,s.jsxs)(n.p,{children:["If you had already added this repo earlier, run ",(0,s.jsx)(n.code,{children:"helm repo update"})," to retrieve the latest versions of the packages. You can then run ",(0,s.jsx)(n.code,{children:"helm search repo cadence"})," to see the charts."]}),"\n",(0,s.jsx)(n.p,{children:"To install the cadence chart:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"helm install my-cadence cadence/cadence\n"})}),"\n",(0,s.jsx)(n.p,{children:"To uninstall the chart:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"helm delete my-cadence\n"})}),"\n",(0,s.jsxs)(n.p,{children:["See ",(0,s.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence-charts/blob/main/CONTRIBUTING.md",children:"CONTRIBUTING.md"})," for details on how to validate the deployment by running sample workflows."]}),"\n",(0,s.jsx)(n.h2,{id:"current-state-of-the-chart",children:"Current State of the Chart"}),"\n",(0,s.jsx)(n.p,{children:"There were a few community-created Cadence Helm charts but they were not actively maintained and had a few glitches that Cadence team @Uber wasn't able to provide support for. With the introduction of the new official Cadence Helm chart, our team is committed to provide support and evolve it with input from community."}),"\n",(0,s.jsx)(n.p,{children:"The v0 chart contains only the basics at the moment:"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:"Cadence backend services as separate deployments: frontend, history, matching, worker."}),"\n",(0,s.jsx)(n.li,{children:"Customizable replica counts and resource limitations."}),"\n",(0,s.jsx)(n.li,{children:"Customizable dynamic config as a configmap."}),"\n",(0,s.jsx)(n.li,{children:"A single instance ephemeral Cassandra container. This is included so that no external dependency is required to get started. Ideally you should have your own external (hosted or managed) DB instance that you can specify in values.yaml."}),"\n",(0,s.jsxs)(n.li,{children:["The chart comes with ",(0,s.jsx)(n.code,{children:"cadence:master-auto-setup"})," as the default image and capable of setting up Cassandra DB schema on first installation."]}),"\n"]}),"\n",(0,s.jsx)(n.p,{children:"What is (obviously) missing:"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:"Support for advanced visibility stores like Elasticsearch or Pinot."}),"\n",(0,s.jsx)(n.li,{children:"Support for persistent plugins configurations besides Cassandra."}),"\n",(0,s.jsx)(n.li,{children:"Support for fully customizable service config via values.yaml."}),"\n",(0,s.jsx)(n.li,{children:"Metrics integration with Prometheus (and more out of the box prometheus dashboards)"}),"\n",(0,s.jsx)(n.li,{children:"Custom annotations/lables/tolerations etc."}),"\n",(0,s.jsx)(n.li,{children:"Support for ingress"}),"\n"]}),"\n",(0,s.jsx)(n.h2,{id:"next-steps",children:"Next Steps"}),"\n",(0,s.jsxs)(n.p,{children:["Since this is an early release, we would love to hear from you. Feel free to start ",(0,s.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence-charts/discussions",children:"discussions"})," or report ",(0,s.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence-charts/issues",children:"issues"}),"."]}),"\n",(0,s.jsxs)(n.p,{children:["Also check out the ",(0,s.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence-charts/blob/main/CONTRIBUTING.md",children:"contribution guideline"})," if you are interested to contribute. Don't hesitate to send a PR and ping us over slack if we miss it."]}),"\n",(0,s.jsxs)(n.p,{children:["P.S. Huge thanks to our summer intern ",(0,s.jsx)(n.a,{href:"https://github.com/nikitab7",children:"Nikita Bhardwaj"})," for kickstarting the Cadence Helm charts initiative."]})]})}function h(e={}){const{wrapper:n}={...(0,i.R)(),...e.components};return n?(0,s.jsx)(n,{...e,children:(0,s.jsx)(d,{...e})}):d(e)}},8453:(e,n,t)=>{t.d(n,{R:()=>r,x:()=>o});var a=t(6540);const s={},i=a.createContext(s);function r(e){const n=a.useContext(i);return a.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function o(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:r(e.components),a.createElement(i.Provider,{value:n},e.children)}},375:e=>{e.exports=JSON.parse('{"permalink":"/Cadence-Docs/blog/2024/10/01/announcing-cadence-helm-charts-v0","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2024-10-01-announcing-cadence-helm-charts-v0.md","source":"@site/blog/2024-10-01-announcing-cadence-helm-charts-v0.md","title":"Announcement: Cadence Helm Charts v0 Release","description":"We\u2019ve heard your feedback: deploying Cadence has been a challenge, especially with limited documentation on operational aspects. So far, we\u2019ve only provided a few docker compose files to help you get started on a development machine. However, deploying and managing Cadence at scale requires a deep understanding of underlying services, configurations and their dependencies.","date":"2024-10-01T00:00:00.000Z","tags":[{"inline":false,"label":"Announcement","permalink":"/Cadence-Docs/blog/tags/announcements","description":"Announcement tag description"}],"readingTime":2.6,"hasTruncateMarker":true,"authors":[{"name":"Taylan Isikdemir","title":"Sr. Staff Software Engineer @ Uber","url":"https://www.linkedin.com/in/taylan-isikdemir","page":{"permalink":"/Cadence-Docs/blog/authors/taylanisikdemir"},"socials":{"linkedin":"https://www.linkedin.com/in/taylan-isikdemir","github":"https://github.com/taylanisikdemir"},"imageURL":"https://github.com/taylanisikdemir.png","key":"taylanisikdemir"}],"frontMatter":{"title":"Announcement: Cadence Helm Charts v0 Release","date":"2024-10-01T00:00:00.000Z","authors":"taylanisikdemir","tags":["announcement"]},"unlisted":false,"prevItem":{"title":"Zonal Isolation for Cadence Workflows","permalink":"/Cadence-Docs/blog/zonal-isolation-v1/zonal-isolation-v1"},"nextItem":{"title":"Minimizing blast radius in Cadence: Introducing Workflow ID-based Rate Limits","permalink":"/Cadence-Docs/blog/2024/09/05/workflow-specific-rate-limits"}}')}}]); \ No newline at end of file diff --git a/assets/js/d33bd0ff.0202e01a.js b/assets/js/d33bd0ff.eabe4dbb.js similarity index 51% rename from assets/js/d33bd0ff.0202e01a.js rename to assets/js/d33bd0ff.eabe4dbb.js index 8c75d5683..c79c640ec 100644 --- a/assets/js/d33bd0ff.0202e01a.js +++ b/assets/js/d33bd0ff.eabe4dbb.js @@ -1 +1 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[1759],{605:(e,t,o)=>{o.r(t),o.d(t,{assets:()=>c,contentTitle:()=>s,default:()=>p,frontMatter:()=>r,metadata:()=>n,toc:()=>l});var n=o(3914),a=o(4848),i=o(8453);const r={title:"Cadence Community Spotlight Update - March 2022",date:new Date("2022-03-31T00:00:00.000Z"),authors:"sharanf",tags:["community-spotlight"]},s=void 0,c={authorsImageUrls:[void 0]},l=[{value:"Updated Cadence Topology Diagram",id:"updated-cadence-topology-diagram",level:2}];function d(e){const t={a:"a",h2:"h2",p:"p",...(0,i.R)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(t.p,{children:"Welcome to our Cadence Community Spotlight update!"}),"\n",(0,a.jsx)(t.p,{children:"This is the latest in our series of monthly blog posts focused on the Cadence community and news about what you have been doing with Cadence."}),"\n",(0,a.jsx)(t.p,{children:"Please see below for a short activity roundup of what has happened recently in the community."}),"\n",(0,a.jsx)(t.h2,{id:"updated-cadence-topology-diagram",children:"Updated Cadence Topology Diagram"}),"\n",(0,a.jsxs)(t.p,{children:["Did you know that we have an updated Cadence Service diagram on the website? Well we do - and you can find it on our ",(0,a.jsx)(t.a,{href:"https://cadenceworkflow.io/docs/concepts/topology/#overview",children:"Deployment Topology"})," page. We are always looking for information that helps makes it easier for people to understand how Cadence works."]}),"\n",(0,a.jsx)(t.p,{children:"Special thanks to Ben Slater for updating the diagram and also to Ender, Emrah and Long for helping review it."})]})}function p(e={}){const{wrapper:t}={...(0,i.R)(),...e.components};return t?(0,a.jsx)(t,{...e,children:(0,a.jsx)(d,{...e})}):d(e)}},8453:(e,t,o)=>{o.d(t,{R:()=>r,x:()=>s});var n=o(6540);const a={},i=n.createContext(a);function r(e){const t=n.useContext(i);return n.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function s(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:r(e.components),n.createElement(i.Provider,{value:t},e.children)}},3914:e=>{e.exports=JSON.parse('{"permalink":"/blog/2022/03/31/community-spotlight-update-march-2022","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2022-03-31-community-spotlight-update-march-2022.md","source":"@site/blog/2022-03-31-community-spotlight-update-march-2022.md","title":"Cadence Community Spotlight Update - March 2022","description":"Welcome to our Cadence Community Spotlight update!","date":"2022-03-31T00:00:00.000Z","tags":[{"inline":false,"label":"Community Spotlight","permalink":"/blog/tags/community-spotlights","description":"Community Spotlight tag description"}],"readingTime":3.235,"hasTruncateMarker":true,"authors":[{"name":"Sharan Foga","title":"Director of Operations & Customer Success @ Encube Technologies","url":"https://www.linkedin.com/in/sfoga/","page":{"permalink":"/blog/authors/sharanf"},"socials":{"linkedin":"https://www.linkedin.com/in/sfoga/","github":"https://github.com/sharanf"},"imageURL":"https://github.com/sharanf.png","key":"sharanf"}],"frontMatter":{"title":"Cadence Community Spotlight Update - March 2022","date":"2022-03-31T00:00:00.000Z","authors":"sharanf","tags":["community-spotlight"]},"unlisted":false,"prevItem":{"title":"Cadence Community Spotlight Update - April 2022","permalink":"/blog/2022/04/30/community-spotlight-update-april-2022"},"nextItem":{"title":"Cadence Community Spotlight Update - February 2022","permalink":"/blog/2022/02/28/community-spotlight-february-2022"}}')}}]); \ No newline at end of file +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[1759],{605:(e,t,o)=>{o.r(t),o.d(t,{assets:()=>c,contentTitle:()=>s,default:()=>p,frontMatter:()=>r,metadata:()=>n,toc:()=>d});var n=o(3914),a=o(4848),i=o(8453);const r={title:"Cadence Community Spotlight Update - March 2022",date:new Date("2022-03-31T00:00:00.000Z"),authors:"sharanf",tags:["community-spotlight"]},s=void 0,c={authorsImageUrls:[void 0]},d=[{value:"Updated Cadence Topology Diagram",id:"updated-cadence-topology-diagram",level:2}];function l(e){const t={a:"a",h2:"h2",p:"p",...(0,i.R)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(t.p,{children:"Welcome to our Cadence Community Spotlight update!"}),"\n",(0,a.jsx)(t.p,{children:"This is the latest in our series of monthly blog posts focused on the Cadence community and news about what you have been doing with Cadence."}),"\n",(0,a.jsx)(t.p,{children:"Please see below for a short activity roundup of what has happened recently in the community."}),"\n",(0,a.jsx)(t.h2,{id:"updated-cadence-topology-diagram",children:"Updated Cadence Topology Diagram"}),"\n",(0,a.jsxs)(t.p,{children:["Did you know that we have an updated Cadence Service diagram on the website? Well we do - and you can find it on our ",(0,a.jsx)(t.a,{href:"https://cadenceworkflow.io/docs/concepts/topology/#overview",children:"Deployment Topology"})," page. We are always looking for information that helps makes it easier for people to understand how Cadence works."]}),"\n",(0,a.jsx)(t.p,{children:"Special thanks to Ben Slater for updating the diagram and also to Ender, Emrah and Long for helping review it."})]})}function p(e={}){const{wrapper:t}={...(0,i.R)(),...e.components};return t?(0,a.jsx)(t,{...e,children:(0,a.jsx)(l,{...e})}):l(e)}},8453:(e,t,o)=>{o.d(t,{R:()=>r,x:()=>s});var n=o(6540);const a={},i=n.createContext(a);function r(e){const t=n.useContext(i);return n.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function s(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:r(e.components),n.createElement(i.Provider,{value:t},e.children)}},3914:e=>{e.exports=JSON.parse('{"permalink":"/Cadence-Docs/blog/2022/03/31/community-spotlight-update-march-2022","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2022-03-31-community-spotlight-update-march-2022.md","source":"@site/blog/2022-03-31-community-spotlight-update-march-2022.md","title":"Cadence Community Spotlight Update - March 2022","description":"Welcome to our Cadence Community Spotlight update!","date":"2022-03-31T00:00:00.000Z","tags":[{"inline":false,"label":"Community Spotlight","permalink":"/Cadence-Docs/blog/tags/community-spotlights","description":"Community Spotlight tag description"}],"readingTime":3.235,"hasTruncateMarker":true,"authors":[{"name":"Sharan Foga","title":"Director of Operations & Customer Success @ Encube Technologies","url":"https://www.linkedin.com/in/sfoga/","page":{"permalink":"/Cadence-Docs/blog/authors/sharanf"},"socials":{"linkedin":"https://www.linkedin.com/in/sfoga/","github":"https://github.com/sharanf"},"imageURL":"https://github.com/sharanf.png","key":"sharanf"}],"frontMatter":{"title":"Cadence Community Spotlight Update - March 2022","date":"2022-03-31T00:00:00.000Z","authors":"sharanf","tags":["community-spotlight"]},"unlisted":false,"prevItem":{"title":"Cadence Community Spotlight Update - April 2022","permalink":"/Cadence-Docs/blog/2022/04/30/community-spotlight-update-april-2022"},"nextItem":{"title":"Cadence Community Spotlight Update - February 2022","permalink":"/Cadence-Docs/blog/2022/02/28/community-spotlight-february-2022"}}')}}]); \ No newline at end of file diff --git a/assets/js/d530ea3c.ad59a794.js b/assets/js/d530ea3c.ad59a794.js new file mode 100644 index 000000000..fd4c0733e --- /dev/null +++ b/assets/js/d530ea3c.ad59a794.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[4639],{976:e=>{e.exports=JSON.parse('{"tag":{"label":"Community Spotlight","permalink":"/Cadence-Docs/blog/tags/community-spotlights","description":"Community Spotlight tag description","allTagsPath":"/Cadence-Docs/blog/tags","count":20,"unlisted":false},"listMetadata":{"permalink":"/Cadence-Docs/blog/tags/community-spotlights","page":1,"postsPerPage":10,"totalPages":2,"totalCount":20,"nextPage":"/Cadence-Docs/blog/tags/community-spotlights/page/2","blogDescription":"The latest news and updates from the Cadence team","blogTitle":"Cadence Blog"}}')}}]); \ No newline at end of file diff --git a/assets/js/d67a7980.5c7df669.js b/assets/js/d67a7980.5c7df669.js new file mode 100644 index 000000000..ac45e7959 --- /dev/null +++ b/assets/js/d67a7980.5c7df669.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[5733],{608:(e,t,o)=>{o.r(t),o.d(t,{assets:()=>l,contentTitle:()=>s,default:()=>h,frontMatter:()=>c,metadata:()=>n,toc:()=>a});const n=JSON.parse('{"id":"go-client/workflow-versioning","title":"Versioning","description":"The definition code of a Cadence must be deterministic because Cadence uses sourcing","source":"@site/docs/05-go-client/14-workflow-versioning.md","sourceDirName":"05-go-client","slug":"/go-client/workflow-versioning","permalink":"/Cadence-Docs/docs/go-client/workflow-versioning","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/05-go-client/14-workflow-versioning.md","tags":[],"version":"current","sidebarPosition":14,"frontMatter":{"layout":"default","title":"Versioning","permalink":"/docs/go-client/workflow-versioning"},"sidebar":"docsSidebar","previous":{"title":"Testing","permalink":"/Cadence-Docs/docs/go-client/workflow-testing"},"next":{"title":"Sessions","permalink":"/Cadence-Docs/docs/go-client/sessions"}}');var r=o(4848),i=o(8453);const c={layout:"default",title:"Versioning",permalink:"/docs/go-client/workflow-versioning"},s="Versioning",l={},a=[{value:"workflow.GetVersion()",id:"workflowgetversion",level:2},{value:"Sanity checking",id:"sanity-checking",level:2}];function d(e){const t={code:"code",h1:"h1",h2:"h2",header:"header",li:"li",ol:"ol",p:"p",pre:"pre",ul:"ul",...(0,i.R)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(t.header,{children:(0,r.jsx)(t.h1,{id:"versioning",children:"Versioning"})}),"\n",(0,r.jsx)(t.p,{children:"The definition code of a Cadence workflow must be deterministic because Cadence uses event sourcing\nto reconstruct the workflow state by replaying the saved history event data on the workflow\ndefinition code. This means that any incompatible update to the workflow definition code could cause\na non-deterministic issue if not handled correctly."}),"\n",(0,r.jsx)(t.h2,{id:"workflowgetversion",children:"workflow.GetVersion()"}),"\n",(0,r.jsx)(t.p,{children:"Consider the following workflow definition:"}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{className:"language-go",children:'func MyWorkflow(ctx workflow.Context, data string) (string, error) {\n ao := workflow.ActivityOptions{\n ScheduleToStartTimeout: time.Minute,\n StartToCloseTimeout: time.Minute,\n }\n ctx = workflow.WithActivityOptions(ctx, ao)\n var result1 string\n err := workflow.ExecuteActivity(ctx, ActivityA, data).Get(ctx, &result1)\n if err != nil {\n return "", err\n }\n var result2 string\n err = workflow.ExecuteActivity(ctx, ActivityB, result1).Get(ctx, &result2)\n return result2, err\n}\n'})}),"\n",(0,r.jsx)(t.p,{children:"Now let's say we have replaced ActivityA with ActivityC, and deployed the updated code. If there\nis an existing workflow_execution that was started by the original version of the workflow code, where\nActivityA had already completed and the result was recorded to history, the new version of the workflow\ncode will pick up that workflow_execution and try to resume from there. However, the workflow will fail\nbecause the new code expects a result for ActivityC from the history data, but instead it gets the\nresult for ActivityA. This causes the workflow to fail on the non-deterministic error."}),"\n",(0,r.jsxs)(t.p,{children:["Thus we use ",(0,r.jsx)(t.code,{children:"workflow.GetVersion()."})]}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{className:"language-go",children:'var err error\nv := workflow.GetVersion(ctx, "Step1", workflow.DefaultVersion, 1)\nif v == workflow.DefaultVersion {\n err = workflow.ExecuteActivity(ctx, ActivityA, data).Get(ctx, &result1)\n} else {\n err = workflow.ExecuteActivity(ctx, ActivityC, data).Get(ctx, &result1)\n}\nif err != nil {\n return "", err\n}\n\nvar result2 string\nerr = workflow.ExecuteActivity(ctx, ActivityB, result1).Get(ctx, &result2)\nreturn result2, err\n'})}),"\n",(0,r.jsxs)(t.p,{children:["When ",(0,r.jsx)(t.code,{children:"workflow.GetVersion()"})," is run for the new workflow_execution, it records a marker in the workflow\nhistory so that all future calls to ",(0,r.jsx)(t.code,{children:"GetVersion"})," for this change ID--",(0,r.jsx)(t.code,{children:"Step 1"})," in the example--on this\nworkflow_execution will always return the given version number, which is ",(0,r.jsx)(t.code,{children:"1"})," in the example."]}),"\n",(0,r.jsx)(t.p,{children:"If you make an additional change, such as replacing ActivityC with ActivityD, you need to\nadd some additional code:"}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{className:"language-go",children:'v := workflow.GetVersion(ctx, "Step1", workflow.DefaultVersion, 2)\nif v == workflow.DefaultVersion {\n err = workflow.ExecuteActivity(ctx, ActivityA, data).Get(ctx, &result1)\n} else if v == 1 {\n err = workflow.ExecuteActivity(ctx, ActivityC, data).Get(ctx, &result1)\n} else {\n err = workflow.ExecuteActivity(ctx, ActivityD, data).Get(ctx, &result1)\n}\n'})}),"\n",(0,r.jsxs)(t.p,{children:["Note that we have changed ",(0,r.jsx)(t.code,{children:"maxSupported"})," from 1 to 2. A workflow that had already passed this\n",(0,r.jsx)(t.code,{children:"GetVersion()"})," call before it was introduced will return ",(0,r.jsx)(t.code,{children:"DefaultVersion"}),". A workflow that was run\nwith ",(0,r.jsx)(t.code,{children:"maxSupported"})," set to 1, will return 1. New workflows will return 2."]}),"\n",(0,r.jsx)(t.p,{children:"After you are sure that all of the workflow_executions prior to version 1 have completed, you can\nremove the code for that version. It should now look like the following:"}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{className:"language-go",children:'v := workflow.GetVersion(ctx, "Step1", 1, 2)\nif v == 1 {\n err = workflow.ExecuteActivity(ctx, ActivityC, data).Get(ctx, &result1)\n} else {\n err = workflow.ExecuteActivity(ctx, ActivityD, data).Get(ctx, &result1)\n}\n'})}),"\n",(0,r.jsxs)(t.p,{children:["You'll note that ",(0,r.jsx)(t.code,{children:"minSupported"})," has changed from ",(0,r.jsx)(t.code,{children:"DefaultVersion"})," to ",(0,r.jsx)(t.code,{children:"1"}),". If an older version of the\nworkflow_execution history is replayed on this code, it will fail because the minimum expected version\nis 1. After you are sure that all of the workflow_executions for version 1 have completed, then you\ncan remove 1 so that your code would look like the following:"]}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{className:"language-go",children:'_ := workflow.GetVersion(ctx, "Step1", 2, 2)\nerr = workflow.ExecuteActivity(ctx, ActivityD, data).Get(ctx, &result1)\n'})}),"\n",(0,r.jsxs)(t.p,{children:["Note that we have preserved the call to ",(0,r.jsx)(t.code,{children:"GetVersion()"}),". There are two reasons to preserve this call:"]}),"\n",(0,r.jsxs)(t.ol,{children:["\n",(0,r.jsx)(t.li,{children:"This ensures that if there is a workflow_execution still running for an older version, it will\nfail here and not proceed."}),"\n",(0,r.jsxs)(t.li,{children:["If you need to make additional changes for ",(0,r.jsx)(t.code,{children:"Step1"}),", such as changing ActivityD to ActivityE, you\nonly need to update ",(0,r.jsx)(t.code,{children:"maxVersion"})," from 2 to 3 and branch from there."]}),"\n"]}),"\n",(0,r.jsxs)(t.p,{children:["You only need to preserve the first call to ",(0,r.jsx)(t.code,{children:"GetVersion()"})," for each ",(0,r.jsx)(t.code,{children:"changeID"}),". All subsequent calls to\n",(0,r.jsx)(t.code,{children:"GetVersion()"})," with the same change ID are safe to remove. If necessary, you can remove the first\n",(0,r.jsx)(t.code,{children:"GetVersion()"})," call, but you need to ensure the following:"]}),"\n",(0,r.jsxs)(t.ul,{children:["\n",(0,r.jsx)(t.li,{children:"All executions with an older version are completed."}),"\n",(0,r.jsxs)(t.li,{children:["You can no longer use ",(0,r.jsx)(t.code,{children:"Step1"})," for the changeID. If you need to make changes to that same part in\nthe future, such as change from ActivityD to ActivityE, you would need to use a different changeID\nlike ",(0,r.jsx)(t.code,{children:"Step1-fix2"}),", and start minVersion from DefaultVersion again. The code would look like the\nfollowing:"]}),"\n"]}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{className:"language-go",children:'v := workflow.GetVersion(ctx, "Step1-fix2", workflow.DefaultVersion, 1)\nif v == workflow.DefaultVersion {\n err = workflow.ExecuteActivity(ctx, ActivityD, data).Get(ctx, &result1)\n} else {\n err = workflow.ExecuteActivity(ctx, ActivityE, data).Get(ctx, &result1)\n}\n'})}),"\n",(0,r.jsxs)(t.p,{children:["Upgrading a workflow is straightforward if you don't need to preserve your currently running\nworkflow_executions. You can simply terminate all of the currently running workflow_executions and\nsuspend new ones from being created while you deploy the new version of your workflow code, which does\nnot use ",(0,r.jsx)(t.code,{children:"GetVersion()"}),", and then resume workflow creation. However, that is often not the case, and\nyou need to take care of the currently running workflow_executions, so using ",(0,r.jsx)(t.code,{children:"GetVersion()"})," to update\nyour code is the method to use."]}),"\n",(0,r.jsxs)(t.p,{children:["However, if you want your currently running workflows to proceed based on the current workflow logic,\nbut you want to ensure new workflows are running on new logic, you can define your workflow as a\nnew ",(0,r.jsx)(t.code,{children:"WorkflowType"}),", and change your start path (calls to ",(0,r.jsx)(t.code,{children:"StartWorkflow()"}),") to start the new workflow\ntype."]}),"\n",(0,r.jsx)(t.h2,{id:"sanity-checking",children:"Sanity checking"}),"\n",(0,r.jsx)(t.p,{children:"The Cadence client SDK performs a sanity check to help prevent obvious incompatible changes.\nThe sanity check verifies whether a decision made in replay matches the event recorded in history,\nin the same order. The decision is generated by calling any of the following methods:"}),"\n",(0,r.jsxs)(t.ul,{children:["\n",(0,r.jsx)(t.li,{children:"workflow.ExecuteActivity()"}),"\n",(0,r.jsx)(t.li,{children:"workflow.ExecuteChildWorkflow()"}),"\n",(0,r.jsx)(t.li,{children:"workflow.NewTimer()"}),"\n",(0,r.jsx)(t.li,{children:"workflow.Sleep()"}),"\n",(0,r.jsx)(t.li,{children:"workflow.SideEffect()"}),"\n",(0,r.jsx)(t.li,{children:"workflow.RequestCancelWorkflow()"}),"\n",(0,r.jsx)(t.li,{children:"workflow.SignalExternalWorkflow()"}),"\n",(0,r.jsx)(t.li,{children:"workflow.UpsertSearchAttributes()"}),"\n"]}),"\n",(0,r.jsx)(t.p,{children:"Adding, removing, or reordering any of the above methods triggers the sanity check and results in\na non-deterministic error."}),"\n",(0,r.jsxs)(t.p,{children:["The sanity check does not perform a thorough check. For example, it does not check on the activity's\ninput arguments or the timer duration. If the check is enforced on every property, then it becomes\ntoo restricted and harder to maintain the workflow code. For example, if you move your activity code\nfrom one package to another package, that changes the ",(0,r.jsx)(t.code,{children:"ActivityType"}),", which technically becomes a different\nactivity. But, we don't want to fail on that change, so we only check the function name part of the\n",(0,r.jsx)(t.code,{children:"ActivityType"}),"."]})]})}function h(e={}){const{wrapper:t}={...(0,i.R)(),...e.components};return t?(0,r.jsx)(t,{...e,children:(0,r.jsx)(d,{...e})}):d(e)}},8453:(e,t,o)=>{o.d(t,{R:()=>c,x:()=>s});var n=o(6540);const r={},i=n.createContext(r);function c(e){const t=n.useContext(i);return n.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function s(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:c(e.components),n.createElement(i.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/d67a7980.6f8efc72.js b/assets/js/d67a7980.6f8efc72.js deleted file mode 100644 index a28eff0ac..000000000 --- a/assets/js/d67a7980.6f8efc72.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[5733],{608:(e,t,o)=>{o.r(t),o.d(t,{assets:()=>l,contentTitle:()=>s,default:()=>h,frontMatter:()=>c,metadata:()=>n,toc:()=>a});const n=JSON.parse('{"id":"go-client/workflow-versioning","title":"Versioning","description":"The definition code of a Cadence must be deterministic because Cadence uses sourcing","source":"@site/docs/05-go-client/14-workflow-versioning.md","sourceDirName":"05-go-client","slug":"/go-client/workflow-versioning","permalink":"/docs/go-client/workflow-versioning","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/05-go-client/14-workflow-versioning.md","tags":[],"version":"current","sidebarPosition":14,"frontMatter":{"layout":"default","title":"Versioning","permalink":"/docs/go-client/workflow-versioning"},"sidebar":"docsSidebar","previous":{"title":"Testing","permalink":"/docs/go-client/workflow-testing"},"next":{"title":"Sessions","permalink":"/docs/go-client/sessions"}}');var r=o(4848),i=o(8453);const c={layout:"default",title:"Versioning",permalink:"/docs/go-client/workflow-versioning"},s="Versioning",l={},a=[{value:"workflow.GetVersion()",id:"workflowgetversion",level:2},{value:"Sanity checking",id:"sanity-checking",level:2}];function d(e){const t={code:"code",h1:"h1",h2:"h2",header:"header",li:"li",ol:"ol",p:"p",pre:"pre",ul:"ul",...(0,i.R)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(t.header,{children:(0,r.jsx)(t.h1,{id:"versioning",children:"Versioning"})}),"\n",(0,r.jsx)(t.p,{children:"The definition code of a Cadence workflow must be deterministic because Cadence uses event sourcing\nto reconstruct the workflow state by replaying the saved history event data on the workflow\ndefinition code. This means that any incompatible update to the workflow definition code could cause\na non-deterministic issue if not handled correctly."}),"\n",(0,r.jsx)(t.h2,{id:"workflowgetversion",children:"workflow.GetVersion()"}),"\n",(0,r.jsx)(t.p,{children:"Consider the following workflow definition:"}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{className:"language-go",children:'func MyWorkflow(ctx workflow.Context, data string) (string, error) {\n ao := workflow.ActivityOptions{\n ScheduleToStartTimeout: time.Minute,\n StartToCloseTimeout: time.Minute,\n }\n ctx = workflow.WithActivityOptions(ctx, ao)\n var result1 string\n err := workflow.ExecuteActivity(ctx, ActivityA, data).Get(ctx, &result1)\n if err != nil {\n return "", err\n }\n var result2 string\n err = workflow.ExecuteActivity(ctx, ActivityB, result1).Get(ctx, &result2)\n return result2, err\n}\n'})}),"\n",(0,r.jsx)(t.p,{children:"Now let's say we have replaced ActivityA with ActivityC, and deployed the updated code. If there\nis an existing workflow_execution that was started by the original version of the workflow code, where\nActivityA had already completed and the result was recorded to history, the new version of the workflow\ncode will pick up that workflow_execution and try to resume from there. However, the workflow will fail\nbecause the new code expects a result for ActivityC from the history data, but instead it gets the\nresult for ActivityA. This causes the workflow to fail on the non-deterministic error."}),"\n",(0,r.jsxs)(t.p,{children:["Thus we use ",(0,r.jsx)(t.code,{children:"workflow.GetVersion()."})]}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{className:"language-go",children:'var err error\nv := workflow.GetVersion(ctx, "Step1", workflow.DefaultVersion, 1)\nif v == workflow.DefaultVersion {\n err = workflow.ExecuteActivity(ctx, ActivityA, data).Get(ctx, &result1)\n} else {\n err = workflow.ExecuteActivity(ctx, ActivityC, data).Get(ctx, &result1)\n}\nif err != nil {\n return "", err\n}\n\nvar result2 string\nerr = workflow.ExecuteActivity(ctx, ActivityB, result1).Get(ctx, &result2)\nreturn result2, err\n'})}),"\n",(0,r.jsxs)(t.p,{children:["When ",(0,r.jsx)(t.code,{children:"workflow.GetVersion()"})," is run for the new workflow_execution, it records a marker in the workflow\nhistory so that all future calls to ",(0,r.jsx)(t.code,{children:"GetVersion"})," for this change ID--",(0,r.jsx)(t.code,{children:"Step 1"})," in the example--on this\nworkflow_execution will always return the given version number, which is ",(0,r.jsx)(t.code,{children:"1"})," in the example."]}),"\n",(0,r.jsx)(t.p,{children:"If you make an additional change, such as replacing ActivityC with ActivityD, you need to\nadd some additional code:"}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{className:"language-go",children:'v := workflow.GetVersion(ctx, "Step1", workflow.DefaultVersion, 2)\nif v == workflow.DefaultVersion {\n err = workflow.ExecuteActivity(ctx, ActivityA, data).Get(ctx, &result1)\n} else if v == 1 {\n err = workflow.ExecuteActivity(ctx, ActivityC, data).Get(ctx, &result1)\n} else {\n err = workflow.ExecuteActivity(ctx, ActivityD, data).Get(ctx, &result1)\n}\n'})}),"\n",(0,r.jsxs)(t.p,{children:["Note that we have changed ",(0,r.jsx)(t.code,{children:"maxSupported"})," from 1 to 2. A workflow that had already passed this\n",(0,r.jsx)(t.code,{children:"GetVersion()"})," call before it was introduced will return ",(0,r.jsx)(t.code,{children:"DefaultVersion"}),". A workflow that was run\nwith ",(0,r.jsx)(t.code,{children:"maxSupported"})," set to 1, will return 1. New workflows will return 2."]}),"\n",(0,r.jsx)(t.p,{children:"After you are sure that all of the workflow_executions prior to version 1 have completed, you can\nremove the code for that version. It should now look like the following:"}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{className:"language-go",children:'v := workflow.GetVersion(ctx, "Step1", 1, 2)\nif v == 1 {\n err = workflow.ExecuteActivity(ctx, ActivityC, data).Get(ctx, &result1)\n} else {\n err = workflow.ExecuteActivity(ctx, ActivityD, data).Get(ctx, &result1)\n}\n'})}),"\n",(0,r.jsxs)(t.p,{children:["You'll note that ",(0,r.jsx)(t.code,{children:"minSupported"})," has changed from ",(0,r.jsx)(t.code,{children:"DefaultVersion"})," to ",(0,r.jsx)(t.code,{children:"1"}),". If an older version of the\nworkflow_execution history is replayed on this code, it will fail because the minimum expected version\nis 1. After you are sure that all of the workflow_executions for version 1 have completed, then you\ncan remove 1 so that your code would look like the following:"]}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{className:"language-go",children:'_ := workflow.GetVersion(ctx, "Step1", 2, 2)\nerr = workflow.ExecuteActivity(ctx, ActivityD, data).Get(ctx, &result1)\n'})}),"\n",(0,r.jsxs)(t.p,{children:["Note that we have preserved the call to ",(0,r.jsx)(t.code,{children:"GetVersion()"}),". There are two reasons to preserve this call:"]}),"\n",(0,r.jsxs)(t.ol,{children:["\n",(0,r.jsx)(t.li,{children:"This ensures that if there is a workflow_execution still running for an older version, it will\nfail here and not proceed."}),"\n",(0,r.jsxs)(t.li,{children:["If you need to make additional changes for ",(0,r.jsx)(t.code,{children:"Step1"}),", such as changing ActivityD to ActivityE, you\nonly need to update ",(0,r.jsx)(t.code,{children:"maxVersion"})," from 2 to 3 and branch from there."]}),"\n"]}),"\n",(0,r.jsxs)(t.p,{children:["You only need to preserve the first call to ",(0,r.jsx)(t.code,{children:"GetVersion()"})," for each ",(0,r.jsx)(t.code,{children:"changeID"}),". All subsequent calls to\n",(0,r.jsx)(t.code,{children:"GetVersion()"})," with the same change ID are safe to remove. If necessary, you can remove the first\n",(0,r.jsx)(t.code,{children:"GetVersion()"})," call, but you need to ensure the following:"]}),"\n",(0,r.jsxs)(t.ul,{children:["\n",(0,r.jsx)(t.li,{children:"All executions with an older version are completed."}),"\n",(0,r.jsxs)(t.li,{children:["You can no longer use ",(0,r.jsx)(t.code,{children:"Step1"})," for the changeID. If you need to make changes to that same part in\nthe future, such as change from ActivityD to ActivityE, you would need to use a different changeID\nlike ",(0,r.jsx)(t.code,{children:"Step1-fix2"}),", and start minVersion from DefaultVersion again. The code would look like the\nfollowing:"]}),"\n"]}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{className:"language-go",children:'v := workflow.GetVersion(ctx, "Step1-fix2", workflow.DefaultVersion, 1)\nif v == workflow.DefaultVersion {\n err = workflow.ExecuteActivity(ctx, ActivityD, data).Get(ctx, &result1)\n} else {\n err = workflow.ExecuteActivity(ctx, ActivityE, data).Get(ctx, &result1)\n}\n'})}),"\n",(0,r.jsxs)(t.p,{children:["Upgrading a workflow is straightforward if you don't need to preserve your currently running\nworkflow_executions. You can simply terminate all of the currently running workflow_executions and\nsuspend new ones from being created while you deploy the new version of your workflow code, which does\nnot use ",(0,r.jsx)(t.code,{children:"GetVersion()"}),", and then resume workflow creation. However, that is often not the case, and\nyou need to take care of the currently running workflow_executions, so using ",(0,r.jsx)(t.code,{children:"GetVersion()"})," to update\nyour code is the method to use."]}),"\n",(0,r.jsxs)(t.p,{children:["However, if you want your currently running workflows to proceed based on the current workflow logic,\nbut you want to ensure new workflows are running on new logic, you can define your workflow as a\nnew ",(0,r.jsx)(t.code,{children:"WorkflowType"}),", and change your start path (calls to ",(0,r.jsx)(t.code,{children:"StartWorkflow()"}),") to start the new workflow\ntype."]}),"\n",(0,r.jsx)(t.h2,{id:"sanity-checking",children:"Sanity checking"}),"\n",(0,r.jsx)(t.p,{children:"The Cadence client SDK performs a sanity check to help prevent obvious incompatible changes.\nThe sanity check verifies whether a decision made in replay matches the event recorded in history,\nin the same order. The decision is generated by calling any of the following methods:"}),"\n",(0,r.jsxs)(t.ul,{children:["\n",(0,r.jsx)(t.li,{children:"workflow.ExecuteActivity()"}),"\n",(0,r.jsx)(t.li,{children:"workflow.ExecuteChildWorkflow()"}),"\n",(0,r.jsx)(t.li,{children:"workflow.NewTimer()"}),"\n",(0,r.jsx)(t.li,{children:"workflow.Sleep()"}),"\n",(0,r.jsx)(t.li,{children:"workflow.SideEffect()"}),"\n",(0,r.jsx)(t.li,{children:"workflow.RequestCancelWorkflow()"}),"\n",(0,r.jsx)(t.li,{children:"workflow.SignalExternalWorkflow()"}),"\n",(0,r.jsx)(t.li,{children:"workflow.UpsertSearchAttributes()"}),"\n"]}),"\n",(0,r.jsx)(t.p,{children:"Adding, removing, or reordering any of the above methods triggers the sanity check and results in\na non-deterministic error."}),"\n",(0,r.jsxs)(t.p,{children:["The sanity check does not perform a thorough check. For example, it does not check on the activity's\ninput arguments or the timer duration. If the check is enforced on every property, then it becomes\ntoo restricted and harder to maintain the workflow code. For example, if you move your activity code\nfrom one package to another package, that changes the ",(0,r.jsx)(t.code,{children:"ActivityType"}),", which technically becomes a different\nactivity. But, we don't want to fail on that change, so we only check the function name part of the\n",(0,r.jsx)(t.code,{children:"ActivityType"}),"."]})]})}function h(e={}){const{wrapper:t}={...(0,i.R)(),...e.components};return t?(0,r.jsx)(t,{...e,children:(0,r.jsx)(d,{...e})}):d(e)}},8453:(e,t,o)=>{o.d(t,{R:()=>c,x:()=>s});var n=o(6540);const r={},i=n.createContext(r);function c(e){const t=n.useContext(i);return n.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function s(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:c(e.components),n.createElement(i.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/d6960a6f.38d08e72.js b/assets/js/d6960a6f.b963172c.js similarity index 55% rename from assets/js/d6960a6f.38d08e72.js rename to assets/js/d6960a6f.b963172c.js index da2c6b8c9..e8b30e2a0 100644 --- a/assets/js/d6960a6f.38d08e72.js +++ b/assets/js/d6960a6f.b963172c.js @@ -1 +1 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[5557],{5234:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>s,contentTitle:()=>a,default:()=>p,frontMatter:()=>c,metadata:()=>o,toc:()=>d});var o=n(3865),i=n(4848),r=n(8453);const c={title:"Implement a Cadence worker service from scratch",date:new Date("2023-07-05T00:00:00.000Z"),authors:"chopincode",tags:["deep-dive","introduction-to-cadence"]},a=void 0,s={authorsImageUrls:[void 0]},d=[];function l(e){const t={a:"a",code:"code",li:"li",ol:"ol",p:"p",pre:"pre",...(0,r.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsxs)(t.p,{children:["In the previous ",(0,i.jsx)(t.a,{href:"/blog/2023/06/28/components-of-cadence-application-setup",children:"blog"}),", we have introduced three critical components for a Cadence application: the Cadence backend, domain, and worker. Among these, the worker service is the most crucial focus for developers as it hosts the activities and workflows of a Cadence application. In this blog, I will provide a short tutorial on how to implement a simple worker service from scratch in Go."]}),"\n",(0,i.jsx)(t.p,{children:"To finish this tutorial, there are two prerequisites you need to finish first"}),"\n",(0,i.jsxs)(t.ol,{children:["\n",(0,i.jsxs)(t.li,{children:["Register a Cadence domain for your worker. For this tutorial, I've already registered a domain named ",(0,i.jsx)(t.code,{children:"test-domain"})]}),"\n",(0,i.jsx)(t.li,{children:"Start the Cadence backend server in background."}),"\n"]}),"\n",(0,i.jsx)(t.p,{children:"To get started, let's simply use the native HTTP package built in Go to start a process listening to port 3000. You may customize the port for your worker, but the port you choose should not conflict with existing port for your Cadence backend."}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{className:"language-go",children:'package main\n\nimport (\n\t"fmt"\n\t"net/http"\n)\n\nfunc main(){\n\tfmt.Println("Cadence worker started at port 3000")\n\thttp.ListenAndServe(":3000", nil)\n}\n'})})]})}function p(e={}){const{wrapper:t}={...(0,r.R)(),...e.components};return t?(0,i.jsx)(t,{...e,children:(0,i.jsx)(l,{...e})}):l(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>c,x:()=>a});var o=n(6540);const i={},r=o.createContext(i);function c(e){const t=o.useContext(r);return o.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function a(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:c(e.components),o.createElement(r.Provider,{value:t},e.children)}},3865:e=>{e.exports=JSON.parse('{"permalink":"/blog/2023/07/05/implement-cadence-worker-from-scratch","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2023-07-05-implement-cadence-worker-from-scratch.md","source":"@site/blog/2023-07-05-implement-cadence-worker-from-scratch.md","title":"Implement a Cadence worker service from scratch","description":"In the previous blog, we have introduced three critical components for a Cadence application: the Cadence backend, domain, and worker. Among these, the worker service is the most crucial focus for developers as it hosts the activities and workflows of a Cadence application. In this blog, I will provide a short tutorial on how to implement a simple worker service from scratch in Go.","date":"2023-07-05T00:00:00.000Z","tags":[{"inline":false,"label":"Deep Dives","permalink":"/blog/tags/deep-dives","description":"Deep Dives tag description"},{"inline":false,"label":"Introduction to Cadence","permalink":"/blog/tags/introduction-to-cadence","description":"Introduction to Cadence tag description"}],"readingTime":3.69,"hasTruncateMarker":true,"authors":[{"name":"Chris Qin","title":"Applications Developer @ Uber","url":"https://www.linkedin.com/in/chrisqin0610/","page":{"permalink":"/blog/authors/chopincode"},"socials":{"linkedin":"https://www.linkedin.com/in/chrisqin0610/","github":"https://github.com/chopincode"},"imageURL":"https://github.com/chopincode.png","key":"chopincode"}],"frontMatter":{"title":"Implement a Cadence worker service from scratch","date":"2023-07-05T00:00:00.000Z","authors":"chopincode","tags":["deep-dive","introduction-to-cadence"]},"unlisted":false,"prevItem":{"title":"Bad practices and Anti-patterns with Cadence (Part 1)","permalink":"/blog/2023/07/10/cadence-bad-practices-part-1"},"nextItem":{"title":"Understanding components of Cadence application","permalink":"/blog/2023/06/28/components-of-cadence-application-setup"}}')}}]); \ No newline at end of file +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[5557],{5234:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>s,contentTitle:()=>a,default:()=>p,frontMatter:()=>c,metadata:()=>o,toc:()=>d});var o=n(3865),i=n(4848),r=n(8453);const c={title:"Implement a Cadence worker service from scratch",date:new Date("2023-07-05T00:00:00.000Z"),authors:"chopincode",tags:["deep-dive","introduction-to-cadence"]},a=void 0,s={authorsImageUrls:[void 0]},d=[];function l(e){const t={a:"a",code:"code",li:"li",ol:"ol",p:"p",pre:"pre",...(0,r.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsxs)(t.p,{children:["In the previous ",(0,i.jsx)(t.a,{href:"/blog/2023/06/28/components-of-cadence-application-setup",children:"blog"}),", we have introduced three critical components for a Cadence application: the Cadence backend, domain, and worker. Among these, the worker service is the most crucial focus for developers as it hosts the activities and workflows of a Cadence application. In this blog, I will provide a short tutorial on how to implement a simple worker service from scratch in Go."]}),"\n",(0,i.jsx)(t.p,{children:"To finish this tutorial, there are two prerequisites you need to finish first"}),"\n",(0,i.jsxs)(t.ol,{children:["\n",(0,i.jsxs)(t.li,{children:["Register a Cadence domain for your worker. For this tutorial, I've already registered a domain named ",(0,i.jsx)(t.code,{children:"test-domain"})]}),"\n",(0,i.jsx)(t.li,{children:"Start the Cadence backend server in background."}),"\n"]}),"\n",(0,i.jsx)(t.p,{children:"To get started, let's simply use the native HTTP package built in Go to start a process listening to port 3000. You may customize the port for your worker, but the port you choose should not conflict with existing port for your Cadence backend."}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{className:"language-go",children:'package main\n\nimport (\n\t"fmt"\n\t"net/http"\n)\n\nfunc main(){\n\tfmt.Println("Cadence worker started at port 3000")\n\thttp.ListenAndServe(":3000", nil)\n}\n'})})]})}function p(e={}){const{wrapper:t}={...(0,r.R)(),...e.components};return t?(0,i.jsx)(t,{...e,children:(0,i.jsx)(l,{...e})}):l(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>c,x:()=>a});var o=n(6540);const i={},r=o.createContext(i);function c(e){const t=o.useContext(r);return o.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function a(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:c(e.components),o.createElement(r.Provider,{value:t},e.children)}},3865:e=>{e.exports=JSON.parse('{"permalink":"/Cadence-Docs/blog/2023/07/05/implement-cadence-worker-from-scratch","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2023-07-05-implement-cadence-worker-from-scratch.md","source":"@site/blog/2023-07-05-implement-cadence-worker-from-scratch.md","title":"Implement a Cadence worker service from scratch","description":"In the previous blog, we have introduced three critical components for a Cadence application: the Cadence backend, domain, and worker. Among these, the worker service is the most crucial focus for developers as it hosts the activities and workflows of a Cadence application. In this blog, I will provide a short tutorial on how to implement a simple worker service from scratch in Go.","date":"2023-07-05T00:00:00.000Z","tags":[{"inline":false,"label":"Deep Dives","permalink":"/Cadence-Docs/blog/tags/deep-dives","description":"Deep Dives tag description"},{"inline":false,"label":"Introduction to Cadence","permalink":"/Cadence-Docs/blog/tags/introduction-to-cadence","description":"Introduction to Cadence tag description"}],"readingTime":3.69,"hasTruncateMarker":true,"authors":[{"name":"Chris Qin","title":"Applications Developer @ Uber","url":"https://www.linkedin.com/in/chrisqin0610/","page":{"permalink":"/Cadence-Docs/blog/authors/chopincode"},"socials":{"linkedin":"https://www.linkedin.com/in/chrisqin0610/","github":"https://github.com/chopincode"},"imageURL":"https://github.com/chopincode.png","key":"chopincode"}],"frontMatter":{"title":"Implement a Cadence worker service from scratch","date":"2023-07-05T00:00:00.000Z","authors":"chopincode","tags":["deep-dive","introduction-to-cadence"]},"unlisted":false,"prevItem":{"title":"Bad practices and Anti-patterns with Cadence (Part 1)","permalink":"/Cadence-Docs/blog/2023/07/10/cadence-bad-practices-part-1"},"nextItem":{"title":"Understanding components of Cadence application","permalink":"/Cadence-Docs/blog/2023/06/28/components-of-cadence-application-setup"}}')}}]); \ No newline at end of file diff --git a/assets/js/d70bd24b.6efb43f1.js b/assets/js/d70bd24b.6efb43f1.js new file mode 100644 index 000000000..e4cc8bd77 --- /dev/null +++ b/assets/js/d70bd24b.6efb43f1.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[1118],{5680:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>c,contentTitle:()=>r,default:()=>h,frontMatter:()=>i,metadata:()=>o,toc:()=>l});var o=n(3468),a=n(4848),s=n(8453);const i={title:"Cadence Community Spotlight Update - July 2023",date:new Date("2023-07-31T00:00:00.000Z"),authors:"sharanf",tags:["release","announcement","community-spotlight"]},r=void 0,c={authorsImageUrls:[void 0]},l=[{value:"Getting Started with Cadence",id:"getting-started-with-cadence",level:2},{value:"Cadence Go Client v1.0 Released",id:"cadence-go-client-v10-released",level:2}];function d(e){const t={a:"a",h2:"h2",p:"p",...(0,s.R)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(t.p,{children:"Welcome to the latest of our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!"}),"\n",(0,a.jsx)(t.p,{children:"Please see below for a roundup of the highlights:"}),"\n",(0,a.jsx)(t.h2,{id:"getting-started-with-cadence",children:"Getting Started with Cadence"}),"\n",(0,a.jsx)(t.p,{children:"Are you new to Cadence and want to understand the basic concepts and architecture? Well we have some great information for you!"}),"\n",(0,a.jsxs)(t.p,{children:["Community member ",(0,a.jsx)(t.a,{href:"https://www.linkedin.com/in/chrisqin0610/",children:"Chris Qin"})," has written a ",(0,a.jsx)(t.a,{href:"https://cadenceworkflow.io/blog/2023/07/01/components-of-cadence-application-setup/",children:"short blog post"})," that takes you through the the three main components that make up a Cadence application. Please take a look and feel free to give us your comments and feedback."]}),"\n",(0,a.jsx)(t.p,{children:"Thanks Chris for sharing your knowledge and helping others to get started."}),"\n",(0,a.jsx)(t.h2,{id:"cadence-go-client-v10-released",children:"Cadence Go Client v1.0 Released"}),"\n",(0,a.jsxs)(t.p,{children:["This month saw the release of ",(0,a.jsx)(t.a,{href:"https://github.com/cadence-workflow/cadence-go-client/releases/tag/v1.0.0",children:"v1.0 of the Cadence Go Client"}),". Note that the work done on this release was as a result of community feedback asking for it - so we are listening and responding to community needs."]}),"\n",(0,a.jsx)(t.p,{children:"Thanks very much to everyone who worked hard to get this release out!"})]})}function h(e={}){const{wrapper:t}={...(0,s.R)(),...e.components};return t?(0,a.jsx)(t,{...e,children:(0,a.jsx)(d,{...e})}):d(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>i,x:()=>r});var o=n(6540);const a={},s=o.createContext(a);function i(e){const t=o.useContext(s);return o.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function r(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:i(e.components),o.createElement(s.Provider,{value:t},e.children)}},3468:e=>{e.exports=JSON.parse('{"permalink":"/Cadence-Docs/blog/2023/07/31/community-spotlight-july-2023","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2023-07-31-community-spotlight-july-2023.md","source":"@site/blog/2023-07-31-community-spotlight-july-2023.md","title":"Cadence Community Spotlight Update - July 2023","description":"Welcome to the latest of our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!","date":"2023-07-31T00:00:00.000Z","tags":[{"inline":false,"label":"Releases","permalink":"/Cadence-Docs/blog/tags/releases","description":"Releases tag description"},{"inline":false,"label":"Announcement","permalink":"/Cadence-Docs/blog/tags/announcements","description":"Announcement tag description"},{"inline":false,"label":"Community Spotlight","permalink":"/Cadence-Docs/blog/tags/community-spotlights","description":"Community Spotlight tag description"}],"readingTime":2.49,"hasTruncateMarker":true,"authors":[{"name":"Sharan Foga","title":"Director of Operations & Customer Success @ Encube Technologies","url":"https://www.linkedin.com/in/sfoga/","page":{"permalink":"/Cadence-Docs/blog/authors/sharanf"},"socials":{"linkedin":"https://www.linkedin.com/in/sfoga/","github":"https://github.com/sharanf"},"imageURL":"https://github.com/sharanf.png","key":"sharanf"}],"frontMatter":{"title":"Cadence Community Spotlight Update - July 2023","date":"2023-07-31T00:00:00.000Z","authors":"sharanf","tags":["release","announcement","community-spotlight"]},"unlisted":false,"prevItem":{"title":"Non-deterministic errors, replayers and shadowers","permalink":"/Cadence-Docs/blog/2023/08/28/nondeterministic-errors-replayers-shadowers"},"nextItem":{"title":"Write your first workflow with Cadence","permalink":"/Cadence-Docs/blog/2023/07/16/2023-07-16-write-your-first-workflow-with-cadence/write-your-first-workflow-with-cadence"}}')}}]); \ No newline at end of file diff --git a/assets/js/d70bd24b.a9e49c4b.js b/assets/js/d70bd24b.a9e49c4b.js deleted file mode 100644 index c24874384..000000000 --- a/assets/js/d70bd24b.a9e49c4b.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[1118],{5680:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>l,contentTitle:()=>r,default:()=>d,frontMatter:()=>s,metadata:()=>o,toc:()=>c});var o=n(3468),a=n(4848),i=n(8453);const s={title:"Cadence Community Spotlight Update - July 2023",date:new Date("2023-07-31T00:00:00.000Z"),authors:"sharanf",tags:["release","announcement","community-spotlight"]},r=void 0,l={authorsImageUrls:[void 0]},c=[{value:"Getting Started with Cadence",id:"getting-started-with-cadence",level:2},{value:"Cadence Go Client v1.0 Released",id:"cadence-go-client-v10-released",level:2}];function h(e){const t={a:"a",h2:"h2",p:"p",...(0,i.R)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(t.p,{children:"Welcome to the latest of our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!"}),"\n",(0,a.jsx)(t.p,{children:"Please see below for a roundup of the highlights:"}),"\n",(0,a.jsx)(t.h2,{id:"getting-started-with-cadence",children:"Getting Started with Cadence"}),"\n",(0,a.jsx)(t.p,{children:"Are you new to Cadence and want to understand the basic concepts and architecture? Well we have some great information for you!"}),"\n",(0,a.jsxs)(t.p,{children:["Community member ",(0,a.jsx)(t.a,{href:"https://www.linkedin.com/in/chrisqin0610/",children:"Chris Qin"})," has written a ",(0,a.jsx)(t.a,{href:"https://cadenceworkflow.io/blog/2023/07/01/components-of-cadence-application-setup/",children:"short blog post"})," that takes you through the the three main components that make up a Cadence application. Please take a look and feel free to give us your comments and feedback."]}),"\n",(0,a.jsx)(t.p,{children:"Thanks Chris for sharing your knowledge and helping others to get started."}),"\n",(0,a.jsx)(t.h2,{id:"cadence-go-client-v10-released",children:"Cadence Go Client v1.0 Released"}),"\n",(0,a.jsxs)(t.p,{children:["This month saw the release of ",(0,a.jsx)(t.a,{href:"https://github.com/cadence-workflow/cadence-go-client/releases/tag/v1.0.0",children:"v1.0 of the Cadence Go Client"}),". Note that the work done on this release was as a result of community feedback asking for it - so we are listening and responding to community needs."]}),"\n",(0,a.jsx)(t.p,{children:"Thanks very much to everyone who worked hard to get this release out!"})]})}function d(e={}){const{wrapper:t}={...(0,i.R)(),...e.components};return t?(0,a.jsx)(t,{...e,children:(0,a.jsx)(h,{...e})}):h(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>s,x:()=>r});var o=n(6540);const a={},i=o.createContext(a);function s(e){const t=o.useContext(i);return o.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function r(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:s(e.components),o.createElement(i.Provider,{value:t},e.children)}},3468:e=>{e.exports=JSON.parse('{"permalink":"/blog/2023/07/31/community-spotlight-july-2023","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2023-07-31-community-spotlight-july-2023.md","source":"@site/blog/2023-07-31-community-spotlight-july-2023.md","title":"Cadence Community Spotlight Update - July 2023","description":"Welcome to the latest of our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!","date":"2023-07-31T00:00:00.000Z","tags":[{"inline":false,"label":"Releases","permalink":"/blog/tags/releases","description":"Releases tag description"},{"inline":false,"label":"Announcement","permalink":"/blog/tags/announcements","description":"Announcement tag description"},{"inline":false,"label":"Community Spotlight","permalink":"/blog/tags/community-spotlights","description":"Community Spotlight tag description"}],"readingTime":2.49,"hasTruncateMarker":true,"authors":[{"name":"Sharan Foga","title":"Director of Operations & Customer Success @ Encube Technologies","url":"https://www.linkedin.com/in/sfoga/","page":{"permalink":"/blog/authors/sharanf"},"socials":{"linkedin":"https://www.linkedin.com/in/sfoga/","github":"https://github.com/sharanf"},"imageURL":"https://github.com/sharanf.png","key":"sharanf"}],"frontMatter":{"title":"Cadence Community Spotlight Update - July 2023","date":"2023-07-31T00:00:00.000Z","authors":"sharanf","tags":["release","announcement","community-spotlight"]},"unlisted":false,"prevItem":{"title":"Non-deterministic errors, replayers and shadowers","permalink":"/blog/2023/08/28/nondeterministic-errors-replayers-shadowers"},"nextItem":{"title":"Write your first workflow with Cadence","permalink":"/blog/2023/07/16/2023-07-16-write-your-first-workflow-with-cadence/write-your-first-workflow-with-cadence"}}')}}]); \ No newline at end of file diff --git a/assets/js/d7b037f3.38bce024.js b/assets/js/d7b037f3.38bce024.js deleted file mode 100644 index cd1d54e28..000000000 --- a/assets/js/d7b037f3.38bce024.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[5385],{3547:(e,s,t)=>{t.r(s),t.d(s,{assets:()=>c,contentTitle:()=>a,default:()=>u,frontMatter:()=>i,metadata:()=>n,toc:()=>l});const n=JSON.parse('{"id":"use-cases/orchestration","title":"Orchestration","description":"It is common that some business processes are implemented as multiple microservice calls.","source":"@site/docs/02-use-cases/02-orchestration.md","sourceDirName":"02-use-cases","slug":"/use-cases/orchestration","permalink":"/docs/use-cases/orchestration","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/02-use-cases/02-orchestration.md","tags":[],"version":"current","sidebarPosition":2,"frontMatter":{"layout":"default","title":"Orchestration","permalink":"/docs/use-cases/orchestration"},"sidebar":"docsSidebar","previous":{"title":"Periodic execution","permalink":"/docs/use-cases/periodic-execution"},"next":{"title":"Polling","permalink":"/docs/use-cases/polling"}}');var o=t(4848),r=t(8453);const i={layout:"default",title:"Orchestration",permalink:"/docs/use-cases/orchestration"},a="Microservice Orchestration and Saga",c={},l=[];function d(e){const s={a:"a",h1:"h1",header:"header",li:"li",p:"p",ul:"ul",...(0,r.R)(),...e.components};return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsx)(s.header,{children:(0,o.jsx)(s.h1,{id:"microservice-orchestration-and-saga",children:"Microservice Orchestration and Saga"})}),"\n",(0,o.jsxs)(s.p,{children:["It is common that some business processes are implemented as multiple microservice calls.\nAnd the implementation must guarantee that all of the calls must eventually succeed even with the occurrence of prolonged downstream service failures.\nIn some cases, instead of trying to complete the process by retrying for a long time, compensation rollback logic should be executed.\n",(0,o.jsx)(s.a,{href:"https://microservices.io/patterns/data/saga.html",children:"Saga Pattern"})," is one way to standardize on compensation APIs."]}),"\n",(0,o.jsx)(s.p,{children:"Cadence is a perfect fit for such scenarios. It guarantees that workflow code eventually completes, has built-in support\nfor unlimited exponential activity retries and simplifies coding of the compensation logic. It also gives full visibility into the state of each workflow, in contrast to an orchestration based on queues where getting a current status of each individual request is practically impossible."}),"\n",(0,o.jsx)(s.p,{children:"Following are some real-world examples of Cadence-based service orchestration scenarios:"}),"\n",(0,o.jsxs)(s.ul,{children:["\n",(0,o.jsx)(s.li,{children:(0,o.jsx)(s.a,{href:"https://github.com/edmondop/cadence-helm-chart",children:"Using Cadence workflows to spin up Kubernetes (Banzai Cloud Fork)"})}),"\n",(0,o.jsx)(s.li,{children:(0,o.jsx)(s.a,{href:"https://eng.uber.com/customer-obsession-ticket-routing-workflow-and-orchestration-engine/",children:"Improving the User Experience with Uber\u2019s Customer Obsession Ticket Routing Workflow and Orchestration Engine"})}),"\n",(0,o.jsx)(s.li,{children:(0,o.jsx)(s.a,{href:"https://doordash.engineering/2022/05/18/enabling-faster-financial-partnership-integrations-using-cadence/",children:"Enabling Faster Financial Partnership Integrations Using Cadence"})}),"\n"]})]})}function u(e={}){const{wrapper:s}={...(0,r.R)(),...e.components};return s?(0,o.jsx)(s,{...e,children:(0,o.jsx)(d,{...e})}):d(e)}},8453:(e,s,t)=>{t.d(s,{R:()=>i,x:()=>a});var n=t(6540);const o={},r=n.createContext(o);function i(e){const s=n.useContext(r);return n.useMemo((function(){return"function"==typeof e?e(s):{...s,...e}}),[s,e])}function a(e){let s;return s=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:i(e.components),n.createElement(r.Provider,{value:s},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/d7b037f3.40a19d54.js b/assets/js/d7b037f3.40a19d54.js new file mode 100644 index 000000000..8c82fb444 --- /dev/null +++ b/assets/js/d7b037f3.40a19d54.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[5385],{3547:(e,s,t)=>{t.r(s),t.d(s,{assets:()=>c,contentTitle:()=>a,default:()=>u,frontMatter:()=>i,metadata:()=>n,toc:()=>l});const n=JSON.parse('{"id":"use-cases/orchestration","title":"Orchestration","description":"It is common that some business processes are implemented as multiple microservice calls.","source":"@site/docs/02-use-cases/02-orchestration.md","sourceDirName":"02-use-cases","slug":"/use-cases/orchestration","permalink":"/Cadence-Docs/docs/use-cases/orchestration","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/02-use-cases/02-orchestration.md","tags":[],"version":"current","sidebarPosition":2,"frontMatter":{"layout":"default","title":"Orchestration","permalink":"/docs/use-cases/orchestration"},"sidebar":"docsSidebar","previous":{"title":"Periodic execution","permalink":"/Cadence-Docs/docs/use-cases/periodic-execution"},"next":{"title":"Polling","permalink":"/Cadence-Docs/docs/use-cases/polling"}}');var o=t(4848),r=t(8453);const i={layout:"default",title:"Orchestration",permalink:"/docs/use-cases/orchestration"},a="Microservice Orchestration and Saga",c={},l=[];function d(e){const s={a:"a",h1:"h1",header:"header",li:"li",p:"p",ul:"ul",...(0,r.R)(),...e.components};return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsx)(s.header,{children:(0,o.jsx)(s.h1,{id:"microservice-orchestration-and-saga",children:"Microservice Orchestration and Saga"})}),"\n",(0,o.jsxs)(s.p,{children:["It is common that some business processes are implemented as multiple microservice calls.\nAnd the implementation must guarantee that all of the calls must eventually succeed even with the occurrence of prolonged downstream service failures.\nIn some cases, instead of trying to complete the process by retrying for a long time, compensation rollback logic should be executed.\n",(0,o.jsx)(s.a,{href:"https://microservices.io/patterns/data/saga.html",children:"Saga Pattern"})," is one way to standardize on compensation APIs."]}),"\n",(0,o.jsx)(s.p,{children:"Cadence is a perfect fit for such scenarios. It guarantees that workflow code eventually completes, has built-in support\nfor unlimited exponential activity retries and simplifies coding of the compensation logic. It also gives full visibility into the state of each workflow, in contrast to an orchestration based on queues where getting a current status of each individual request is practically impossible."}),"\n",(0,o.jsx)(s.p,{children:"Following are some real-world examples of Cadence-based service orchestration scenarios:"}),"\n",(0,o.jsxs)(s.ul,{children:["\n",(0,o.jsx)(s.li,{children:(0,o.jsx)(s.a,{href:"https://github.com/edmondop/cadence-helm-chart",children:"Using Cadence workflows to spin up Kubernetes (Banzai Cloud Fork)"})}),"\n",(0,o.jsx)(s.li,{children:(0,o.jsx)(s.a,{href:"https://eng.uber.com/customer-obsession-ticket-routing-workflow-and-orchestration-engine/",children:"Improving the User Experience with Uber\u2019s Customer Obsession Ticket Routing Workflow and Orchestration Engine"})}),"\n",(0,o.jsx)(s.li,{children:(0,o.jsx)(s.a,{href:"https://doordash.engineering/2022/05/18/enabling-faster-financial-partnership-integrations-using-cadence/",children:"Enabling Faster Financial Partnership Integrations Using Cadence"})}),"\n"]})]})}function u(e={}){const{wrapper:s}={...(0,r.R)(),...e.components};return s?(0,o.jsx)(s,{...e,children:(0,o.jsx)(d,{...e})}):d(e)}},8453:(e,s,t)=>{t.d(s,{R:()=>i,x:()=>a});var n=t(6540);const o={},r=n.createContext(o);function i(e){const s=n.useContext(r);return n.useMemo((function(){return"function"==typeof e?e(s):{...s,...e}}),[s,e])}function a(e){let s;return s=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:i(e.components),n.createElement(r.Provider,{value:s},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/d87fba2a.1e35568c.js b/assets/js/d87fba2a.1e35568c.js new file mode 100644 index 000000000..9fbea6397 --- /dev/null +++ b/assets/js/d87fba2a.1e35568c.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[104],{2171:(e,a,t)=>{t.r(a),t.d(a,{assets:()=>c,contentTitle:()=>i,default:()=>m,frontMatter:()=>r,metadata:()=>n,toc:()=>l});const n=JSON.parse('{"id":"use-cases/operational-management","title":"Operational management","description":"Imagine that you have to create a self operating database similar to Amazon RDS. Cadence is used in multiple projects","source":"@site/docs/02-use-cases/09-operational-management.md","sourceDirName":"02-use-cases","slug":"/use-cases/operational-management","permalink":"/Cadence-Docs/docs/use-cases/operational-management","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/02-use-cases/09-operational-management.md","tags":[],"version":"current","sidebarPosition":9,"frontMatter":{"layout":"default","title":"Operational management","permalink":"/docs/use-cases/operational-management"},"sidebar":"docsSidebar","previous":{"title":"Deployment","permalink":"/Cadence-Docs/docs/use-cases/deployment"},"next":{"title":"Interactive application","permalink":"/Cadence-Docs/docs/use-cases/interactive"}}');var s=t(4848),o=t(8453);const r={layout:"default",title:"Operational management",permalink:"/docs/use-cases/operational-management"},i="Operational management",c={},l=[];function d(e){const a={h1:"h1",header:"header",p:"p",...(0,o.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(a.header,{children:(0,s.jsx)(a.h1,{id:"operational-management",children:"Operational management"})}),"\n",(0,s.jsx)(a.p,{children:"Imagine that you have to create a self operating database similar to Amazon RDS. Cadence is used in multiple projects\nthat automate managing and automatic recovery of various products like MySQL, Elasticsearch and Apache Cassandra."}),"\n",(0,s.jsx)(a.p,{children:"Such systems are usually a mixture of different use cases. They need to monitor the status of resources using polling. They have to execute orchestration API calls to administrative interfaces of a database. They have to provision new hardware or Docker instances if necessary. They need to push configuration updates and perform other actions like backups periodically."})]})}function m(e={}){const{wrapper:a}={...(0,o.R)(),...e.components};return a?(0,s.jsx)(a,{...e,children:(0,s.jsx)(d,{...e})}):d(e)}},8453:(e,a,t)=>{t.d(a,{R:()=>r,x:()=>i});var n=t(6540);const s={},o=n.createContext(s);function r(e){const a=n.useContext(o);return n.useMemo((function(){return"function"==typeof e?e(a):{...a,...e}}),[a,e])}function i(e){let a;return a=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:r(e.components),n.createElement(o.Provider,{value:a},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/d87fba2a.94f01d21.js b/assets/js/d87fba2a.94f01d21.js deleted file mode 100644 index 077b1ec70..000000000 --- a/assets/js/d87fba2a.94f01d21.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[104],{2171:(e,a,t)=>{t.r(a),t.d(a,{assets:()=>c,contentTitle:()=>i,default:()=>u,frontMatter:()=>r,metadata:()=>n,toc:()=>l});const n=JSON.parse('{"id":"use-cases/operational-management","title":"Operational management","description":"Imagine that you have to create a self operating database similar to Amazon RDS. Cadence is used in multiple projects","source":"@site/docs/02-use-cases/09-operational-management.md","sourceDirName":"02-use-cases","slug":"/use-cases/operational-management","permalink":"/docs/use-cases/operational-management","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/02-use-cases/09-operational-management.md","tags":[],"version":"current","sidebarPosition":9,"frontMatter":{"layout":"default","title":"Operational management","permalink":"/docs/use-cases/operational-management"},"sidebar":"docsSidebar","previous":{"title":"Deployment","permalink":"/docs/use-cases/deployment"},"next":{"title":"Interactive application","permalink":"/docs/use-cases/interactive"}}');var s=t(4848),o=t(8453);const r={layout:"default",title:"Operational management",permalink:"/docs/use-cases/operational-management"},i="Operational management",c={},l=[];function m(e){const a={h1:"h1",header:"header",p:"p",...(0,o.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(a.header,{children:(0,s.jsx)(a.h1,{id:"operational-management",children:"Operational management"})}),"\n",(0,s.jsx)(a.p,{children:"Imagine that you have to create a self operating database similar to Amazon RDS. Cadence is used in multiple projects\nthat automate managing and automatic recovery of various products like MySQL, Elasticsearch and Apache Cassandra."}),"\n",(0,s.jsx)(a.p,{children:"Such systems are usually a mixture of different use cases. They need to monitor the status of resources using polling. They have to execute orchestration API calls to administrative interfaces of a database. They have to provision new hardware or Docker instances if necessary. They need to push configuration updates and perform other actions like backups periodically."})]})}function u(e={}){const{wrapper:a}={...(0,o.R)(),...e.components};return a?(0,s.jsx)(a,{...e,children:(0,s.jsx)(m,{...e})}):m(e)}},8453:(e,a,t)=>{t.d(a,{R:()=>r,x:()=>i});var n=t(6540);const s={},o=n.createContext(s);function r(e){const a=n.useContext(o);return n.useMemo((function(){return"function"==typeof e?e(a):{...a,...e}}),[a,e])}function i(e){let a;return a=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:r(e.components),n.createElement(o.Provider,{value:a},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/d8ddffe9.b0a661ee.js b/assets/js/d8ddffe9.b0a661ee.js new file mode 100644 index 000000000..fc8580f71 --- /dev/null +++ b/assets/js/d8ddffe9.b0a661ee.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[1973],{6771:e=>{e.exports=JSON.parse('{"author":{"name":"Josu\xe9 Alexander Ibarra","title":"Developer Advocate @ Uber","url":"https://github.com/ibarrajo/","page":{"permalink":"/Cadence-Docs/blog/authors/ibarrajo"},"socials":{"github":"https://github.com/ibarrajo","linkedin":"https://www.linkedin.com/in/elninja/"},"imageURL":"https://github.com/ibarrajo.png","key":"ibarrajo","count":1},"listMetadata":{"permalink":"/Cadence-Docs/blog/authors/ibarrajo","page":1,"postsPerPage":10,"totalPages":1,"totalCount":1,"blogDescription":"The latest news and updates from the Cadence team","blogTitle":"Cadence Blog"}}')}}]); \ No newline at end of file diff --git a/assets/js/de3708c6.820e22e3.js b/assets/js/de3708c6.820e22e3.js new file mode 100644 index 000000000..daebdb064 --- /dev/null +++ b/assets/js/de3708c6.820e22e3.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[4619],{988:(e,n,o)=>{o.r(n),o.d(n,{assets:()=>c,contentTitle:()=>r,default:()=>d,frontMatter:()=>s,metadata:()=>t,toc:()=>u});var t=o(4131),a=o(4848),i=o(8453);const s={title:"Announcing Cadence OSS office hours and community sync up",date:new Date("2021-10-13T00:00:00.000Z"),authors:"meiliang86",tags:["announcement","roadmap"]},r=void 0,c={authorsImageUrls:[void 0]},u=[];function l(e){const n={a:"a",p:"p",strong:"strong",...(0,i.R)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(n.p,{children:"Are you a current Cadence user, do you operate Cadence services, or are you interested in learning about workflow technologies and wonder what problems Cadence could solve for you? We would like to talk to you!"}),"\n",(0,a.jsxs)(n.p,{children:["Our team has spent a significant amount of time working with users and partner teams at Uber to design, scale and operate their workflows. This helps our users understand the technology better, smooth their learning curve and ramp up experience, and at the same time allows us to get fast and direct feedback so we can improve the developer experience and close feature gaps. As our product and community grows, we would like to expand this practice to our users in the OSS community. ",(0,a.jsx)(n.strong,{children:"For the first time ever, members of the Cadence team along with core contributors from the community will host bi-weekly office hours to answer any questions you have about Cadence, or workflow technology in general."})," We can also dedicate future sessions to specific topics that have a common interest. Please don\u2019t hesitate to let us know your thoughts."]}),"\n",(0,a.jsx)(n.p,{children:"Please join a session if you would like to talk about any of the following topics:"}),"\n",(0,a.jsxs)("ol",{children:[(0,a.jsx)("li",{children:"Understand what Cadence is and why it might be useful for you and your company"}),(0,a.jsx)("li",{children:"Guidance about running Cadence services and workers in production"}),(0,a.jsx)("li",{children:"Workflow design and operation consultation"}),(0,a.jsx)("li",{children:"Product update, future roadmaps as well as collaboration opportunities"})]}),"\n",(0,a.jsx)(n.p,{children:"Building and maintaining a healthy and growing community is the key to the success of Cadence, and one of the top priorities for our team. We would like to use the office hours as an opportunity to understand and help our customers, seek feedback, and forge partnerships. We look forward to seeing you in one of the meetings."}),"\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.strong,{children:"Upcoming Office Hours"})}),"\n",(0,a.jsxs)(n.p,{children:["As we have a geo-distributed userbase, we are still trying to figure out a time that works for most of the people. In the meanwhile, we will manually schedule the first few instances of the meeting until we settle on a fixed schedule. Our next office hours will take place on ",(0,a.jsx)(n.strong,{children:"Thursday, October 21 2pm-3pm PT/5pm-6pm EST/9pm-10pm GMT"}),". Please join via ",(0,a.jsx)(n.a,{href:"https://uber.zoom.us/j/92356466350?pwd=RFVTc2pwV0xoVTdlK3VxN3N2eU5UZz09",children:"this zoom link"}),"."]}),"\n",(0,a.jsx)(n.p,{children:"The Uber Cadence team"})]})}function d(e={}){const{wrapper:n}={...(0,i.R)(),...e.components};return n?(0,a.jsx)(n,{...e,children:(0,a.jsx)(l,{...e})}):l(e)}},8453:(e,n,o)=>{o.d(n,{R:()=>s,x:()=>r});var t=o(6540);const a={},i=t.createContext(a);function s(e){const n=t.useContext(i);return t.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function r(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:s(e.components),t.createElement(i.Provider,{value:n},e.children)}},4131:e=>{e.exports=JSON.parse('{"permalink":"/Cadence-Docs/blog/2021/10/13/announcing-cadence-oss-office-hours-and-community-sync-up","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2021-10-13-announcing-cadence-oss-office-hours-and-community-sync-up.md","source":"@site/blog/2021-10-13-announcing-cadence-oss-office-hours-and-community-sync-up.md","title":"Announcing Cadence OSS office hours and community sync up","description":"Are you a current Cadence user, do you operate Cadence services, or are you interested in learning about workflow technologies and wonder what problems Cadence could solve for you? We would like to talk to you!","date":"2021-10-13T00:00:00.000Z","tags":[{"inline":false,"label":"Announcement","permalink":"/Cadence-Docs/blog/tags/announcements","description":"Announcement tag description"},{"inline":false,"label":"Roadmap","permalink":"/Cadence-Docs/blog/tags/roadmap","description":"Roadmap tag description"}],"readingTime":1.83,"hasTruncateMarker":true,"authors":[{"name":"Liang Mei","title":"Engineering Manager @ Uber","url":"https://www.linkedin.com/in/meiliang86/","page":{"permalink":"/Cadence-Docs/blog/authors/meiliang-86"},"socials":{"linkedin":"https://www.linkedin.com/in/meiliang86/","github":"https://github.com/meiliang86"},"imageURL":"https://github.com/meiliang86.png","key":"meiliang86"}],"frontMatter":{"title":"Announcing Cadence OSS office hours and community sync up","date":"2021-10-13T00:00:00.000Z","authors":"meiliang86","tags":["announcement","roadmap"]},"unlisted":false,"prevItem":{"title":"Moving to gRPC","permalink":"/Cadence-Docs/blog/2021/10/19/2021-10-19-moving-to-grpc/moving-to-grpc"},"nextItem":{"title":"Long-term commitment and support for the Cadence project, and its community","permalink":"/Cadence-Docs/blog/2021/09/30/long-term-commitment-and-support-for-the-cadence-project-and-its-community"}}')}}]); \ No newline at end of file diff --git a/assets/js/de3708c6.8c0038c5.js b/assets/js/de3708c6.8c0038c5.js deleted file mode 100644 index 4c64e8e68..000000000 --- a/assets/js/de3708c6.8c0038c5.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[4619],{988:(e,n,o)=>{o.r(n),o.d(n,{assets:()=>c,contentTitle:()=>s,default:()=>d,frontMatter:()=>r,metadata:()=>t,toc:()=>u});var t=o(4131),i=o(4848),a=o(8453);const r={title:"Announcing Cadence OSS office hours and community sync up",date:new Date("2021-10-13T00:00:00.000Z"),authors:"meiliang86",tags:["announcement","roadmap"]},s=void 0,c={authorsImageUrls:[void 0]},u=[];function l(e){const n={a:"a",p:"p",strong:"strong",...(0,a.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.p,{children:"Are you a current Cadence user, do you operate Cadence services, or are you interested in learning about workflow technologies and wonder what problems Cadence could solve for you? We would like to talk to you!"}),"\n",(0,i.jsxs)(n.p,{children:["Our team has spent a significant amount of time working with users and partner teams at Uber to design, scale and operate their workflows. This helps our users understand the technology better, smooth their learning curve and ramp up experience, and at the same time allows us to get fast and direct feedback so we can improve the developer experience and close feature gaps. As our product and community grows, we would like to expand this practice to our users in the OSS community. ",(0,i.jsx)(n.strong,{children:"For the first time ever, members of the Cadence team along with core contributors from the community will host bi-weekly office hours to answer any questions you have about Cadence, or workflow technology in general."})," We can also dedicate future sessions to specific topics that have a common interest. Please don\u2019t hesitate to let us know your thoughts."]}),"\n",(0,i.jsx)(n.p,{children:"Please join a session if you would like to talk about any of the following topics:"}),"\n",(0,i.jsxs)("ol",{children:[(0,i.jsx)("li",{children:"Understand what Cadence is and why it might be useful for you and your company"}),(0,i.jsx)("li",{children:"Guidance about running Cadence services and workers in production"}),(0,i.jsx)("li",{children:"Workflow design and operation consultation"}),(0,i.jsx)("li",{children:"Product update, future roadmaps as well as collaboration opportunities"})]}),"\n",(0,i.jsx)(n.p,{children:"Building and maintaining a healthy and growing community is the key to the success of Cadence, and one of the top priorities for our team. We would like to use the office hours as an opportunity to understand and help our customers, seek feedback, and forge partnerships. We look forward to seeing you in one of the meetings."}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.strong,{children:"Upcoming Office Hours"})}),"\n",(0,i.jsxs)(n.p,{children:["As we have a geo-distributed userbase, we are still trying to figure out a time that works for most of the people. In the meanwhile, we will manually schedule the first few instances of the meeting until we settle on a fixed schedule. Our next office hours will take place on ",(0,i.jsx)(n.strong,{children:"Thursday, October 21 2pm-3pm PT/5pm-6pm EST/9pm-10pm GMT"}),". Please join via ",(0,i.jsx)(n.a,{href:"https://uber.zoom.us/j/92356466350?pwd=RFVTc2pwV0xoVTdlK3VxN3N2eU5UZz09",children:"this zoom link"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"The Uber Cadence team"})]})}function d(e={}){const{wrapper:n}={...(0,a.R)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(l,{...e})}):l(e)}},8453:(e,n,o)=>{o.d(n,{R:()=>r,x:()=>s});var t=o(6540);const i={},a=t.createContext(i);function r(e){const n=t.useContext(a);return t.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function s(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:r(e.components),t.createElement(a.Provider,{value:n},e.children)}},4131:e=>{e.exports=JSON.parse('{"permalink":"/blog/2021/10/13/announcing-cadence-oss-office-hours-and-community-sync-up","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2021-10-13-announcing-cadence-oss-office-hours-and-community-sync-up.md","source":"@site/blog/2021-10-13-announcing-cadence-oss-office-hours-and-community-sync-up.md","title":"Announcing Cadence OSS office hours and community sync up","description":"Are you a current Cadence user, do you operate Cadence services, or are you interested in learning about workflow technologies and wonder what problems Cadence could solve for you? We would like to talk to you!","date":"2021-10-13T00:00:00.000Z","tags":[{"inline":false,"label":"Announcement","permalink":"/blog/tags/announcements","description":"Announcement tag description"},{"inline":false,"label":"Roadmap","permalink":"/blog/tags/roadmap","description":"Roadmap tag description"}],"readingTime":1.83,"hasTruncateMarker":true,"authors":[{"name":"Liang Mei","title":"Engineering Manager @ Uber","url":"https://www.linkedin.com/in/meiliang86/","page":{"permalink":"/blog/authors/meiliang-86"},"socials":{"linkedin":"https://www.linkedin.com/in/meiliang86/","github":"https://github.com/meiliang86"},"imageURL":"https://github.com/meiliang86.png","key":"meiliang86"}],"frontMatter":{"title":"Announcing Cadence OSS office hours and community sync up","date":"2021-10-13T00:00:00.000Z","authors":"meiliang86","tags":["announcement","roadmap"]},"unlisted":false,"prevItem":{"title":"Moving to gRPC","permalink":"/blog/2021/10/19/2021-10-19-moving-to-grpc/moving-to-grpc"},"nextItem":{"title":"Long-term commitment and support for the Cadence project, and its community","permalink":"/blog/2021/09/30/long-term-commitment-and-support-for-the-cadence-project-and-its-community"}}')}}]); \ No newline at end of file diff --git a/assets/js/dec4f520.04aa9673.js b/assets/js/dec4f520.04aa9673.js new file mode 100644 index 000000000..ecb5ff5bf --- /dev/null +++ b/assets/js/dec4f520.04aa9673.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[4898],{190:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>r,contentTitle:()=>c,default:()=>l,frontMatter:()=>i,metadata:()=>o,toc:()=>h});var o=n(9350),a=n(4848),s=n(8453);const i={title:"Cadence Community Spotlight Update - October 2022",date:new Date("2022-10-31T00:00:00.000Z"),authors:"sharanf",tags:["community-spotlight"]},c=void 0,r={authorsImageUrls:[void 0]},h=[{value:"Cadence Meetup Postponed",id:"cadence-meetup-postponed",level:2},{value:"Doordash Technnical Showcase Featuring Cadence",id:"doordash-technnical-showcase-featuring-cadence",level:2}];function d(e){const t={a:"a",h2:"h2",p:"p",...(0,s.R)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(t.p,{children:"Here\u2019s the latest in our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!"}),"\n",(0,a.jsx)(t.p,{children:"Please see below for a roundup of the highlights:"}),"\n",(0,a.jsx)(t.h2,{id:"cadence-meetup-postponed",children:"Cadence Meetup Postponed"}),"\n",(0,a.jsx)(t.p,{children:"It's always great to get the community together and we had planned to run another Cadence Meetup in early November. Unfortunately we didn't have enough time to get things organised so we've decided to postpone it. So please watch out for an announcement for the new Cadence meetup date."}),"\n",(0,a.jsx)(t.h2,{id:"doordash-technnical-showcase-featuring-cadence",children:"Doordash Technnical Showcase Featuring Cadence"}),"\n",(0,a.jsx)(t.p,{children:"We have had some great feedback from people who attended Technical Showcase that was run this month by Doordash. It featured their financial products but also highlighted some of the key technologies they use...and guess what Cadence is one of them!"}),"\n",(0,a.jsxs)(t.p,{children:["If you missed the session then you will be happy to know that it was recorded and we've inlcuded a link to the ",(0,a.jsx)(t.a,{href:"https://www.youtube.com/watch?v=uNwbdQyLpns",children:"the recording on Youtube"}),"."]}),"\n",(0,a.jsx)(t.p,{children:"Thanks to the Doordash team for running the session and helping support Cadence by sharing their knowledge."})]})}function l(e={}){const{wrapper:t}={...(0,s.R)(),...e.components};return t?(0,a.jsx)(t,{...e,children:(0,a.jsx)(d,{...e})}):d(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>i,x:()=>c});var o=n(6540);const a={},s=o.createContext(a);function i(e){const t=o.useContext(s);return o.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function c(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:i(e.components),o.createElement(s.Provider,{value:t},e.children)}},9350:e=>{e.exports=JSON.parse('{"permalink":"/Cadence-Docs/blog/2022/10/31/community-spotlight-october-2022","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2022-10-31-community-spotlight-october-2022.md","source":"@site/blog/2022-10-31-community-spotlight-october-2022.md","title":"Cadence Community Spotlight Update - October 2022","description":"Here\u2019s the latest in our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!","date":"2022-10-31T00:00:00.000Z","tags":[{"inline":false,"label":"Community Spotlight","permalink":"/Cadence-Docs/blog/tags/community-spotlights","description":"Community Spotlight tag description"}],"readingTime":1.93,"hasTruncateMarker":true,"authors":[{"name":"Sharan Foga","title":"Director of Operations & Customer Success @ Encube Technologies","url":"https://www.linkedin.com/in/sfoga/","page":{"permalink":"/Cadence-Docs/blog/authors/sharanf"},"socials":{"linkedin":"https://www.linkedin.com/in/sfoga/","github":"https://github.com/sharanf"},"imageURL":"https://github.com/sharanf.png","key":"sharanf"}],"frontMatter":{"title":"Cadence Community Spotlight Update - October 2022","date":"2022-10-31T00:00:00.000Z","authors":"sharanf","tags":["community-spotlight"]},"unlisted":false,"prevItem":{"title":"Cadence Community Spotlight Update - November 2022","permalink":"/Cadence-Docs/blog/2022/11/30/community-spotlight-november-2022"},"nextItem":{"title":"Cadence Community Spotlight Update - September 2022","permalink":"/Cadence-Docs/blog/2022/09/30/community-spotlight-september-2022"}}')}}]); \ No newline at end of file diff --git a/assets/js/dec4f520.fa5af0ec.js b/assets/js/dec4f520.fa5af0ec.js deleted file mode 100644 index 2d1760f57..000000000 --- a/assets/js/dec4f520.fa5af0ec.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[4898],{190:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>c,contentTitle:()=>r,default:()=>l,frontMatter:()=>s,metadata:()=>o,toc:()=>h});var o=n(9350),a=n(4848),i=n(8453);const s={title:"Cadence Community Spotlight Update - October 2022",date:new Date("2022-10-31T00:00:00.000Z"),authors:"sharanf",tags:["community-spotlight"]},r=void 0,c={authorsImageUrls:[void 0]},h=[{value:"Cadence Meetup Postponed",id:"cadence-meetup-postponed",level:2},{value:"Doordash Technnical Showcase Featuring Cadence",id:"doordash-technnical-showcase-featuring-cadence",level:2}];function d(e){const t={a:"a",h2:"h2",p:"p",...(0,i.R)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(t.p,{children:"Here\u2019s the latest in our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!"}),"\n",(0,a.jsx)(t.p,{children:"Please see below for a roundup of the highlights:"}),"\n",(0,a.jsx)(t.h2,{id:"cadence-meetup-postponed",children:"Cadence Meetup Postponed"}),"\n",(0,a.jsx)(t.p,{children:"It's always great to get the community together and we had planned to run another Cadence Meetup in early November. Unfortunately we didn't have enough time to get things organised so we've decided to postpone it. So please watch out for an announcement for the new Cadence meetup date."}),"\n",(0,a.jsx)(t.h2,{id:"doordash-technnical-showcase-featuring-cadence",children:"Doordash Technnical Showcase Featuring Cadence"}),"\n",(0,a.jsx)(t.p,{children:"We have had some great feedback from people who attended Technical Showcase that was run this month by Doordash. It featured their financial products but also highlighted some of the key technologies they use...and guess what Cadence is one of them!"}),"\n",(0,a.jsxs)(t.p,{children:["If you missed the session then you will be happy to know that it was recorded and we've inlcuded a link to the ",(0,a.jsx)(t.a,{href:"https://www.youtube.com/watch?v=uNwbdQyLpns",children:"the recording on Youtube"}),"."]}),"\n",(0,a.jsx)(t.p,{children:"Thanks to the Doordash team for running the session and helping support Cadence by sharing their knowledge."})]})}function l(e={}){const{wrapper:t}={...(0,i.R)(),...e.components};return t?(0,a.jsx)(t,{...e,children:(0,a.jsx)(d,{...e})}):d(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>s,x:()=>r});var o=n(6540);const a={},i=o.createContext(a);function s(e){const t=o.useContext(i);return o.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function r(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:s(e.components),o.createElement(i.Provider,{value:t},e.children)}},9350:e=>{e.exports=JSON.parse('{"permalink":"/blog/2022/10/31/community-spotlight-october-2022","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2022-10-31-community-spotlight-october-2022.md","source":"@site/blog/2022-10-31-community-spotlight-october-2022.md","title":"Cadence Community Spotlight Update - October 2022","description":"Here\u2019s the latest in our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!","date":"2022-10-31T00:00:00.000Z","tags":[{"inline":false,"label":"Community Spotlight","permalink":"/blog/tags/community-spotlights","description":"Community Spotlight tag description"}],"readingTime":1.93,"hasTruncateMarker":true,"authors":[{"name":"Sharan Foga","title":"Director of Operations & Customer Success @ Encube Technologies","url":"https://www.linkedin.com/in/sfoga/","page":{"permalink":"/blog/authors/sharanf"},"socials":{"linkedin":"https://www.linkedin.com/in/sfoga/","github":"https://github.com/sharanf"},"imageURL":"https://github.com/sharanf.png","key":"sharanf"}],"frontMatter":{"title":"Cadence Community Spotlight Update - October 2022","date":"2022-10-31T00:00:00.000Z","authors":"sharanf","tags":["community-spotlight"]},"unlisted":false,"prevItem":{"title":"Cadence Community Spotlight Update - November 2022","permalink":"/blog/2022/11/30/community-spotlight-november-2022"},"nextItem":{"title":"Cadence Community Spotlight Update - September 2022","permalink":"/blog/2022/09/30/community-spotlight-september-2022"}}')}}]); \ No newline at end of file diff --git a/assets/js/df4cf6e6.aff7098c.js b/assets/js/df4cf6e6.f027bd9e.js similarity index 68% rename from assets/js/df4cf6e6.aff7098c.js rename to assets/js/df4cf6e6.f027bd9e.js index 23a24dcfa..e22a54206 100644 --- a/assets/js/df4cf6e6.aff7098c.js +++ b/assets/js/df4cf6e6.f027bd9e.js @@ -1 +1 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[2379],{2652:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>c,contentTitle:()=>s,default:()=>d,frontMatter:()=>i,metadata:()=>o,toc:()=>l});var o=t(5432),a=t(4848),r=t(8453);const i={title:"Long-term commitment and support for the Cadence project, and its community",date:new Date("2021-09-30T00:00:00.000Z"),authors:"meiliang86",tags:["announcement"]},s=void 0,c={authorsImageUrls:[void 0]},l=[];function m(e){const n={a:"a",p:"p",strong:"strong",...(0,r.R)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(n.p,{children:"Dear valued Cadence users and developers,"}),"\n",(0,a.jsx)(n.p,{children:"Some of you might have read Temporal\u2019s recent announcement about their decision to drop the support for the Cadence project. This message caused some confusion in the community, so we would like to take this opportunity to clear things out."}),"\n",(0,a.jsxs)(n.p,{children:["First of all, ",(0,a.jsx)(n.strong,{children:"Uber is committed to the long-term success of the Cadence project"}),". Since its inception 5 years ago, use cases built on Cadence and their scale have grown significantly at Uber. Today, Cadence powers a variety of our most business-critical use cases (some public stories are available ",(0,a.jsx)(n.a,{href:"https://eng.uber.com/hadoop-container-blog/",children:"here"})," and ",(0,a.jsx)(n.a,{href:"https://eng.uber.com/meet-sao-paulo-tech/",children:"here"}),"). At the same time, the Cadence development team at Uber has enjoyed rapid growth with the product and has been driving innovations of workflow technology across the board, from new features (e.g. ",(0,a.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence/pulls?q=is%3Apr+graceful+failover",children:"graceful failover"}),", ",(0,a.jsx)(n.a,{href:"https://cadenceworkflow.io/docs/java-client/workflow-replay-shadowing/#workflow-replayer",children:"workflow shadowing"}),", ",(0,a.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence-web/commits/master",children:"UI improvements"}),") to better engineering foundations (e.g. ",(0,a.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence/pulls?q=is%3Apr+grpc",children:"gRPC support"}),", ",(0,a.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence/pulls?q=is%3Apr+label%3A%22cadence+multi-tenancy%22+",children:"multi-tenancy support"}),"), all in a backwards compatible manner. Neither Uber\u2019s use nor support of Cadence is going to change with Temporal\u2019s announcement. We have a long list of features and exciting roadmaps ahead of us, and we will share more details in our next meetup in November \u201821. As always we will continue to push the boundaries of scale and reliability as our usage within Uber grows."]})]})}function d(e={}){const{wrapper:n}={...(0,r.R)(),...e.components};return n?(0,a.jsx)(n,{...e,children:(0,a.jsx)(m,{...e})}):m(e)}},8453:(e,n,t)=>{t.d(n,{R:()=>i,x:()=>s});var o=t(6540);const a={},r=o.createContext(a);function i(e){const n=o.useContext(r);return o.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function s(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:i(e.components),o.createElement(r.Provider,{value:n},e.children)}},5432:e=>{e.exports=JSON.parse('{"permalink":"/blog/2021/09/30/long-term-commitment-and-support-for-the-cadence-project-and-its-community","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2021-09-30-long-term-commitment-and-support-for-the-cadence-project-and-its-community.md","source":"@site/blog/2021-09-30-long-term-commitment-and-support-for-the-cadence-project-and-its-community.md","title":"Long-term commitment and support for the Cadence project, and its community","description":"Dear valued Cadence users and developers,","date":"2021-09-30T00:00:00.000Z","tags":[{"inline":false,"label":"Announcement","permalink":"/blog/tags/announcements","description":"Announcement tag description"}],"readingTime":2.545,"hasTruncateMarker":true,"authors":[{"name":"Liang Mei","title":"Engineering Manager @ Uber","url":"https://www.linkedin.com/in/meiliang86/","page":{"permalink":"/blog/authors/meiliang-86"},"socials":{"linkedin":"https://www.linkedin.com/in/meiliang86/","github":"https://github.com/meiliang86"},"imageURL":"https://github.com/meiliang86.png","key":"meiliang86"}],"frontMatter":{"title":"Long-term commitment and support for the Cadence project, and its community","date":"2021-09-30T00:00:00.000Z","authors":"meiliang86","tags":["announcement"]},"unlisted":false,"prevItem":{"title":"Announcing Cadence OSS office hours and community sync up","permalink":"/blog/2021/10/13/announcing-cadence-oss-office-hours-and-community-sync-up"}}')}}]); \ No newline at end of file +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[2379],{2652:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>c,contentTitle:()=>s,default:()=>d,frontMatter:()=>i,metadata:()=>o,toc:()=>l});var o=t(5432),a=t(4848),r=t(8453);const i={title:"Long-term commitment and support for the Cadence project, and its community",date:new Date("2021-09-30T00:00:00.000Z"),authors:"meiliang86",tags:["announcement"]},s=void 0,c={authorsImageUrls:[void 0]},l=[];function m(e){const n={a:"a",p:"p",strong:"strong",...(0,r.R)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(n.p,{children:"Dear valued Cadence users and developers,"}),"\n",(0,a.jsx)(n.p,{children:"Some of you might have read Temporal\u2019s recent announcement about their decision to drop the support for the Cadence project. This message caused some confusion in the community, so we would like to take this opportunity to clear things out."}),"\n",(0,a.jsxs)(n.p,{children:["First of all, ",(0,a.jsx)(n.strong,{children:"Uber is committed to the long-term success of the Cadence project"}),". Since its inception 5 years ago, use cases built on Cadence and their scale have grown significantly at Uber. Today, Cadence powers a variety of our most business-critical use cases (some public stories are available ",(0,a.jsx)(n.a,{href:"https://eng.uber.com/hadoop-container-blog/",children:"here"})," and ",(0,a.jsx)(n.a,{href:"https://eng.uber.com/meet-sao-paulo-tech/",children:"here"}),"). At the same time, the Cadence development team at Uber has enjoyed rapid growth with the product and has been driving innovations of workflow technology across the board, from new features (e.g. ",(0,a.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence/pulls?q=is%3Apr+graceful+failover",children:"graceful failover"}),", ",(0,a.jsx)(n.a,{href:"https://cadenceworkflow.io/docs/java-client/workflow-replay-shadowing/#workflow-replayer",children:"workflow shadowing"}),", ",(0,a.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence-web/commits/master",children:"UI improvements"}),") to better engineering foundations (e.g. ",(0,a.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence/pulls?q=is%3Apr+grpc",children:"gRPC support"}),", ",(0,a.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence/pulls?q=is%3Apr+label%3A%22cadence+multi-tenancy%22+",children:"multi-tenancy support"}),"), all in a backwards compatible manner. Neither Uber\u2019s use nor support of Cadence is going to change with Temporal\u2019s announcement. We have a long list of features and exciting roadmaps ahead of us, and we will share more details in our next meetup in November \u201821. As always we will continue to push the boundaries of scale and reliability as our usage within Uber grows."]})]})}function d(e={}){const{wrapper:n}={...(0,r.R)(),...e.components};return n?(0,a.jsx)(n,{...e,children:(0,a.jsx)(m,{...e})}):m(e)}},8453:(e,n,t)=>{t.d(n,{R:()=>i,x:()=>s});var o=t(6540);const a={},r=o.createContext(a);function i(e){const n=o.useContext(r);return o.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function s(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:i(e.components),o.createElement(r.Provider,{value:n},e.children)}},5432:e=>{e.exports=JSON.parse('{"permalink":"/Cadence-Docs/blog/2021/09/30/long-term-commitment-and-support-for-the-cadence-project-and-its-community","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2021-09-30-long-term-commitment-and-support-for-the-cadence-project-and-its-community.md","source":"@site/blog/2021-09-30-long-term-commitment-and-support-for-the-cadence-project-and-its-community.md","title":"Long-term commitment and support for the Cadence project, and its community","description":"Dear valued Cadence users and developers,","date":"2021-09-30T00:00:00.000Z","tags":[{"inline":false,"label":"Announcement","permalink":"/Cadence-Docs/blog/tags/announcements","description":"Announcement tag description"}],"readingTime":2.545,"hasTruncateMarker":true,"authors":[{"name":"Liang Mei","title":"Engineering Manager @ Uber","url":"https://www.linkedin.com/in/meiliang86/","page":{"permalink":"/Cadence-Docs/blog/authors/meiliang-86"},"socials":{"linkedin":"https://www.linkedin.com/in/meiliang86/","github":"https://github.com/meiliang86"},"imageURL":"https://github.com/meiliang86.png","key":"meiliang86"}],"frontMatter":{"title":"Long-term commitment and support for the Cadence project, and its community","date":"2021-09-30T00:00:00.000Z","authors":"meiliang86","tags":["announcement"]},"unlisted":false,"prevItem":{"title":"Announcing Cadence OSS office hours and community sync up","permalink":"/Cadence-Docs/blog/2021/10/13/announcing-cadence-oss-office-hours-and-community-sync-up"}}')}}]); \ No newline at end of file diff --git a/assets/js/e1ea741a.8d1c0417.js b/assets/js/e1ea741a.8d1c0417.js deleted file mode 100644 index 6494ce868..000000000 --- a/assets/js/e1ea741a.8d1c0417.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[2192],{1612:(e,n,o)=>{o.r(n),o.d(n,{assets:()=>c,contentTitle:()=>a,default:()=>u,frontMatter:()=>l,metadata:()=>s,toc:()=>r});const s=JSON.parse('{"id":"use-cases/polling","title":"Polling","description":"Polling is executing a periodic action checking for a state change. Examples are pinging a host, calling a REST API, or listing an Amazon S3 bucket for newly uploaded files.","source":"@site/docs/02-use-cases/03-polling.md","sourceDirName":"02-use-cases","slug":"/use-cases/polling","permalink":"/docs/use-cases/polling","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/02-use-cases/03-polling.md","tags":[],"version":"current","sidebarPosition":3,"frontMatter":{"layout":"default","title":"Polling","permalink":"/docs/use-cases/polling"},"sidebar":"docsSidebar","previous":{"title":"Orchestration","permalink":"/docs/use-cases/orchestration"},"next":{"title":"Event driven application","permalink":"/docs/use-cases/event-driven"}}');var i=o(4848),t=o(8453);const l={layout:"default",title:"Polling",permalink:"/docs/use-cases/polling"},a="Polling",c={},r=[];function d(e){const n={a:"a",h1:"h1",header:"header",li:"li",p:"p",ul:"ul",...(0,t.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.header,{children:(0,i.jsx)(n.h1,{id:"polling",children:"Polling"})}),"\n",(0,i.jsx)(n.p,{children:"Polling is executing a periodic action checking for a state change. Examples are pinging a host, calling a REST API, or listing an Amazon S3 bucket for newly uploaded files."}),"\n",(0,i.jsx)(n.p,{children:"Cadence support for long running activities and unlimited retries makes it a good fit."}),"\n",(0,i.jsx)(n.p,{children:"Some real-world use cases:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"Network, host and service monitoring"}),"\n",(0,i.jsx)(n.li,{children:"Processing files uploaded to FTP or S3"}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"https://github.com/instaclustr/cadence-cookbooks-instafood/blob/main/cookbooks/polling/polling-megafood.md",children:"Cadence Polling Cookbook by Instaclustr: Polling an external API for a specific resource to become available: "})}),"\n"]})]})}function u(e={}){const{wrapper:n}={...(0,t.R)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(d,{...e})}):d(e)}},8453:(e,n,o)=>{o.d(n,{R:()=>l,x:()=>a});var s=o(6540);const i={},t=s.createContext(i);function l(e){const n=s.useContext(t);return s.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function a(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:l(e.components),s.createElement(t.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/e1ea741a.d6a99047.js b/assets/js/e1ea741a.d6a99047.js new file mode 100644 index 000000000..8f87ab947 --- /dev/null +++ b/assets/js/e1ea741a.d6a99047.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[2192],{1612:(e,n,o)=>{o.r(n),o.d(n,{assets:()=>c,contentTitle:()=>a,default:()=>u,frontMatter:()=>l,metadata:()=>s,toc:()=>r});const s=JSON.parse('{"id":"use-cases/polling","title":"Polling","description":"Polling is executing a periodic action checking for a state change. Examples are pinging a host, calling a REST API, or listing an Amazon S3 bucket for newly uploaded files.","source":"@site/docs/02-use-cases/03-polling.md","sourceDirName":"02-use-cases","slug":"/use-cases/polling","permalink":"/Cadence-Docs/docs/use-cases/polling","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/02-use-cases/03-polling.md","tags":[],"version":"current","sidebarPosition":3,"frontMatter":{"layout":"default","title":"Polling","permalink":"/docs/use-cases/polling"},"sidebar":"docsSidebar","previous":{"title":"Orchestration","permalink":"/Cadence-Docs/docs/use-cases/orchestration"},"next":{"title":"Event driven application","permalink":"/Cadence-Docs/docs/use-cases/event-driven"}}');var i=o(4848),t=o(8453);const l={layout:"default",title:"Polling",permalink:"/docs/use-cases/polling"},a="Polling",c={},r=[];function d(e){const n={a:"a",h1:"h1",header:"header",li:"li",p:"p",ul:"ul",...(0,t.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.header,{children:(0,i.jsx)(n.h1,{id:"polling",children:"Polling"})}),"\n",(0,i.jsx)(n.p,{children:"Polling is executing a periodic action checking for a state change. Examples are pinging a host, calling a REST API, or listing an Amazon S3 bucket for newly uploaded files."}),"\n",(0,i.jsx)(n.p,{children:"Cadence support for long running activities and unlimited retries makes it a good fit."}),"\n",(0,i.jsx)(n.p,{children:"Some real-world use cases:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"Network, host and service monitoring"}),"\n",(0,i.jsx)(n.li,{children:"Processing files uploaded to FTP or S3"}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"https://github.com/instaclustr/cadence-cookbooks-instafood/blob/main/cookbooks/polling/polling-megafood.md",children:"Cadence Polling Cookbook by Instaclustr: Polling an external API for a specific resource to become available: "})}),"\n"]})]})}function u(e={}){const{wrapper:n}={...(0,t.R)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(d,{...e})}):d(e)}},8453:(e,n,o)=>{o.d(n,{R:()=>l,x:()=>a});var s=o(6540);const i={},t=s.createContext(i);function l(e){const n=s.useContext(t);return s.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function a(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:l(e.components),s.createElement(t.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/e8018edf.083b7cba.js b/assets/js/e8018edf.083b7cba.js new file mode 100644 index 000000000..e97e1bea8 --- /dev/null +++ b/assets/js/e8018edf.083b7cba.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[2422],{3822:e=>{e.exports=JSON.parse('{"tag":{"label":"Cadence Operations","permalink":"/Cadence-Docs/blog/tags/cadence-operations","description":"Cadence Operations tag description","allTagsPath":"/Cadence-Docs/blog/tags","count":2,"unlisted":false},"listMetadata":{"permalink":"/Cadence-Docs/blog/tags/cadence-operations","page":1,"postsPerPage":10,"totalPages":1,"totalCount":2,"blogDescription":"The latest news and updates from the Cadence team","blogTitle":"Cadence Blog"}}')}}]); \ No newline at end of file diff --git a/assets/js/e8c8106b.8bfef7ff.js b/assets/js/e8c8106b.8bfef7ff.js deleted file mode 100644 index a032397a5..000000000 --- a/assets/js/e8c8106b.8bfef7ff.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[22],{2863:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>a,contentTitle:()=>c,default:()=>d,frontMatter:()=>s,metadata:()=>r,toc:()=>l});const r=JSON.parse('{"id":"go-client/queries","title":"Queries","description":"If a has been stuck at a state for longer than an expected period of time, you","source":"@site/docs/05-go-client/11-queries.md","sourceDirName":"05-go-client","slug":"/go-client/queries","permalink":"/docs/go-client/queries","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/05-go-client/11-queries.md","tags":[],"version":"current","sidebarPosition":11,"frontMatter":{"layout":"default","title":"Queries","permalink":"/docs/go-client/queries"},"sidebar":"docsSidebar","previous":{"title":"Side effect","permalink":"/docs/go-client/side-effect"},"next":{"title":"Async activity completion","permalink":"/docs/go-client/activity-async-completion"}}');var i=t(4848),o=t(8453);const s={layout:"default",title:"Queries",permalink:"/docs/go-client/queries"},c="Queries",a={},l=[{value:"Consistent Query",id:"consistent-query",level:2}];function u(e){const n={code:"code",h1:"h1",h2:"h2",header:"header",li:"li",ol:"ol",p:"p",pre:"pre",...(0,o.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.header,{children:(0,i.jsx)(n.h1,{id:"queries",children:"Queries"})}),"\n",(0,i.jsx)(n.p,{children:"If a workflow_execution has been stuck at a state for longer than an expected period of time, you\nmight want to query the current call stack. You can use the Cadence CLI to perform this query. For\nexample:"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.code,{children:"cadence-cli --domain samples-domain workflow query -w my_workflow_id -r my_run_id -qt __stack_trace"})}),"\n",(0,i.jsxs)(n.p,{children:["This command uses ",(0,i.jsx)(n.code,{children:"__stack_trace"}),", which is a built-in query type supported by the Cadence client\nlibrary. You can add custom query types to handle queries such as querying the current state of a\nworkflow, or querying how many activities the workflow has completed. To do this, you need to set\nup a query handler using ",(0,i.jsx)(n.code,{children:"workflow.SetQueryHandler"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"The handler must be a function that returns two values:"}),"\n",(0,i.jsxs)(n.ol,{children:["\n",(0,i.jsx)(n.li,{children:"A serializable result"}),"\n",(0,i.jsx)(n.li,{children:"An error"}),"\n"]}),"\n",(0,i.jsxs)(n.p,{children:["The handler function can receive any number of input parameters, but all input parameters must be\nserializable. The following sample code sets up a query handler that handles the query type of\n",(0,i.jsx)(n.code,{children:"current_state"}),":"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-go",children:'func MyWorkflow(ctx workflow.Context, input string) error {\n currentState := "started" // This could be any serializable struct.\n err := workflow.SetQueryHandler(ctx, "current_state", func() (string, error) {\n return currentState, nil\n })\n if err != nil {\n currentState = "failed to register query handler"\n return err\n }\n // Your normal workflow code begins here, and you update the currentState as the code makes progress.\n currentState = "waiting timer"\n err = NewTimer(ctx, time.Hour).Get(ctx, nil)\n if err != nil {\n currentState = "timer failed"\n return err\n }\n\n currentState = "waiting activity"\n ctx = WithActivityOptions(ctx, myActivityOptions)\n err = ExecuteActivity(ctx, MyActivity, "my_input").Get(ctx, nil)\n if err != nil {\n currentState = "activity failed"\n return err\n }\n currentState = "done"\n return nil\n}\n'})}),"\n",(0,i.jsxs)(n.p,{children:["You can now query ",(0,i.jsx)(n.code,{children:"current_state"})," by using the "]}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.code,{children:"cadence-cli --domain samples-domain workflow query -w my_workflow_id -r my_run_id -qt current_state"})}),"\n",(0,i.jsxs)(n.p,{children:["You can also issue a query from code using the ",(0,i.jsx)(n.code,{children:"QueryWorkflow()"})," API on a Cadence client object."]}),"\n",(0,i.jsx)(n.h2,{id:"consistent-query",children:"Consistent Query"}),"\n",(0,i.jsx)(n.p,{children:"Query has two consistency levels, eventual and strong. Consider if you were to signal a workflow and then\nimmediately query the "}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.code,{children:"cadence-cli --domain samples-domain workflow signal -w my_workflow_id -r my_run_id -n signal_name -if ./input.json"})}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.code,{children:"cadence-cli --domain samples-domain workflow query -w my_workflow_id -r my_run_id -qt current_state"})}),"\n",(0,i.jsx)(n.p,{children:"In this example if signal were to change workflow state, query may or may not see that state update reflected\nin the query result. This is what it means for query to be eventually consistent."}),"\n",(0,i.jsx)(n.p,{children:"Query has another consistency level called strong consistency. A strongly consistent query is guaranteed\nto be based on workflow state which includes all events that came before the query was issued. An event\nis considered to have come before a query if the call creating the external event returned success before\nthe query was issued. External events which are created while the query is outstanding may or may not\nbe reflected in the workflow state the query result is based on."}),"\n",(0,i.jsx)(n.p,{children:"In order to run consistent query through the CLI do the following:"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.code,{children:"cadence-cli --domain samples-domain workflow query -w my_workflow_id -r my_run_id -qt current_state --qcl strong"})}),"\n",(0,i.jsx)(n.p,{children:"In order to run a query using the go client do the following:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-go",children:"resp, err := cadenceClient.QueryWorkflowWithOptions(ctx, &client.QueryWorkflowWithOptionsRequest{\n WorkflowID: workflowID,\n RunID: runID,\n QueryType: queryType,\n QueryConsistencyLevel: shared.QueryConsistencyLevelStrong.Ptr(),\n})\n"})}),"\n",(0,i.jsx)(n.p,{children:"When using strongly consistent query you should expect higher latency than eventually consistent query."})]})}function d(e={}){const{wrapper:n}={...(0,o.R)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(u,{...e})}):u(e)}},8453:(e,n,t)=>{t.d(n,{R:()=>s,x:()=>c});var r=t(6540);const i={},o=r.createContext(i);function s(e){const n=r.useContext(o);return r.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function c(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:s(e.components),r.createElement(o.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/e8c8106b.e17be639.js b/assets/js/e8c8106b.e17be639.js new file mode 100644 index 000000000..2553ad69f --- /dev/null +++ b/assets/js/e8c8106b.e17be639.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[22],{2863:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>a,contentTitle:()=>c,default:()=>d,frontMatter:()=>s,metadata:()=>r,toc:()=>l});const r=JSON.parse('{"id":"go-client/queries","title":"Queries","description":"If a has been stuck at a state for longer than an expected period of time, you","source":"@site/docs/05-go-client/11-queries.md","sourceDirName":"05-go-client","slug":"/go-client/queries","permalink":"/Cadence-Docs/docs/go-client/queries","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/05-go-client/11-queries.md","tags":[],"version":"current","sidebarPosition":11,"frontMatter":{"layout":"default","title":"Queries","permalink":"/docs/go-client/queries"},"sidebar":"docsSidebar","previous":{"title":"Side effect","permalink":"/Cadence-Docs/docs/go-client/side-effect"},"next":{"title":"Async activity completion","permalink":"/Cadence-Docs/docs/go-client/activity-async-completion"}}');var i=t(4848),o=t(8453);const s={layout:"default",title:"Queries",permalink:"/docs/go-client/queries"},c="Queries",a={},l=[{value:"Consistent Query",id:"consistent-query",level:2}];function u(e){const n={code:"code",h1:"h1",h2:"h2",header:"header",li:"li",ol:"ol",p:"p",pre:"pre",...(0,o.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.header,{children:(0,i.jsx)(n.h1,{id:"queries",children:"Queries"})}),"\n",(0,i.jsx)(n.p,{children:"If a workflow_execution has been stuck at a state for longer than an expected period of time, you\nmight want to query the current call stack. You can use the Cadence CLI to perform this query. For\nexample:"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.code,{children:"cadence-cli --domain samples-domain workflow query -w my_workflow_id -r my_run_id -qt __stack_trace"})}),"\n",(0,i.jsxs)(n.p,{children:["This command uses ",(0,i.jsx)(n.code,{children:"__stack_trace"}),", which is a built-in query type supported by the Cadence client\nlibrary. You can add custom query types to handle queries such as querying the current state of a\nworkflow, or querying how many activities the workflow has completed. To do this, you need to set\nup a query handler using ",(0,i.jsx)(n.code,{children:"workflow.SetQueryHandler"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"The handler must be a function that returns two values:"}),"\n",(0,i.jsxs)(n.ol,{children:["\n",(0,i.jsx)(n.li,{children:"A serializable result"}),"\n",(0,i.jsx)(n.li,{children:"An error"}),"\n"]}),"\n",(0,i.jsxs)(n.p,{children:["The handler function can receive any number of input parameters, but all input parameters must be\nserializable. The following sample code sets up a query handler that handles the query type of\n",(0,i.jsx)(n.code,{children:"current_state"}),":"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-go",children:'func MyWorkflow(ctx workflow.Context, input string) error {\n currentState := "started" // This could be any serializable struct.\n err := workflow.SetQueryHandler(ctx, "current_state", func() (string, error) {\n return currentState, nil\n })\n if err != nil {\n currentState = "failed to register query handler"\n return err\n }\n // Your normal workflow code begins here, and you update the currentState as the code makes progress.\n currentState = "waiting timer"\n err = NewTimer(ctx, time.Hour).Get(ctx, nil)\n if err != nil {\n currentState = "timer failed"\n return err\n }\n\n currentState = "waiting activity"\n ctx = WithActivityOptions(ctx, myActivityOptions)\n err = ExecuteActivity(ctx, MyActivity, "my_input").Get(ctx, nil)\n if err != nil {\n currentState = "activity failed"\n return err\n }\n currentState = "done"\n return nil\n}\n'})}),"\n",(0,i.jsxs)(n.p,{children:["You can now query ",(0,i.jsx)(n.code,{children:"current_state"})," by using the "]}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.code,{children:"cadence-cli --domain samples-domain workflow query -w my_workflow_id -r my_run_id -qt current_state"})}),"\n",(0,i.jsxs)(n.p,{children:["You can also issue a query from code using the ",(0,i.jsx)(n.code,{children:"QueryWorkflow()"})," API on a Cadence client object."]}),"\n",(0,i.jsx)(n.h2,{id:"consistent-query",children:"Consistent Query"}),"\n",(0,i.jsx)(n.p,{children:"Query has two consistency levels, eventual and strong. Consider if you were to signal a workflow and then\nimmediately query the "}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.code,{children:"cadence-cli --domain samples-domain workflow signal -w my_workflow_id -r my_run_id -n signal_name -if ./input.json"})}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.code,{children:"cadence-cli --domain samples-domain workflow query -w my_workflow_id -r my_run_id -qt current_state"})}),"\n",(0,i.jsx)(n.p,{children:"In this example if signal were to change workflow state, query may or may not see that state update reflected\nin the query result. This is what it means for query to be eventually consistent."}),"\n",(0,i.jsx)(n.p,{children:"Query has another consistency level called strong consistency. A strongly consistent query is guaranteed\nto be based on workflow state which includes all events that came before the query was issued. An event\nis considered to have come before a query if the call creating the external event returned success before\nthe query was issued. External events which are created while the query is outstanding may or may not\nbe reflected in the workflow state the query result is based on."}),"\n",(0,i.jsx)(n.p,{children:"In order to run consistent query through the CLI do the following:"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.code,{children:"cadence-cli --domain samples-domain workflow query -w my_workflow_id -r my_run_id -qt current_state --qcl strong"})}),"\n",(0,i.jsx)(n.p,{children:"In order to run a query using the go client do the following:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-go",children:"resp, err := cadenceClient.QueryWorkflowWithOptions(ctx, &client.QueryWorkflowWithOptionsRequest{\n WorkflowID: workflowID,\n RunID: runID,\n QueryType: queryType,\n QueryConsistencyLevel: shared.QueryConsistencyLevelStrong.Ptr(),\n})\n"})}),"\n",(0,i.jsx)(n.p,{children:"When using strongly consistent query you should expect higher latency than eventually consistent query."})]})}function d(e={}){const{wrapper:n}={...(0,o.R)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(u,{...e})}):u(e)}},8453:(e,n,t)=>{t.d(n,{R:()=>s,x:()=>c});var r=t(6540);const i={},o=r.createContext(i);function s(e){const n=r.useContext(o);return r.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function c(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:s(e.components),r.createElement(o.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/e9c26ae5.68917989.js b/assets/js/e9c26ae5.e33a84c2.js similarity index 71% rename from assets/js/e9c26ae5.68917989.js rename to assets/js/e9c26ae5.e33a84c2.js index 838aaa55c..337e9b30f 100644 --- a/assets/js/e9c26ae5.68917989.js +++ b/assets/js/e9c26ae5.e33a84c2.js @@ -1 +1 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[8631],{5726:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>c,contentTitle:()=>s,default:()=>d,frontMatter:()=>r,metadata:()=>i,toc:()=>l});var i=t(5386),a=t(4848),o=t(8453);const r={title:"Cadence Community Spotlight Update - November 2022",date:new Date("2022-11-30T00:00:00.000Z"),authors:"sharanf",tags:["community-spotlight"]},s=void 0,c={authorsImageUrls:[void 0]},l=[{value:"Cadence @ Uber",id:"cadence--uber",level:2},{value:"Cadence @ DeveloperWeek Enterprise",id:"cadence--developerweek-enterprise",level:2},{value:"Cadence at W-JAX",id:"cadence-at-w-jax",level:2},{value:"Cadence in the News!",id:"cadence-in-the-news",level:2},{value:"Upcoming Events",id:"upcoming-events",level:2}];function h(e){const n={a:"a",h2:"h2",li:"li",p:"p",strong:"strong",ul:"ul",...(0,o.R)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(n.p,{children:"Here\u2019s the latest in our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!"}),"\n",(0,a.jsx)(n.p,{children:"Please see below for a roundup of the highlights:"}),"\n",(0,a.jsx)(n.h2,{id:"cadence--uber",children:"Cadence @ Uber"}),"\n",(0,a.jsxs)(n.p,{children:["This month Uber Engineering published a really nice article on one of the ways they are using Cadence. The article is called ",(0,a.jsx)(n.a,{href:"https://www.uber.com/en-US/blog/how-uber-optimizes-push-notifications-using-ml/",children:"How Uber Optimizes the Timing of Push Notifications using ML and Linear Programming"}),"."]}),"\n",(0,a.jsx)(n.p,{children:"The Uber team take you through the details of the problem that they are looking to solve, so you can understand the scope limitations and depedencies - so please take a look."}),"\n",(0,a.jsx)(n.h2,{id:"cadence--developerweek-enterprise",children:"Cadence @ DeveloperWeek Enterprise"}),"\n",(0,a.jsxs)(n.p,{children:["DevNetwork run a series of conferences and during November Cadence was featured in at ",(0,a.jsx)(n.a,{href:"https://www.developerweek.com/global/conference/enterprise/",children:"DeveloperWeek Enterprise"}),". ",(0,a.jsx)(n.a,{href:"https://www.linkedin.com/in/enderdemirkaya/",children:"Ender Demirkaya"})," and ",(0,a.jsx)(n.a,{href:"https://www.linkedin.com/in/ben-slater-2720562/",children:"Ben Slater"})," presented a talk called ",(0,a.jsx)(n.a,{href:"https://embed.emamo.com/event/developerweek-enterprise-2022/s/express-complex-business-logic-as-code-with-open-source-cadence-WKLMvo",children:"Espress Complex Business Logic as Code with Open Source Cadence!"}),"."]}),"\n",(0,a.jsx)(n.p,{children:"It is good to see that we are finding new channels for us to present the benefits of using Cadence. Huge hanks to Ben and Ender for the presentation and to everyone that attended."}),"\n",(0,a.jsx)(n.h2,{id:"cadence-at-w-jax",children:"Cadence at W-JAX"}),"\n",(0,a.jsxs)(n.p,{children:["It must be presentation month as we have had yet another Cadence presentation! Earlier this month a Cadence talk was featured at the ",(0,a.jsx)(n.a,{href:"https://jax.de/munich/",children:"W-JAX Conference"})," in Munich, Germany. ",(0,a.jsx)(n.a,{href:"https://www.linkedin.com/in/merlin-walter/",children:"Merlin Walter"})," presented a talk called ",(0,a.jsx)(n.a,{href:"https://jax.de/microservices/microservices-modern-orchestration-approach-with-cadence/",children:"Microservices - Modern Orchestration with Cadence"})]}),"\n",(0,a.jsx)(n.p,{children:"Session feedback received was very positive and it's great to see that new audiences are interested in learning more about Cadence and seeing how it works."}),"\n",(0,a.jsx)(n.h2,{id:"cadence-in-the-news",children:"Cadence in the News!"}),"\n",(0,a.jsx)(n.p,{children:"Below are a selection of Cadence related articles, blogs and whitepapers. Please take a look and feel free to share via your own social media channels."}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsxs)(n.li,{children:["\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.a,{href:"https://www.uber.com/en-US/blog/how-uber-optimizes-push-notifications-using-ml/",children:"How Uber Optimizes the Timing of Push Notifications using ML and Linear Programming"})}),"\n"]}),"\n",(0,a.jsxs)(n.li,{children:["\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.a,{href:"https://www.instaclustr.com/blog/building-with-cadence-quantifiable-efficiency/",children:"Building with Cadence: Quantifiable Efficiency"})}),"\n"]}),"\n"]}),"\n",(0,a.jsx)(n.h2,{id:"upcoming-events",children:"Upcoming Events"}),"\n",(0,a.jsxs)(n.p,{children:[(0,a.jsx)(n.strong,{children:"PLEASE NOTE:"})," No Office Hours on 26th December 2022"]}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsx)(n.li,{children:(0,a.jsx)(n.a,{href:"https://calendar.google.com/calendar/u/0/embed?src=e6r40gp3c2r01054id7e99dlac@group.calendar.google.com&ctz=America/Los_Angeles",children:"Cadence Technical Office Hours - 30th January 2023 @ 9am PT"})}),"\n"]}),"\n",(0,a.jsxs)(n.p,{children:["If you have any news or topics you'd like us to include in our next update then please join our ",(0,a.jsx)(n.a,{href:"http://t.uber.com/cadence-slack",children:"Slack"}),"#community channel."]}),"\n",(0,a.jsxs)(n.p,{children:["Please remember that this update is for you - so if you have any comments or feedback that could help us improve it then please share it with us in the #community ",(0,a.jsx)(n.a,{href:"http://t.uber.com/cadence-slack",children:"Slack"})," channel."]})]})}function d(e={}){const{wrapper:n}={...(0,o.R)(),...e.components};return n?(0,a.jsx)(n,{...e,children:(0,a.jsx)(h,{...e})}):h(e)}},8453:(e,n,t)=>{t.d(n,{R:()=>r,x:()=>s});var i=t(6540);const a={},o=i.createContext(a);function r(e){const n=i.useContext(o);return i.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function s(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:r(e.components),i.createElement(o.Provider,{value:n},e.children)}},5386:e=>{e.exports=JSON.parse('{"permalink":"/blog/2022/11/30/community-spotlight-november-2022","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2022-11-30-community-spotlight-november-2022.md","source":"@site/blog/2022-11-30-community-spotlight-november-2022.md","title":"Cadence Community Spotlight Update - November 2022","description":"Here\u2019s the latest in our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!","date":"2022-11-30T00:00:00.000Z","tags":[{"inline":false,"label":"Community Spotlight","permalink":"/blog/tags/community-spotlights","description":"Community Spotlight tag description"}],"readingTime":1.91,"hasTruncateMarker":true,"authors":[{"name":"Sharan Foga","title":"Director of Operations & Customer Success @ Encube Technologies","url":"https://www.linkedin.com/in/sfoga/","page":{"permalink":"/blog/authors/sharanf"},"socials":{"linkedin":"https://www.linkedin.com/in/sfoga/","github":"https://github.com/sharanf"},"imageURL":"https://github.com/sharanf.png","key":"sharanf"}],"frontMatter":{"title":"Cadence Community Spotlight Update - November 2022","date":"2022-11-30T00:00:00.000Z","authors":"sharanf","tags":["community-spotlight"]},"unlisted":false,"prevItem":{"title":"Cadence Community Spotlight Update - December 2022","permalink":"/blog/2022/12/23/community-spotlight-december-2022"},"nextItem":{"title":"Cadence Community Spotlight Update - October 2022","permalink":"/blog/2022/10/31/community-spotlight-october-2022"}}')}}]); \ No newline at end of file +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[8631],{5726:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>c,contentTitle:()=>r,default:()=>h,frontMatter:()=>s,metadata:()=>i,toc:()=>l});var i=t(5386),a=t(4848),o=t(8453);const s={title:"Cadence Community Spotlight Update - November 2022",date:new Date("2022-11-30T00:00:00.000Z"),authors:"sharanf",tags:["community-spotlight"]},r=void 0,c={authorsImageUrls:[void 0]},l=[{value:"Cadence @ Uber",id:"cadence--uber",level:2},{value:"Cadence @ DeveloperWeek Enterprise",id:"cadence--developerweek-enterprise",level:2},{value:"Cadence at W-JAX",id:"cadence-at-w-jax",level:2},{value:"Cadence in the News!",id:"cadence-in-the-news",level:2},{value:"Upcoming Events",id:"upcoming-events",level:2}];function d(e){const n={a:"a",h2:"h2",li:"li",p:"p",strong:"strong",ul:"ul",...(0,o.R)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(n.p,{children:"Here\u2019s the latest in our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!"}),"\n",(0,a.jsx)(n.p,{children:"Please see below for a roundup of the highlights:"}),"\n",(0,a.jsx)(n.h2,{id:"cadence--uber",children:"Cadence @ Uber"}),"\n",(0,a.jsxs)(n.p,{children:["This month Uber Engineering published a really nice article on one of the ways they are using Cadence. The article is called ",(0,a.jsx)(n.a,{href:"https://www.uber.com/en-US/blog/how-uber-optimizes-push-notifications-using-ml/",children:"How Uber Optimizes the Timing of Push Notifications using ML and Linear Programming"}),"."]}),"\n",(0,a.jsx)(n.p,{children:"The Uber team take you through the details of the problem that they are looking to solve, so you can understand the scope limitations and depedencies - so please take a look."}),"\n",(0,a.jsx)(n.h2,{id:"cadence--developerweek-enterprise",children:"Cadence @ DeveloperWeek Enterprise"}),"\n",(0,a.jsxs)(n.p,{children:["DevNetwork run a series of conferences and during November Cadence was featured in at ",(0,a.jsx)(n.a,{href:"https://www.developerweek.com/global/conference/enterprise/",children:"DeveloperWeek Enterprise"}),". ",(0,a.jsx)(n.a,{href:"https://www.linkedin.com/in/enderdemirkaya/",children:"Ender Demirkaya"})," and ",(0,a.jsx)(n.a,{href:"https://www.linkedin.com/in/ben-slater-2720562/",children:"Ben Slater"})," presented a talk called ",(0,a.jsx)(n.a,{href:"https://embed.emamo.com/event/developerweek-enterprise-2022/s/express-complex-business-logic-as-code-with-open-source-cadence-WKLMvo",children:"Espress Complex Business Logic as Code with Open Source Cadence!"}),"."]}),"\n",(0,a.jsx)(n.p,{children:"It is good to see that we are finding new channels for us to present the benefits of using Cadence. Huge hanks to Ben and Ender for the presentation and to everyone that attended."}),"\n",(0,a.jsx)(n.h2,{id:"cadence-at-w-jax",children:"Cadence at W-JAX"}),"\n",(0,a.jsxs)(n.p,{children:["It must be presentation month as we have had yet another Cadence presentation! Earlier this month a Cadence talk was featured at the ",(0,a.jsx)(n.a,{href:"https://jax.de/munich/",children:"W-JAX Conference"})," in Munich, Germany. ",(0,a.jsx)(n.a,{href:"https://www.linkedin.com/in/merlin-walter/",children:"Merlin Walter"})," presented a talk called ",(0,a.jsx)(n.a,{href:"https://jax.de/microservices/microservices-modern-orchestration-approach-with-cadence/",children:"Microservices - Modern Orchestration with Cadence"})]}),"\n",(0,a.jsx)(n.p,{children:"Session feedback received was very positive and it's great to see that new audiences are interested in learning more about Cadence and seeing how it works."}),"\n",(0,a.jsx)(n.h2,{id:"cadence-in-the-news",children:"Cadence in the News!"}),"\n",(0,a.jsx)(n.p,{children:"Below are a selection of Cadence related articles, blogs and whitepapers. Please take a look and feel free to share via your own social media channels."}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsxs)(n.li,{children:["\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.a,{href:"https://www.uber.com/en-US/blog/how-uber-optimizes-push-notifications-using-ml/",children:"How Uber Optimizes the Timing of Push Notifications using ML and Linear Programming"})}),"\n"]}),"\n",(0,a.jsxs)(n.li,{children:["\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.a,{href:"https://www.instaclustr.com/blog/building-with-cadence-quantifiable-efficiency/",children:"Building with Cadence: Quantifiable Efficiency"})}),"\n"]}),"\n"]}),"\n",(0,a.jsx)(n.h2,{id:"upcoming-events",children:"Upcoming Events"}),"\n",(0,a.jsxs)(n.p,{children:[(0,a.jsx)(n.strong,{children:"PLEASE NOTE:"})," No Office Hours on 26th December 2022"]}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsx)(n.li,{children:(0,a.jsx)(n.a,{href:"https://calendar.google.com/calendar/u/0/embed?src=e6r40gp3c2r01054id7e99dlac@group.calendar.google.com&ctz=America/Los_Angeles",children:"Cadence Technical Office Hours - 30th January 2023 @ 9am PT"})}),"\n"]}),"\n",(0,a.jsxs)(n.p,{children:["If you have any news or topics you'd like us to include in our next update then please join our ",(0,a.jsx)(n.a,{href:"http://t.uber.com/cadence-slack",children:"Slack"}),"#community channel."]}),"\n",(0,a.jsxs)(n.p,{children:["Please remember that this update is for you - so if you have any comments or feedback that could help us improve it then please share it with us in the #community ",(0,a.jsx)(n.a,{href:"http://t.uber.com/cadence-slack",children:"Slack"})," channel."]})]})}function h(e={}){const{wrapper:n}={...(0,o.R)(),...e.components};return n?(0,a.jsx)(n,{...e,children:(0,a.jsx)(d,{...e})}):d(e)}},8453:(e,n,t)=>{t.d(n,{R:()=>s,x:()=>r});var i=t(6540);const a={},o=i.createContext(a);function s(e){const n=i.useContext(o);return i.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function r(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:s(e.components),i.createElement(o.Provider,{value:n},e.children)}},5386:e=>{e.exports=JSON.parse('{"permalink":"/Cadence-Docs/blog/2022/11/30/community-spotlight-november-2022","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2022-11-30-community-spotlight-november-2022.md","source":"@site/blog/2022-11-30-community-spotlight-november-2022.md","title":"Cadence Community Spotlight Update - November 2022","description":"Here\u2019s the latest in our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!","date":"2022-11-30T00:00:00.000Z","tags":[{"inline":false,"label":"Community Spotlight","permalink":"/Cadence-Docs/blog/tags/community-spotlights","description":"Community Spotlight tag description"}],"readingTime":1.91,"hasTruncateMarker":true,"authors":[{"name":"Sharan Foga","title":"Director of Operations & Customer Success @ Encube Technologies","url":"https://www.linkedin.com/in/sfoga/","page":{"permalink":"/Cadence-Docs/blog/authors/sharanf"},"socials":{"linkedin":"https://www.linkedin.com/in/sfoga/","github":"https://github.com/sharanf"},"imageURL":"https://github.com/sharanf.png","key":"sharanf"}],"frontMatter":{"title":"Cadence Community Spotlight Update - November 2022","date":"2022-11-30T00:00:00.000Z","authors":"sharanf","tags":["community-spotlight"]},"unlisted":false,"prevItem":{"title":"Cadence Community Spotlight Update - December 2022","permalink":"/Cadence-Docs/blog/2022/12/23/community-spotlight-december-2022"},"nextItem":{"title":"Cadence Community Spotlight Update - October 2022","permalink":"/Cadence-Docs/blog/2022/10/31/community-spotlight-october-2022"}}')}}]); \ No newline at end of file diff --git a/assets/js/ea1e4697.dc7eff37.js b/assets/js/ea1e4697.fbfecff3.js similarity index 73% rename from assets/js/ea1e4697.dc7eff37.js rename to assets/js/ea1e4697.fbfecff3.js index 5ff1875b8..eb1f502bb 100644 --- a/assets/js/ea1e4697.dc7eff37.js +++ b/assets/js/ea1e4697.fbfecff3.js @@ -1 +1 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[9617],{8442:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>c,contentTitle:()=>r,default:()=>d,frontMatter:()=>s,metadata:()=>o,toc:()=>h});var o=t(9350),a=t(4848),i=t(8453);const s={title:"Cadence Community Spotlight Update - October 2022",date:new Date("2022-10-31T00:00:00.000Z"),authors:"sharanf",tags:["community-spotlight"]},r=void 0,c={authorsImageUrls:[void 0]},h=[{value:"Cadence Meetup Postponed",id:"cadence-meetup-postponed",level:2},{value:"Doordash Technnical Showcase Featuring Cadence",id:"doordash-technnical-showcase-featuring-cadence",level:2},{value:"iWF Support for Cadence",id:"iwf-support-for-cadence",level:2},{value:"Cadence in the News!",id:"cadence-in-the-news",level:2},{value:"Upcoming Events",id:"upcoming-events",level:2}];function l(e){const n={a:"a",h2:"h2",li:"li",p:"p",ul:"ul",...(0,i.R)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(n.p,{children:"Here\u2019s the latest in our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!"}),"\n",(0,a.jsx)(n.p,{children:"Please see below for a roundup of the highlights:"}),"\n",(0,a.jsx)(n.h2,{id:"cadence-meetup-postponed",children:"Cadence Meetup Postponed"}),"\n",(0,a.jsx)(n.p,{children:"It's always great to get the community together and we had planned to run another Cadence Meetup in early November. Unfortunately we didn't have enough time to get things organised so we've decided to postpone it. So please watch out for an announcement for the new Cadence meetup date."}),"\n",(0,a.jsx)(n.h2,{id:"doordash-technnical-showcase-featuring-cadence",children:"Doordash Technnical Showcase Featuring Cadence"}),"\n",(0,a.jsx)(n.p,{children:"We have had some great feedback from people who attended Technical Showcase that was run this month by Doordash. It featured their financial products but also highlighted some of the key technologies they use...and guess what Cadence is one of them!"}),"\n",(0,a.jsxs)(n.p,{children:["If you missed the session then you will be happy to know that it was recorded and we've inlcuded a link to the ",(0,a.jsx)(n.a,{href:"https://www.youtube.com/watch?v=uNwbdQyLpns",children:"the recording on Youtube"}),"."]}),"\n",(0,a.jsx)(n.p,{children:"Thanks to the Doordash team for running the session and helping support Cadence by sharing their knowledge."}),"\n",(0,a.jsx)(n.h2,{id:"iwf-support-for-cadence",children:"iWF Support for Cadence"}),"\n",(0,a.jsxs)(n.p,{children:["Community member ",(0,a.jsx)(n.a,{href:"https://www.linkedin.com/in/prclqz/",children:"Quanzheng Long"})," has been busy working on a new project that has been built on top of Cadence. The project is called ",(0,a.jsx)(n.a,{href:"https://github.com/indeedeng/iwf",children:"iWF - Interpreter for Workflow"}),". It's great to see that Cadence is now growing it's own ecosystem!"]}),"\n",(0,a.jsx)(n.p,{children:"Please feel free to take a look and let Long know what you think!"}),"\n",(0,a.jsx)(n.h2,{id:"cadence-in-the-news",children:"Cadence in the News!"}),"\n",(0,a.jsx)(n.p,{children:"Below are a selection of Cadence related articles, blogs and whitepapers. Please take a look and feel free to share via your own social media channels."}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsxs)(n.li,{children:["\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.a,{href:"https://www.instaclustr.com/blog/airflow-vs-cadence-a-side-to-side-comparison/",children:"Apache Airflow vs Cadence: A Side by Side Comparison"})}),"\n"]}),"\n",(0,a.jsxs)(n.li,{children:["\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.a,{href:"https://www.instaclustr.com/blog/managing-custom-search-attributes-for-advanced-visibility-cadence/",children:"Managing Custom Search Attributes for Advance Visibility Cadence"})}),"\n"]}),"\n"]}),"\n",(0,a.jsx)(n.h2,{id:"upcoming-events",children:"Upcoming Events"}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsxs)(n.li,{children:["\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.a,{href:"https://info.instaclustr.com/webinar-spinning-drones-cadence-kafka.html",children:"Webinar: Spinning Your Drones with Cadence and Apache Kafka - 15th November 2022"})}),"\n"]}),"\n",(0,a.jsxs)(n.li,{children:["\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.a,{href:"https://info.instaclustr.com/webinar-emea-fitting-cadence.html",children:"Webinar: Fitting Cadence in Your Corporate Architecture - 24th November 2022"})}),"\n"]}),"\n",(0,a.jsxs)(n.li,{children:["\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.a,{href:"https://calendar.google.com/calendar/u/0/embed?src=e6r40gp3c2r01054id7e99dlac@group.calendar.google.com&ctz=America/Los_Angeles",children:"Cadence Technical Office Hours - 28th November 2022 @ 9am PT"})}),"\n"]}),"\n"]}),"\n",(0,a.jsxs)(n.p,{children:["If you have any news or topics you'd like us to include in our next update then please join our ",(0,a.jsx)(n.a,{href:"http://t.uber.com/cadence-slack",children:"Slack"}),"#community channel."]}),"\n",(0,a.jsxs)(n.p,{children:["Please remember that this update is for you - so if you have any comments or feedback that could help us improve it then please share it with us in the #community ",(0,a.jsx)(n.a,{href:"http://t.uber.com/cadence-slack",children:"Slack"})," channel."]})]})}function d(e={}){const{wrapper:n}={...(0,i.R)(),...e.components};return n?(0,a.jsx)(n,{...e,children:(0,a.jsx)(l,{...e})}):l(e)}},8453:(e,n,t)=>{t.d(n,{R:()=>s,x:()=>r});var o=t(6540);const a={},i=o.createContext(a);function s(e){const n=o.useContext(i);return o.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function r(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:s(e.components),o.createElement(i.Provider,{value:n},e.children)}},9350:e=>{e.exports=JSON.parse('{"permalink":"/blog/2022/10/31/community-spotlight-october-2022","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2022-10-31-community-spotlight-october-2022.md","source":"@site/blog/2022-10-31-community-spotlight-october-2022.md","title":"Cadence Community Spotlight Update - October 2022","description":"Here\u2019s the latest in our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!","date":"2022-10-31T00:00:00.000Z","tags":[{"inline":false,"label":"Community Spotlight","permalink":"/blog/tags/community-spotlights","description":"Community Spotlight tag description"}],"readingTime":1.93,"hasTruncateMarker":true,"authors":[{"name":"Sharan Foga","title":"Director of Operations & Customer Success @ Encube Technologies","url":"https://www.linkedin.com/in/sfoga/","page":{"permalink":"/blog/authors/sharanf"},"socials":{"linkedin":"https://www.linkedin.com/in/sfoga/","github":"https://github.com/sharanf"},"imageURL":"https://github.com/sharanf.png","key":"sharanf"}],"frontMatter":{"title":"Cadence Community Spotlight Update - October 2022","date":"2022-10-31T00:00:00.000Z","authors":"sharanf","tags":["community-spotlight"]},"unlisted":false,"prevItem":{"title":"Cadence Community Spotlight Update - November 2022","permalink":"/blog/2022/11/30/community-spotlight-november-2022"},"nextItem":{"title":"Cadence Community Spotlight Update - September 2022","permalink":"/blog/2022/09/30/community-spotlight-september-2022"}}')}}]); \ No newline at end of file +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[9617],{8442:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>r,contentTitle:()=>c,default:()=>d,frontMatter:()=>s,metadata:()=>o,toc:()=>h});var o=t(9350),a=t(4848),i=t(8453);const s={title:"Cadence Community Spotlight Update - October 2022",date:new Date("2022-10-31T00:00:00.000Z"),authors:"sharanf",tags:["community-spotlight"]},c=void 0,r={authorsImageUrls:[void 0]},h=[{value:"Cadence Meetup Postponed",id:"cadence-meetup-postponed",level:2},{value:"Doordash Technnical Showcase Featuring Cadence",id:"doordash-technnical-showcase-featuring-cadence",level:2},{value:"iWF Support for Cadence",id:"iwf-support-for-cadence",level:2},{value:"Cadence in the News!",id:"cadence-in-the-news",level:2},{value:"Upcoming Events",id:"upcoming-events",level:2}];function l(e){const n={a:"a",h2:"h2",li:"li",p:"p",ul:"ul",...(0,i.R)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(n.p,{children:"Here\u2019s the latest in our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!"}),"\n",(0,a.jsx)(n.p,{children:"Please see below for a roundup of the highlights:"}),"\n",(0,a.jsx)(n.h2,{id:"cadence-meetup-postponed",children:"Cadence Meetup Postponed"}),"\n",(0,a.jsx)(n.p,{children:"It's always great to get the community together and we had planned to run another Cadence Meetup in early November. Unfortunately we didn't have enough time to get things organised so we've decided to postpone it. So please watch out for an announcement for the new Cadence meetup date."}),"\n",(0,a.jsx)(n.h2,{id:"doordash-technnical-showcase-featuring-cadence",children:"Doordash Technnical Showcase Featuring Cadence"}),"\n",(0,a.jsx)(n.p,{children:"We have had some great feedback from people who attended Technical Showcase that was run this month by Doordash. It featured their financial products but also highlighted some of the key technologies they use...and guess what Cadence is one of them!"}),"\n",(0,a.jsxs)(n.p,{children:["If you missed the session then you will be happy to know that it was recorded and we've inlcuded a link to the ",(0,a.jsx)(n.a,{href:"https://www.youtube.com/watch?v=uNwbdQyLpns",children:"the recording on Youtube"}),"."]}),"\n",(0,a.jsx)(n.p,{children:"Thanks to the Doordash team for running the session and helping support Cadence by sharing their knowledge."}),"\n",(0,a.jsx)(n.h2,{id:"iwf-support-for-cadence",children:"iWF Support for Cadence"}),"\n",(0,a.jsxs)(n.p,{children:["Community member ",(0,a.jsx)(n.a,{href:"https://www.linkedin.com/in/prclqz/",children:"Quanzheng Long"})," has been busy working on a new project that has been built on top of Cadence. The project is called ",(0,a.jsx)(n.a,{href:"https://github.com/indeedeng/iwf",children:"iWF - Interpreter for Workflow"}),". It's great to see that Cadence is now growing it's own ecosystem!"]}),"\n",(0,a.jsx)(n.p,{children:"Please feel free to take a look and let Long know what you think!"}),"\n",(0,a.jsx)(n.h2,{id:"cadence-in-the-news",children:"Cadence in the News!"}),"\n",(0,a.jsx)(n.p,{children:"Below are a selection of Cadence related articles, blogs and whitepapers. Please take a look and feel free to share via your own social media channels."}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsxs)(n.li,{children:["\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.a,{href:"https://www.instaclustr.com/blog/airflow-vs-cadence-a-side-to-side-comparison/",children:"Apache Airflow vs Cadence: A Side by Side Comparison"})}),"\n"]}),"\n",(0,a.jsxs)(n.li,{children:["\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.a,{href:"https://www.instaclustr.com/blog/managing-custom-search-attributes-for-advanced-visibility-cadence/",children:"Managing Custom Search Attributes for Advance Visibility Cadence"})}),"\n"]}),"\n"]}),"\n",(0,a.jsx)(n.h2,{id:"upcoming-events",children:"Upcoming Events"}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsxs)(n.li,{children:["\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.a,{href:"https://info.instaclustr.com/webinar-spinning-drones-cadence-kafka.html",children:"Webinar: Spinning Your Drones with Cadence and Apache Kafka - 15th November 2022"})}),"\n"]}),"\n",(0,a.jsxs)(n.li,{children:["\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.a,{href:"https://info.instaclustr.com/webinar-emea-fitting-cadence.html",children:"Webinar: Fitting Cadence in Your Corporate Architecture - 24th November 2022"})}),"\n"]}),"\n",(0,a.jsxs)(n.li,{children:["\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.a,{href:"https://calendar.google.com/calendar/u/0/embed?src=e6r40gp3c2r01054id7e99dlac@group.calendar.google.com&ctz=America/Los_Angeles",children:"Cadence Technical Office Hours - 28th November 2022 @ 9am PT"})}),"\n"]}),"\n"]}),"\n",(0,a.jsxs)(n.p,{children:["If you have any news or topics you'd like us to include in our next update then please join our ",(0,a.jsx)(n.a,{href:"http://t.uber.com/cadence-slack",children:"Slack"}),"#community channel."]}),"\n",(0,a.jsxs)(n.p,{children:["Please remember that this update is for you - so if you have any comments or feedback that could help us improve it then please share it with us in the #community ",(0,a.jsx)(n.a,{href:"http://t.uber.com/cadence-slack",children:"Slack"})," channel."]})]})}function d(e={}){const{wrapper:n}={...(0,i.R)(),...e.components};return n?(0,a.jsx)(n,{...e,children:(0,a.jsx)(l,{...e})}):l(e)}},8453:(e,n,t)=>{t.d(n,{R:()=>s,x:()=>c});var o=t(6540);const a={},i=o.createContext(a);function s(e){const n=o.useContext(i);return o.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function c(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:s(e.components),o.createElement(i.Provider,{value:n},e.children)}},9350:e=>{e.exports=JSON.parse('{"permalink":"/Cadence-Docs/blog/2022/10/31/community-spotlight-october-2022","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2022-10-31-community-spotlight-october-2022.md","source":"@site/blog/2022-10-31-community-spotlight-october-2022.md","title":"Cadence Community Spotlight Update - October 2022","description":"Here\u2019s the latest in our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!","date":"2022-10-31T00:00:00.000Z","tags":[{"inline":false,"label":"Community Spotlight","permalink":"/Cadence-Docs/blog/tags/community-spotlights","description":"Community Spotlight tag description"}],"readingTime":1.93,"hasTruncateMarker":true,"authors":[{"name":"Sharan Foga","title":"Director of Operations & Customer Success @ Encube Technologies","url":"https://www.linkedin.com/in/sfoga/","page":{"permalink":"/Cadence-Docs/blog/authors/sharanf"},"socials":{"linkedin":"https://www.linkedin.com/in/sfoga/","github":"https://github.com/sharanf"},"imageURL":"https://github.com/sharanf.png","key":"sharanf"}],"frontMatter":{"title":"Cadence Community Spotlight Update - October 2022","date":"2022-10-31T00:00:00.000Z","authors":"sharanf","tags":["community-spotlight"]},"unlisted":false,"prevItem":{"title":"Cadence Community Spotlight Update - November 2022","permalink":"/Cadence-Docs/blog/2022/11/30/community-spotlight-november-2022"},"nextItem":{"title":"Cadence Community Spotlight Update - September 2022","permalink":"/Cadence-Docs/blog/2022/09/30/community-spotlight-september-2022"}}')}}]); \ No newline at end of file diff --git a/assets/js/eb57c500.225e3359.js b/assets/js/eb57c500.225e3359.js deleted file mode 100644 index d88c52c3d..000000000 --- a/assets/js/eb57c500.225e3359.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[7246],{266:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>d,contentTitle:()=>r,default:()=>l,frontMatter:()=>s,metadata:()=>c,toc:()=>a});const c=JSON.parse('{"id":"go-client/side-effect","title":"Side effect","description":"workflow.SideEffect is useful for short, nondeterministic code snippets, such as getting a random","source":"@site/docs/05-go-client/10-side-effect.md","sourceDirName":"05-go-client","slug":"/go-client/side-effect","permalink":"/docs/go-client/side-effect","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/05-go-client/10-side-effect.md","tags":[],"version":"current","sidebarPosition":10,"frontMatter":{"layout":"default","title":"Side effect","permalink":"/docs/go-client/side-effect"},"sidebar":"docsSidebar","previous":{"title":"Continue as new","permalink":"/docs/go-client/continue-as-new"},"next":{"title":"Queries","permalink":"/docs/go-client/queries"}}');var o=t(4848),i=t(8453);const s={layout:"default",title:"Side effect",permalink:"/docs/go-client/side-effect"},r="Side effect",d={},a=[];function f(e){const n={code:"code",h1:"h1",header:"header",p:"p",pre:"pre",...(0,i.R)(),...e.components};return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsx)(n.header,{children:(0,o.jsx)(n.h1,{id:"side-effect",children:"Side effect"})}),"\n",(0,o.jsxs)(n.p,{children:[(0,o.jsx)(n.code,{children:"workflow.SideEffect"})," is useful for short, nondeterministic code snippets, such as getting a random\nvalue or generating a UUID. It executes the provided function once and records its result into the\nworkflow history. ",(0,o.jsx)(n.code,{children:"workflow.SideEffect"}),' does not re-execute upon replay, but instead returns the\nrecorded result. It can be seen as an "inline" activity. Something to note about ',(0,o.jsx)(n.code,{children:"workflow.SideEffect"}),"\nis that, unlike the Cadence guarantee of at-most-once execution for activities, there is no such\nguarantee with ",(0,o.jsx)(n.code,{children:"workflow.SideEffect"}),". Under certain failure conditions, ",(0,o.jsx)(n.code,{children:"workflow.SideEffect"})," can\nend up executing a function more than once."]}),"\n",(0,o.jsxs)(n.p,{children:["The only way to fail ",(0,o.jsx)(n.code,{children:"SideEffect"})," is to panic, which causes a decision_task failure. After the\ntimeout, Cadence reschedules and then re-executes the decision_task, giving ",(0,o.jsx)(n.code,{children:"SideEffect"})," another chance\nto succeed. Do not return any data from ",(0,o.jsx)(n.code,{children:"SideEffect"})," other than through its recorded return value."]}),"\n",(0,o.jsxs)(n.p,{children:["The following sample demonstrates how to use ",(0,o.jsx)(n.code,{children:"SideEffect"}),":"]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-go",children:"encodedRandom := SideEffect(func(ctx cadence.Context) interface{} {\n return rand.Intn(100)\n})\n\nvar random int\nencodedRandom.Get(&random)\nif random < 50 {\n ...\n} else {\n ...\n}\n"})})]})}function l(e={}){const{wrapper:n}={...(0,i.R)(),...e.components};return n?(0,o.jsx)(n,{...e,children:(0,o.jsx)(f,{...e})}):f(e)}},8453:(e,n,t)=>{t.d(n,{R:()=>s,x:()=>r});var c=t(6540);const o={},i=c.createContext(o);function s(e){const n=c.useContext(i);return c.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function r(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:s(e.components),c.createElement(i.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/eb57c500.a7ba6131.js b/assets/js/eb57c500.a7ba6131.js new file mode 100644 index 000000000..d7c72d56b --- /dev/null +++ b/assets/js/eb57c500.a7ba6131.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[7246],{266:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>d,contentTitle:()=>r,default:()=>l,frontMatter:()=>s,metadata:()=>c,toc:()=>a});const c=JSON.parse('{"id":"go-client/side-effect","title":"Side effect","description":"workflow.SideEffect is useful for short, nondeterministic code snippets, such as getting a random","source":"@site/docs/05-go-client/10-side-effect.md","sourceDirName":"05-go-client","slug":"/go-client/side-effect","permalink":"/Cadence-Docs/docs/go-client/side-effect","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/05-go-client/10-side-effect.md","tags":[],"version":"current","sidebarPosition":10,"frontMatter":{"layout":"default","title":"Side effect","permalink":"/docs/go-client/side-effect"},"sidebar":"docsSidebar","previous":{"title":"Continue as new","permalink":"/Cadence-Docs/docs/go-client/continue-as-new"},"next":{"title":"Queries","permalink":"/Cadence-Docs/docs/go-client/queries"}}');var o=t(4848),i=t(8453);const s={layout:"default",title:"Side effect",permalink:"/docs/go-client/side-effect"},r="Side effect",d={},a=[];function f(e){const n={code:"code",h1:"h1",header:"header",p:"p",pre:"pre",...(0,i.R)(),...e.components};return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsx)(n.header,{children:(0,o.jsx)(n.h1,{id:"side-effect",children:"Side effect"})}),"\n",(0,o.jsxs)(n.p,{children:[(0,o.jsx)(n.code,{children:"workflow.SideEffect"})," is useful for short, nondeterministic code snippets, such as getting a random\nvalue or generating a UUID. It executes the provided function once and records its result into the\nworkflow history. ",(0,o.jsx)(n.code,{children:"workflow.SideEffect"}),' does not re-execute upon replay, but instead returns the\nrecorded result. It can be seen as an "inline" activity. Something to note about ',(0,o.jsx)(n.code,{children:"workflow.SideEffect"}),"\nis that, unlike the Cadence guarantee of at-most-once execution for activities, there is no such\nguarantee with ",(0,o.jsx)(n.code,{children:"workflow.SideEffect"}),". Under certain failure conditions, ",(0,o.jsx)(n.code,{children:"workflow.SideEffect"})," can\nend up executing a function more than once."]}),"\n",(0,o.jsxs)(n.p,{children:["The only way to fail ",(0,o.jsx)(n.code,{children:"SideEffect"})," is to panic, which causes a decision_task failure. After the\ntimeout, Cadence reschedules and then re-executes the decision_task, giving ",(0,o.jsx)(n.code,{children:"SideEffect"})," another chance\nto succeed. Do not return any data from ",(0,o.jsx)(n.code,{children:"SideEffect"})," other than through its recorded return value."]}),"\n",(0,o.jsxs)(n.p,{children:["The following sample demonstrates how to use ",(0,o.jsx)(n.code,{children:"SideEffect"}),":"]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-go",children:"encodedRandom := SideEffect(func(ctx cadence.Context) interface{} {\n return rand.Intn(100)\n})\n\nvar random int\nencodedRandom.Get(&random)\nif random < 50 {\n ...\n} else {\n ...\n}\n"})})]})}function l(e={}){const{wrapper:n}={...(0,i.R)(),...e.components};return n?(0,o.jsx)(n,{...e,children:(0,o.jsx)(f,{...e})}):f(e)}},8453:(e,n,t)=>{t.d(n,{R:()=>s,x:()=>r});var c=t(6540);const o={},i=c.createContext(o);function s(e){const n=c.useContext(i);return c.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function r(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:s(e.components),c.createElement(i.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/ec02fbe0.d779414d.js b/assets/js/ec02fbe0.d779414d.js deleted file mode 100644 index dcb8357b1..000000000 --- a/assets/js/ec02fbe0.d779414d.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[5438],{3231:(e,t,i)=>{i.r(t),i.d(t,{assets:()=>s,contentTitle:()=>c,default:()=>h,frontMatter:()=>o,metadata:()=>n,toc:()=>l});const n=JSON.parse('{"id":"go-client/activities","title":"Activity overview","description":"An is the implementation of a particular in the business logic.","source":"@site/docs/05-go-client/03-activities.md","sourceDirName":"05-go-client","slug":"/go-client/activities","permalink":"/docs/go-client/activities","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/05-go-client/03-activities.md","tags":[],"version":"current","sidebarPosition":3,"frontMatter":{"layout":"default","title":"Activity overview","permalink":"/docs/go-client/activities"},"sidebar":"docsSidebar","previous":{"title":"Starting workflows","permalink":"/docs/go-client/02.5-starting-workflows"},"next":{"title":"Executing activities","permalink":"/docs/go-client/execute-activity"}}');var a=i(4848),r=i(8453);const o={layout:"default",title:"Activity overview",permalink:"/docs/go-client/activities"},c="Activity overview",s={},l=[{value:"Overview",id:"overview",level:2},{value:"Declaration",id:"declaration",level:3},{value:"Implementation",id:"implementation",level:3},{value:"Heart Beating",id:"heart-beating",level:4},{value:"Cancellation",id:"cancellation",level:4},{value:"Registration",id:"registration",level:3},{value:"Failing an Activity",id:"failing-an-activity",level:2}];function d(e){const t={a:"a",code:"code",h1:"h1",h2:"h2",h3:"h3",h4:"h4",header:"header",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,r.R)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(t.header,{children:(0,a.jsx)(t.h1,{id:"activity-overview",children:"Activity overview"})}),"\n",(0,a.jsx)(t.p,{children:"An activity is the implementation of a particular task in the business logic."}),"\n",(0,a.jsxs)(t.p,{children:["Activities are implemented as functions. Data can be passed directly to an activity via function\nparameters. The parameters can be either basic types or structs, with the only requirement being that\nthe parameters must be serializable. Though it is not required, we recommend that the first parameter\nof an activity function is of type ",(0,a.jsx)(t.code,{children:"context.Context"}),", in order to allow the activity to interact with\nother framework methods. The function must return an ",(0,a.jsx)(t.code,{children:"error"})," value, and can optionally return a result\nvalue. The result value can be either a basic type or a struct with the only requirement being that\nit is serializable."]}),"\n",(0,a.jsx)(t.p,{children:"The values passed to activities through invocation parameters or returned through the result value\nare recorded in the execution history. The entire execution history is transferred from the Cadence\nservice to workflow_workers with every event that the workflow logic needs to process. A large execution\nhistory can thus adversely impact the performance of your workflow. Therefore, be mindful of the amount\nof data you transfer via activity invocation parameters or return values. Otherwise, no additional\nlimitations exist on activity implementations."}),"\n",(0,a.jsx)(t.h2,{id:"overview",children:"Overview"}),"\n",(0,a.jsx)(t.p,{children:"The following example demonstrates a simple activity that accepts a string parameter, appends a word\nto it, and then returns a result."}),"\n",(0,a.jsx)(t.pre,{children:(0,a.jsx)(t.code,{className:"language-go",children:'package simple\n\nimport (\n "context"\n\n "go.uber.org/cadence/activity"\n "go.uber.org/zap"\n)\n\nfunc init() {\n activity.Register(SimpleActivity)\n}\n\n// SimpleActivity is a sample Cadence activity function that takes one parameter and\n// returns a string containing the parameter value.\nfunc SimpleActivity(ctx context.Context, value string) (string, error) {\n activity.GetLogger(ctx).Info("SimpleActivity called.", zap.String("Value", value))\n return "Processed: " + value, nil\n}\n'})}),"\n",(0,a.jsx)(t.p,{children:"Let's take a look at each component of this activity."}),"\n",(0,a.jsx)(t.h3,{id:"declaration",children:"Declaration"}),"\n",(0,a.jsx)(t.p,{children:"In the Cadence programing model, an activity is implemented with a function. The function declaration specifies the parameters the activity accepts as well as any values it might return. An activity function can take zero or many activity specific parameters and can return one or two values. It must always at least return an error value. The activity function can accept as parameters and return as results any serializable type."}),"\n",(0,a.jsx)(t.p,{children:(0,a.jsx)(t.code,{children:"func SimpleActivity(ctx context.Context, value string) (string, error)"})}),"\n",(0,a.jsx)(t.p,{children:"The first parameter to the function is context.Context. This is an optional parameter and can be omitted. This parameter is the standard Go context.\nThe second string parameter is a custom activity specific parameter that can be used to pass data into the activity on start. An activity can have one or more such parameters. All parameters to an activity function must be serializable, which essentially means that params can\u2019t be channels, functions, variadic, or unsafe pointers.\nThe activity declares two return values: string and error. The string return value is used to return the result of the activity. The error return value is used to indicate that an error was encountered during execution."}),"\n",(0,a.jsx)(t.h3,{id:"implementation",children:"Implementation"}),"\n",(0,a.jsx)(t.p,{children:"You can write activity implementation code in the same way that you would any other Go service code.\nAdditionally, you can use the usual loggers and metrics controllers, and the standard Go concurrency\nconstructs."}),"\n",(0,a.jsx)(t.h4,{id:"heart-beating",children:"Heart Beating"}),"\n",(0,a.jsx)(t.p,{children:"For long-running activities, Cadence provides an API for the activity code to report both liveness and\nprogress back to the Cadence managed service."}),"\n",(0,a.jsx)(t.pre,{children:(0,a.jsx)(t.code,{className:"language-go",children:"progress := 0\nfor hasWork {\n // Send heartbeat message to the server.\n cadence.RecordActivityHeartbeat(ctx, progress)\n // Do some work.\n ...\n progress++\n}\n"})}),"\n",(0,a.jsxs)(t.p,{children:["When an activity times out due to a missed heartbeat, the last value of the details (",(0,a.jsx)(t.code,{children:"progress"})," in the\nabove sample) is returned from the ",(0,a.jsx)(t.code,{children:"cadence.ExecuteActivity"})," function as the details field of ",(0,a.jsx)(t.code,{children:"TimeoutError"}),"\nwith ",(0,a.jsx)(t.code,{children:"TimeoutType_HEARTBEAT"}),"."]}),"\n",(0,a.jsxs)(t.p,{children:["New ",(0,a.jsx)(t.strong,{children:"auto heartbeat"})," option in ",(0,a.jsx)(t.a,{href:"https://github.com/cadence-workflow/cadence-go-client/releases/tag/v0.17.0",children:"Cadence Go Client 0.17.0 release"}),":\nIn case you don't need to report progress, but still want to report liveness of your worker through heartbeating for your long running activities, there's a new auto-heartbeat option that you can enable when you register your activity. When this option is enabled Cadence library will do the heartbeat for you in the background."]}),"\n",(0,a.jsx)(t.pre,{children:(0,a.jsx)(t.code,{className:"language-go",children:"\tRegisterActivityOptions struct {\n\t\t...\n\t\t// Automatically send heartbeats for this activity at an interval that is less than the HeartbeatTimeout.\n\t\t// This option has no effect if the activity is executed with a HeartbeatTimeout of 0.\n\t\t// Default: false\n\t\tEnableAutoHeartbeat bool\n\t}\n"})}),"\n",(0,a.jsx)(t.p,{children:"You can also heartbeat an activity from an external source:"}),"\n",(0,a.jsx)(t.pre,{children:(0,a.jsx)(t.code,{className:"language-go",children:"// Instantiate a Cadence service client.\ncadence.Client client = cadence.NewClient(...)\n\n// Record heartbeat.\nerr := client.RecordActivityHeartbeat(taskToken, details)\n"})}),"\n",(0,a.jsxs)(t.p,{children:["The parameters of the ",(0,a.jsx)(t.code,{children:"RecordActivityHeartbeat"})," function are:"]}),"\n",(0,a.jsxs)(t.ul,{children:["\n",(0,a.jsxs)(t.li,{children:[(0,a.jsx)(t.code,{children:"taskToken"}),": The value of the binary ",(0,a.jsx)(t.code,{children:"TaskToken"})," field of the ",(0,a.jsx)(t.code,{children:"ActivityInfo"})," struct retrieved inside\nthe activity."]}),"\n",(0,a.jsxs)(t.li,{children:[(0,a.jsx)(t.code,{children:"details"}),": The serializable payload containing progress information."]}),"\n"]}),"\n",(0,a.jsx)(t.h4,{id:"cancellation",children:"Cancellation"}),"\n",(0,a.jsxs)(t.p,{children:["When an activity is cancelled, or its workflow_execution has completed or failed, the context passed\ninto its function is cancelled, which sets its channel\u2019s closed state to ",(0,a.jsx)(t.code,{children:"Done"}),". An activity can use that\nto perform any necessary cleanup and abort its execution. Cancellation is only delivered to activities\nthat call ",(0,a.jsx)(t.code,{children:"RecordActivityHeartbeat"}),"."]}),"\n",(0,a.jsx)(t.h3,{id:"registration",children:"Registration"}),"\n",(0,a.jsxs)(t.p,{children:["To make the activity visible to the worker process hosting it, the activity must be registered via a\ncall to ",(0,a.jsx)(t.code,{children:"activity.Register"}),"."]}),"\n",(0,a.jsx)(t.pre,{children:(0,a.jsx)(t.code,{className:"language-go",children:"func init() {\n activity.Register(SimpleActivity)\n}\n"})}),"\n",(0,a.jsx)(t.p,{children:"This call creates an in-memory mapping inside the worker process between the fully qualified function\nname and the implementation. If a worker receives a request to start an activity execution for an\nactivity type it does not know, it will fail that request."}),"\n",(0,a.jsx)(t.h2,{id:"failing-an-activity",children:"Failing an Activity"}),"\n",(0,a.jsxs)(t.p,{children:["To mark an activity as failed, the activity function must return an error via the ",(0,a.jsx)(t.code,{children:"error"})," return value."]})]})}function h(e={}){const{wrapper:t}={...(0,r.R)(),...e.components};return t?(0,a.jsx)(t,{...e,children:(0,a.jsx)(d,{...e})}):d(e)}},8453:(e,t,i)=>{i.d(t,{R:()=>o,x:()=>c});var n=i(6540);const a={},r=n.createContext(a);function o(e){const t=n.useContext(r);return n.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function c(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:o(e.components),n.createElement(r.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/ec02fbe0.f75756a8.js b/assets/js/ec02fbe0.f75756a8.js new file mode 100644 index 000000000..edd660deb --- /dev/null +++ b/assets/js/ec02fbe0.f75756a8.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[5438],{3231:(e,t,i)=>{i.r(t),i.d(t,{assets:()=>s,contentTitle:()=>c,default:()=>h,frontMatter:()=>o,metadata:()=>n,toc:()=>l});const n=JSON.parse('{"id":"go-client/activities","title":"Activity overview","description":"An is the implementation of a particular in the business logic.","source":"@site/docs/05-go-client/03-activities.md","sourceDirName":"05-go-client","slug":"/go-client/activities","permalink":"/Cadence-Docs/docs/go-client/activities","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/05-go-client/03-activities.md","tags":[],"version":"current","sidebarPosition":3,"frontMatter":{"layout":"default","title":"Activity overview","permalink":"/docs/go-client/activities"},"sidebar":"docsSidebar","previous":{"title":"Starting workflows","permalink":"/Cadence-Docs/docs/go-client/02.5-starting-workflows"},"next":{"title":"Executing activities","permalink":"/Cadence-Docs/docs/go-client/execute-activity"}}');var a=i(4848),r=i(8453);const o={layout:"default",title:"Activity overview",permalink:"/docs/go-client/activities"},c="Activity overview",s={},l=[{value:"Overview",id:"overview",level:2},{value:"Declaration",id:"declaration",level:3},{value:"Implementation",id:"implementation",level:3},{value:"Heart Beating",id:"heart-beating",level:4},{value:"Cancellation",id:"cancellation",level:4},{value:"Registration",id:"registration",level:3},{value:"Failing an Activity",id:"failing-an-activity",level:2}];function d(e){const t={a:"a",code:"code",h1:"h1",h2:"h2",h3:"h3",h4:"h4",header:"header",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,r.R)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(t.header,{children:(0,a.jsx)(t.h1,{id:"activity-overview",children:"Activity overview"})}),"\n",(0,a.jsx)(t.p,{children:"An activity is the implementation of a particular task in the business logic."}),"\n",(0,a.jsxs)(t.p,{children:["Activities are implemented as functions. Data can be passed directly to an activity via function\nparameters. The parameters can be either basic types or structs, with the only requirement being that\nthe parameters must be serializable. Though it is not required, we recommend that the first parameter\nof an activity function is of type ",(0,a.jsx)(t.code,{children:"context.Context"}),", in order to allow the activity to interact with\nother framework methods. The function must return an ",(0,a.jsx)(t.code,{children:"error"})," value, and can optionally return a result\nvalue. The result value can be either a basic type or a struct with the only requirement being that\nit is serializable."]}),"\n",(0,a.jsx)(t.p,{children:"The values passed to activities through invocation parameters or returned through the result value\nare recorded in the execution history. The entire execution history is transferred from the Cadence\nservice to workflow_workers with every event that the workflow logic needs to process. A large execution\nhistory can thus adversely impact the performance of your workflow. Therefore, be mindful of the amount\nof data you transfer via activity invocation parameters or return values. Otherwise, no additional\nlimitations exist on activity implementations."}),"\n",(0,a.jsx)(t.h2,{id:"overview",children:"Overview"}),"\n",(0,a.jsx)(t.p,{children:"The following example demonstrates a simple activity that accepts a string parameter, appends a word\nto it, and then returns a result."}),"\n",(0,a.jsx)(t.pre,{children:(0,a.jsx)(t.code,{className:"language-go",children:'package simple\n\nimport (\n "context"\n\n "go.uber.org/cadence/activity"\n "go.uber.org/zap"\n)\n\nfunc init() {\n activity.Register(SimpleActivity)\n}\n\n// SimpleActivity is a sample Cadence activity function that takes one parameter and\n// returns a string containing the parameter value.\nfunc SimpleActivity(ctx context.Context, value string) (string, error) {\n activity.GetLogger(ctx).Info("SimpleActivity called.", zap.String("Value", value))\n return "Processed: " + value, nil\n}\n'})}),"\n",(0,a.jsx)(t.p,{children:"Let's take a look at each component of this activity."}),"\n",(0,a.jsx)(t.h3,{id:"declaration",children:"Declaration"}),"\n",(0,a.jsx)(t.p,{children:"In the Cadence programing model, an activity is implemented with a function. The function declaration specifies the parameters the activity accepts as well as any values it might return. An activity function can take zero or many activity specific parameters and can return one or two values. It must always at least return an error value. The activity function can accept as parameters and return as results any serializable type."}),"\n",(0,a.jsx)(t.p,{children:(0,a.jsx)(t.code,{children:"func SimpleActivity(ctx context.Context, value string) (string, error)"})}),"\n",(0,a.jsx)(t.p,{children:"The first parameter to the function is context.Context. This is an optional parameter and can be omitted. This parameter is the standard Go context.\nThe second string parameter is a custom activity specific parameter that can be used to pass data into the activity on start. An activity can have one or more such parameters. All parameters to an activity function must be serializable, which essentially means that params can\u2019t be channels, functions, variadic, or unsafe pointers.\nThe activity declares two return values: string and error. The string return value is used to return the result of the activity. The error return value is used to indicate that an error was encountered during execution."}),"\n",(0,a.jsx)(t.h3,{id:"implementation",children:"Implementation"}),"\n",(0,a.jsx)(t.p,{children:"You can write activity implementation code in the same way that you would any other Go service code.\nAdditionally, you can use the usual loggers and metrics controllers, and the standard Go concurrency\nconstructs."}),"\n",(0,a.jsx)(t.h4,{id:"heart-beating",children:"Heart Beating"}),"\n",(0,a.jsx)(t.p,{children:"For long-running activities, Cadence provides an API for the activity code to report both liveness and\nprogress back to the Cadence managed service."}),"\n",(0,a.jsx)(t.pre,{children:(0,a.jsx)(t.code,{className:"language-go",children:"progress := 0\nfor hasWork {\n // Send heartbeat message to the server.\n cadence.RecordActivityHeartbeat(ctx, progress)\n // Do some work.\n ...\n progress++\n}\n"})}),"\n",(0,a.jsxs)(t.p,{children:["When an activity times out due to a missed heartbeat, the last value of the details (",(0,a.jsx)(t.code,{children:"progress"})," in the\nabove sample) is returned from the ",(0,a.jsx)(t.code,{children:"cadence.ExecuteActivity"})," function as the details field of ",(0,a.jsx)(t.code,{children:"TimeoutError"}),"\nwith ",(0,a.jsx)(t.code,{children:"TimeoutType_HEARTBEAT"}),"."]}),"\n",(0,a.jsxs)(t.p,{children:["New ",(0,a.jsx)(t.strong,{children:"auto heartbeat"})," option in ",(0,a.jsx)(t.a,{href:"https://github.com/cadence-workflow/cadence-go-client/releases/tag/v0.17.0",children:"Cadence Go Client 0.17.0 release"}),":\nIn case you don't need to report progress, but still want to report liveness of your worker through heartbeating for your long running activities, there's a new auto-heartbeat option that you can enable when you register your activity. When this option is enabled Cadence library will do the heartbeat for you in the background."]}),"\n",(0,a.jsx)(t.pre,{children:(0,a.jsx)(t.code,{className:"language-go",children:"\tRegisterActivityOptions struct {\n\t\t...\n\t\t// Automatically send heartbeats for this activity at an interval that is less than the HeartbeatTimeout.\n\t\t// This option has no effect if the activity is executed with a HeartbeatTimeout of 0.\n\t\t// Default: false\n\t\tEnableAutoHeartbeat bool\n\t}\n"})}),"\n",(0,a.jsx)(t.p,{children:"You can also heartbeat an activity from an external source:"}),"\n",(0,a.jsx)(t.pre,{children:(0,a.jsx)(t.code,{className:"language-go",children:"// Instantiate a Cadence service client.\ncadence.Client client = cadence.NewClient(...)\n\n// Record heartbeat.\nerr := client.RecordActivityHeartbeat(taskToken, details)\n"})}),"\n",(0,a.jsxs)(t.p,{children:["The parameters of the ",(0,a.jsx)(t.code,{children:"RecordActivityHeartbeat"})," function are:"]}),"\n",(0,a.jsxs)(t.ul,{children:["\n",(0,a.jsxs)(t.li,{children:[(0,a.jsx)(t.code,{children:"taskToken"}),": The value of the binary ",(0,a.jsx)(t.code,{children:"TaskToken"})," field of the ",(0,a.jsx)(t.code,{children:"ActivityInfo"})," struct retrieved inside\nthe activity."]}),"\n",(0,a.jsxs)(t.li,{children:[(0,a.jsx)(t.code,{children:"details"}),": The serializable payload containing progress information."]}),"\n"]}),"\n",(0,a.jsx)(t.h4,{id:"cancellation",children:"Cancellation"}),"\n",(0,a.jsxs)(t.p,{children:["When an activity is cancelled, or its workflow_execution has completed or failed, the context passed\ninto its function is cancelled, which sets its channel\u2019s closed state to ",(0,a.jsx)(t.code,{children:"Done"}),". An activity can use that\nto perform any necessary cleanup and abort its execution. Cancellation is only delivered to activities\nthat call ",(0,a.jsx)(t.code,{children:"RecordActivityHeartbeat"}),"."]}),"\n",(0,a.jsx)(t.h3,{id:"registration",children:"Registration"}),"\n",(0,a.jsxs)(t.p,{children:["To make the activity visible to the worker process hosting it, the activity must be registered via a\ncall to ",(0,a.jsx)(t.code,{children:"activity.Register"}),"."]}),"\n",(0,a.jsx)(t.pre,{children:(0,a.jsx)(t.code,{className:"language-go",children:"func init() {\n activity.Register(SimpleActivity)\n}\n"})}),"\n",(0,a.jsx)(t.p,{children:"This call creates an in-memory mapping inside the worker process between the fully qualified function\nname and the implementation. If a worker receives a request to start an activity execution for an\nactivity type it does not know, it will fail that request."}),"\n",(0,a.jsx)(t.h2,{id:"failing-an-activity",children:"Failing an Activity"}),"\n",(0,a.jsxs)(t.p,{children:["To mark an activity as failed, the activity function must return an error via the ",(0,a.jsx)(t.code,{children:"error"})," return value."]})]})}function h(e={}){const{wrapper:t}={...(0,r.R)(),...e.components};return t?(0,a.jsx)(t,{...e,children:(0,a.jsx)(d,{...e})}):d(e)}},8453:(e,t,i)=>{i.d(t,{R:()=>o,x:()=>c});var n=i(6540);const a={},r=n.createContext(a);function o(e){const t=n.useContext(r);return n.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function c(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:o(e.components),n.createElement(r.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/ef69cbb3.6cc269cf.js b/assets/js/ef69cbb3.6cc269cf.js new file mode 100644 index 000000000..fa23326e6 --- /dev/null +++ b/assets/js/ef69cbb3.6cc269cf.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[6267],{5864:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>c,contentTitle:()=>r,default:()=>d,frontMatter:()=>s,metadata:()=>o,toc:()=>l});var o=t(3258),a=t(4848),i=t(8453);const s={title:"Cadence Community Spotlight Update - January 2023",date:new Date("2023-01-31T00:00:00.000Z"),authors:"sharanf",tags:["community-spotlight"]},r=void 0,c={authorsImageUrls:[void 0]},l=[{value:"Closing Down Cadence Office Hours",id:"closing-down-cadence-office-hours",level:2},{value:"Update on iWF Support for Cadence",id:"update-on-iwf-support-for-cadence",level:2},{value:"Cadence in the News!",id:"cadence-in-the-news",level:2},{value:"Upcoming Events",id:"upcoming-events",level:2}];function h(e){const n={a:"a",h2:"h2",li:"li",p:"p",ul:"ul",...(0,i.R)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(n.p,{children:"Happy New Year everyone! Here\u2019s the latest in our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!"}),"\n",(0,a.jsx)(n.p,{children:"Please see below for a roundup of the highlights:"}),"\n",(0,a.jsx)(n.h2,{id:"closing-down-cadence-office-hours",children:"Closing Down Cadence Office Hours"}),"\n",(0,a.jsx)(n.p,{children:"We have been running Office Hours sessions every month since May last year. The aim was to give the community an opportunity to speak directly with some of the Cadence core developers and experts to answer questions on particular issues you may be having. We have found that the most preferred method for community questions has been the support Slack channel so have decided to stop this monthly call."}),"\n",(0,a.jsxs)(n.p,{children:["Thanks very much to ",(0,a.jsx)(n.a,{href:"https://www.linkedin.com/in/enderdemirkaya/",children:"Ender Demirkaya"}),"and the Uber team for making themselves available for these sessions."]}),"\n",(0,a.jsxs)(n.p,{children:["Please remember that if you have question about Cadence or are facing a specific issue then you can post your question in our #support ",(0,a.jsx)(n.a,{href:"http://t.uber.com/cadence-slack",children:"Slack"})," channel. If you also post the details on StackOverflow with the cadence workflow tag then there will be a searchable history for others who encounter the same issue to find a solution."]}),"\n",(0,a.jsx)(n.h2,{id:"update-on-iwf-support-for-cadence",children:"Update on iWF Support for Cadence"}),"\n",(0,a.jsxs)(n.p,{children:["Last October we featured an update in our monthly blog about ",(0,a.jsx)(n.a,{href:"https://github.com/indeedeng/iwf",children:"iWF - Interpreter for Workflow"}),", a project built on top of Cadence by community member ",(0,a.jsx)(n.a,{href:"https://www.linkedin.com/in/prclqz/",children:"Quanzheng Long"}),". It was announced recently that iWF has released a ",(0,a.jsx)(n.a,{href:"https://github.com/iworkflowio/iwf-golang-sdk",children:"Golang SDK"})," and updated versions of the ",(0,a.jsx)(n.a,{href:"https://github.com/indeedeng/iwf",children:"Java SDK and server"}),"."]}),"\n",(0,a.jsx)(n.p,{children:"Long is really keen to get feedback so please take a look at iWF, try them out and presented him any feedback.\nLong has also created a couple of blog posts about iWF that we have featured in the Cadence in the News section below so please take a look."}),"\n",(0,a.jsx)(n.h2,{id:"cadence-in-the-news",children:"Cadence in the News!"}),"\n",(0,a.jsx)(n.p,{children:"Below are a selection of Cadence related articles, blogs and whitepapers. Please take a look and feel free to share via your own social media channels."}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsxs)(n.li,{children:["\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.a,{href:"https://medium.com/@qlong/a-letter-to-cadence-temporal-and-workflow-tech-community-b32e9fa97a0c",children:"A Letter to Cadence/Temporal and Workflow Tech Community"})}),"\n"]}),"\n",(0,a.jsxs)(n.li,{children:["\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.a,{href:"https://medium.com/@qlong/iwf-vs-cadence-temporal-1e11b35960fe",children:"iWF vs Cadence/Temporal"})}),"\n"]}),"\n",(0,a.jsxs)(n.li,{children:["\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.a,{href:"https://www.instaclustr.com/blog/aws-privatelink-for-cadence-on-instaclustr-by-netapp/",children:"AWS PrivateLink Connectivity Is Now Available with Instaclustr for Cadence"})}),"\n"]}),"\n"]}),"\n",(0,a.jsx)(n.h2,{id:"upcoming-events",children:"Upcoming Events"}),"\n",(0,a.jsx)(n.p,{children:"No upcoming events at the moment."}),"\n",(0,a.jsxs)(n.p,{children:["If you have any news or topics you'd like us to include in our next update then please join our ",(0,a.jsx)(n.a,{href:"http://t.uber.com/cadence-slack",children:"Slack"}),"#community channel."]}),"\n",(0,a.jsxs)(n.p,{children:["Please remember that this update is for you - so if you have any comments or feedback that could help us improve it then please share it with us in the #community ",(0,a.jsx)(n.a,{href:"http://t.uber.com/cadence-slack",children:"Slack"})," channel."]})]})}function d(e={}){const{wrapper:n}={...(0,i.R)(),...e.components};return n?(0,a.jsx)(n,{...e,children:(0,a.jsx)(h,{...e})}):h(e)}},8453:(e,n,t)=>{t.d(n,{R:()=>s,x:()=>r});var o=t(6540);const a={},i=o.createContext(a);function s(e){const n=o.useContext(i);return o.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function r(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:s(e.components),o.createElement(i.Provider,{value:n},e.children)}},3258:e=>{e.exports=JSON.parse('{"permalink":"/Cadence-Docs/blog/2023/01/31/community-spotlight-january-2023","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2023-01-31-community-spotlight-january-2023.md","source":"@site/blog/2023-01-31-community-spotlight-january-2023.md","title":"Cadence Community Spotlight Update - January 2023","description":"Happy New Year everyone! Here\u2019s the latest in our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!","date":"2023-01-31T00:00:00.000Z","tags":[{"inline":false,"label":"Community Spotlight","permalink":"/Cadence-Docs/blog/tags/community-spotlights","description":"Community Spotlight tag description"}],"readingTime":2.06,"hasTruncateMarker":true,"authors":[{"name":"Sharan Foga","title":"Director of Operations & Customer Success @ Encube Technologies","url":"https://www.linkedin.com/in/sfoga/","page":{"permalink":"/Cadence-Docs/blog/authors/sharanf"},"socials":{"linkedin":"https://www.linkedin.com/in/sfoga/","github":"https://github.com/sharanf"},"imageURL":"https://github.com/sharanf.png","key":"sharanf"}],"frontMatter":{"title":"Cadence Community Spotlight Update - January 2023","date":"2023-01-31T00:00:00.000Z","authors":"sharanf","tags":["community-spotlight"]},"unlisted":false,"prevItem":{"title":"Cadence Community Spotlight Update - February 2023","permalink":"/Cadence-Docs/blog/2023/02/28/community-spotlight-february"},"nextItem":{"title":"Cadence Community Spotlight Update - December 2022","permalink":"/Cadence-Docs/blog/2022/12/23/community-spotlight-december-2022"}}')}}]); \ No newline at end of file diff --git a/assets/js/ef69cbb3.d4ae49c6.js b/assets/js/ef69cbb3.d4ae49c6.js deleted file mode 100644 index 2b34b315e..000000000 --- a/assets/js/ef69cbb3.d4ae49c6.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[6267],{5864:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>c,contentTitle:()=>r,default:()=>d,frontMatter:()=>s,metadata:()=>o,toc:()=>l});var o=n(3258),a=n(4848),i=n(8453);const s={title:"Cadence Community Spotlight Update - January 2023",date:new Date("2023-01-31T00:00:00.000Z"),authors:"sharanf",tags:["community-spotlight"]},r=void 0,c={authorsImageUrls:[void 0]},l=[{value:"Closing Down Cadence Office Hours",id:"closing-down-cadence-office-hours",level:2},{value:"Update on iWF Support for Cadence",id:"update-on-iwf-support-for-cadence",level:2},{value:"Cadence in the News!",id:"cadence-in-the-news",level:2},{value:"Upcoming Events",id:"upcoming-events",level:2}];function h(e){const t={a:"a",h2:"h2",li:"li",p:"p",ul:"ul",...(0,i.R)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(t.p,{children:"Happy New Year everyone! Here\u2019s the latest in our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!"}),"\n",(0,a.jsx)(t.p,{children:"Please see below for a roundup of the highlights:"}),"\n",(0,a.jsx)(t.h2,{id:"closing-down-cadence-office-hours",children:"Closing Down Cadence Office Hours"}),"\n",(0,a.jsx)(t.p,{children:"We have been running Office Hours sessions every month since May last year. The aim was to give the community an opportunity to speak directly with some of the Cadence core developers and experts to answer questions on particular issues you may be having. We have found that the most preferred method for community questions has been the support Slack channel so have decided to stop this monthly call."}),"\n",(0,a.jsxs)(t.p,{children:["Thanks very much to ",(0,a.jsx)(t.a,{href:"https://www.linkedin.com/in/enderdemirkaya/",children:"Ender Demirkaya"}),"and the Uber team for making themselves available for these sessions."]}),"\n",(0,a.jsxs)(t.p,{children:["Please remember that if you have question about Cadence or are facing a specific issue then you can post your question in our #support ",(0,a.jsx)(t.a,{href:"http://t.uber.com/cadence-slack",children:"Slack"})," channel. If you also post the details on StackOverflow with the cadence workflow tag then there will be a searchable history for others who encounter the same issue to find a solution."]}),"\n",(0,a.jsx)(t.h2,{id:"update-on-iwf-support-for-cadence",children:"Update on iWF Support for Cadence"}),"\n",(0,a.jsxs)(t.p,{children:["Last October we featured an update in our monthly blog about ",(0,a.jsx)(t.a,{href:"https://github.com/indeedeng/iwf",children:"iWF - Interpreter for Workflow"}),", a project built on top of Cadence by community member ",(0,a.jsx)(t.a,{href:"https://www.linkedin.com/in/prclqz/",children:"Quanzheng Long"}),". It was announced recently that iWF has released a ",(0,a.jsx)(t.a,{href:"https://github.com/iworkflowio/iwf-golang-sdk",children:"Golang SDK"})," and updated versions of the ",(0,a.jsx)(t.a,{href:"https://github.com/indeedeng/iwf",children:"Java SDK and server"}),"."]}),"\n",(0,a.jsx)(t.p,{children:"Long is really keen to get feedback so please take a look at iWF, try them out and presented him any feedback.\nLong has also created a couple of blog posts about iWF that we have featured in the Cadence in the News section below so please take a look."}),"\n",(0,a.jsx)(t.h2,{id:"cadence-in-the-news",children:"Cadence in the News!"}),"\n",(0,a.jsx)(t.p,{children:"Below are a selection of Cadence related articles, blogs and whitepapers. Please take a look and feel free to share via your own social media channels."}),"\n",(0,a.jsxs)(t.ul,{children:["\n",(0,a.jsxs)(t.li,{children:["\n",(0,a.jsx)(t.p,{children:(0,a.jsx)(t.a,{href:"https://medium.com/@qlong/a-letter-to-cadence-temporal-and-workflow-tech-community-b32e9fa97a0c",children:"A Letter to Cadence/Temporal and Workflow Tech Community"})}),"\n"]}),"\n",(0,a.jsxs)(t.li,{children:["\n",(0,a.jsx)(t.p,{children:(0,a.jsx)(t.a,{href:"https://medium.com/@qlong/iwf-vs-cadence-temporal-1e11b35960fe",children:"iWF vs Cadence/Temporal"})}),"\n"]}),"\n",(0,a.jsxs)(t.li,{children:["\n",(0,a.jsx)(t.p,{children:(0,a.jsx)(t.a,{href:"https://www.instaclustr.com/blog/aws-privatelink-for-cadence-on-instaclustr-by-netapp/",children:"AWS PrivateLink Connectivity Is Now Available with Instaclustr for Cadence"})}),"\n"]}),"\n"]}),"\n",(0,a.jsx)(t.h2,{id:"upcoming-events",children:"Upcoming Events"}),"\n",(0,a.jsx)(t.p,{children:"No upcoming events at the moment."}),"\n",(0,a.jsxs)(t.p,{children:["If you have any news or topics you'd like us to include in our next update then please join our ",(0,a.jsx)(t.a,{href:"http://t.uber.com/cadence-slack",children:"Slack"}),"#community channel."]}),"\n",(0,a.jsxs)(t.p,{children:["Please remember that this update is for you - so if you have any comments or feedback that could help us improve it then please share it with us in the #community ",(0,a.jsx)(t.a,{href:"http://t.uber.com/cadence-slack",children:"Slack"})," channel."]})]})}function d(e={}){const{wrapper:t}={...(0,i.R)(),...e.components};return t?(0,a.jsx)(t,{...e,children:(0,a.jsx)(h,{...e})}):h(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>s,x:()=>r});var o=n(6540);const a={},i=o.createContext(a);function s(e){const t=o.useContext(i);return o.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function r(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:s(e.components),o.createElement(i.Provider,{value:t},e.children)}},3258:e=>{e.exports=JSON.parse('{"permalink":"/blog/2023/01/31/community-spotlight-january-2023","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2023-01-31-community-spotlight-january-2023.md","source":"@site/blog/2023-01-31-community-spotlight-january-2023.md","title":"Cadence Community Spotlight Update - January 2023","description":"Happy New Year everyone! Here\u2019s the latest in our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!","date":"2023-01-31T00:00:00.000Z","tags":[{"inline":false,"label":"Community Spotlight","permalink":"/blog/tags/community-spotlights","description":"Community Spotlight tag description"}],"readingTime":2.06,"hasTruncateMarker":true,"authors":[{"name":"Sharan Foga","title":"Director of Operations & Customer Success @ Encube Technologies","url":"https://www.linkedin.com/in/sfoga/","page":{"permalink":"/blog/authors/sharanf"},"socials":{"linkedin":"https://www.linkedin.com/in/sfoga/","github":"https://github.com/sharanf"},"imageURL":"https://github.com/sharanf.png","key":"sharanf"}],"frontMatter":{"title":"Cadence Community Spotlight Update - January 2023","date":"2023-01-31T00:00:00.000Z","authors":"sharanf","tags":["community-spotlight"]},"unlisted":false,"prevItem":{"title":"Cadence Community Spotlight Update - February 2023","permalink":"/blog/2023/02/28/community-spotlight-february"},"nextItem":{"title":"Cadence Community Spotlight Update - December 2022","permalink":"/blog/2022/12/23/community-spotlight-december-2022"}}')}}]); \ No newline at end of file diff --git a/assets/js/ef8b811a.34f08480.js b/assets/js/ef8b811a.34f08480.js deleted file mode 100644 index 767995da3..000000000 --- a/assets/js/ef8b811a.34f08480.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[8947],{6600:i=>{i.exports=JSON.parse('{"authors":[{"name":"Chris Qin","title":"Applications Developer @ Uber","url":"https://www.linkedin.com/in/chrisqin0610/","page":{"permalink":"/blog/authors/chopincode"},"socials":{"linkedin":"https://www.linkedin.com/in/chrisqin0610/","github":"https://github.com/chopincode"},"imageURL":"https://github.com/chopincode.png","key":"chopincode","count":6},{"name":"Ender Demirkaya","title":"Senior Manager at Uber, Cadence. Author of the Software Engineering Handbook","url":"https://www.linkedin.com/in/enderdemirkaya/","page":{"permalink":"/blog/authors/enderdemirkaya"},"socials":{"linkedin":"https://www.linkedin.com/in/enderdemirkaya/","github":"https://github.com/demirkayaender"},"imageURL":"https://github.com/demirkayaender.png","key":"enderdemirkaya","count":2},{"name":"Jakob Haahr Taankvist","title":"Software Engineer II @ Uber","url":"https://www.linkedin.com/in/jakob-taankvist/","page":{"permalink":"/blog/authors/jakobht"},"socials":{"linkedin":"https://www.linkedin.com/in/jakob-taankvist/","github":"https://github.com/jakobht"},"imageURL":"https://github.com/jakobht.png","key":"jakobht","count":1},{"name":"Josu\xe9 Alexander Ibarra","title":"Developer Advocate @ Uber","url":"https://github.com/ibarrajo/","page":{"permalink":"/blog/authors/ibarrajo"},"socials":{"github":"https://github.com/ibarrajo","linkedin":"https://www.linkedin.com/in/elninja/"},"imageURL":"https://github.com/ibarrajo.png","key":"ibarrajo","count":1},{"name":"Kevin Corbett","title":"Open Source Community Manager | @instaclustr @NetApp","url":"https://github.com/kcorbett-netapp","page":{"permalink":"/blog/authors/kcorbett-netapp"},"socials":{"linkedin":"https://www.linkedin.com/in/kcorb95/","github":"https://github.com/kcorbett-netapp"},"imageURL":"https://github.com/kcorbett-netapp.png","key":"kcorbett-netapp","count":1},{"name":"Liang Mei","title":"Engineering Manager @ Uber","url":"https://www.linkedin.com/in/meiliang86/","page":{"permalink":"/blog/authors/meiliang-86"},"socials":{"linkedin":"https://www.linkedin.com/in/meiliang86/","github":"https://github.com/meiliang86"},"imageURL":"https://github.com/meiliang86.png","key":"meiliang86","count":2},{"name":"Sharan Foga","title":"Director of Operations & Customer Success @ Encube Technologies","url":"https://www.linkedin.com/in/sfoga/","page":{"permalink":"/blog/authors/sharanf"},"socials":{"linkedin":"https://www.linkedin.com/in/sfoga/","github":"https://github.com/sharanf"},"imageURL":"https://github.com/sharanf.png","key":"sharanf","count":19},{"name":"Taylan Isikdemir","title":"Sr. Staff Software Engineer @ Uber","url":"https://www.linkedin.com/in/taylan-isikdemir","page":{"permalink":"/blog/authors/taylanisikdemir"},"socials":{"linkedin":"https://www.linkedin.com/in/taylan-isikdemir","github":"https://github.com/taylanisikdemir"},"imageURL":"https://github.com/taylanisikdemir.png","key":"taylanisikdemir","count":1},{"name":"Vytautas Karpavicius","title":"Software Engineer @ Uber","url":"https://www.linkedin.com/in/vytautas-karpavicius","page":{"permalink":"/blog/authors/vytautas-karpavicius"},"socials":{"linkedin":"https://www.linkedin.com/in/vytautas-karpavicius","github":"https://github.com/vytautas-karpavicius"},"imageURL":"https://github.com/vytautas-karpavicius.png","key":"vytautas-karpavicius","count":1},{"name":"Zijian Chen","title":"Software Engineer @ Uber","url":"https://www.linkedin.com/in/zijian-chen-5868938b/","page":{"permalink":"/blog/authors/shaddoll"},"socials":{"linkedin":"https://www.linkedin.com/in/zijian-chen-5868938b/","github":"https://github.com/Shaddoll"},"imageURL":"https://github.com/Shaddoll.png","key":"shaddoll","count":1}]}')}}]); \ No newline at end of file diff --git a/assets/js/f09be712.35008691.js b/assets/js/f09be712.35008691.js deleted file mode 100644 index 23bbf7b4a..000000000 --- a/assets/js/f09be712.35008691.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[3493],{3122:e=>{e.exports=JSON.parse('{"author":{"name":"Liang Mei","title":"Engineering Manager @ Uber","url":"https://www.linkedin.com/in/meiliang86/","page":{"permalink":"/blog/authors/meiliang-86"},"socials":{"linkedin":"https://www.linkedin.com/in/meiliang86/","github":"https://github.com/meiliang86"},"imageURL":"https://github.com/meiliang86.png","key":"meiliang86","count":2},"listMetadata":{"permalink":"/blog/authors/meiliang-86","page":1,"postsPerPage":10,"totalPages":1,"totalCount":2,"blogDescription":"The latest news and updates from the Cadence team","blogTitle":"Cadence Blog"}}')}}]); \ No newline at end of file diff --git a/assets/js/f0ea030e.101cbb3e.js b/assets/js/f0ea030e.101cbb3e.js deleted file mode 100644 index b764b0979..000000000 --- a/assets/js/f0ea030e.101cbb3e.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[93],{1267:e=>{e.exports=JSON.parse('{"tag":{"label":"Introduction to Cadence","permalink":"/blog/tags/introduction-to-cadence","description":"Introduction to Cadence tag description","allTagsPath":"/blog/tags","count":5,"unlisted":false},"listMetadata":{"permalink":"/blog/tags/introduction-to-cadence","page":1,"postsPerPage":10,"totalPages":1,"totalCount":5,"blogDescription":"The latest news and updates from the Cadence team","blogTitle":"Cadence Blog"}}')}}]); \ No newline at end of file diff --git a/assets/js/f0efcb43.b5ca7984.js b/assets/js/f0efcb43.b5ca7984.js deleted file mode 100644 index bcc9dfc84..000000000 --- a/assets/js/f0efcb43.b5ca7984.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[4144],{71:(e,o,t)=>{t.r(o),t.d(o,{assets:()=>s,contentTitle:()=>c,default:()=>h,frontMatter:()=>i,metadata:()=>n,toc:()=>a});const n=JSON.parse('{"id":"go-client/child-workflows","title":"Child workflows","description":"workflow.ExecuteChildWorkflow enables the scheduling of otherworkflowsworkflow\'s","source":"@site/docs/05-go-client/05-child-workflows.md","sourceDirName":"05-go-client","slug":"/go-client/child-workflows","permalink":"/docs/go-client/child-workflows","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/05-go-client/05-child-workflows.md","tags":[],"version":"current","sidebarPosition":5,"frontMatter":{"layout":"default","title":"Child workflows","permalink":"/docs/go-client/child-workflows"},"sidebar":"docsSidebar","previous":{"title":"Executing activities","permalink":"/docs/go-client/execute-activity"},"next":{"title":"Activity and workflow retries","permalink":"/docs/go-client/retries"}}');var r=t(4848),l=t(8453);const i={layout:"default",title:"Child workflows",permalink:"/docs/go-client/child-workflows"},c="Child workflows",s={},a=[];function d(e){const o={code:"code",h1:"h1",header:"header",p:"p",pre:"pre",...(0,l.R)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(o.header,{children:(0,r.jsx)(o.h1,{id:"child-workflows",children:"Child workflows"})}),"\n",(0,r.jsxs)(o.p,{children:[(0,r.jsx)(o.code,{children:"workflow.ExecuteChildWorkflow"})," enables the scheduling of other workflows from within a workflow's\nimplementation. The parent workflow has the ability to monitor and impact the lifecycle of the child\nworkflow, similar to the way it does for an activity that it invoked."]}),"\n",(0,r.jsx)(o.pre,{children:(0,r.jsx)(o.code,{className:"language-go",children:'cwo := workflow.ChildWorkflowOptions{\n // Do not specify WorkflowID if you want Cadence to generate a unique ID for the child execution.\n WorkflowID: "BID-SIMPLE-CHILD-WORKFLOW",\n ExecutionStartToCloseTimeout: time.Minute * 30,\n}\nctx = workflow.WithChildWorkflowOptions(ctx, cwo)\n\nvar result string\nfuture := workflow.ExecuteChildWorkflow(ctx, SimpleChildWorkflow, value)\nif err := future.Get(ctx, &result); err != nil {\n workflow.GetLogger(ctx).Error("SimpleChildWorkflow failed.", zap.Error(err))\n return err\n}\n'})}),"\n",(0,r.jsx)(o.p,{children:"Let's take a look at each component of this call."}),"\n",(0,r.jsxs)(o.p,{children:["Before calling ",(0,r.jsx)(o.code,{children:"workflow.ExecuteChildworkflow()"}),", you must configure ",(0,r.jsx)(o.code,{children:"ChildWorkflowOptions"})," for the\ninvocation. These options customize various execution timeouts, and are passed in by creating a child\ncontext from the initial context and overwriting the desired values. The child context is then passed\ninto the ",(0,r.jsx)(o.code,{children:"workflow.ExecuteChildWorkflow()"})," call. If multiple child workflows are sharing the same option\nvalues, then the same context instance can be used when calling ",(0,r.jsx)(o.code,{children:"workflow.ExecuteChildworkflow()"}),"."]}),"\n",(0,r.jsxs)(o.p,{children:["The first parameter in the call is the required ",(0,r.jsx)(o.code,{children:"cadence.Context"})," object. This type is a copy of\n",(0,r.jsx)(o.code,{children:"context.Context"})," with the ",(0,r.jsx)(o.code,{children:"Done()"})," method returning ",(0,r.jsx)(o.code,{children:"cadence.Channel"})," instead of the native Go ",(0,r.jsx)(o.code,{children:"chan"}),"."]}),"\n",(0,r.jsx)(o.p,{children:"The second parameter is the function that we registered as a workflow function. This parameter can\nalso be a string representing the fully qualified name of the workflow function. The benefit of this\nis that when you pass in the actual function object, the framework can validate workflow parameters."}),"\n",(0,r.jsxs)(o.p,{children:["The remaining parameters are passed to the workflow as part of the call. In our example, we have a\nsingle parameter: ",(0,r.jsx)(o.code,{children:"value"}),". This list of parameters must match the list of parameters declared by\nthe workflow function."]}),"\n",(0,r.jsxs)(o.p,{children:["The method call returns immediately and returns a ",(0,r.jsx)(o.code,{children:"cadence.Future"}),". This allows you to execute more\ncode without having to wait for the scheduled workflow to complete."]}),"\n",(0,r.jsxs)(o.p,{children:["When you are ready to process the results of the workflow, call the ",(0,r.jsx)(o.code,{children:"Get()"})," method on the returned future\nobject. The parameters to this method is the ",(0,r.jsx)(o.code,{children:"ctx"})," object we passed to the\n",(0,r.jsx)(o.code,{children:"workflow.ExecuteChildWorkflow()"})," call and an output parameter that will receive the output of the\nworkflow. The type of the output parameter must match the type of the return value declared by the\nworkflow function. The ",(0,r.jsx)(o.code,{children:"Get()"})," method will block until the workflow completes and results are\navailable."]}),"\n",(0,r.jsxs)(o.p,{children:["The ",(0,r.jsx)(o.code,{children:"workflow.ExecuteChildWorkflow()"})," function is similar to ",(0,r.jsx)(o.code,{children:"workflow.ExecuteActivity()"}),". All of the\npatterns described for using ",(0,r.jsx)(o.code,{children:"workflow.ExecuteActivity()"})," apply to the ",(0,r.jsx)(o.code,{children:"workflow.ExecuteChildWorkflow()"}),"\nfunction as well."]}),"\n",(0,r.jsx)(o.p,{children:"When a parent workflow is cancelled by the user, the child workflow can be cancelled or abandoned\nbased on a configurable child policy."})]})}function h(e={}){const{wrapper:o}={...(0,l.R)(),...e.components};return o?(0,r.jsx)(o,{...e,children:(0,r.jsx)(d,{...e})}):d(e)}},8453:(e,o,t)=>{t.d(o,{R:()=>i,x:()=>c});var n=t(6540);const r={},l=n.createContext(r);function i(e){const o=n.useContext(l);return n.useMemo((function(){return"function"==typeof e?e(o):{...o,...e}}),[o,e])}function c(e){let o;return o=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:i(e.components),n.createElement(l.Provider,{value:o},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/f0efcb43.c22f362b.js b/assets/js/f0efcb43.c22f362b.js new file mode 100644 index 000000000..147eb3042 --- /dev/null +++ b/assets/js/f0efcb43.c22f362b.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[4144],{71:(e,o,t)=>{t.r(o),t.d(o,{assets:()=>s,contentTitle:()=>c,default:()=>h,frontMatter:()=>i,metadata:()=>n,toc:()=>a});const n=JSON.parse('{"id":"go-client/child-workflows","title":"Child workflows","description":"workflow.ExecuteChildWorkflow enables the scheduling of otherworkflowsworkflow\'s","source":"@site/docs/05-go-client/05-child-workflows.md","sourceDirName":"05-go-client","slug":"/go-client/child-workflows","permalink":"/Cadence-Docs/docs/go-client/child-workflows","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/05-go-client/05-child-workflows.md","tags":[],"version":"current","sidebarPosition":5,"frontMatter":{"layout":"default","title":"Child workflows","permalink":"/docs/go-client/child-workflows"},"sidebar":"docsSidebar","previous":{"title":"Executing activities","permalink":"/Cadence-Docs/docs/go-client/execute-activity"},"next":{"title":"Activity and workflow retries","permalink":"/Cadence-Docs/docs/go-client/retries"}}');var r=t(4848),l=t(8453);const i={layout:"default",title:"Child workflows",permalink:"/docs/go-client/child-workflows"},c="Child workflows",s={},a=[];function d(e){const o={code:"code",h1:"h1",header:"header",p:"p",pre:"pre",...(0,l.R)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(o.header,{children:(0,r.jsx)(o.h1,{id:"child-workflows",children:"Child workflows"})}),"\n",(0,r.jsxs)(o.p,{children:[(0,r.jsx)(o.code,{children:"workflow.ExecuteChildWorkflow"})," enables the scheduling of other workflows from within a workflow's\nimplementation. The parent workflow has the ability to monitor and impact the lifecycle of the child\nworkflow, similar to the way it does for an activity that it invoked."]}),"\n",(0,r.jsx)(o.pre,{children:(0,r.jsx)(o.code,{className:"language-go",children:'cwo := workflow.ChildWorkflowOptions{\n // Do not specify WorkflowID if you want Cadence to generate a unique ID for the child execution.\n WorkflowID: "BID-SIMPLE-CHILD-WORKFLOW",\n ExecutionStartToCloseTimeout: time.Minute * 30,\n}\nctx = workflow.WithChildWorkflowOptions(ctx, cwo)\n\nvar result string\nfuture := workflow.ExecuteChildWorkflow(ctx, SimpleChildWorkflow, value)\nif err := future.Get(ctx, &result); err != nil {\n workflow.GetLogger(ctx).Error("SimpleChildWorkflow failed.", zap.Error(err))\n return err\n}\n'})}),"\n",(0,r.jsx)(o.p,{children:"Let's take a look at each component of this call."}),"\n",(0,r.jsxs)(o.p,{children:["Before calling ",(0,r.jsx)(o.code,{children:"workflow.ExecuteChildworkflow()"}),", you must configure ",(0,r.jsx)(o.code,{children:"ChildWorkflowOptions"})," for the\ninvocation. These options customize various execution timeouts, and are passed in by creating a child\ncontext from the initial context and overwriting the desired values. The child context is then passed\ninto the ",(0,r.jsx)(o.code,{children:"workflow.ExecuteChildWorkflow()"})," call. If multiple child workflows are sharing the same option\nvalues, then the same context instance can be used when calling ",(0,r.jsx)(o.code,{children:"workflow.ExecuteChildworkflow()"}),"."]}),"\n",(0,r.jsxs)(o.p,{children:["The first parameter in the call is the required ",(0,r.jsx)(o.code,{children:"cadence.Context"})," object. This type is a copy of\n",(0,r.jsx)(o.code,{children:"context.Context"})," with the ",(0,r.jsx)(o.code,{children:"Done()"})," method returning ",(0,r.jsx)(o.code,{children:"cadence.Channel"})," instead of the native Go ",(0,r.jsx)(o.code,{children:"chan"}),"."]}),"\n",(0,r.jsx)(o.p,{children:"The second parameter is the function that we registered as a workflow function. This parameter can\nalso be a string representing the fully qualified name of the workflow function. The benefit of this\nis that when you pass in the actual function object, the framework can validate workflow parameters."}),"\n",(0,r.jsxs)(o.p,{children:["The remaining parameters are passed to the workflow as part of the call. In our example, we have a\nsingle parameter: ",(0,r.jsx)(o.code,{children:"value"}),". This list of parameters must match the list of parameters declared by\nthe workflow function."]}),"\n",(0,r.jsxs)(o.p,{children:["The method call returns immediately and returns a ",(0,r.jsx)(o.code,{children:"cadence.Future"}),". This allows you to execute more\ncode without having to wait for the scheduled workflow to complete."]}),"\n",(0,r.jsxs)(o.p,{children:["When you are ready to process the results of the workflow, call the ",(0,r.jsx)(o.code,{children:"Get()"})," method on the returned future\nobject. The parameters to this method is the ",(0,r.jsx)(o.code,{children:"ctx"})," object we passed to the\n",(0,r.jsx)(o.code,{children:"workflow.ExecuteChildWorkflow()"})," call and an output parameter that will receive the output of the\nworkflow. The type of the output parameter must match the type of the return value declared by the\nworkflow function. The ",(0,r.jsx)(o.code,{children:"Get()"})," method will block until the workflow completes and results are\navailable."]}),"\n",(0,r.jsxs)(o.p,{children:["The ",(0,r.jsx)(o.code,{children:"workflow.ExecuteChildWorkflow()"})," function is similar to ",(0,r.jsx)(o.code,{children:"workflow.ExecuteActivity()"}),". All of the\npatterns described for using ",(0,r.jsx)(o.code,{children:"workflow.ExecuteActivity()"})," apply to the ",(0,r.jsx)(o.code,{children:"workflow.ExecuteChildWorkflow()"}),"\nfunction as well."]}),"\n",(0,r.jsx)(o.p,{children:"When a parent workflow is cancelled by the user, the child workflow can be cancelled or abandoned\nbased on a configurable child policy."})]})}function h(e={}){const{wrapper:o}={...(0,l.R)(),...e.components};return o?(0,r.jsx)(o,{...e,children:(0,r.jsx)(d,{...e})}):d(e)}},8453:(e,o,t)=>{t.d(o,{R:()=>i,x:()=>c});var n=t(6540);const r={},l=n.createContext(r);function i(e){const o=n.useContext(l);return n.useMemo((function(){return"function"==typeof e?e(o):{...o,...e}}),[o,e])}function c(e){let o;return o=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:i(e.components),n.createElement(l.Provider,{value:o},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/f1de825c.301e9aa7.js b/assets/js/f1de825c.301e9aa7.js deleted file mode 100644 index 857cfc24b..000000000 --- a/assets/js/f1de825c.301e9aa7.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[9407],{4834:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>l,contentTitle:()=>r,default:()=>d,frontMatter:()=>s,metadata:()=>i,toc:()=>c});var i=t(5550),o=t(4848),a=t(8453);const s={title:"Cadence Community Spotlight Update - August 2023",date:new Date("2023-08-31T00:00:00.000Z"),authors:"sharanf",tags:["introduction-to-cadence","community-spotlight"]},r=void 0,l={authorsImageUrls:[void 0]},c=[{value:"More Cadence How To's",id:"more-cadence-how-tos",level:2},{value:"More iWF Examaples",id:"more-iwf-examaples",level:2},{value:"Cadence At the Helm!",id:"cadence-at-the-helm",level:2},{value:"Community Support!",id:"community-support",level:2},{value:"Cadence in the News!",id:"cadence-in-the-news",level:2},{value:"Upcoming Events",id:"upcoming-events",level:2}];function h(e){const n={a:"a",h2:"h2",li:"li",p:"p",ul:"ul",...(0,a.R)(),...e.components};return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsx)(n.p,{children:"Welcome to the latest of our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!"}),"\n",(0,o.jsx)(n.p,{children:"Please see below for a roundup of the highlights:"}),"\n",(0,o.jsx)(n.h2,{id:"more-cadence-how-tos",children:"More Cadence How To's"}),"\n",(0,o.jsxs)(n.p,{children:["You might have noticed that we have had a few more contributions to our blog from ",(0,o.jsx)(n.a,{href:"https://www.linkedin.com/in/chrisqin0610",children:"Chris Qin"}),". Chris has been busy sharing insights, and tips on a few important Cadence topics. The objective is to help the community with any potential problems."]}),"\n",(0,o.jsx)(n.p,{children:"Here are the latest topics:"}),"\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsxs)(n.li,{children:["\n",(0,o.jsx)(n.p,{children:(0,o.jsx)(n.a,{href:"https://cadenceworkflow.io/blog/2023/07/10/cadence-bad-practices-part-1/",children:"Bad Practices and Anti-Patterns with Cadence - Part 1"})}),"\n"]}),"\n",(0,o.jsxs)(n.li,{children:["\n",(0,o.jsx)(n.p,{children:(0,o.jsx)(n.a,{href:"https://cadenceworkflow.io/blog/2023/08/27/nondeterministic-errors-replayers-shadowers/",children:"Non-Determistic Errors, Replayers and Shadowers"})}),"\n"]}),"\n"]}),"\n",(0,o.jsx)(n.p,{children:"Even if you have not encountered these use cases - it is good to be prepared and have a solution ready.Please take a look and let us have your feedback."}),"\n",(0,o.jsxs)(n.p,{children:["Chris is also going to take a look at the ",(0,o.jsx)(n.a,{href:"https://cadenceworkflow.io/docs/java-client/client-overview/#samples",children:"Cadence Samples"})," to make sure they are all working and if not - he's going to re-write them so that they do!"]}),"\n",(0,o.jsx)(n.p,{children:"Thanks very much Chris for all the work you are doing to help improve the project!"}),"\n",(0,o.jsx)(n.h2,{id:"more-iwf-examaples",children:"More iWF Examaples"}),"\n",(0,o.jsxs)(n.p,{children:["Community member ",(0,o.jsx)(n.a,{href:"https://www.linkedin.com/in/prclqz/",children:"Quanzheng Long"})," has also been busy writing this month. In previous blogs Long has told us about ",(0,o.jsx)(n.a,{href:"https://github.com/indeedeng/iwf",children:"iWF"})," that is a layer implemented over of Cadence."]}),"\n",(0,o.jsx)(n.p,{children:"During August Long has published a couple of articles on using the 'ContinueAsNew' functionality in iWF. Links to Part 1 and Part are below:"}),"\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsxs)(n.li,{children:["\n",(0,o.jsx)(n.p,{children:(0,o.jsx)(n.a,{href:"https://medium.com/@qlong/guide-to-continueasnew-in-cadence-temporal-workflow-using-iwf-as-an-example-part-2-cedabd732bec",children:"Guide to ContinueAsNew in Cadence/Temporal Workflow Using iWF as an example - Part 1"})}),"\n"]}),"\n",(0,o.jsxs)(n.li,{children:["\n",(0,o.jsx)(n.p,{children:(0,o.jsx)(n.a,{href:"https://medium.com/@qlong/guide-to-continueasnew-in-cadence-temporal-workflow-using-iwf-as-an-example-part-1-c24ae5266f07",children:"Guide to ContinueAsNew in Cadence/Temporal Workflow Using iWF as an example - Part 2"})}),"\n"]}),"\n"]}),"\n",(0,o.jsx)(n.p,{children:"Please take a look and if you've enjoyed reading them then let Long and us know!"}),"\n",(0,o.jsx)(n.h2,{id:"cadence-at-the-helm",children:"Cadence At the Helm!"}),"\n",(0,o.jsxs)(n.p,{children:["Last month we mentioned the Cadence Helm charts and all the previous work that had been done by ",(0,o.jsx)(n.a,{href:"https://www.linkedin.com/in/sagikazarmark/",children:"Mark Sagi-Kazar"}),". We were looking to ensure they are maintained."]}),"\n",(0,o.jsxs)(n.p,{children:["So a special thanks goes out this month to ",(0,o.jsx)(n.a,{href:"ttps://github.com/edmondop",children:"Edmondo"})," for contributing some work on the ",(0,o.jsx)(n.a,{href:"https://github.com/edmondop/cadence-helm-chart/",children:"Cadence Helm Chart"}),"."]}),"\n",(0,o.jsx)(n.h2,{id:"community-support",children:"Community Support!"}),"\n",(0,o.jsxs)(n.p,{children:["Our ",(0,o.jsx)(n.a,{href:"http://t.uber.com/cadence-slack",children:"Slack"})," channel continues to be the main place where people are asking for help and support with Cadence. During August (which is supposed to be holiday season), we still had 9 questions raised around various topics."]}),"\n",(0,o.jsx)(n.p,{children:"Huge thanks to the following community members who took time to respond and help others: David, Edmondo, Chris Qin, Rony Rahman and Ben Slater."}),"\n",(0,o.jsx)(n.p,{children:"It's good to see that we are continuing to support each other - doing exactly what communities do!"}),"\n",(0,o.jsx)(n.h2,{id:"cadence-in-the-news",children:"Cadence in the News!"}),"\n",(0,o.jsx)(n.p,{children:"Below are a selection of Cadence related articles, blogs and whitepapers.\nPlease take a look and feel free to share via your own social media channels."}),"\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsxs)(n.li,{children:["\n",(0,o.jsx)(n.p,{children:(0,o.jsx)(n.a,{href:"https://medium.com/@qlong/guide-to-continueasnew-in-cadence-temporal-workflow-using-iwf-as-an-example-part-2-cedabd732bec",children:"Guide to ContinueAsNew in Cadence/Temporal Workflow Using iWF as an example - Part 1"})}),"\n"]}),"\n",(0,o.jsxs)(n.li,{children:["\n",(0,o.jsx)(n.p,{children:(0,o.jsx)(n.a,{href:"https://medium.com/@qlong/guide-to-continueasnew-in-cadence-temporal-workflow-using-iwf-as-an-example-part-1-c24ae5266f07",children:"Guide to ContinueAsNew in Cadence/Temporal Workflow Using iWF as an example - Part 2"})}),"\n"]}),"\n",(0,o.jsxs)(n.li,{children:["\n",(0,o.jsx)(n.p,{children:(0,o.jsx)(n.a,{href:"https://www.instaclustr.com/blog/aws-privatelink-for-cadence-on-instaclustr-by-netapp/",children:"AWS PrivateLink Connectivity is now Available with Instaclustr for Cadence"})}),"\n"]}),"\n"]}),"\n",(0,o.jsx)(n.h2,{id:"upcoming-events",children:"Upcoming Events"}),"\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsxs)(n.li,{children:["\n",(0,o.jsx)(n.p,{children:(0,o.jsx)(n.a,{href:"https://netapp.zoom.us/webinar/register/WN_Uh9Y6ruiQSS5EiylNlsMug#/registration",children:"Webinar: Introducing the Cadence Workflow HTTP API - 21st September 2023 "})}),"\n"]}),"\n",(0,o.jsxs)(n.li,{children:["\n",(0,o.jsx)(n.p,{children:(0,o.jsx)(n.a,{href:"https://netapp.zoom.us/webinar/register/WN_Hv9lO9QtSqyPPWkSAIRj5g#/registration",children:"On Demand Webinar: Microservices - A Modern Orchestration Approach with Cadence"})}),"\n"]}),"\n",(0,o.jsxs)(n.li,{children:["\n",(0,o.jsx)(n.p,{children:(0,o.jsx)(n.a,{href:"https://www.instaclustr.com/events/spinning-your-drones-with-cadence-and-apache-kafka/",children:"On Demand Webinar: Spinning Your Drones with Cadence and Apache Kafka"})}),"\n"]}),"\n"]}),"\n",(0,o.jsxs)(n.p,{children:["If you have any news or topics you'd like us to include in our next update then please join our ",(0,o.jsx)(n.a,{href:"http://t.uber.com/cadence-slack",children:"Slack"})," #community channel."]}),"\n",(0,o.jsxs)(n.p,{children:["Please remember that this update is for you - so if you have any comments or feedback that could help us improve it then please share it with us in the #community ",(0,o.jsx)(n.a,{href:"http://t.uber.com/cadence-slack",children:"Slack"})," channel."]})]})}function d(e={}){const{wrapper:n}={...(0,a.R)(),...e.components};return n?(0,o.jsx)(n,{...e,children:(0,o.jsx)(h,{...e})}):h(e)}},8453:(e,n,t)=>{t.d(n,{R:()=>s,x:()=>r});var i=t(6540);const o={},a=i.createContext(o);function s(e){const n=i.useContext(a);return i.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function r(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:s(e.components),i.createElement(a.Provider,{value:n},e.children)}},5550:e=>{e.exports=JSON.parse('{"permalink":"/blog/2023/08/31/community-spotlight-august-2023","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2023-08-31-community-spotlight-august-2023.md","source":"@site/blog/2023-08-31-community-spotlight-august-2023.md","title":"Cadence Community Spotlight Update - August 2023","description":"Welcome to the latest of our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!","date":"2023-08-31T00:00:00.000Z","tags":[{"inline":false,"label":"Introduction to Cadence","permalink":"/blog/tags/introduction-to-cadence","description":"Introduction to Cadence tag description"},{"inline":false,"label":"Community Spotlight","permalink":"/blog/tags/community-spotlights","description":"Community Spotlight tag description"}],"readingTime":2.955,"hasTruncateMarker":true,"authors":[{"name":"Sharan Foga","title":"Director of Operations & Customer Success @ Encube Technologies","url":"https://www.linkedin.com/in/sfoga/","page":{"permalink":"/blog/authors/sharanf"},"socials":{"linkedin":"https://www.linkedin.com/in/sfoga/","github":"https://github.com/sharanf"},"imageURL":"https://github.com/sharanf.png","key":"sharanf"}],"frontMatter":{"title":"Cadence Community Spotlight Update - August 2023","date":"2023-08-31T00:00:00.000Z","authors":"sharanf","tags":["introduction-to-cadence","community-spotlight"]},"unlisted":false,"prevItem":{"title":"Cadence Community Spotlight Update - November 2023","permalink":"/blog/2023/11/30/community-spotlight-update-november-2023"},"nextItem":{"title":"Non-deterministic errors, replayers and shadowers","permalink":"/blog/2023/08/28/nondeterministic-errors-replayers-shadowers"}}')}}]); \ No newline at end of file diff --git a/assets/js/f1de825c.b641c329.js b/assets/js/f1de825c.b641c329.js new file mode 100644 index 000000000..d3364fe31 --- /dev/null +++ b/assets/js/f1de825c.b641c329.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[9407],{4834:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>c,contentTitle:()=>r,default:()=>d,frontMatter:()=>s,metadata:()=>o,toc:()=>l});var o=t(5550),i=t(4848),a=t(8453);const s={title:"Cadence Community Spotlight Update - August 2023",date:new Date("2023-08-31T00:00:00.000Z"),authors:"sharanf",tags:["introduction-to-cadence","community-spotlight"]},r=void 0,c={authorsImageUrls:[void 0]},l=[{value:"More Cadence How To's",id:"more-cadence-how-tos",level:2},{value:"More iWF Examaples",id:"more-iwf-examaples",level:2},{value:"Cadence At the Helm!",id:"cadence-at-the-helm",level:2},{value:"Community Support!",id:"community-support",level:2},{value:"Cadence in the News!",id:"cadence-in-the-news",level:2},{value:"Upcoming Events",id:"upcoming-events",level:2}];function h(e){const n={a:"a",h2:"h2",li:"li",p:"p",ul:"ul",...(0,a.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.p,{children:"Welcome to the latest of our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!"}),"\n",(0,i.jsx)(n.p,{children:"Please see below for a roundup of the highlights:"}),"\n",(0,i.jsx)(n.h2,{id:"more-cadence-how-tos",children:"More Cadence How To's"}),"\n",(0,i.jsxs)(n.p,{children:["You might have noticed that we have had a few more contributions to our blog from ",(0,i.jsx)(n.a,{href:"https://www.linkedin.com/in/chrisqin0610",children:"Chris Qin"}),". Chris has been busy sharing insights, and tips on a few important Cadence topics. The objective is to help the community with any potential problems."]}),"\n",(0,i.jsx)(n.p,{children:"Here are the latest topics:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://cadenceworkflow.io/blog/2023/07/10/cadence-bad-practices-part-1/",children:"Bad Practices and Anti-Patterns with Cadence - Part 1"})}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://cadenceworkflow.io/blog/2023/08/27/nondeterministic-errors-replayers-shadowers/",children:"Non-Determistic Errors, Replayers and Shadowers"})}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Even if you have not encountered these use cases - it is good to be prepared and have a solution ready.Please take a look and let us have your feedback."}),"\n",(0,i.jsxs)(n.p,{children:["Chris is also going to take a look at the ",(0,i.jsx)(n.a,{href:"https://cadenceworkflow.io/docs/java-client/client-overview/#samples",children:"Cadence Samples"})," to make sure they are all working and if not - he's going to re-write them so that they do!"]}),"\n",(0,i.jsx)(n.p,{children:"Thanks very much Chris for all the work you are doing to help improve the project!"}),"\n",(0,i.jsx)(n.h2,{id:"more-iwf-examaples",children:"More iWF Examaples"}),"\n",(0,i.jsxs)(n.p,{children:["Community member ",(0,i.jsx)(n.a,{href:"https://www.linkedin.com/in/prclqz/",children:"Quanzheng Long"})," has also been busy writing this month. In previous blogs Long has told us about ",(0,i.jsx)(n.a,{href:"https://github.com/indeedeng/iwf",children:"iWF"})," that is a layer implemented over of Cadence."]}),"\n",(0,i.jsx)(n.p,{children:"During August Long has published a couple of articles on using the 'ContinueAsNew' functionality in iWF. Links to Part 1 and Part are below:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://medium.com/@qlong/guide-to-continueasnew-in-cadence-temporal-workflow-using-iwf-as-an-example-part-2-cedabd732bec",children:"Guide to ContinueAsNew in Cadence/Temporal Workflow Using iWF as an example - Part 1"})}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://medium.com/@qlong/guide-to-continueasnew-in-cadence-temporal-workflow-using-iwf-as-an-example-part-1-c24ae5266f07",children:"Guide to ContinueAsNew in Cadence/Temporal Workflow Using iWF as an example - Part 2"})}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Please take a look and if you've enjoyed reading them then let Long and us know!"}),"\n",(0,i.jsx)(n.h2,{id:"cadence-at-the-helm",children:"Cadence At the Helm!"}),"\n",(0,i.jsxs)(n.p,{children:["Last month we mentioned the Cadence Helm charts and all the previous work that had been done by ",(0,i.jsx)(n.a,{href:"https://www.linkedin.com/in/sagikazarmark/",children:"Mark Sagi-Kazar"}),". We were looking to ensure they are maintained."]}),"\n",(0,i.jsxs)(n.p,{children:["So a special thanks goes out this month to ",(0,i.jsx)(n.a,{href:"ttps://github.com/edmondop",children:"Edmondo"})," for contributing some work on the ",(0,i.jsx)(n.a,{href:"https://github.com/edmondop/cadence-helm-chart/",children:"Cadence Helm Chart"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"community-support",children:"Community Support!"}),"\n",(0,i.jsxs)(n.p,{children:["Our ",(0,i.jsx)(n.a,{href:"http://t.uber.com/cadence-slack",children:"Slack"})," channel continues to be the main place where people are asking for help and support with Cadence. During August (which is supposed to be holiday season), we still had 9 questions raised around various topics."]}),"\n",(0,i.jsx)(n.p,{children:"Huge thanks to the following community members who took time to respond and help others: David, Edmondo, Chris Qin, Rony Rahman and Ben Slater."}),"\n",(0,i.jsx)(n.p,{children:"It's good to see that we are continuing to support each other - doing exactly what communities do!"}),"\n",(0,i.jsx)(n.h2,{id:"cadence-in-the-news",children:"Cadence in the News!"}),"\n",(0,i.jsx)(n.p,{children:"Below are a selection of Cadence related articles, blogs and whitepapers.\nPlease take a look and feel free to share via your own social media channels."}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://medium.com/@qlong/guide-to-continueasnew-in-cadence-temporal-workflow-using-iwf-as-an-example-part-2-cedabd732bec",children:"Guide to ContinueAsNew in Cadence/Temporal Workflow Using iWF as an example - Part 1"})}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://medium.com/@qlong/guide-to-continueasnew-in-cadence-temporal-workflow-using-iwf-as-an-example-part-1-c24ae5266f07",children:"Guide to ContinueAsNew in Cadence/Temporal Workflow Using iWF as an example - Part 2"})}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://www.instaclustr.com/blog/aws-privatelink-for-cadence-on-instaclustr-by-netapp/",children:"AWS PrivateLink Connectivity is now Available with Instaclustr for Cadence"})}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.h2,{id:"upcoming-events",children:"Upcoming Events"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://netapp.zoom.us/webinar/register/WN_Uh9Y6ruiQSS5EiylNlsMug#/registration",children:"Webinar: Introducing the Cadence Workflow HTTP API - 21st September 2023 "})}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://netapp.zoom.us/webinar/register/WN_Hv9lO9QtSqyPPWkSAIRj5g#/registration",children:"On Demand Webinar: Microservices - A Modern Orchestration Approach with Cadence"})}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://www.instaclustr.com/events/spinning-your-drones-with-cadence-and-apache-kafka/",children:"On Demand Webinar: Spinning Your Drones with Cadence and Apache Kafka"})}),"\n"]}),"\n"]}),"\n",(0,i.jsxs)(n.p,{children:["If you have any news or topics you'd like us to include in our next update then please join our ",(0,i.jsx)(n.a,{href:"http://t.uber.com/cadence-slack",children:"Slack"})," #community channel."]}),"\n",(0,i.jsxs)(n.p,{children:["Please remember that this update is for you - so if you have any comments or feedback that could help us improve it then please share it with us in the #community ",(0,i.jsx)(n.a,{href:"http://t.uber.com/cadence-slack",children:"Slack"})," channel."]})]})}function d(e={}){const{wrapper:n}={...(0,a.R)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(h,{...e})}):h(e)}},8453:(e,n,t)=>{t.d(n,{R:()=>s,x:()=>r});var o=t(6540);const i={},a=o.createContext(i);function s(e){const n=o.useContext(a);return o.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function r(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:s(e.components),o.createElement(a.Provider,{value:n},e.children)}},5550:e=>{e.exports=JSON.parse('{"permalink":"/Cadence-Docs/blog/2023/08/31/community-spotlight-august-2023","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2023-08-31-community-spotlight-august-2023.md","source":"@site/blog/2023-08-31-community-spotlight-august-2023.md","title":"Cadence Community Spotlight Update - August 2023","description":"Welcome to the latest of our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!","date":"2023-08-31T00:00:00.000Z","tags":[{"inline":false,"label":"Introduction to Cadence","permalink":"/Cadence-Docs/blog/tags/introduction-to-cadence","description":"Introduction to Cadence tag description"},{"inline":false,"label":"Community Spotlight","permalink":"/Cadence-Docs/blog/tags/community-spotlights","description":"Community Spotlight tag description"}],"readingTime":2.955,"hasTruncateMarker":true,"authors":[{"name":"Sharan Foga","title":"Director of Operations & Customer Success @ Encube Technologies","url":"https://www.linkedin.com/in/sfoga/","page":{"permalink":"/Cadence-Docs/blog/authors/sharanf"},"socials":{"linkedin":"https://www.linkedin.com/in/sfoga/","github":"https://github.com/sharanf"},"imageURL":"https://github.com/sharanf.png","key":"sharanf"}],"frontMatter":{"title":"Cadence Community Spotlight Update - August 2023","date":"2023-08-31T00:00:00.000Z","authors":"sharanf","tags":["introduction-to-cadence","community-spotlight"]},"unlisted":false,"prevItem":{"title":"Cadence Community Spotlight Update - November 2023","permalink":"/Cadence-Docs/blog/2023/11/30/community-spotlight-update-november-2023"},"nextItem":{"title":"Non-deterministic errors, replayers and shadowers","permalink":"/Cadence-Docs/blog/2023/08/28/nondeterministic-errors-replayers-shadowers"}}')}}]); \ No newline at end of file diff --git a/assets/js/f2a162ea.03af1bea.js b/assets/js/f2a162ea.03af1bea.js deleted file mode 100644 index 433d3c02c..000000000 --- a/assets/js/f2a162ea.03af1bea.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[3087],{1592:(e,n,o)=>{o.r(n),o.d(n,{assets:()=>s,contentTitle:()=>i,default:()=>h,frontMatter:()=>r,metadata:()=>t,toc:()=>c});const t=JSON.parse('{"id":"java-client/signals","title":"Signals","description":"Signalsworkflow:. Previously, you had","source":"@site/docs/04-java-client/10-signals.md","sourceDirName":"04-java-client","slug":"/java-client/signals","permalink":"/docs/java-client/signals","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/04-java-client/10-signals.md","tags":[],"version":"current","sidebarPosition":10,"frontMatter":{"layout":"default","title":"Signals","permalink":"/docs/java-client/signals"},"sidebar":"docsSidebar","previous":{"title":"Worker service","permalink":"/docs/java-client/workers"},"next":{"title":"Queries","permalink":"/docs/java-client/queries"}}');var a=o(4848),l=o(8453);const r={layout:"default",title:"Signals",permalink:"/docs/java-client/signals"},i="Signals",s={},c=[{value:"Implement Signal Handler in Workflow",id:"implement-signal-handler-in-workflow",level:2},{value:"Signal From Command Line",id:"signal-from-command-line",level:2},{value:"SignalWithStart From Command Line",id:"signalwithstart-from-command-line",level:2},{value:"Signal from user/application code",id:"signal-from-userapplication-code",level:2}];function d(e){const n={a:"a",code:"code",em:"em",h1:"h1",h2:"h2",header:"header",li:"li",p:"p",pre:"pre",ul:"ul",...(0,l.R)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(n.header,{children:(0,a.jsx)(n.h1,{id:"signals",children:"Signals"})}),"\n",(0,a.jsx)(n.p,{children:"Signals provide a mechanism to send data directly to a running workflow. Previously, you had\ntwo options for passing data to the workflow implementation:"}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsx)(n.li,{children:"Via start parameters"}),"\n",(0,a.jsx)(n.li,{children:"As return values from activities"}),"\n"]}),"\n",(0,a.jsx)(n.p,{children:"With start parameters, we could only pass in values before workflow_execution began."}),"\n",(0,a.jsx)(n.p,{children:"Return values from activities allowed us to pass information to a running workflow, but this\napproach comes with its own complications. One major drawback is reliance on polling. This means\nthat the data needs to be stored in a third-party location until it's ready to be picked up by\nthe activity. Further, the lifecycle of this activity requires management, and the activity\nrequires manual restart if it fails before acquiring the data."}),"\n",(0,a.jsx)(n.p,{children:"Signals, on the other hand, provide a fully asynchronous and durable mechanism for providing data to\na running workflow. When a signal is received for a running workflow, Cadence persists the event\nand the payload in the workflow history. The workflow can then process the signal at any time\nafterwards without the risk of losing the information. The workflow also has the option to stop\nexecution by blocking on a signal channel."}),"\n",(0,a.jsx)(n.h2,{id:"implement-signal-handler-in-workflow",children:"Implement Signal Handler in Workflow"}),"\n",(0,a.jsxs)(n.p,{children:["See the below example from ",(0,a.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence-java-samples/blob/master/src/main/java/com/uber/cadence/samples/hello/HelloSignal.java",children:"sample"}),"."]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-java",children:'public interface HelloWorld {\n @WorkflowMethod\n void sayHello(String name);\n\n @SignalMethod\n void updateGreeting(String greeting);\n}\n\npublic static class HelloWorldImpl implements HelloWorld {\n\n private String greeting = "Hello";\n\n @Override\n public void sayHello(String name) {\n int count = 0;\n while (!"Bye".equals(greeting)) {\n logger.info(++count + ": " + greeting + " " + name + "!");\n String oldGreeting = greeting;\n Workflow.await(() -> !Objects.equals(greeting, oldGreeting));\n }\n logger.info(++count + ": " + greeting + " " + name + "!");\n }\n\n @Override\n public void updateGreeting(String greeting) {\n this.greeting = greeting;\n }\n}\n'})}),"\n",(0,a.jsxs)(n.p,{children:['The workflow interface now has a new method annotated with @SignalMethod. It is a callback method that is invoked\nevery time a new signal of "HelloWorldupdateGreeting" is delivered to a workflow. The workflow interface can have only\none @WorkflowMethod which is a ',(0,a.jsx)(n.em,{children:"main"})," function of the workflow and as many signal methods as needed."]}),"\n",(0,a.jsxs)(n.p,{children:["The updated workflow implementation demonstrates a few important Cadence concepts. The first is that workflow is stateful and can\nhave fields of any complex type. Another is that the ",(0,a.jsx)(n.code,{children:"Workflow.await"})," function that blocks until the function it receives as a parameter evaluates to true. The condition is going to be evaluated only on workflow state changes, so it is not a busy wait in traditional sense."]}),"\n",(0,a.jsx)(n.h2,{id:"signal-from-command-line",children:"Signal From Command Line"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-bash",children:'cadence: docker run --network=host --rm ubercadence/cli:master --do test-domain workflow start --workflow_id "HelloSignal" --tasklist HelloWorldTaskList --workflow_type HelloWorld::sayHello --execution_timeout 3600 --input \\"World\\"\nStarted Workflow Id: HelloSignal, run Id: 6fa204cb-f478-469a-9432-78060b83b6cd\n'})}),"\n",(0,a.jsx)(n.p,{children:"Program output:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-bash",children:"16:53:56.120 [workflow-root] INFO c.u.c.samples.hello.GettingStarted - 1: Hello World!\n"})}),"\n",(0,a.jsx)(n.p,{children:"Let's send a signal using "}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-bash",children:'cadence: docker run --network=host --rm ubercadence/cli:master --do test-domain workflow signal --workflow_id "HelloSignal" --name "HelloWorld::updateGreeting" --input \\"Hi\\"\nSignal workflow succeeded.\n'})}),"\n",(0,a.jsx)(n.p,{children:"Program output:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-bash",children:"16:53:56.120 [workflow-root] INFO c.u.c.samples.hello.GettingStarted - 1: Hello World!\n16:54:57.901 [workflow-root] INFO c.u.c.samples.hello.GettingStarted - 2: Hi World!\n"})}),"\n",(0,a.jsx)(n.p,{children:"Try sending the same signal with the same input again. Note that the output doesn't change. This happens because the await condition\ndoesn't unblock when it sees the same value. But a new greeting unblocks it:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-bash",children:'cadence: docker run --network=host --rm ubercadence/cli:master --do test-domain workflow signal --workflow_id "HelloSignal" --name "HelloWorld::updateGreeting" --input \\"Welcome\\"\nSignal workflow succeeded.\n'})}),"\n",(0,a.jsx)(n.p,{children:"Program output:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-bash",children:"16:53:56.120 [workflow-root] INFO c.u.c.samples.hello.GettingStarted - 1: Hello World!\n16:54:57.901 [workflow-root] INFO c.u.c.samples.hello.GettingStarted - 2: Hi World!\n16:56:24.400 [workflow-root] INFO c.u.c.samples.hello.GettingStarted - 3: Welcome World!\n"})}),"\n",(0,a.jsx)(n.p,{children:"Now shut down the worker and send the same signal again:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-bash",children:'cadence: docker run --network=host --rm ubercadence/cli:master --do test-domain workflow signal --workflow_id "HelloSignal" --name "HelloWorld::updateGreeting" --input \\"Welcome\\"\nSignal workflow succeeded.\n'})}),"\n",(0,a.jsx)(n.p,{children:"Note that sending signals as well as starting workflows does not need a worker running. The requests are queued inside the Cadence service."}),"\n",(0,a.jsx)(n.p,{children:"Now bring the worker back. Note that it doesn't log anything besides the standard startup messages.\nThis occurs because it ignores the queued signal that contains the same input as the current value of greeting.\nNote that the restart of the worker didn't affect the workflow_execution. It is still blocked on the same line of code as before the failure.\nThis is the most important feature of Cadence. The workflow code doesn't need to deal with worker failures at all. Its state is fully recovered to its current state that includes all the local variables and threads."}),"\n",(0,a.jsx)(n.p,{children:"Let's look at the line where the workflow is blocked:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-sh-session",children:'$ docker run --network=host --rm ubercadence/cli:master --do test-domain workflow stack --workflow_id "Hello2"\nQuery result:\n"workflow-root: (BLOCKED on await)\ncom.uber.cadence.internal.sync.SyncDecisionContext.await(SyncDecisionContext.java:546)\ncom.uber.cadence.internal.sync.WorkflowInternal.await(WorkflowInternal.java:243)\ncom.uber.cadence.workflow.Workflow.await(Workflow.java:611)\ncom.uber.cadence.samples.hello.GettingStarted$HelloWorldImpl.sayHello(GettingStarted.java:32)\nsun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)\nsun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)"\n'})}),"\n",(0,a.jsx)(n.p,{children:'Yes, indeed the workflow is blocked on await. This feature works for any open workflow, greatly simplifying troubleshooting in production.\nLet\'s complete the workflow by sending a signal with a "Bye" greeting:'}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-log",children:"16:58:22.962 [workflow-root] INFO c.u.c.samples.hello.GettingStarted - 4: Bye World!\n"})}),"\n",(0,a.jsx)(n.p,{children:"Note that the value of the count variable was not lost during the restart."}),"\n",(0,a.jsx)(n.p,{children:"Also note that while a single worker instance is used for this\nwalkthrough, any real production deployment has multiple worker instances running. So any worker failure or restart does not delay any\nworkflow_execution because it is just migrated to any other available worker."}),"\n",(0,a.jsx)(n.h2,{id:"signalwithstart-from-command-line",children:"SignalWithStart From Command Line"}),"\n",(0,a.jsxs)(n.p,{children:["You may not know if a workflow is running and can accept a signal.\nThe signalWithStart feature allows you to send a signal to the current workflow instance if one exists or to create a new\nrun and then send the signal. ",(0,a.jsx)(n.code,{children:"SignalWithStartWorkflow"})," therefore doesn't take a run_ID as a\nparameter."]}),"\n",(0,a.jsxs)(n.p,{children:["Learn more from the ",(0,a.jsx)(n.code,{children:"--help"})," manual:"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-sh-session",children:"$ docker run --network=host --rm ubercadence/cli:master --do test-domain workflow signalwithstart -h\nNAME:\n cadence workflow signalwithstart - signal the current open workflow if exists, or attempt to start a new run based on IDResuePolicy and signals it\n\nUSAGE:\n cadence workflow signalwithstart [command options] [arguments...]\n...\n...\n...\n"})}),"\n",(0,a.jsx)(n.h2,{id:"signal-from-userapplication-code",children:"Signal from user/application code"}),"\n",(0,a.jsx)(n.p,{children:"You may want to signal workflows without running the command line."}),"\n",(0,a.jsxs)(n.p,{children:["The\n",(0,a.jsx)(n.a,{href:"https://www.javadoc.io/doc/com.uber.cadence/cadence-client/latest/com/cadence-workflow/cadence/client/WorkflowClient.html",children:"WorkflowClient"})," API allows you to send signal (or SignalWithStartWorkflow) from outside of the workflow\nto send a signal to the current workflow."]}),"\n",(0,a.jsxs)(n.p,{children:["Note that when using ",(0,a.jsx)(n.code,{children:"newWorkflowStub"})," to signal a workflow, you MUST NOT passing WorkflowOptions."]}),"\n",(0,a.jsxs)(n.p,{children:["The ",(0,a.jsx)(n.a,{href:"https://www.javadoc.io/static/com.uber.cadence/cadence-client/2.7.9-alpha/com/cadence-workflow/cadence/client/WorkflowClient.html#newWorkflowStub-java.lang.Class-com.uber.cadence.client.WorkflowOptions-",children:"WorkflowStub"})," with WorkflowOptions is only for starting workflows."]}),"\n",(0,a.jsxs)(n.p,{children:["The ",(0,a.jsx)(n.a,{href:"https://www.javadoc.io/static/com.uber.cadence/cadence-client/2.7.9-alpha/com/cadence-workflow/cadence/client/WorkflowClient.html#newWorkflowStub-java.lang.Class-java.lang.String-",children:"WorkflowStub"})," without WorkflowOptions is for signal or ",(0,a.jsx)(n.a,{href:"/docs/java-client/queries",children:"query"})]})]})}function h(e={}){const{wrapper:n}={...(0,l.R)(),...e.components};return n?(0,a.jsx)(n,{...e,children:(0,a.jsx)(d,{...e})}):d(e)}},8453:(e,n,o)=>{o.d(n,{R:()=>r,x:()=>i});var t=o(6540);const a={},l=t.createContext(a);function r(e){const n=t.useContext(l);return t.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function i(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:r(e.components),t.createElement(l.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/f2a162ea.660341e3.js b/assets/js/f2a162ea.660341e3.js new file mode 100644 index 000000000..c8b072c39 --- /dev/null +++ b/assets/js/f2a162ea.660341e3.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[3087],{1592:(e,n,o)=>{o.r(n),o.d(n,{assets:()=>s,contentTitle:()=>i,default:()=>h,frontMatter:()=>r,metadata:()=>t,toc:()=>c});const t=JSON.parse('{"id":"java-client/signals","title":"Signals","description":"Signalsworkflow:. Previously, you had","source":"@site/docs/04-java-client/10-signals.md","sourceDirName":"04-java-client","slug":"/java-client/signals","permalink":"/Cadence-Docs/docs/java-client/signals","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/04-java-client/10-signals.md","tags":[],"version":"current","sidebarPosition":10,"frontMatter":{"layout":"default","title":"Signals","permalink":"/docs/java-client/signals"},"sidebar":"docsSidebar","previous":{"title":"Worker service","permalink":"/Cadence-Docs/docs/java-client/workers"},"next":{"title":"Queries","permalink":"/Cadence-Docs/docs/java-client/queries"}}');var a=o(4848),l=o(8453);const r={layout:"default",title:"Signals",permalink:"/docs/java-client/signals"},i="Signals",s={},c=[{value:"Implement Signal Handler in Workflow",id:"implement-signal-handler-in-workflow",level:2},{value:"Signal From Command Line",id:"signal-from-command-line",level:2},{value:"SignalWithStart From Command Line",id:"signalwithstart-from-command-line",level:2},{value:"Signal from user/application code",id:"signal-from-userapplication-code",level:2}];function d(e){const n={a:"a",code:"code",em:"em",h1:"h1",h2:"h2",header:"header",li:"li",p:"p",pre:"pre",ul:"ul",...(0,l.R)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(n.header,{children:(0,a.jsx)(n.h1,{id:"signals",children:"Signals"})}),"\n",(0,a.jsx)(n.p,{children:"Signals provide a mechanism to send data directly to a running workflow. Previously, you had\ntwo options for passing data to the workflow implementation:"}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsx)(n.li,{children:"Via start parameters"}),"\n",(0,a.jsx)(n.li,{children:"As return values from activities"}),"\n"]}),"\n",(0,a.jsx)(n.p,{children:"With start parameters, we could only pass in values before workflow_execution began."}),"\n",(0,a.jsx)(n.p,{children:"Return values from activities allowed us to pass information to a running workflow, but this\napproach comes with its own complications. One major drawback is reliance on polling. This means\nthat the data needs to be stored in a third-party location until it's ready to be picked up by\nthe activity. Further, the lifecycle of this activity requires management, and the activity\nrequires manual restart if it fails before acquiring the data."}),"\n",(0,a.jsx)(n.p,{children:"Signals, on the other hand, provide a fully asynchronous and durable mechanism for providing data to\na running workflow. When a signal is received for a running workflow, Cadence persists the event\nand the payload in the workflow history. The workflow can then process the signal at any time\nafterwards without the risk of losing the information. The workflow also has the option to stop\nexecution by blocking on a signal channel."}),"\n",(0,a.jsx)(n.h2,{id:"implement-signal-handler-in-workflow",children:"Implement Signal Handler in Workflow"}),"\n",(0,a.jsxs)(n.p,{children:["See the below example from ",(0,a.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence-java-samples/blob/master/src/main/java/com/uber/cadence/samples/hello/HelloSignal.java",children:"sample"}),"."]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-java",children:'public interface HelloWorld {\n @WorkflowMethod\n void sayHello(String name);\n\n @SignalMethod\n void updateGreeting(String greeting);\n}\n\npublic static class HelloWorldImpl implements HelloWorld {\n\n private String greeting = "Hello";\n\n @Override\n public void sayHello(String name) {\n int count = 0;\n while (!"Bye".equals(greeting)) {\n logger.info(++count + ": " + greeting + " " + name + "!");\n String oldGreeting = greeting;\n Workflow.await(() -> !Objects.equals(greeting, oldGreeting));\n }\n logger.info(++count + ": " + greeting + " " + name + "!");\n }\n\n @Override\n public void updateGreeting(String greeting) {\n this.greeting = greeting;\n }\n}\n'})}),"\n",(0,a.jsxs)(n.p,{children:['The workflow interface now has a new method annotated with @SignalMethod. It is a callback method that is invoked\nevery time a new signal of "HelloWorldupdateGreeting" is delivered to a workflow. The workflow interface can have only\none @WorkflowMethod which is a ',(0,a.jsx)(n.em,{children:"main"})," function of the workflow and as many signal methods as needed."]}),"\n",(0,a.jsxs)(n.p,{children:["The updated workflow implementation demonstrates a few important Cadence concepts. The first is that workflow is stateful and can\nhave fields of any complex type. Another is that the ",(0,a.jsx)(n.code,{children:"Workflow.await"})," function that blocks until the function it receives as a parameter evaluates to true. The condition is going to be evaluated only on workflow state changes, so it is not a busy wait in traditional sense."]}),"\n",(0,a.jsx)(n.h2,{id:"signal-from-command-line",children:"Signal From Command Line"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-bash",children:'cadence: docker run --network=host --rm ubercadence/cli:master --do test-domain workflow start --workflow_id "HelloSignal" --tasklist HelloWorldTaskList --workflow_type HelloWorld::sayHello --execution_timeout 3600 --input \\"World\\"\nStarted Workflow Id: HelloSignal, run Id: 6fa204cb-f478-469a-9432-78060b83b6cd\n'})}),"\n",(0,a.jsx)(n.p,{children:"Program output:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-bash",children:"16:53:56.120 [workflow-root] INFO c.u.c.samples.hello.GettingStarted - 1: Hello World!\n"})}),"\n",(0,a.jsx)(n.p,{children:"Let's send a signal using "}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-bash",children:'cadence: docker run --network=host --rm ubercadence/cli:master --do test-domain workflow signal --workflow_id "HelloSignal" --name "HelloWorld::updateGreeting" --input \\"Hi\\"\nSignal workflow succeeded.\n'})}),"\n",(0,a.jsx)(n.p,{children:"Program output:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-bash",children:"16:53:56.120 [workflow-root] INFO c.u.c.samples.hello.GettingStarted - 1: Hello World!\n16:54:57.901 [workflow-root] INFO c.u.c.samples.hello.GettingStarted - 2: Hi World!\n"})}),"\n",(0,a.jsx)(n.p,{children:"Try sending the same signal with the same input again. Note that the output doesn't change. This happens because the await condition\ndoesn't unblock when it sees the same value. But a new greeting unblocks it:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-bash",children:'cadence: docker run --network=host --rm ubercadence/cli:master --do test-domain workflow signal --workflow_id "HelloSignal" --name "HelloWorld::updateGreeting" --input \\"Welcome\\"\nSignal workflow succeeded.\n'})}),"\n",(0,a.jsx)(n.p,{children:"Program output:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-bash",children:"16:53:56.120 [workflow-root] INFO c.u.c.samples.hello.GettingStarted - 1: Hello World!\n16:54:57.901 [workflow-root] INFO c.u.c.samples.hello.GettingStarted - 2: Hi World!\n16:56:24.400 [workflow-root] INFO c.u.c.samples.hello.GettingStarted - 3: Welcome World!\n"})}),"\n",(0,a.jsx)(n.p,{children:"Now shut down the worker and send the same signal again:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-bash",children:'cadence: docker run --network=host --rm ubercadence/cli:master --do test-domain workflow signal --workflow_id "HelloSignal" --name "HelloWorld::updateGreeting" --input \\"Welcome\\"\nSignal workflow succeeded.\n'})}),"\n",(0,a.jsx)(n.p,{children:"Note that sending signals as well as starting workflows does not need a worker running. The requests are queued inside the Cadence service."}),"\n",(0,a.jsx)(n.p,{children:"Now bring the worker back. Note that it doesn't log anything besides the standard startup messages.\nThis occurs because it ignores the queued signal that contains the same input as the current value of greeting.\nNote that the restart of the worker didn't affect the workflow_execution. It is still blocked on the same line of code as before the failure.\nThis is the most important feature of Cadence. The workflow code doesn't need to deal with worker failures at all. Its state is fully recovered to its current state that includes all the local variables and threads."}),"\n",(0,a.jsx)(n.p,{children:"Let's look at the line where the workflow is blocked:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-sh-session",children:'$ docker run --network=host --rm ubercadence/cli:master --do test-domain workflow stack --workflow_id "Hello2"\nQuery result:\n"workflow-root: (BLOCKED on await)\ncom.uber.cadence.internal.sync.SyncDecisionContext.await(SyncDecisionContext.java:546)\ncom.uber.cadence.internal.sync.WorkflowInternal.await(WorkflowInternal.java:243)\ncom.uber.cadence.workflow.Workflow.await(Workflow.java:611)\ncom.uber.cadence.samples.hello.GettingStarted$HelloWorldImpl.sayHello(GettingStarted.java:32)\nsun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)\nsun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)"\n'})}),"\n",(0,a.jsx)(n.p,{children:'Yes, indeed the workflow is blocked on await. This feature works for any open workflow, greatly simplifying troubleshooting in production.\nLet\'s complete the workflow by sending a signal with a "Bye" greeting:'}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-log",children:"16:58:22.962 [workflow-root] INFO c.u.c.samples.hello.GettingStarted - 4: Bye World!\n"})}),"\n",(0,a.jsx)(n.p,{children:"Note that the value of the count variable was not lost during the restart."}),"\n",(0,a.jsx)(n.p,{children:"Also note that while a single worker instance is used for this\nwalkthrough, any real production deployment has multiple worker instances running. So any worker failure or restart does not delay any\nworkflow_execution because it is just migrated to any other available worker."}),"\n",(0,a.jsx)(n.h2,{id:"signalwithstart-from-command-line",children:"SignalWithStart From Command Line"}),"\n",(0,a.jsxs)(n.p,{children:["You may not know if a workflow is running and can accept a signal.\nThe signalWithStart feature allows you to send a signal to the current workflow instance if one exists or to create a new\nrun and then send the signal. ",(0,a.jsx)(n.code,{children:"SignalWithStartWorkflow"})," therefore doesn't take a run_ID as a\nparameter."]}),"\n",(0,a.jsxs)(n.p,{children:["Learn more from the ",(0,a.jsx)(n.code,{children:"--help"})," manual:"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-sh-session",children:"$ docker run --network=host --rm ubercadence/cli:master --do test-domain workflow signalwithstart -h\nNAME:\n cadence workflow signalwithstart - signal the current open workflow if exists, or attempt to start a new run based on IDResuePolicy and signals it\n\nUSAGE:\n cadence workflow signalwithstart [command options] [arguments...]\n...\n...\n...\n"})}),"\n",(0,a.jsx)(n.h2,{id:"signal-from-userapplication-code",children:"Signal from user/application code"}),"\n",(0,a.jsx)(n.p,{children:"You may want to signal workflows without running the command line."}),"\n",(0,a.jsxs)(n.p,{children:["The\n",(0,a.jsx)(n.a,{href:"https://www.javadoc.io/doc/com.uber.cadence/cadence-client/latest/com/cadence-workflow/cadence/client/WorkflowClient.html",children:"WorkflowClient"})," API allows you to send signal (or SignalWithStartWorkflow) from outside of the workflow\nto send a signal to the current workflow."]}),"\n",(0,a.jsxs)(n.p,{children:["Note that when using ",(0,a.jsx)(n.code,{children:"newWorkflowStub"})," to signal a workflow, you MUST NOT passing WorkflowOptions."]}),"\n",(0,a.jsxs)(n.p,{children:["The ",(0,a.jsx)(n.a,{href:"https://www.javadoc.io/static/com.uber.cadence/cadence-client/2.7.9-alpha/com/cadence-workflow/cadence/client/WorkflowClient.html#newWorkflowStub-java.lang.Class-com.uber.cadence.client.WorkflowOptions-",children:"WorkflowStub"})," with WorkflowOptions is only for starting workflows."]}),"\n",(0,a.jsxs)(n.p,{children:["The ",(0,a.jsx)(n.a,{href:"https://www.javadoc.io/static/com.uber.cadence/cadence-client/2.7.9-alpha/com/cadence-workflow/cadence/client/WorkflowClient.html#newWorkflowStub-java.lang.Class-java.lang.String-",children:"WorkflowStub"})," without WorkflowOptions is for signal or ",(0,a.jsx)(n.a,{href:"/docs/java-client/queries",children:"query"})]})]})}function h(e={}){const{wrapper:n}={...(0,l.R)(),...e.components};return n?(0,a.jsx)(n,{...e,children:(0,a.jsx)(d,{...e})}):d(e)}},8453:(e,n,o)=>{o.d(n,{R:()=>r,x:()=>i});var t=o(6540);const a={},l=t.createContext(a);function r(e){const n=t.useContext(l);return t.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function i(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:r(e.components),t.createElement(l.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/f5140c76.0fa5d57f.js b/assets/js/f5140c76.0fa5d57f.js new file mode 100644 index 000000000..f54147121 --- /dev/null +++ b/assets/js/f5140c76.0fa5d57f.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[6763],{5658:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>l,contentTitle:()=>r,default:()=>u,frontMatter:()=>a,metadata:()=>i,toc:()=>c});const i=JSON.parse('{"id":"java-client/testing","title":"Testing","description":"TestActivityEnvironment is the helper class for unit testing activity implementations. Supports calls to Activity methods from the tested activities. An example test:","source":"@site/docs/04-java-client/17-testing.md","sourceDirName":"04-java-client","slug":"/java-client/testing","permalink":"/Cadence-Docs/docs/java-client/testing","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/04-java-client/17-testing.md","tags":[],"version":"current","sidebarPosition":17,"frontMatter":{"layout":"default","title":"Testing","permalink":"/docs/java-client/testing"},"sidebar":"docsSidebar","previous":{"title":"Side Effect","permalink":"/Cadence-Docs/docs/java-client/side-effect"},"next":{"title":"Workflow Replay and Shadowing","permalink":"/Cadence-Docs/docs/java-client/workflow-replay-shadowing"}}');var s=n(4848),o=n(8453);const a={layout:"default",title:"Testing",permalink:"/docs/java-client/testing"},r="Activity Test Environment",l={},c=[{value:"Workflow Test Environment",id:"workflow-test-environment",level:2}];function d(e){const t={a:"a",code:"code",h1:"h1",h2:"h2",header:"header",p:"p",pre:"pre",...(0,o.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(t.header,{children:(0,s.jsx)(t.h1,{id:"activity-test-environment",children:"Activity Test Environment"})}),"\n",(0,s.jsxs)(t.p,{children:[(0,s.jsx)(t.a,{href:"https://www.javadoc.io/static/com.uber.cadence/cadence-client/2.7.9-alpha/com/cadence-workflow/cadence/testing/TestActivityEnvironment.html",children:"TestActivityEnvironment"})," is the helper class for unit testing activity implementations. Supports calls to Activity methods from the tested activities. An example test:"]}),"\n",(0,s.jsx)(t.p,{children:(0,s.jsx)(t.a,{href:"https://github.com/cadence-workflow/cadence-java-samples/blob/master/src/test/java/com/uber/cadence/samples/hello/HelloActivityTest.java",children:"See full example here."})}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-java",children:'\n public interface TestActivity {\n String activity1(String input);\n }\n\n private static class ActivityImpl implements TestActivity {\n @Override\n public String activity1(String input) {\n return Activity.getTask().getActivityType().getName() + "-" + input;\n }\n }\n\n @Test\n public void testSuccess() {\n testEnvironment.registerActivitiesImplementations(new ActivityImpl());\n TestActivity activity = testEnvironment.newActivityStub(TestActivity.class);\n String result = activity.activity1("input1");\n assertEquals("TestActivity::activity1-input1", result);\n }\n\n'})}),"\n",(0,s.jsx)(t.h2,{id:"workflow-test-environment",children:"Workflow Test Environment"}),"\n",(0,s.jsx)(t.p,{children:"TestWorkflowEnvironment provides workflow unit testing capabilities."}),"\n",(0,s.jsx)(t.p,{children:"Testing the workflow code is hard as it might be potentially very long running. The included in-memory implementation of the Cadence service supports an automatic time skipping. Anytime a workflow under the test as well as the unit test code are waiting on a timer (or sleep) the internal service time is automatically advanced to the nearest time that unblocks one of the waiting threads. This way a workflow that runs in production for months is unit tested in milliseconds. Here is an example of a test that executes in a few milliseconds instead of over two hours that are needed for the workflow to complete."}),"\n",(0,s.jsx)(t.p,{children:(0,s.jsx)(t.a,{href:"https://github.com/cadence-workflow/cadence-java-samples/blob/master/src/test/java/com/uber/cadence/samples/hello/HelloSignalTest.java#L76",children:"See full example here. "})}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-java",children:'public class SignaledWorkflowImpl implements SignaledWorkflow {\n private String signalInput;\n\n @Override\n public String workflow1(String input) {\n Workflow.sleep(Duration.ofHours(1));\n Workflow.await(() -> signalInput != null);\n Workflow.sleep(Duration.ofHours(1));\n return signalInput + "-" + input;\n }\n\n @Override\n public void processSignal(String input) {\n signalInput = input;\n }\n}\n\n@Test\npublic void testSignal() throws ExecutionException, InterruptedException {\n // Get a workflow stub using the same task list the worker uses.\n WorkflowOptions workflowOptions =\n new WorkflowOptions.Builder()\n .setTaskList(HelloSignal.TASK_LIST)\n .setExecutionStartToCloseTimeout(Duration.ofDays(30))\n .build();\n GreetingWorkflow workflow =\n workflowClient.newWorkflowStub(GreetingWorkflow.class, workflowOptions);\n\n // Start workflow asynchronously to not use another thread to signal.\n WorkflowClient.start(workflow::getGreetings);\n\n // After start for getGreeting returns, the workflow is guaranteed to be started.\n // So we can send a signal to it using workflow stub immediately.\n // But just to demonstrate the unit testing of a long running workflow adding a long sleep here.\n testEnv.sleep(Duration.ofDays(1));\n // This workflow keeps receiving signals until exit is called\n workflow.waitForName("World");\n workflow.waitForName("Universe");\n workflow.exit();\n // Calling synchronous getGreeting after workflow has started reconnects to the existing\n // workflow and\n // blocks until result is available. Note that this behavior assumes that WorkflowOptions are\n // not configured\n // with WorkflowIdReusePolicy.AllowDuplicate. In that case the call would fail with\n // WorkflowExecutionAlreadyStartedException.\n List<String> greetings = workflow.getGreetings();\n assertEquals(2, greetings.size());\n assertEquals("Hello World!", greetings.get(0));\n assertEquals("Hello Universe!", greetings.get(1));\n}\n'})})]})}function u(e={}){const{wrapper:t}={...(0,o.R)(),...e.components};return t?(0,s.jsx)(t,{...e,children:(0,s.jsx)(d,{...e})}):d(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>a,x:()=>r});var i=n(6540);const s={},o=i.createContext(s);function a(e){const t=i.useContext(o);return i.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function r(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:a(e.components),i.createElement(o.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/f5140c76.d0a614cd.js b/assets/js/f5140c76.d0a614cd.js deleted file mode 100644 index ab8cb1adc..000000000 --- a/assets/js/f5140c76.d0a614cd.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[6763],{5658:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>l,contentTitle:()=>r,default:()=>d,frontMatter:()=>a,metadata:()=>i,toc:()=>c});const i=JSON.parse('{"id":"java-client/testing","title":"Testing","description":"TestActivityEnvironment is the helper class for unit testing activity implementations. Supports calls to Activity methods from the tested activities. An example test:","source":"@site/docs/04-java-client/17-testing.md","sourceDirName":"04-java-client","slug":"/java-client/testing","permalink":"/docs/java-client/testing","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/04-java-client/17-testing.md","tags":[],"version":"current","sidebarPosition":17,"frontMatter":{"layout":"default","title":"Testing","permalink":"/docs/java-client/testing"},"sidebar":"docsSidebar","previous":{"title":"Side Effect","permalink":"/docs/java-client/side-effect"},"next":{"title":"Workflow Replay and Shadowing","permalink":"/docs/java-client/workflow-replay-shadowing"}}');var s=n(4848),o=n(8453);const a={layout:"default",title:"Testing",permalink:"/docs/java-client/testing"},r="Activity Test Environment",l={},c=[{value:"Workflow Test Environment",id:"workflow-test-environment",level:2}];function u(e){const t={a:"a",code:"code",h1:"h1",h2:"h2",header:"header",p:"p",pre:"pre",...(0,o.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(t.header,{children:(0,s.jsx)(t.h1,{id:"activity-test-environment",children:"Activity Test Environment"})}),"\n",(0,s.jsxs)(t.p,{children:[(0,s.jsx)(t.a,{href:"https://www.javadoc.io/static/com.uber.cadence/cadence-client/2.7.9-alpha/com/cadence-workflow/cadence/testing/TestActivityEnvironment.html",children:"TestActivityEnvironment"})," is the helper class for unit testing activity implementations. Supports calls to Activity methods from the tested activities. An example test:"]}),"\n",(0,s.jsx)(t.p,{children:(0,s.jsx)(t.a,{href:"https://github.com/cadence-workflow/cadence-java-samples/blob/master/src/test/java/com/uber/cadence/samples/hello/HelloActivityTest.java",children:"See full example here."})}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-java",children:'\n public interface TestActivity {\n String activity1(String input);\n }\n\n private static class ActivityImpl implements TestActivity {\n @Override\n public String activity1(String input) {\n return Activity.getTask().getActivityType().getName() + "-" + input;\n }\n }\n\n @Test\n public void testSuccess() {\n testEnvironment.registerActivitiesImplementations(new ActivityImpl());\n TestActivity activity = testEnvironment.newActivityStub(TestActivity.class);\n String result = activity.activity1("input1");\n assertEquals("TestActivity::activity1-input1", result);\n }\n\n'})}),"\n",(0,s.jsx)(t.h2,{id:"workflow-test-environment",children:"Workflow Test Environment"}),"\n",(0,s.jsx)(t.p,{children:"TestWorkflowEnvironment provides workflow unit testing capabilities."}),"\n",(0,s.jsx)(t.p,{children:"Testing the workflow code is hard as it might be potentially very long running. The included in-memory implementation of the Cadence service supports an automatic time skipping. Anytime a workflow under the test as well as the unit test code are waiting on a timer (or sleep) the internal service time is automatically advanced to the nearest time that unblocks one of the waiting threads. This way a workflow that runs in production for months is unit tested in milliseconds. Here is an example of a test that executes in a few milliseconds instead of over two hours that are needed for the workflow to complete."}),"\n",(0,s.jsx)(t.p,{children:(0,s.jsx)(t.a,{href:"https://github.com/cadence-workflow/cadence-java-samples/blob/master/src/test/java/com/uber/cadence/samples/hello/HelloSignalTest.java#L76",children:"See full example here. "})}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-java",children:'public class SignaledWorkflowImpl implements SignaledWorkflow {\n private String signalInput;\n\n @Override\n public String workflow1(String input) {\n Workflow.sleep(Duration.ofHours(1));\n Workflow.await(() -> signalInput != null);\n Workflow.sleep(Duration.ofHours(1));\n return signalInput + "-" + input;\n }\n\n @Override\n public void processSignal(String input) {\n signalInput = input;\n }\n}\n\n@Test\npublic void testSignal() throws ExecutionException, InterruptedException {\n // Get a workflow stub using the same task list the worker uses.\n WorkflowOptions workflowOptions =\n new WorkflowOptions.Builder()\n .setTaskList(HelloSignal.TASK_LIST)\n .setExecutionStartToCloseTimeout(Duration.ofDays(30))\n .build();\n GreetingWorkflow workflow =\n workflowClient.newWorkflowStub(GreetingWorkflow.class, workflowOptions);\n\n // Start workflow asynchronously to not use another thread to signal.\n WorkflowClient.start(workflow::getGreetings);\n\n // After start for getGreeting returns, the workflow is guaranteed to be started.\n // So we can send a signal to it using workflow stub immediately.\n // But just to demonstrate the unit testing of a long running workflow adding a long sleep here.\n testEnv.sleep(Duration.ofDays(1));\n // This workflow keeps receiving signals until exit is called\n workflow.waitForName("World");\n workflow.waitForName("Universe");\n workflow.exit();\n // Calling synchronous getGreeting after workflow has started reconnects to the existing\n // workflow and\n // blocks until result is available. Note that this behavior assumes that WorkflowOptions are\n // not configured\n // with WorkflowIdReusePolicy.AllowDuplicate. In that case the call would fail with\n // WorkflowExecutionAlreadyStartedException.\n List<String> greetings = workflow.getGreetings();\n assertEquals(2, greetings.size());\n assertEquals("Hello World!", greetings.get(0));\n assertEquals("Hello Universe!", greetings.get(1));\n}\n'})})]})}function d(e={}){const{wrapper:t}={...(0,o.R)(),...e.components};return t?(0,s.jsx)(t,{...e,children:(0,s.jsx)(u,{...e})}):u(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>a,x:()=>r});var i=n(6540);const s={},o=i.createContext(s);function a(e){const t=i.useContext(o);return i.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function r(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:a(e.components),i.createElement(o.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/f7be646d.39465925.js b/assets/js/f7be646d.fe7f4eab.js similarity index 67% rename from assets/js/f7be646d.39465925.js rename to assets/js/f7be646d.fe7f4eab.js index c8b4ec5c2..219a462f4 100644 --- a/assets/js/f7be646d.39465925.js +++ b/assets/js/f7be646d.fe7f4eab.js @@ -1 +1 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[5429],{455:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>c,contentTitle:()=>s,default:()=>u,frontMatter:()=>r,metadata:()=>o,toc:()=>l});var o=n(1900),a=n(4848),i=n(8453);const r={title:"Cadence Community Spotlight Update - March 2023",date:new Date("2023-03-31T00:00:00.000Z"),authors:"sharanf",tags:["community-spotlight"]},s=void 0,c={authorsImageUrls:[void 0]},l=[{value:"Cadence at Open Source Summit, North America",id:"cadence-at-open-source-summit-north-america",level:2},{value:"Community Activity",id:"community-activity",level:2}];function h(e){const t={a:"a",h2:"h2",li:"li",p:"p",ul:"ul",...(0,i.R)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(t.p,{children:"Welcome to the latest of our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!"}),"\n",(0,a.jsx)(t.p,{children:"Please see below for a roundup of the highlights:"}),"\n",(0,a.jsx)(t.h2,{id:"cadence-at-open-source-summit-north-america",children:"Cadence at Open Source Summit, North America"}),"\n",(0,a.jsxs)(t.p,{children:["We are very pleased to let you know that a talk on Cadence has been accepted for the Linux Foundation's ",(0,a.jsx)(t.a,{href:"https://events.linuxfoundation.org/open-source-summit-north-america/",children:"Open Source Summit, North America"})," in Vancouver on 10th - 12th May 2023."]}),"\n",(0,a.jsxs)(t.p,{children:["The talk called ",(0,a.jsx)(t.a,{href:"https://ossna2023.sched.com/event/1K5B1",children:"Cadence: The New Open Source Project for Building Complex Distributed Applications"})," will be given by ",(0,a.jsx)(t.a,{href:"https://www.linkedin.com/in/enderdemirkaya/",children:"Ender Demirkaya"})," and ",(0,a.jsx)(t.a,{href:"https://www.linkedin.com/in/emrahseker/",children:"Emrah Seker"})," If you are planning to attend the Open Source Summit then please don't forget to attend the talk and take time catch up with Ender and Emrah!"]}),"\n",(0,a.jsx)(t.h2,{id:"community-activity",children:"Community Activity"}),"\n",(0,a.jsx)(t.p,{children:"Our Slack #support channel has been very active over the last few months as we continue to get an continual stream of questions. Here are the stats:"}),"\n",(0,a.jsxs)(t.ul,{children:["\n",(0,a.jsx)(t.li,{children:"February 2023 : 16 questions asked"}),"\n",(0,a.jsx)(t.li,{children:"March 2023 : 12 questions asked"}),"\n"]}),"\n",(0,a.jsx)(t.p,{children:"All of these questions are being answered collaboratively by the community. Thanks everyone for sharing your knowledge and we are looking forward to receiving more of your questions!"})]})}function u(e={}){const{wrapper:t}={...(0,i.R)(),...e.components};return t?(0,a.jsx)(t,{...e,children:(0,a.jsx)(h,{...e})}):h(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>r,x:()=>s});var o=n(6540);const a={},i=o.createContext(a);function r(e){const t=o.useContext(i);return o.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function s(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:r(e.components),o.createElement(i.Provider,{value:t},e.children)}},1900:e=>{e.exports=JSON.parse('{"permalink":"/blog/2023/03/31/community-spotlight-march-2023","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2023-03-31-community-spotlight-march-2023.md","source":"@site/blog/2023-03-31-community-spotlight-march-2023.md","title":"Cadence Community Spotlight Update - March 2023","description":"Welcome to the latest of our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!","date":"2023-03-31T00:00:00.000Z","tags":[{"inline":false,"label":"Community Spotlight","permalink":"/blog/tags/community-spotlights","description":"Community Spotlight tag description"}],"readingTime":1.885,"hasTruncateMarker":true,"authors":[{"name":"Sharan Foga","title":"Director of Operations & Customer Success @ Encube Technologies","url":"https://www.linkedin.com/in/sfoga/","page":{"permalink":"/blog/authors/sharanf"},"socials":{"linkedin":"https://www.linkedin.com/in/sfoga/","github":"https://github.com/sharanf"},"imageURL":"https://github.com/sharanf.png","key":"sharanf"}],"frontMatter":{"title":"Cadence Community Spotlight Update - March 2023","date":"2023-03-31T00:00:00.000Z","authors":"sharanf","tags":["community-spotlight"]},"unlisted":false,"prevItem":{"title":"2023 Cadence Community Survey Results","permalink":"/blog/2023/06/08/2023-06-08-survey-results/survey-results"},"nextItem":{"title":"Cadence Community Spotlight Update - March 2024","permalink":"/blog/2024/3/11/community-spotlight-update-march-2024"}}')}}]); \ No newline at end of file +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[5429],{455:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>c,contentTitle:()=>s,default:()=>u,frontMatter:()=>r,metadata:()=>o,toc:()=>l});var o=n(1900),a=n(4848),i=n(8453);const r={title:"Cadence Community Spotlight Update - March 2023",date:new Date("2023-03-31T00:00:00.000Z"),authors:"sharanf",tags:["community-spotlight"]},s=void 0,c={authorsImageUrls:[void 0]},l=[{value:"Cadence at Open Source Summit, North America",id:"cadence-at-open-source-summit-north-america",level:2},{value:"Community Activity",id:"community-activity",level:2}];function h(e){const t={a:"a",h2:"h2",li:"li",p:"p",ul:"ul",...(0,i.R)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(t.p,{children:"Welcome to the latest of our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!"}),"\n",(0,a.jsx)(t.p,{children:"Please see below for a roundup of the highlights:"}),"\n",(0,a.jsx)(t.h2,{id:"cadence-at-open-source-summit-north-america",children:"Cadence at Open Source Summit, North America"}),"\n",(0,a.jsxs)(t.p,{children:["We are very pleased to let you know that a talk on Cadence has been accepted for the Linux Foundation's ",(0,a.jsx)(t.a,{href:"https://events.linuxfoundation.org/open-source-summit-north-america/",children:"Open Source Summit, North America"})," in Vancouver on 10th - 12th May 2023."]}),"\n",(0,a.jsxs)(t.p,{children:["The talk called ",(0,a.jsx)(t.a,{href:"https://ossna2023.sched.com/event/1K5B1",children:"Cadence: The New Open Source Project for Building Complex Distributed Applications"})," will be given by ",(0,a.jsx)(t.a,{href:"https://www.linkedin.com/in/enderdemirkaya/",children:"Ender Demirkaya"})," and ",(0,a.jsx)(t.a,{href:"https://www.linkedin.com/in/emrahseker/",children:"Emrah Seker"})," If you are planning to attend the Open Source Summit then please don't forget to attend the talk and take time catch up with Ender and Emrah!"]}),"\n",(0,a.jsx)(t.h2,{id:"community-activity",children:"Community Activity"}),"\n",(0,a.jsx)(t.p,{children:"Our Slack #support channel has been very active over the last few months as we continue to get an continual stream of questions. Here are the stats:"}),"\n",(0,a.jsxs)(t.ul,{children:["\n",(0,a.jsx)(t.li,{children:"February 2023 : 16 questions asked"}),"\n",(0,a.jsx)(t.li,{children:"March 2023 : 12 questions asked"}),"\n"]}),"\n",(0,a.jsx)(t.p,{children:"All of these questions are being answered collaboratively by the community. Thanks everyone for sharing your knowledge and we are looking forward to receiving more of your questions!"})]})}function u(e={}){const{wrapper:t}={...(0,i.R)(),...e.components};return t?(0,a.jsx)(t,{...e,children:(0,a.jsx)(h,{...e})}):h(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>r,x:()=>s});var o=n(6540);const a={},i=o.createContext(a);function r(e){const t=o.useContext(i);return o.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function s(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:r(e.components),o.createElement(i.Provider,{value:t},e.children)}},1900:e=>{e.exports=JSON.parse('{"permalink":"/Cadence-Docs/blog/2023/03/31/community-spotlight-march-2023","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2023-03-31-community-spotlight-march-2023.md","source":"@site/blog/2023-03-31-community-spotlight-march-2023.md","title":"Cadence Community Spotlight Update - March 2023","description":"Welcome to the latest of our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!","date":"2023-03-31T00:00:00.000Z","tags":[{"inline":false,"label":"Community Spotlight","permalink":"/Cadence-Docs/blog/tags/community-spotlights","description":"Community Spotlight tag description"}],"readingTime":1.885,"hasTruncateMarker":true,"authors":[{"name":"Sharan Foga","title":"Director of Operations & Customer Success @ Encube Technologies","url":"https://www.linkedin.com/in/sfoga/","page":{"permalink":"/Cadence-Docs/blog/authors/sharanf"},"socials":{"linkedin":"https://www.linkedin.com/in/sfoga/","github":"https://github.com/sharanf"},"imageURL":"https://github.com/sharanf.png","key":"sharanf"}],"frontMatter":{"title":"Cadence Community Spotlight Update - March 2023","date":"2023-03-31T00:00:00.000Z","authors":"sharanf","tags":["community-spotlight"]},"unlisted":false,"prevItem":{"title":"2023 Cadence Community Survey Results","permalink":"/Cadence-Docs/blog/2023/06/08/2023-06-08-survey-results/survey-results"},"nextItem":{"title":"Cadence Community Spotlight Update - March 2024","permalink":"/Cadence-Docs/blog/2024/3/11/community-spotlight-update-march-2024"}}')}}]); \ No newline at end of file diff --git a/assets/js/f81c1134.3f16e91e.js b/assets/js/f81c1134.3f16e91e.js deleted file mode 100644 index caa5aabc4..000000000 --- a/assets/js/f81c1134.3f16e91e.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[8130],{7735:e=>{e.exports=JSON.parse('{"archive":{"blogPosts":[{"id":"/2024/11/18/cadence-workflows-github-organization","metadata":{"permalink":"/blog/2024/11/18/cadence-workflows-github-organization","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2024-11-18-cadence-workflows-github-organization.md","source":"@site/blog/2024-11-18-cadence-workflows-github-organization.md","title":"Cadence Repositories Have Moved!","description":"Discover the latest update for Cadence Workflow! Our GitHub repositories have moved to the new cadence-workflow organization. Learn more about the migration, including updated links and how this change supports the growing Cadence community","date":"2024-11-18T14:00:00.000Z","tags":[{"inline":false,"label":"Announcement","permalink":"/blog/tags/announcements","description":"Announcement tag description"}],"readingTime":0.6,"hasTruncateMarker":true,"authors":[{"name":"Josu\xe9 Alexander Ibarra","title":"Developer Advocate @ Uber","url":"https://github.com/ibarrajo/","page":{"permalink":"/blog/authors/ibarrajo"},"socials":{"github":"https://github.com/ibarrajo","linkedin":"https://www.linkedin.com/in/elninja/"},"imageURL":"https://github.com/ibarrajo.png","key":"ibarrajo"}],"frontMatter":{"title":"Cadence Repositories Have Moved!","description":"Discover the latest update for Cadence Workflow! Our GitHub repositories have moved to the new cadence-workflow organization. Learn more about the migration, including updated links and how this change supports the growing Cadence community","authors":"ibarrajo","tags":["announcement"],"date":"2024-11-18T14:00"},"unlisted":false,"nextItem":{"title":"Zonal Isolation for Cadence Workflows","permalink":"/blog/zonal-isolation-v1/zonal-isolation-v1"}},"content":"We\u2019re excited to announce that all Cadence GitHub repositories have been consolidated under the [cadence-workflow](https://github.com/cadence-workflow) organization! \ud83c\udf89\\n\\nPreviously, Cadence repositories were distributed across multiple organizations at Uber: [`uber`](https://github.com/uber), [`uber-go`](https://github.com/uber-go), [`uber-common`](https://github.com/uber-common). To improve developer cohesiveness and simplify access, the Cadence Core team has migrated all open-source repositories to the [`cadence-workflow`](https://github.com/cadence-workflow) organization.\\n\\nFor example, our main repository has moved from:\\n\\n\ud83d\udc49 [uber/cadence](https://github.com/cadence-workflow/cadence)\\n\\nTo its new home:\\n\\n\ud83d\udc49 [cadence-workflow/cadence](https://github.com/cadence-workflow/cadence)\\n\\nYou can find the full list of Cadence repositories here \ud83d\udc49 [orgs/cadence-workflow/repositories](https://github.com/orgs/cadence-workflow/repositories)\\n\\n\x3c!-- truncate --\x3e\\n\\nThis move reflects our continued commitment to growing the Cadence community and making the project even more accessible to contributors and users. Please update your bookmarks and links accordingly.\\n\\nThank you for being part of the Cadence journey! \ud83d\ude80"},{"id":"/zonal-isolation-v1/zonal-isolation-v1","metadata":{"permalink":"/blog/zonal-isolation-v1/zonal-isolation-v1","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/zonal-isolation-v1/zonal-isolation-v1.md","source":"@site/blog/zonal-isolation-v1/zonal-isolation-v1.md","title":"Zonal Isolation for Cadence Workflows","description":"At Uber, we want to achieve regional resilience such that losing a zone within a region can be tolerated without requiring a cross-region failover. We also want to make sure that losing a zone only affects a subset of workload, at most, rather than everything. However, in Cadence-based systems, the workload in a region is distributed randomly across all workers in the region at a \u201ctask-level granularity\u201d, which means a workflow may be worked on by any worker in the region where the domain is active. To achieve this goal, we introduced Zonal Isolation for Cadence Workflows - a feature designed to pin workflows to the zone they are started in, so that zonal isolation can be achieved at a workflow-level.","date":"2024-10-14T00:00:00.000Z","tags":[{"inline":false,"label":"Deep Dives","permalink":"/blog/tags/deep-dives","description":"Deep Dives tag description"},{"inline":false,"label":"Cadence Operations","permalink":"/blog/tags/cadence-operations","description":"Cadence Operations tag description"}],"readingTime":7.985,"hasTruncateMarker":true,"authors":[{"name":"Zijian Chen","title":"Software Engineer @ Uber","url":"https://www.linkedin.com/in/zijian-chen-5868938b/","page":{"permalink":"/blog/authors/shaddoll"},"socials":{"linkedin":"https://www.linkedin.com/in/zijian-chen-5868938b/","github":"https://github.com/Shaddoll"},"imageURL":"https://github.com/Shaddoll.png","key":"shaddoll"}],"frontMatter":{"title":"Zonal Isolation for Cadence Workflows","subtitle":"test","date":"2024-10-14T00:00:00.000Z","authors":"shaddoll","tags":["deep-dive","cadence-operations"]},"unlisted":false,"prevItem":{"title":"Cadence Repositories Have Moved!","permalink":"/blog/2024/11/18/cadence-workflows-github-organization"},"nextItem":{"title":"Announcement: Cadence Helm Charts v0 Release","permalink":"/blog/2024/10/01/announcing-cadence-helm-charts-v0"}},"content":"At Uber, we want to achieve regional resilience such that losing a zone within a region can be tolerated without requiring a cross-region failover. We also want to make sure that losing a zone only affects a subset of workload, at most, rather than everything. However, in Cadence-based systems, the workload in a region is distributed randomly across all workers in the region at a \u201ctask-level granularity\u201d, which means a workflow may be worked on by any worker in the region where the domain is active. To achieve this goal, we introduced Zonal Isolation for Cadence Workflows - a feature designed to pin workflows to the zone they are started in, so that zonal isolation can be achieved at a workflow-level.\\n\\n## What is Zonal Isolation for Cadence Workflows?\\nAt high-level, Zonal Isolation for Cadence Workflows can be thought in 2 levels:\\n\\n1. **Task-level isolation:** All decision tasks and activity tasks of a workflow are only processed by workers from the zone where the workflow was started\\n2. **Infrastructure-level isolation:** Within a regional Cadence cluster, workflows are handled by server instances in the same zone where they were started, and the corresponding data is stored in that zone as well.\\n\\nInfrastructure-level isolation is quite challenging to implement as it requires significant changes to the core design of the Cadence server. Due to the complexity involved, support for this feature is not planned for the foreseeable future.\\n\\nAs a result, the focus remains on achieving task-level zonal isolation outside the Cadence server, which offers a more practical and immediate way to improve system resilience. It provides the capability of ensuring that an unhealthy zone (i.e. bad deployment of workers) only affect a subset of workflows (started from a certain zone) rather than every workflow in a Cadence domain.\\n\\n\x3c!-- truncate --\x3e\\n\\n## How Zonal Isolation Works in Cadence?\\n\\n### Architecture\\nHere is what the architecture of a zonally isolated Cadence-based system looks like:\\n![zonal isolation overview](./zone-isolation.png)\\n*<p>Fig: Workflows started in one zone are only dispatched to workers from the same zone. Colors to emphasize pinning.</p>*\\n### Implementation\\n\\n#### Determine the zone of a workflow and workers\\n\\nTo ensure that tasks are dispatched to workers in the same zone as the workflows, we must identify the origin zone of both. The zone of a workflow is determined by the origin zone of the StartWorkflowExecution request, while the zone of workers is determined by the origin zone of the PollForDecisionTask and PollForActivityTask requests. There are three possible ways to determine the origin zone for these requests:\\n\\n- **Uber\'s Approach:** Let Cadence SDK set the origin zone in the headers of the requests before sending the request to Cadence.\\n- **Preferred Approach:** Get the origin zone of the requests from headers set by network infrastructure.\\n- Determine the origin zone of the requests from the zone of the cadence-frontend instance receiving the request, if the network layer has already achieved zonal isolation.\\n\\nThe 2nd approach is the ideal one, but Uber\'s network infrastructure doesn\'t provide such headers and the network layer is not ready for zonal isolation. As a result, we adopt the 1st approach. At Uber, we have internal libraries in Go and Java acting as wrappers around Cadence SDK injecting necessary configurations. These libraries have been updated to include the origin zone in the request headers using a header called `cadence-client-isolation-group`.\\n\\n#### How to dispatch tasks to workers from the same zone?\\nTo implement task-level isolation, we introduce a new dimension to the tasklist \u2014 **isolation group**. When a workflow is initiated, the origin zone of the workflow is stored in the database. Each time a decision or activity task is dispatched to cadence-matching, the workflow\'s origin zone is used as the isolation group for that task.\\n\\nWhen a worker sends a `PollForDecisionTask` or `PollForActivityTask` request to cadence-matching, the request is labeled with the worker\'s isolation group (i.e., the worker\'s zone). Tasks are then dispatched only to poller requests that have the same isolation group, ensuring that tasks are processed by workers in the same zone as the workflow\'s origin.\\n#### How to handle workflows from a drained zone?\\nIn the event of an outage, such as a bad deployment, customers may want to drain workers from a specific zone to mitigate the impact. There are two types of drains that can occur:\\n1. **Implicit drain:** Workers from a zone completely stop operating, either due to failures or manual shutdowns.\\n2. **Explicit drain:** Customers explicitly mark workers from a zone as drained.\\n\\nWithin cadence-matching, a list of pollers is maintained for each tasklist, tracking the zone from which the pollers originate. An implicit drain can be detected by checking whether there are any active pollers from a particular zone. If a zone is drained (either explicitly or implicitly), workflows that were started in that zone will be reassigned and spread to workers in the remaining healthy zones.\\n##### How to drain a zone explicitly?\\nExplicitly draining a zone can be done at two levels:\\n1. **Domain-level drain:** This applies to a specific domain, allowing the zone to be drained only for workflows within that domain.\\n2. **Cluster-level drain:** This applies to the entire Cadence cluster, draining the zone for all domains and workflows within the cluster.\\n\\nFor domain-level drain, the draining status is stored in [`domains`](https://github.com/cadence-workflow/cadence/blob/v1.2.13/schema/cassandra/cadence/schema.cql#L412) table. For cluster-level drain, the status is stored in [`cluster_config`](https://github.com/cadence-workflow/cadence/blob/v1.2.13/schema/cassandra/cadence/schema.cql#L498) table.\\n\\n## How to enable Zonal Isolation?\\n### Server Update\\nIn order to enable this feature, please upgrade Cadence server to [v1.2.1](https://github.com/cadence-workflow/cadence/releases/tag/v1.2.1) or later.\\n\\n**NOTE:** If you\'re not using the provided main binary located in `cmd/server`, you must adopt this [middleware](https://github.com/cadence-workflow/cadence/blob/v1.2.1/common/rpc/middleware.go#L188). Depends on the appoach to [determine the origin zone of requests](#determine-the-zone-of-a-workflow-and-workers), you can adopt this [middleware](https://github.com/cadence-workflow/cadence/blob/v1.2.1/common/rpc/middleware.go#L229) or build your own middleware using [`partition.ContextWithConfig`](https://github.com/cadence-workflow/cadence/blob/v1.2.1/common/partition/context.go#L42) function to inject origin zone into the context.\\n\\nThis feature is controlled by 2 dynamic config properties.\\n- `system.allIsolationGroups`: This property provides the list of available zones within a region.\\n- `system.enableTasklistIsolation`: This property enables Zonal Isolation at domain level.\\nIt\u2019s important to note that any update to the `system.allIsolationGroups` property requires a restart of the cadence-matching service for the changes to take effect. This ensures that the new zone configuration is properly loaded and applied. However, the `system.enableTasklistIsolation` property can be updated dynamically without requiring a restart, making it more flexible for enabling or disabling Zonal Isolation on a per-domain basis.\\n\\nAn example configuration using the file based dynamic configuration could look like this:\\n```yaml\\nsystem.allIsolationGroups:\\n- value: []\\n constraints: {}\\n- value: [\\"dca1\\", \\"dca2\\", \\"dca3\\"]\\n constraints:\\n clusterName: prod-dca\\n- value: [\\"phx1\\", \\"phx2\\", \\"phx3\\"]\\n constraints:\\n clusterName: prod-phx\\nsystem.enableTasklistIsolation:\\n- value: false\\n constraints: {}\\n- value: true\\n constraints:\\n domainName: samples-domain\\n```\\nIn this example, the Cadence cluster spans two regions, each containing three zones: `dca1`, `dca2`, `dca3` in the `dca` region and `phx1`, `phx2`, `phx3` in the `phx` region. Zonal isolation is enabled only for the `samples-domain`, while it remains disabled for other domains.\\n\\n### SDK Update\\nNOTE: This update is only necessary if you\'re using the 1st approach to [determine the origin zone of requests](#determine-the-zone-of-a-workflow-and-workers).\\n\\nTo support Zonal Isolation, please upgrade your SDK versions:\\n- **Go SDK:** Upgrade to [v1.0.2](https://github.com/cadence-workflow/cadence-go-client/releases/tag/v1.0.2) or later.\\n- **Java SDK:** Upgrade to [v3.9.0](https://github.com/cadence-workflow/cadence-java-client/releases/tag/v3.9.0) or later.\\n\\n**For Java SDK users**, set the [`isolationGroup`](https://github.com/cadence-workflow/cadence-java-client/blob/v3.9.0/src/main/java/com/uber/cadence/serviceclient/ClientOptions.java#L83) field to the zone of the instance when creating `serviceClient`.\\n\\n**For Go SDK users**, set the [`isolationGroup`](https://github.com/cadence-workflow/cadence-go-client/blob/v1.0.2/internal/worker.go#L132) field to the zone of the instance when creating `Worker`. Additionally, you need to use [this method](https://github.com/cadence-workflow/cadence-go-client/blob/v1.0.2/isolationgroup/wrapper.go#L29C39-L29C70) to wrap `workflowserviceclient.Interface`.\\n## How to drain a zone explicitly?\\nDrains can be done via the [Admin APIs](https://github.com/cadence-workflow/cadence-idl/blob/50a4ee241e50c6baab8e5d47540b176c5ee022a4/proto/cadence-workflow/cadence/admin/v1/service.proto#L125) of cadence-frontend or CLI.\\n\\nYou can check the help message for the CLI by running:\\n```bash\\ncadence admin isolation-groups -h\\n```\\n## Monitoring\\nA new metric is introduced to help detect the leakage of tasks and skewness of traffic.\\n\\n`isolation_task_matches_per_tl`: This is a counter that counts the number of tasks polled by workers. The metric is tagged with the domain, tasklist name, tasklist type, the origin zone of the workflow and the origin zone of the worker polling the task.\\n\\nThis metric can be used in the following ways:\\n\\n**Detecting task leakage:** By grouping tasks based on the origin zones of both the workflows and workers, you can identify tasks that have leaked, i.e., tasks assigned to workers in zones different from the workflow\'s origin zone.\\n\\n**Identifying traffic skewness:** By grouping tasks based solely on the origin zones of workflows, you can determine if traffic is disproportionately distributed among the zones, helping to detect any uneven load or traffic imbalance across zones.\\n\\n## Status at Uber\\n- We launched this feature at Uber in July 2023. More than 100 domains have Zonal Isolation enabled.\\n- However, as of 2024, the rollout of Zonal Isolation is paused due to a traffic skewness issue:\\n - Some customers have highly skewed traffic that some zones have more workflows than other zones, but the number of workers are evenly distributed in all zones. Enabling Zonal Isolation for the customers will decrease the utilization of their workers and may cause high latency for the customers.\\n\\n## Next Step\\nCurrently, Zonal Isolation is implemented as **hard isolation**, where tasks are strictly limited to the same zone as the originating workflow. To address the traffic skewness issue, we are working on iterating this feature to introduce **soft isolation**. This relaxed version will allow for some task leakage between zones if traffic skewness is detected, ensuring better worker utilization and reducing latency.\\n\\nThis enhancement is one of our major ongoing projects, and we plan to share more details in a future blog post once it is launched."},{"id":"/2024/10/01/announcing-cadence-helm-charts-v0","metadata":{"permalink":"/blog/2024/10/01/announcing-cadence-helm-charts-v0","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2024-10-01-announcing-cadence-helm-charts-v0.md","source":"@site/blog/2024-10-01-announcing-cadence-helm-charts-v0.md","title":"Announcement: Cadence Helm Charts v0 Release","description":"We\u2019ve heard your feedback: deploying Cadence has been a challenge, especially with limited documentation on operational aspects. So far, we\u2019ve only provided a few docker compose files to help you get started on a development machine. However, deploying and managing Cadence at scale requires a deep understanding of underlying services, configurations and their dependencies.","date":"2024-10-01T00:00:00.000Z","tags":[{"inline":false,"label":"Announcement","permalink":"/blog/tags/announcements","description":"Announcement tag description"}],"readingTime":2.6,"hasTruncateMarker":true,"authors":[{"name":"Taylan Isikdemir","title":"Sr. Staff Software Engineer @ Uber","url":"https://www.linkedin.com/in/taylan-isikdemir","page":{"permalink":"/blog/authors/taylanisikdemir"},"socials":{"linkedin":"https://www.linkedin.com/in/taylan-isikdemir","github":"https://github.com/taylanisikdemir"},"imageURL":"https://github.com/taylanisikdemir.png","key":"taylanisikdemir"}],"frontMatter":{"title":"Announcement: Cadence Helm Charts v0 Release","date":"2024-10-01T00:00:00.000Z","authors":"taylanisikdemir","tags":["announcement"]},"unlisted":false,"prevItem":{"title":"Zonal Isolation for Cadence Workflows","permalink":"/blog/zonal-isolation-v1/zonal-isolation-v1"},"nextItem":{"title":"Minimizing blast radius in Cadence: Introducing Workflow ID-based Rate Limits","permalink":"/blog/2024/09/05/workflow-specific-rate-limits"}},"content":"We\u2019ve heard your feedback: deploying Cadence has been a challenge, especially with limited documentation on operational aspects. So far, we\u2019ve only provided a few [docker compose files](https://github.com/cadence-workflow/cadence/tree/master/docker) to help you get started on a development machine. However, deploying and managing Cadence at scale requires a deep understanding of underlying services, configurations and their dependencies.\\n\\nTo address these challenges, we\u2019re launching several initiatives to make it easier to deploy and operate Cadence clusters. These include deployment specs for common scenarios, monitoring dashboards, alerts, runbooks, and more comprehensive documentation.\\n\\n\x3c!-- truncate --\x3e\\n\\n## Introducing Cadence Kubernetes Helm Chart v0\\n\\nToday, we are happy to announce the release of [Cadence Kubernetes Helm Chart v0](https://github.com/cadence-workflow/cadence-charts). This will be the starting point for standardizing Cadence deployments on Kubernetes. We chose Kubernetes because it\'s the leading compute platform, but Cadence remains flexible and can run on any infrastructure.\\n\\n## How to Get Started\\n\\n[Helm](https://helm.sh) must be installed to use the charts. Please refer to Helm\'s [documentation](https://helm.sh/docs) to get started.\\n\\nOnce Helm has been set up correctly, add the repo as follows:\\n\\n```bash\\nhelm repo add cadence https://uber.github.io/cadence-charts\\n```\\n\\nIf you had already added this repo earlier, run `helm repo update` to retrieve the latest versions of the packages. You can then run `helm search repo cadence` to see the charts.\\n\\nTo install the cadence chart:\\n```bash\\nhelm install my-cadence cadence/cadence\\n```\\n\\nTo uninstall the chart:\\n```bash\\nhelm delete my-cadence\\n```\\n\\nSee [CONTRIBUTING.md](https://github.com/cadence-workflow/cadence-charts/blob/main/CONTRIBUTING.md) for details on how to validate the deployment by running sample workflows.\\n\\n## Current State of the Chart\\n\\nThere were a few community-created Cadence Helm charts but they were not actively maintained and had a few glitches that Cadence team @Uber wasn\'t able to provide support for. With the introduction of the new official Cadence Helm chart, our team is committed to provide support and evolve it with input from community.\\n\\nThe v0 chart contains only the basics at the moment:\\n- Cadence backend services as separate deployments: frontend, history, matching, worker.\\n- Customizable replica counts and resource limitations.\\n- Customizable dynamic config as a configmap.\\n- A single instance ephemeral Cassandra container. This is included so that no external dependency is required to get started. Ideally you should have your own external (hosted or managed) DB instance that you can specify in values.yaml.\\n- The chart comes with `cadence:master-auto-setup` as the default image and capable of setting up Cassandra DB schema on first installation.\\n\\nWhat is (obviously) missing:\\n- Support for advanced visibility stores like Elasticsearch or Pinot.\\n- Support for persistent plugins configurations besides Cassandra.\\n- Support for fully customizable service config via values.yaml.\\n- Metrics integration with Prometheus (and more out of the box prometheus dashboards)\\n- Custom annotations/lables/tolerations etc.\\n- Support for ingress\\n\\n\\n## Next Steps\\n\\nSince this is an early release, we would love to hear from you. Feel free to start [discussions](https://github.com/cadence-workflow/cadence-charts/discussions) or report [issues](https://github.com/cadence-workflow/cadence-charts/issues).\\n\\nAlso check out the [contribution guideline](https://github.com/cadence-workflow/cadence-charts/blob/main/CONTRIBUTING.md) if you are interested to contribute. Don\'t hesitate to send a PR and ping us over slack if we miss it.\\n\\nP.S. Huge thanks to our summer intern [Nikita Bhardwaj](https://github.com/nikitab7) for kickstarting the Cadence Helm charts initiative."},{"id":"/2024/09/05/workflow-specific-rate-limits","metadata":{"permalink":"/blog/2024/09/05/workflow-specific-rate-limits","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2024-09-05-workflow-specific-rate-limits.md","source":"@site/blog/2024-09-05-workflow-specific-rate-limits.md","title":"Minimizing blast radius in Cadence: Introducing Workflow ID-based Rate Limits","description":"At Uber, we run several big multitenant Cadence clusters with hundreds of domains in each. The clusters being multi-tenant means potential noisy neighbor effects between domains.","date":"2024-09-05T00:00:00.000Z","tags":[{"inline":false,"label":"Deep Dives","permalink":"/blog/tags/deep-dives","description":"Deep Dives tag description"}],"readingTime":6.335,"hasTruncateMarker":true,"authors":[{"name":"Jakob Haahr Taankvist","title":"Software Engineer II @ Uber","url":"https://www.linkedin.com/in/jakob-taankvist/","page":{"permalink":"/blog/authors/jakobht"},"socials":{"linkedin":"https://www.linkedin.com/in/jakob-taankvist/","github":"https://github.com/jakobht"},"imageURL":"https://github.com/jakobht.png","key":"jakobht"}],"frontMatter":{"title":"Minimizing blast radius in Cadence: Introducing Workflow ID-based Rate Limits","date":"2024-09-05T00:00:00.000Z","authors":"jakobht","tags":["deep-dive"]},"unlisted":false,"prevItem":{"title":"Announcement: Cadence Helm Charts v0 Release","permalink":"/blog/2024/10/01/announcing-cadence-helm-charts-v0"},"nextItem":{"title":"2024 Cadence Yearly Roadmap Update","permalink":"/blog/2024/07/11/2024-07-11-yearly-roadmap-update/yearly-roadmap-update"}},"content":"At Uber, we run several big multitenant Cadence clusters with hundreds of domains in each. The clusters being multi-tenant means potential [noisy neighbor](https://en.wikipedia.org/wiki/Cloud_computing_issues#Performance_interference_and_noisy_neighbors) effects between domains.\\n\\nAn essential aspect of avoiding this is managing how workflows interact with our infrastructure to prevent any single workflow from causing instability for the whole cluster. To this end, we are excited to introduce Workflow ID-based rate limits \u2014 a new feature designed to protect our clusters from problematic workflows and ensure stability across the board.\\n\\n## Why Workflow ID-based Rate Limits?\\nWe already have rate limits for how many requests can be sent to a domain. However, since Cadence is sharded on the workflow ID, a user-provided input, an overused workflow with a particular id might overwhelm a shard by making too many requests. There are two main ways this happens:\\n\\n1. A user starts, or signals the same workflow ID too aggressively,\\n2. A workflow starts too many activities over a short period of time (e.g. thousands of activities in seconds).\\n\\n\x3c!-- truncate --\x3e\\n\\nFor example, the following workflow would cause issues for Cadence. It would create huge amounts of traffic to a single shard in a very small time frame:\\n\\n```go\\nfunc Workflow(ctx workflow.Context, input sampleInput) (string, error) {\\n\\t...\\n\\tfor _, elem := range longList {\\n\\t\\terr := workflow.ExecuteActivity(ctx, QuickActivity, elem).Get(ctx, nil)\\n\\t}\\n\\t...\\n}\\n```\\n\\nThis heavy load creates what we call _hot shards_. Hot shards degrade performance not just for the workflow causing the issue, but for all workflows that interact with the affected shard. This can grow to a point where the whole cluster becomes unstable.\\n\\nNow, with Workflow ID-based rate limits, we limit the number of external calls and actions per second for each individual workflow, reducing the blast radius (impact on the cluster) of a badly behaved workflow to an absolute minimum where only the offending workflow is impacted.\\n\\n## Why _not_ Shard Rate Limits?\\n\\nAn obvious question is \u201cwhy don\u2019t we rate limit the requests to the shard?\u201d. After all, the shard is what we want to protect. We have several reasons for choosing to rate limit the workflow ID instead of the shard:\\n\\n- __Hashing__ The workflow ID to shard is random. This means that rate limiting a workflow is a good proxy for rate limiting a shard. The likelihood that many requests from different workflows hit the same shard is very low.\\n- __Communication__ It is easy to explain to a user that their domain is rate limited because they are sending too many requests to a specific workflow ID. Shards are an internal implementation detail that users should not have to worry about.\\n- __Noisy neighbors__ Shards are shared across the different domains in a Cadence cluster. If a user is sending too many requests to a shard, we would choose to rate limit requests to that shard. Since other users in other domains are also using the shard, they will also be rate limited.\\nRate limiting users of a healthy domain because of requests from a completely different domain goes against the isolation the domains are meant to ensure.\\n\\n## How Does It Work?\\nWorkflow ID-based rate limits are set for all workflow IDs in a domain. If the external limit for a domain is e.g. set to 100 it means that any single workflow ID in that domain can at most be signaled 100 times a second. The rate limits are implemented in two main areas:\\n\\n1. __External Calls__ Cadence limits the number of requests per second for each workflow ID, which includes operations like starting, querying, or signaling a workflow. If this limit is exceeded, a ServiceBusyError with message \u201cToo many requests for the workflow ID\u201d is triggered, indicating that the rate limit for the workflow has been reached.\\n\\n2. __Actions Within a Workflow__ This limit controls the number of tasks processed per second within a workflow, focusing on managing decision tasks and activity tasks. When these limits are reached, Cadence slows down task processing without requiring any intervention from the user, though they might notice an increase in task execution time, eventually causing timeouts.\\n\\n### How do I Enable It?\\n\\nThe limits are controlled using six dynamic config properties, three for the internal limits, and a corresponding three for the external limits, all with a domain filter, so the limits can be controlled for each domain.\\n\\n- history.workflowIDCacheInternalEnabled\\\\\\n history.workflowIDCacheExternalEnabled\\n - Controls if the statistics needed to do the rate limiting should be collected. The feature keeps an in-memory record in the history service for each workflow ID.\\n- history.workflowIDInternalRPS\\\\\\n history.workflowIDExternalRPS\\n - Sets the number of requests allowed per second per workflow in a particular domain.\\n- history.workflowIDExternalRateLimitEnabled\\\\\\n history.workflowIDInternalRateLimitEnabled\\n - Set whether rate limiting should happen. Setting this to false allows us to see which domains _would have_ been rate limited and adjust them before enforcing the limits.\\n\\nAn example configuration using the file based dynamic configuration could look like this:\\n\\n```yaml\\nhistory.workflowIDCacheExternalEnabled:\\n- value: true\\n constraints: {}\\nhistory.workflowIDExternalRateLimitEnabled:\\n- value: false\\n constraints:\\n domainName: samples-domain\\n- value: true\\n constraints: {}\\nhistory.workflowIDExternalRPS:\\n- value: 100\\n constraints: {}\\n```\\n\\nHere only the external rate limits are enabled. The internal rate limits have the same structure. We see that \u200cthe rate limiting is enabled for all domains, with a max RPS of 100. The domain samples-domain is however running in shadow mode, so its requests are not rate limited, but metrics and logs are still emitted.\\n\\nThe exact RPS to set for a specific domain and cluster, depends on many things, such as the number of shards, the selected persistent layer, the general load on the cluster etc.\\n\\n## Monitoring and Troubleshooting\\n\\nThe new feature introduces both new metrics and new logs. The new logs help us find workflows that are being rate limited, while the new metrics let us see if domains are being rate limited, and how close to being rate limited they are.\\n\\nThere are four new metrics, two for internal limits and two corresponding metrics for external limits, all emitted from history.\\n\\n- workflow_id_external_requests_ratelimited\\\\\\n workflow_id_internal_requests_ratelimited\\n - This is a counter that counts the number of rate limited requests. The metric is tagged with the domain, so we can track the rate limiting per domain.\\n- workflow_id_external_requests_max_requests_per_second\\\\\\n workflow_id_internal_requests_max_requests_per_second\\n - This is a timer metric. The upper series gives the max number of requests to a single workflow ID. This is again tagged with the domain, so we can for each domain see how close its workflows are to the limit.\\n\\nThese metrics let us monitor and alert on the new rate limits. Additionally, when breaking a rate limit, the history service will emit an info log with the message \u201cRate limiting workflowID\u201d, these logs are tagged with the workflowID that is being limited, so it is easy to find the offending workflow. An example log would look like this:\\n\\n```json\\n{\\n \\"level\\":\\"info\\",\\n \\"ts\\":\\"2024-09-02T08:47:12.843Z\\",\\n \\"msg\\":\\"Rate limiting workflowID\\",\\n \\"service\\":\\"cadence-history\\",\\n \\"request-type\\":\\"external\\",\\n \\"wf-domain-id\\":\\"fc0c7fcb-5796-4c80-b0d7-10bbbc66614e\\",\\n \\"wf-domain-name\\":\\"samples-domain\\",\\n \\"wf-id\\":\\"test\\",\\n \\"logging-call-at\\":\\"cache.go:175\\"\\n}\\n```\\n\\n## Conclusion\\n\\nImplementing these rate limits highly improves the reliability of a Cadence cluster, as users now cannot send too many requests to a single shard. This fine-grained control helps in maintaining optimal performance and enhances the ability to forecast and mitigate potential issues before they impact the service.\\n\\nWorkflow ID-based rate limits are a significant step forward in our ongoing effort to provide a robust and efficient workflow management service. By preventing hot shards and ensuring equitable resource distribution, we can offer more reliable performance, even under peak loads. We encourage all Cadence users to familiarize themselves with these new limits and adjust their workflow configurations to achieve optimal results."},{"id":"/2024/07/11/2024-07-11-yearly-roadmap-update/yearly-roadmap-update","metadata":{"permalink":"/blog/2024/07/11/2024-07-11-yearly-roadmap-update/yearly-roadmap-update","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2024-07-11-yearly-roadmap-update/2024-07-11-yearly-roadmap-update.md","source":"@site/blog/2024-07-11-yearly-roadmap-update/2024-07-11-yearly-roadmap-update.md","title":"2024 Cadence Yearly Roadmap Update","description":"Introduction","date":"2024-07-11T00:00:00.000Z","tags":[{"inline":false,"label":"Roadmap","permalink":"/blog/tags/roadmap","description":"Roadmap tag description"},{"inline":false,"label":"Deep Dives","permalink":"/blog/tags/deep-dives","description":"Deep Dives tag description"}],"readingTime":16.31,"hasTruncateMarker":true,"authors":[{"name":"Ender Demirkaya","title":"Senior Manager at Uber, Cadence. Author of the Software Engineering Handbook","url":"https://www.linkedin.com/in/enderdemirkaya/","page":{"permalink":"/blog/authors/enderdemirkaya"},"socials":{"linkedin":"https://www.linkedin.com/in/enderdemirkaya/","github":"https://github.com/demirkayaender"},"imageURL":"https://github.com/demirkayaender.png","key":"enderdemirkaya"}],"frontMatter":{"title":"2024 Cadence Yearly Roadmap Update","date":"2024-07-11T00:00:00.000Z","authors":"enderdemirkaya","tags":["roadmap","deep-dive"]},"unlisted":false,"prevItem":{"title":"Minimizing blast radius in Cadence: Introducing Workflow ID-based Rate Limits","permalink":"/blog/2024/09/05/workflow-specific-rate-limits"},"nextItem":{"title":"Cadence non-derministic errors common question Q&A (part 1)","permalink":"/blog/2024/02/15/cadence-non-deterministic-common-qa"}},"content":"## Introduction\\n\\nIf you haven\u2019t heard about Cadence, this section is for you. In a short description, Cadence is a code-driven workflow orchestration engine. The definition itself may not tell enough, so it would help splitting it into three parts:\\n\\n* What\u2019s a workflow? (everyone has a different definition)\\n* Why does it matter to be code-driven?\\n* Benefits of Cadence\\n\\n### What is a Workflow?\\n\\n![workflow.png](./2024-yearly-update/workflow.png)\\n\\nIn the simplest definition, it is \u201ca multi-step execution\u201d. Step here represents individual operations that are a little heavier than small in-process function calls. Although they are not limited to those: it could be a separate service call, processing a large dataset, map-reduce, thread sleep, scheduling next run, waiting for an external input, starting a sub workflow etc. It\u2019s anything a user thinks as a single unit of logic in their code. Those steps often have dependencies among themselves. Some steps, including the very first step, might require external triggers (e.g. button click) or schedules. In the more broader meaning, any multi-step function or service is a workflow in principle.\\n\\n\x3c!-- truncate --\x3e\\n\\nWhile the above is a more correct way to define workflows, specialized workflows are more widely known: such as data pipelines, directed acyclic graphs, state machines, cron jobs, (micro)service orchestration, etc. This is why typically everyone has a different workflow meaning in mind. Specialized workflows also have simplified interfaces such as UI, configs or a DSL (domain specific language) to make it easy to express the workflow definition.\\n\\n### Code-Driven Workflows\\n\\nOver time, any workflow interface evolves to support more scenarios. For any non-code (UI, config, DSL) technology, this means more APIs, concepts and tooling. However, eventually, the technology\u2019s capabilities will be limited by its interface itself. Otherwise the interface will get more complicated to operate.\\n\\nWhat happens here is users love the seamless way of creating workflow applications and try to fit more scenarios into it. Natural user tendency is to be able to write any program with such simplicity and confidence.\\n\\nGiven this natural evolution of workflow requirements, it\u2019s better to have a code-driven workflow orchestration engine that can meet any future needs with its powerful expressiveness. On top of this, it is ideal if the interface is seamless, where engineers learn as little as possible and change almost nothing in their local code to write a distributed and durable workflow code. This would virtually remove any limitation and enable implementing any service as a workflow. This is what Cadence aims for.\\n\\n### Benefits\\n\\n![cadence-benefits.png](./2024-yearly-update/cadence-benefits.png)\\n\\nWith Cadence, many overheads that need to be built for any well-supported service come for free. Here are some highlights (see [cadenceworkflow.io](http://cadenceworkflow.io)):\\n\\n* Disaster recovery is supported by default through data replication and failovers\\n* Strong multi tenancy support in Cadence clusters. Capacity and traffic management.\\n* Users can use Cadence APIs to start and interact with their workflows instead of writing new APIs for them\\n* They can schedule their workflows (distributed cron, scheduled start) or any step in their workflows\\n* They have tooling to get updates or cancel their workflows.\\n* Cadence comes with default metrics and logging support so users already get great insights about their workflows without implementing any observability tooling.\\n* Cadence has a web UI where users can list and filter their workflows, inspect workflow/activity inputs and outputs.\\n* They can scale their service just like true stateless services even though their workflows maintain a certain state.\\n* Behavior on failure modes can easily be configured with a few lines, providing high reliability.\\n* With Cadence testing capabilities, they can write unit tests or test against production data to prevent backward incompatibility issues.\\n* \u2026\\n\\n## Project Support\\n\\n### Team\\n\\nToday the Cadence team comprises 26 people. We have people working from Uber\u2019s US offices (Seattle, San Francisco and Sunnyvale) as well as Europe offices (Aarhus-DK and Amsterdam-NL).\\n\\n### Community\\n\\nCadence is an actively built open source project. We invest in both our internal and open source community ([Slack](http://t.uber.com/cadence-slack), [Github](https://github.com/cadence-workflow/cadence/issues)), responding to new features and enhancements.\\n\\n### Scale\\n\\nIt\u2019s one of the most popular platforms at Uber executing ~100K workflow updates per second. There are about 30 different Cadence clusters, several of which serve hundreds of domains. There are ~1000 domains (use cases) varying from tier 0 (most critical) to tier 5 scenarios.\\n\\n### Managed Solutions\\n\\nWhile Uber doesn\u2019t officially sell a managed Cadence solution, there are companies (e.g. [Instaclustr](https://www.instaclustr.com/platform/managed-cadence/)) in our community that we work closely with selling Managed Cadence. Due to efficiency investments and other factors, it\u2019s significantly cheaper than its competitors. It can be run in users\u2019 on-prem machines or their cloud service of choice. Pricing is defined based on allocated hosts instead of number of requests so users can get more with the same resources by utilizing multi-tenant clusters.\\n\\n## After V1 Release\\n\\nLast year, around this time we announced [Cadence V1](https://www.uber.com/blog/announcing-cadence/) and shared our roadmap. In this section we will talk about updates since then. At a high level, you will notice that we continue investing in high reliability and efficiency while also developing new features.\\n\\n### Frequent Releases\\n\\nWe announced plans to make more frequent releases last year and started making more frequent releases. Today we aim to release biweekly and sometimes release as frequently as weekly. About the format, we listened to our community and heard about having too frequent releases potentially being painful. Therefore, we decided to increment the patch version with releases while incrementing the minor version close to quarterly. This helped us ship much more robust releases and improved our reliability. Here are some highlights:\\n\\n### Zonal Isolation\\n\\nCadence clusters have already been regionally isolated until this change. However, in the cloud, inter-zone communications matter as they are more expensive and their latencies are higher. Zones can individually have problems without impacting other cloud zones. In a regional architecture, a single zone problem might impact every request; however, with zonal isolation traffic from a zone with issues can easily be failed over to other zones, eliminating its impact on the whole cluster. Therefore, we implemented zonal isolation keeping domain traffic inside a single zone to help improve efficiency and reliability.\\n\\n### Narrowing Blast Radius\\n\\nWhen there are issues in a Cadence cluster, it\u2019s often from a single misbehaving workflow. When this happens the whole domain or the cluster could have had issues until the specific workflow is addressed. With this change, we are able to contain the issue only to the offending workflow without impacting others. This is the narrowest blast radius possible.\\n\\n### Async APIs\\n\\nAt Uber, there are many batch work streams that run a high number of workflows (thousands to millions) at the same time causing bottlenecks for Cadence clusters, causing noisy neighbor issues. This is because StartWorkflow and SignalWorkflow APIs are synchronous, which means when Cadence acks the user requests are successfully saved in their workflow history.\\n\\nEven after successful initiations, users would then need to deal with high concurrency. This often means constant worker cache thrashing, followed by history rebuilds at every update, increasing workflow execution complexity to O(n^2) from O(n). Alternatively, they would need to quickly scale out and down their service hosts in a very short amount of time to avoid this.\\n\\nWhen we took a step back and analyzed such scenarios, we realized that users simply wanted to \u201ccomplete N workflows (jobs) in K time\u201d. The guarantees around starts and signals were not really important for their use cases. Therefore, we implemented async versions of our sync API, by which we can control the consumption rate, guaranteeing the fastest execution with no disruption in the cluster.\\n\\nLater this year, we plan to expand this feature to cron workflows and timers as well.\\n\\n### Pinot as Visibility Store\\n\\n[Apache Pinot](https://pinot.apache.org/) is becoming popular due to its cost efficient nature. Several teams reported significant savings by changing their observability storage to Pinot. Cadence now has a Pinot plugin for its visibility store. We are still rolling out this change. Latencies and cost savings will be shared later.\\n\\n### Code Coverage\\n\\nWe have received many requests from our community to actively contribute to our codebase, especially after our V1 release. While we have been already collaborating with some companies, this is a challenge with individuals who are just learning about Cadence. One of the main reasons was to avoid bugs that can be introduced.\\n\\nWhile Cadence has many integration tests, its unit test coverage was lower than desired. With better unit test coverage we can catch changes that break previous logic and prevent them getting into the main branch. Our team covered additional 50K+ lines in various Cadence repos. We hope to bring our code coverage to 85%+ by the end of year so we can welcome such inquiries a lot easier.\\n\\n### Replayer Improvements\\n\\nThis is still an ongoing project. As mentioned in our V1 release, we are revisiting some core parts of Cadence where less-than-ideal architectural decisions were made in the past. Replayer/shadower is one of such parts. We have been working on improving its precision, eliminating false negatives and positives.\\n\\n### Global Rate Limiters\\n\\nCadence rate limiters are equally distributed across zones and hosts. However, when the user\'s traffic is skewed, rate limits can get activated even though the user has more capacity. To avoid this, we built global rate limiters. This will make rate limits much more predictable and capacity management a lot easier.\\n\\n### Regular Failover Drills\\n\\nCadence has been performing monthly regional and zonal failover drills to ensure its failover operations are working properly in case we need it. We are failing over hundreds of domains at the same time to validate the scale of this operation, capacity elasticity and correctness of workflows.\\n\\n### Cadence Web v4\\n\\nWe are migrating Cadence web from Vue.js to React.js to use a more modern infrastructure and to have better feature velocity. We are about 70% complete with this migration and hope to release the new version of it soon.\\n\\n### Code Review Time Non-determinism Checks\\n\\n(This is an internal-only feature that we hope to release soon) Cadence non-determinism errors and versioning were common pain points for our customers. There are available tools but they require ongoing effort to validate. We have built a tool that generates a shadower test with a single line command (one time only operation) and continuously validates any code change against production data.\\n\\nThis feature reduced the detect-and-fix time from days/weeks to minutes. Just by launching this feature to the domains with the most non-determinism errors, the number of related incidents reduced by 40%. We have already blocked 500+ diffs that would potentially impact production negatively. This boosted our users\u2019 confidence in using Cadence.\\n\\n### Domain Reports\\n\\n(This is an internal-only feature that we hope to release soon) We are able to detect potential issues (bugs, antipatterns, inefficiencies, failures) with domains upon manual investigation. We have automated this process and now generate reports for each domain. This information can be accessed historically (to see the progression over time) and on-demand (to see the current state). This has already driven domain reliability and efficiency improvements.\\n\\nThis feature and above are at MVP level where we plan to generalize, expand and release for open source soon. In the V1 release, we have mentioned that we would build certain features internally first to be able to have enough velocity, to see where they are going and to make breaking changes until it\u2019s mature.\\n\\n### Client Based Migrations\\n\\nWith 30 clusters and ~1000 domains in production, migrating a domain from a cluster to another became a somewhat frequent operation for Cadence. While this feature is mostly automated, we would like to fully automate it to a level that this would be a single click or command operation. Client based migrations (as opposed to server based ones) give us big flexibility that we can have migrations from many to many environments at the same time. Each migration happens in isolation without impacting any other domain or the cluster.\\n\\nThis is an ongoing project where remaining parts are migrating long running workflows faster and seamless technology to technology migrations even if the \u201cfrom-technology\u201d is not Cadence in the first place. There are many users that migrated from Cadence-like or different technologies to Cadence so we hope to remove the repeating overhead for such users.\\n\\n## Roadmap (Next Year)\\n\\nOur priorities for next year look similar with reliability, efficiency, and new features as our focus. We have seen significant improvements especially in our users\u2019 reliability and efficiency on top of the improvements in our servers. This both reduces operational load on our users and makes Cadence one step closer to being a standard way to build services. Here is a short list of what\'s coming over the next 12 months:\\n\\n### Database efficiency\\n\\nWe are increasing our investment in improving Cadence\u2019s database usage. Even though Cadence\u2019s cost looks a lot better compared to the same family of technologies, it can still be significantly improved by eliminating certain bottlenecks coming from its original design.\\n\\n### Helm Charts\\n\\nWe are grateful to the Cadence community for introducing and maintaining our Helm charts for operating Cadence clusters. We are taking its ownership so it can be officially released and tested. We expect to release this in 2024.\\n\\n### Dashboard Templates\\n\\nDuring our tech talks, demos and user talks, we have received inquiries about what metrics care about. We plan to release templates for our dashboards so our community would look at a similar picture.\\n\\n### Client V2 Modernization\\n\\nAs we announced last year that we plan to make breaking changes to significantly improve our interfaces, we are working on modernizing our client interface.\\n\\n### Higher Parallelization and Prioritization in Task Processing\\n\\nIn an effort to have better domain prioritization in multitenant Cadence clusters, we are improving our task processing with higher parallelization and better prioritization. This is a lot better model than just having domains with defined limits. We expect to provide more resources to high priority domains during their peak hours while allowing low priority domains to consume much bigger resources than allocated during quiet times.\\n\\n### Timer and Cron Burst Handling\\n\\nAfter addressing start and signal burst scenarios, we are continuing with bursty timers and cron jobs. Many users set their schedules and timers for the same second with the intention of being able to finish N jobs within a certain amount of time. Current scheduling design isn\u2019t friendly for such intents and high loads can cause temporary starvation in the cluster. By introducing better batch scheduling support, clusters can continue with no disruption while timers are processed in the most efficient way.\\n\\n### High zonal skew handling\\n\\nFor users operating in their own cloud and having multiple independent zones in every region, zonal skews can be a problem and can create unnecessary bottlenecks when Zonal Isolation feature is enabled. We are working on addressing such issues to improve task matching across zones when skew is detected.\\n\\n### Tasklist Improvements\\n\\nWhen a user scenario grows, there are many knobs that need to be manually adjusted. We would like to automatically partition and smartly forward tasks to improve tasklist efficiency significantly to avoid backlogs, timeouts and hot shards.\\n\\n### Shard Movement/Assignment Improvements\\n\\nCadence shard movements are based on consistent hash and this can be a limiting factor for many different reasons. Certain hosts can end up getting unlucky by having many shards, or having heavy shards. During deployments we might observe a much higher number of shard movements than desired, which reduces the availability. With improved shard movements and assignments we can have more homogenous load among hosts while also having a minimum amount of shard movements during deployments with much better availability.\\n\\n### Worker Heartbeats\\n\\nToday, there\u2019s no worker liveliness tracking in Cadence. Instead, task or activity heartbeat timeouts are used to reassign tasks to different workers. For latency sensitive users this can become a big disruption. For long activities without heartbeats, this can cause big delays. This feature is to eliminate depending on manual timeout or heartbeat configs to reassign tasks by tracking if workers are still healthy. This feature will also enable so many other new efficiency and reliability features we would like to get to in the future.\\n\\n### Domain and Workflow Diagnostics\\n\\nProbably the two most common user questions are \u201cWhat\u2019s wrong with my domain?\u201d and \u201cWhat\u2019s wrong with my workflow?\u201d. Today, diagnosing what happened and what could be wrong isn\u2019t that easy apart from some basic cases. We are working on tools that would run diagnostics on workflows and domains to point out things that might potentially be wrong with public runbook links attached. This feature will not only help diagnose what is wrong with our workflows and domains but will also help fix them.\\n\\n### Self Serve Operations\\n\\nCertain Cadence operations are performed through admin CLI operations. However, these should be able to be done via Cadence UI by users. Admins shouldn\u2019t need to be involved in every step or the checks they validate should be able to be automated. This is what the initiative is about including domain registration, auth/authz onboarding or adding new search attributes but it\u2019s not limited to these operations.\\n\\n### Cost Estimation\\n\\nOne big question we receive when users are onboarding to Cadence is \u201cHow much will this cost me?\u201d. This is not an easy question to answer since data and traffic load can be quite different. We plan to automate this process to help users understand how much resources they will need. Especially in multi-tenant clusters, this will help users understand how much room they still have in their clusters and how much the new scenario will consume.\\n\\n### Domain Reports (continue)\\n\\nWe plan to release this internal feature to open source as soon as possible. On top of presenting this data on built-in Cadence surfaces (web, CLI. etc.) we will create APIs to make it integratable with deployment systems, user service UIs, periodic reports and any other service that would like to consume.\\n\\n### Non-determinism Detection Improvements (continue)\\n\\nWe have seen great reliability improvements and reduction in incidents with this feature on the user side last year. We continue to invest in this feature and make it available in open source as soon as possible.\\n\\n### Domain Migrations (continue)\\n\\nIn the next year, we plan to finish our seamless client based migration to be able to safely migrate domains from one cluster to another, one technology (even if it\u2019s not Cadence) to another and one cloud solution to another. There are only a few features left to achieve this.\\n\\n## Community\\n\\nDo you want to hear more about Cadence? Do you need help with your set-up or usage? Are you evaluating your options? Do you want to contribute? Feel free to join our community and reach out to us.\\n\\nSlack: [https://uber-cadence.slack.com/](https://uber-cadence.slack.com/)\\n\\nGithub: [https://github.com/cadence-workflow/cadence](https://github.com/cadence-workflow/cadence)\\n\\nSince last year, we have been contacted by various companies to take on bigger projects on the Cadence project. As we have been investing in code coverage and refactoring Cadence for a cleaner codebase, this will be a lot easier now. Let us know if you have project ideas to contribute or if you\u2019d like to pick something we already planned.\\n\\nOur monthly community meetings are still ongoing, too. That is the best place to get heard and be involved in our decision-making process. Let us know so we can send you an invite. We are also working on a broader governing model to open up this project to more people. Stay tuned for updates on this topic!"},{"id":"/2024/02/15/cadence-non-deterministic-common-qa","metadata":{"permalink":"/blog/2024/02/15/cadence-non-deterministic-common-qa","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2024-02-15-cadence-non-deterministic-common-qa.md","source":"@site/blog/2024-02-15-cadence-non-deterministic-common-qa.md","title":"Cadence non-derministic errors common question Q&A (part 1)","description":"If I change code logic inside an Cadence activity (for example, my activity is calling database A but now I want it to call database B), will it trigger an non-deterministic error?","date":"2024-03-10T00:00:00.000Z","tags":[{"inline":false,"label":"Deep Dives","permalink":"/blog/tags/deep-dives","description":"Deep Dives tag description"}],"readingTime":2.625,"hasTruncateMarker":true,"authors":[{"name":"Chris Qin","title":"Applications Developer @ Uber","url":"https://www.linkedin.com/in/chrisqin0610/","page":{"permalink":"/blog/authors/chopincode"},"socials":{"linkedin":"https://www.linkedin.com/in/chrisqin0610/","github":"https://github.com/chopincode"},"imageURL":"https://github.com/chopincode.png","key":"chopincode"}],"frontMatter":{"title":"Cadence non-derministic errors common question Q&A (part 1)","date":"2024-03-10T00:00:00.000Z","authors":"chopincode","tags":["deep-dive"]},"unlisted":false,"prevItem":{"title":"2024 Cadence Yearly Roadmap Update","permalink":"/blog/2024/07/11/2024-07-11-yearly-roadmap-update/yearly-roadmap-update"},"nextItem":{"title":"Cadence Community Spotlight Update - November 2023","permalink":"/blog/2023/11/30/community-spotlight-update-november-2023"}},"content":"### If I change code logic inside an Cadence activity (for example, my activity is calling database A but now I want it to call database B), will it trigger an non-deterministic error?\\n\\n<b>NO</b>. This change will not trigger non-deterministic error.\\n\\nAn Activity is the smallest unit of execution for Cadence and what happens inside activities are not recorded as historical events and therefore will not be replayed. In short, this change is deterministic and it is fine to modify logic inside activities.\\n\\n### Does changing the workflow definition trigger non-determinstic errors?\\n\\n<b>YES</b>. This is a very typical non-deterministic error.\\n\\nWhen a new workflow code change is deployed, Cadence will find if it is compatible with\\nCadence history. Changes to workflow definition will fail the replay process of Cadence\\nas it finds the new workflow definition imcompatible with previous historical events.\\n\\nHere is a list of common workflow definition changes.\\n- Changing workflow parameter counts\\n- Changing workflow parameter types\\n- Changing workflow return types\\n\\nThe following changes are not categorized as definition changes and therefore will not\\ntrigger non-deterministic errors.\\n- Changes of workflow return values\\n- Changing workflow parameter names as they are just positional\\n\\n\x3c!-- truncate --\x3e\\n\\n### Does changing activity definitions trigger non-determinstic errors?\\n\\n<b>YES</b>. Similar to workflow definition change, this is also a very typical non-deterministic error.\\n\\nActivities are also recorded and replayed by Cadence. Therefore, changes to activity must also be compatible with Cadence history. The following changes are common ones that trigger non-deterministic errors.\\n- Changing activity parameter counts\\n- Changing activity parameter types\\n- Changing activity return types\\n\\nAs activity paremeters are also positional, these two changes will NOT trigger non-deterministic errors.\\n- Changes of activity return values\\n- Changing activity parameter names\\n\\nActivity return values inside workflows are not recorded and replayed.\\n\\n### What changes inside workflows may potentially trigger non-deterministic errors?\\n\\nCadence records each execution of a workflow and activity execution inside each of them.Therefore, new changes must be compatible with execution orders inside the workflow. The following changes will fail the non-deterministic check.\\n\\n- Append another activity\\n- Delete an existing activity\\n- Reordering activities\\n\\nIf you really need to change the activity implementation based on new business requirements, you may consider using versioning your workflow.\\n\\n### Are Cadence signals replayed? If definition of signal is changed, will it trigger non-deterministic errors?\\n\\nYes. If a signal is used in a workflow, it becomes a critical component of your workflow. Because signals also involve I/O to your workflow, it is also recorded and replayed. Modifications on signal definitions or usage may yield to non-deterministic errors, for instance, changing return type of a signal.\\n\\n### If I have new business requirement and really need to change the definition of a workflow, what should I do?\\n\\nYou may introduce a new workflow registered to your worker and divert traffic to it or use versioning for your workflow. Check out [Cadence website](https://cadenceworkflow.io/docs/go-client/workflow-versioning/) for more information about versioning.\\n\\n### Does changes to local activities\' definition trigger non-deterministic errors?\\n\\nYes. Local activities are recorded and therefore replayed by Cadence. Imcompatible changes on local activity definitions will yield to non-deterministic errors."},{"id":"/2023/11/30/community-spotlight-update-november-2023","metadata":{"permalink":"/blog/2023/11/30/community-spotlight-update-november-2023","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2023-11-30-community-spotlight-update-november-2023.md","source":"@site/blog/2023-11-30-community-spotlight-update-november-2023.md","title":"Cadence Community Spotlight Update - November 2023","description":"Welcome to the latest of our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!","date":"2023-11-30T00:00:00.000Z","tags":[{"inline":false,"label":"Community Spotlight","permalink":"/blog/tags/community-spotlights","description":"Community Spotlight tag description"},{"inline":false,"label":"Announcement","permalink":"/blog/tags/announcements","description":"Announcement tag description"}],"readingTime":3.46,"hasTruncateMarker":true,"authors":[{"name":"Sharan Foga","title":"Director of Operations & Customer Success @ Encube Technologies","url":"https://www.linkedin.com/in/sfoga/","page":{"permalink":"/blog/authors/sharanf"},"socials":{"linkedin":"https://www.linkedin.com/in/sfoga/","github":"https://github.com/sharanf"},"imageURL":"https://github.com/sharanf.png","key":"sharanf"}],"frontMatter":{"title":"Cadence Community Spotlight Update - November 2023","date":"2023-11-30T00:00:00.000Z","authors":"sharanf","tags":["community-spotlight","announcement"]},"unlisted":false,"prevItem":{"title":"Cadence non-derministic errors common question Q&A (part 1)","permalink":"/blog/2024/02/15/cadence-non-deterministic-common-qa"},"nextItem":{"title":"Cadence Community Spotlight Update - August 2023","permalink":"/blog/2023/08/31/community-spotlight-august-2023"}},"content":"Welcome to the latest of our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!\\n\\nIt\'s been a couple of months since our last update so we have a lot of updates to share with you.\\n\\nPlease see below for a roundup of the highlights:\\n\\n\x3c!-- truncate --\x3e\\n\\n## Proposal for Cadence Native Authentication ##\\n\\nCommunity member [Mantas Sidlauskas](https://lt.linkedin.com/in/mantassidlauskas) has drafted a proposal around Cadence native authentication and is asking for community feedback. If you are interested in reviewing the current proposal and providing comments or feedback then please find the proposal details at the link below:\\n\\n- [Cadence Native Authentication Proposal](https://docs.google.com/document/d/13GxRBZfQkLyhDCrpFaZmRcw7DJJG-zdy0_mPXy3CcWw/edit#heading=h.c8u99ansg7ma)\\n\\n This is a great example of how we can focus on collaborating together to find a collective solution. A big thank you to Mantas for initiating this work and we hope to see the results of the community input soon!\\n\\n## iWF Deep Dive and More! ##\\n\\nDuring the last few months community member [Quanzheng Long](https://www.linkedin.com/in/prclqz/) has continued to share his thoughts about [iWF](https://github.com/indeedeng/iwf), a layer implemented on top of Cadence. Since our last update iWF now has a[Python SDK](https://github.com/indeedeng/iwf-python-sdk). Long has been busy writing articles to share iWF tips and tricks as well as some general ideas about workflows and processes. Links to Long\'s articles can be found below:\\n\\n- [iWF Deep Dive: workflowState+Durable Timer#1](https://medium.com/@qlong/iwf-deep-dive-workflowstate-durable-timer-1-0bb89e6d6fd4)\\n\\n- [Gotchas About SignalWithStart in Cadence/Temporal](https://medium.com/@qlong/gotchas-about-signalwithstart-in-cadence-temporal-c3783fe1cc2e)\\n\\n- [\\"Workflow\\" could be \\"Process\\" in WorkflowAsCode frameworks](https://medium.com/@qlong/workflow-could-be-process-in-workflowascode-frameworks-63dcb632c248)\\n\\n## New Go Samples for Cadence ##\\n\\nThe Cadence core team is deprecating the old samples for Go and replacing them with new version 2 (V2) samples. They have received a lot of feedback from the community that people are having trouble with old samples, so are in the process of publishing a completely new set of samples for Go.\\n\\nHere are some major changes to the new samples:\\n\\n- Easy to use the read - the new samples will be completely based on CLIs instead of running a binary. (This is consistent with current Cadence use experience)\\n- Simple and transparent worker configuration - the old samples did not provide user a clear demonstration about the relationship between the worker and workflow themselves\\n- The new samples will help you bootstrap your Cadence workflow faster and easier.\\n- More vivid and self-explanatory - instead of the traditional \\"HelloWorld\\" type of samples, we want to make it more interesting and engaging. (Each sample will try to simulate a real-life use case to make them more understandable and fun to learn!)\\n\\nWe hope the community will enjoy these changes. If you have any questions or have new an idea for a new sample then please reach out to [Chris Qin](https://www.linkedin.com/in/chrisqin0610).\\n\\nThe new Go samples can be found at:\\n- https://github.com/cadence-workflow/cadence-samples/tree/master/new_samples.\\n\\nNote that the old samples will be removed once the new samples are fully refreshed.\\n\\n## Cadence Retrospective ##\\n\\nWe are nearly at the end of another year and yes it has gone so fast! Over this year Cadence and the community have evolved and grown. This is a good time to reflect about all the things that have happened in the project over the year and think about a possible roadmap for the future.\\n\\nIf you have any feedback, or comments about the project or ideas about what features you\'d like to see in the roadmap then please feel free to begin a discussion in the #community [Slack](http://t.uber.com/cadence-slack) channel.\\n\\n## Cadence in the News!\\n\\nBelow are a selection of Cadence related articles, blogs and whitepapers.\\nPlease take a look and feel free to share via your own social media channels.\\n\\n- [How to Throttle Cadence](https://www.instaclustr.com/blog/how-to-throttle-cadence/)\\n\\n- [iWF Deep Dive: workflowState+Durable Timer#1](https://medium.com/@qlong/iwf-deep-dive-workflowstate-durable-timer-1-0bb89e6d6fd4)\\n\\n- [Gotchas About SignalWithStart in Cadence/Temporal](https://medium.com/@qlong/gotchas-about-signalwithstart-in-cadence-temporal-c3783fe1cc2e)\\n\\n- [\\"Workflow\\" could be \\"Process\\" in WorkflowAsCode frameworks](https://medium.com/@qlong/workflow-could-be-process-in-workflowascode-frameworks-63dcb632c248)\\n\\n## Upcoming Events\\n\\n- [On Demand Webinar: Building With Cadence:Quantifiable Efficiency](https://netapp.zoom.us/webinar/register/WN_jT5fxSldRhuzV0NSllBd7g#/registration)\\n\\nIf you have any news or topics you\'d like us to include in our next update then please join our [Slack](http://t.uber.com/cadence-slack) #community channel.\\n\\nPlease remember that this update is for you - so if you have any comments or feedback that could help us improve it then please share it with us in the #community [Slack](http://t.uber.com/cadence-slack) channel."},{"id":"/2023/08/31/community-spotlight-august-2023","metadata":{"permalink":"/blog/2023/08/31/community-spotlight-august-2023","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2023-08-31-community-spotlight-august-2023.md","source":"@site/blog/2023-08-31-community-spotlight-august-2023.md","title":"Cadence Community Spotlight Update - August 2023","description":"Welcome to the latest of our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!","date":"2023-08-31T00:00:00.000Z","tags":[{"inline":false,"label":"Introduction to Cadence","permalink":"/blog/tags/introduction-to-cadence","description":"Introduction to Cadence tag description"},{"inline":false,"label":"Community Spotlight","permalink":"/blog/tags/community-spotlights","description":"Community Spotlight tag description"}],"readingTime":2.955,"hasTruncateMarker":true,"authors":[{"name":"Sharan Foga","title":"Director of Operations & Customer Success @ Encube Technologies","url":"https://www.linkedin.com/in/sfoga/","page":{"permalink":"/blog/authors/sharanf"},"socials":{"linkedin":"https://www.linkedin.com/in/sfoga/","github":"https://github.com/sharanf"},"imageURL":"https://github.com/sharanf.png","key":"sharanf"}],"frontMatter":{"title":"Cadence Community Spotlight Update - August 2023","date":"2023-08-31T00:00:00.000Z","authors":"sharanf","tags":["introduction-to-cadence","community-spotlight"]},"unlisted":false,"prevItem":{"title":"Cadence Community Spotlight Update - November 2023","permalink":"/blog/2023/11/30/community-spotlight-update-november-2023"},"nextItem":{"title":"Non-deterministic errors, replayers and shadowers","permalink":"/blog/2023/08/28/nondeterministic-errors-replayers-shadowers"}},"content":"Welcome to the latest of our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!\\n\\nPlease see below for a roundup of the highlights:\\n\\n## More Cadence How To\'s ##\\n\\nYou might have noticed that we have had a few more contributions to our blog from [Chris Qin](https://www.linkedin.com/in/chrisqin0610). Chris has been busy sharing insights, and tips on a few important Cadence topics. The objective is to help the community with any potential problems.\\n\\nHere are the latest topics:\\n\\n- [Bad Practices and Anti-Patterns with Cadence - Part 1](https://cadenceworkflow.io/blog/2023/07/10/cadence-bad-practices-part-1/)\\n\\n- [Non-Determistic Errors, Replayers and Shadowers](https://cadenceworkflow.io/blog/2023/08/27/nondeterministic-errors-replayers-shadowers/)\\n\\nEven if you have not encountered these use cases - it is good to be prepared and have a solution ready.Please take a look and let us have your feedback.\\n\\nChris is also going to take a look at the [Cadence Samples](https://cadenceworkflow.io/docs/java-client/client-overview/#samples) to make sure they are all working and if not - he\'s going to re-write them so that they do!\\n\\nThanks very much Chris for all the work you are doing to help improve the project!\\n\\n\x3c!-- truncate --\x3e\\n\\n## More iWF Examaples ##\\n\\nCommunity member [Quanzheng Long](https://www.linkedin.com/in/prclqz/) has also been busy writing this month. In previous blogs Long has told us about [iWF](https://github.com/indeedeng/iwf) that is a layer implemented over of Cadence.\\n\\nDuring August Long has published a couple of articles on using the \'ContinueAsNew\' functionality in iWF. Links to Part 1 and Part are below:\\n\\n- [Guide to ContinueAsNew in Cadence/Temporal Workflow Using iWF as an example - Part 1](https://medium.com/@qlong/guide-to-continueasnew-in-cadence-temporal-workflow-using-iwf-as-an-example-part-2-cedabd732bec)\\n\\n- [Guide to ContinueAsNew in Cadence/Temporal Workflow Using iWF as an example - Part 2](https://medium.com/@qlong/guide-to-continueasnew-in-cadence-temporal-workflow-using-iwf-as-an-example-part-1-c24ae5266f07)\\n\\nPlease take a look and if you\'ve enjoyed reading them then let Long and us know!\\n\\n## Cadence At the Helm! ##\\n\\nLast month we mentioned the Cadence Helm charts and all the previous work that had been done by [Mark Sagi-Kazar](https://www.linkedin.com/in/sagikazarmark/). We were looking to ensure they are maintained.\\n\\nSo a special thanks goes out this month to [Edmondo](ttps://github.com/edmondop ) for contributing some work on the [Cadence Helm Chart](https://github.com/edmondop/cadence-helm-chart/).\\n\\n## Community Support! ##\\n\\nOur [Slack](http://t.uber.com/cadence-slack) channel continues to be the main place where people are asking for help and support with Cadence. During August (which is supposed to be holiday season), we still had 9 questions raised around various topics.\\n\\nHuge thanks to the following community members who took time to respond and help others: David, Edmondo, Chris Qin, Rony Rahman and Ben Slater.\\n\\nIt\'s good to see that we are continuing to support each other - doing exactly what communities do!\\n\\n## Cadence in the News!\\n\\nBelow are a selection of Cadence related articles, blogs and whitepapers.\\nPlease take a look and feel free to share via your own social media channels.\\n\\n\\n- [Guide to ContinueAsNew in Cadence/Temporal Workflow Using iWF as an example - Part 1](https://medium.com/@qlong/guide-to-continueasnew-in-cadence-temporal-workflow-using-iwf-as-an-example-part-2-cedabd732bec)\\n\\n- [Guide to ContinueAsNew in Cadence/Temporal Workflow Using iWF as an example - Part 2](https://medium.com/@qlong/guide-to-continueasnew-in-cadence-temporal-workflow-using-iwf-as-an-example-part-1-c24ae5266f07)\\n\\n- [AWS PrivateLink Connectivity is now Available with Instaclustr for Cadence](https://www.instaclustr.com/blog/aws-privatelink-for-cadence-on-instaclustr-by-netapp/)\\n\\n## Upcoming Events\\n\\n- [Webinar: Introducing the Cadence Workflow HTTP API - 21st September 2023 ](https://netapp.zoom.us/webinar/register/WN_Uh9Y6ruiQSS5EiylNlsMug#/registration)\\n\\n- [On Demand Webinar: Microservices - A Modern Orchestration Approach with Cadence](https://netapp.zoom.us/webinar/register/WN_Hv9lO9QtSqyPPWkSAIRj5g#/registration)\\n\\n- [On Demand Webinar: Spinning Your Drones with Cadence and Apache Kafka](https://www.instaclustr.com/events/spinning-your-drones-with-cadence-and-apache-kafka/)\\n\\nIf you have any news or topics you\'d like us to include in our next update then please join our [Slack](http://t.uber.com/cadence-slack) #community channel.\\n\\nPlease remember that this update is for you - so if you have any comments or feedback that could help us improve it then please share it with us in the #community [Slack](http://t.uber.com/cadence-slack) channel."},{"id":"/2023/08/28/nondeterministic-errors-replayers-shadowers","metadata":{"permalink":"/blog/2023/08/28/nondeterministic-errors-replayers-shadowers","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2023-08-28-nondeterministic-errors-replayers-shadowers.md","source":"@site/blog/2023-08-28-nondeterministic-errors-replayers-shadowers.md","title":"Non-deterministic errors, replayers and shadowers","description":"It is conceivable that developers constantly update their Cadence workflow code based upon new business use cases and needs. However,","date":"2023-08-27T00:00:00.000Z","tags":[{"inline":false,"label":"Deep Dives","permalink":"/blog/tags/deep-dives","description":"Deep Dives tag description"},{"inline":false,"label":"Testing","permalink":"/blog/tags/testing","description":"Testing tag description"}],"readingTime":2.305,"hasTruncateMarker":true,"authors":[{"name":"Chris Qin","title":"Applications Developer @ Uber","url":"https://www.linkedin.com/in/chrisqin0610/","page":{"permalink":"/blog/authors/chopincode"},"socials":{"linkedin":"https://www.linkedin.com/in/chrisqin0610/","github":"https://github.com/chopincode"},"imageURL":"https://github.com/chopincode.png","key":"chopincode"}],"frontMatter":{"title":"Non-deterministic errors, replayers and shadowers","date":"2023-08-27T00:00:00.000Z","authors":"chopincode","tags":["deep-dive","testing"]},"unlisted":false,"prevItem":{"title":"Cadence Community Spotlight Update - August 2023","permalink":"/blog/2023/08/31/community-spotlight-august-2023"},"nextItem":{"title":"Cadence Community Spotlight Update - July 2023","permalink":"/blog/2023/07/31/community-spotlight-july-2023"}},"content":"It is conceivable that developers constantly update their Cadence workflow code based upon new business use cases and needs. However,\\nthe definition of a Cadence workflow must be deterministic because behind the scenes cadence uses event sourcing to construct\\nthe workflow state by replaying the historical events stored for this specific workflow. Introducing components that are not compatible\\nwith an existing running workflow will yield to non-deterministic errors and sometimes developers find it tricky to debug. Consider the\\nfollowing workflow that executes two activities.\\n\\n```go\\nfunc SampleWorkflow(ctx workflow.Context, data string) (string, error) {\\n ao := workflow.ActivityOptions{\\n ScheduleToStartTimeout: time.Minute,\\n StartToCloseTimeout: time.Minute,\\n }\\n ctx = workflow.WithActivityOptions(ctx, ao)\\n var result1 string\\n err := workflow.ExecuteActivity(ctx, ActivityA, data).Get(ctx, &result1)\\n if err != nil {\\n return \\"\\", err\\n }\\n var result2 string\\n err = workflow.ExecuteActivity(ctx, ActivityB, result1).Get(ctx, &result2)\\n return result2, err\\n}\\n\\n```\\n\\n\x3c!-- truncate --\x3e\\n\\nIn this example, the workflow will execute ActivityA and Activity B in sequence. These activities may have other logics in background, such as polling long running operations or manipulate database reads or writes. Now if the developer replaces ActivityA with another activity ActivityC, a non-deterministic error could happen for an existing workflow. It is because the workflow expects results from ActivityA but since the definition of the workflow has been changed to use results from ActivityC, the workflow will fail due to failure of identifying history data of ActivityA. Such issues can be detected by introducing replayers and shadowers to the workflow unit tests.\\n\\nCadence workflow replayer is a testing component for replaying existing workflow histories against a workflow definition. You may think of replayer as a mock which will rerun your workflow with exactly the same history as your real workflow. The replaying logic is the same as the one used for processing workflow tasks. If it detects any incompatible changes, the replay test will fail.\\nWorkflow Replayer works well when verifying the compatibility against a small number of workflow histories. If there are lots of workflows in production that need to be verified, dumping all histories manually clearly won\'t work. Directly fetching histories from the cadence server might be a solution, but the time to replay all workflow histories might be too long for a test.\\n\\nWorkflow Shadower is built on top of Workflow Replayer to address this problem. The basic idea of shadowing is: scan workflows based on the filters you defined, fetch history for each workflow in the scan result from Cadence server and run the replay test. It can be run either as a test to serve local development purposes or as a workflow in your worker to continuously replay production workflows.\\n\\nYou may find detailed instructions on how to use replayers and shadowers on [our website](https://cadenceworkflow.io/docs/go-client/workflow-replay-shadowing/). We will introduce versioning in the next coming blogs."},{"id":"/2023/07/31/community-spotlight-july-2023","metadata":{"permalink":"/blog/2023/07/31/community-spotlight-july-2023","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2023-07-31-community-spotlight-july-2023.md","source":"@site/blog/2023-07-31-community-spotlight-july-2023.md","title":"Cadence Community Spotlight Update - July 2023","description":"Welcome to the latest of our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!","date":"2023-07-31T00:00:00.000Z","tags":[{"inline":false,"label":"Releases","permalink":"/blog/tags/releases","description":"Releases tag description"},{"inline":false,"label":"Announcement","permalink":"/blog/tags/announcements","description":"Announcement tag description"},{"inline":false,"label":"Community Spotlight","permalink":"/blog/tags/community-spotlights","description":"Community Spotlight tag description"}],"readingTime":2.49,"hasTruncateMarker":true,"authors":[{"name":"Sharan Foga","title":"Director of Operations & Customer Success @ Encube Technologies","url":"https://www.linkedin.com/in/sfoga/","page":{"permalink":"/blog/authors/sharanf"},"socials":{"linkedin":"https://www.linkedin.com/in/sfoga/","github":"https://github.com/sharanf"},"imageURL":"https://github.com/sharanf.png","key":"sharanf"}],"frontMatter":{"title":"Cadence Community Spotlight Update - July 2023","date":"2023-07-31T00:00:00.000Z","authors":"sharanf","tags":["release","announcement","community-spotlight"]},"unlisted":false,"prevItem":{"title":"Non-deterministic errors, replayers and shadowers","permalink":"/blog/2023/08/28/nondeterministic-errors-replayers-shadowers"},"nextItem":{"title":"Write your first workflow with Cadence","permalink":"/blog/2023/07/16/2023-07-16-write-your-first-workflow-with-cadence/write-your-first-workflow-with-cadence"}},"content":"Welcome to the latest of our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!\\n\\nPlease see below for a roundup of the highlights:\\n\\n## Getting Started with Cadence ##\\n\\nAre you new to Cadence and want to understand the basic concepts and architecture? Well we have some great information for you!\\n\\nCommunity member [Chris Qin](https://www.linkedin.com/in/chrisqin0610/) has written a [short blog post](https://cadenceworkflow.io/blog/2023/07/01/components-of-cadence-application-setup/) that takes you through the the three main components that make up a Cadence application. Please take a look and feel free to give us your comments and feedback.\\n\\nThanks Chris for sharing your knowledge and helping others to get started.\\n\\n## Cadence Go Client v1.0 Released ##\\n\\nThis month saw the release of [v1.0 of the Cadence Go Client](https://github.com/cadence-workflow/cadence-go-client/releases/tag/v1.0.0). Note that the work done on this release was as a result of community feedback asking for it - so we are listening and responding to community needs.\\n\\nThanks very much to everyone who worked hard to get this release out!\\n\\n\x3c!-- truncate --\x3e\\n\\n## Cadence Release Strategy ##\\n\\nA recent discussion on the Cadence Release strategy was posted in [Cadence Github Discussions](https://github.com/cadence-workflow/cadence/discussions/5362) (and also our #general channel on our [Slack](http://t.uber.com/cadence-slack) about the approach we\'d like to take for future releases. As a community we want to ensure code stability and to not burden people with having to upgrade frequently.\\n\\nBased on feedback from the community we will be introducing quarterly release cycles but also give people the ability to make use of patches and minor releases. We will be communicating the intention to make a release at least a month beforehand so that the community has time to finalise any features they want to be included in the upcoming release.\\n\\nFor those of you wanting to keep up to date or try out new features in between releases, the core team at Uber will continue to make patch and minor version updates available to the community.\\n\\nAs always we welcome your feedback so please feel free to add your thoughts and comments to the discussion.\\n\\n## Cadence Helm Charts ##\\n\\nCommunity member [Mark Sagi-Kazar](https://www.linkedin.com/in/sagikazarmark/) has been maintaining the Banzai Cloud Cadence Helm Charts for the community. As the Helm Charts are a key tool for the community we are planning to take over the maintenance of them.\\n\\nOur plan is to move the charts into the Cadence repository and to maintain an official and supported Kubernetes solution with Cadence.\\n\\nHuge thanks to Mark for all the work you have done and it\'s great to see the task being handed over and made into a community effort.\\n\\n## Upcoming Events\\n\\n- None\\n\\nIf you have any news or topics you\'d like us to include in our next update then please join our [Slack](http://t.uber.com/cadence-slack) #community channel.\\n\\nPlease remember that this update is for you - so if you have any comments or feedback that could help us improve it then please share it with us in the #community [Slack](http://t.uber.com/cadence-slack) channel."},{"id":"/2023/07/16/2023-07-16-write-your-first-workflow-with-cadence/write-your-first-workflow-with-cadence","metadata":{"permalink":"/blog/2023/07/16/2023-07-16-write-your-first-workflow-with-cadence/write-your-first-workflow-with-cadence","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2023-07-16-write-your-first-workflow-with-cadence/2023-07-16-write-your-first-workflow-with-cadence.md","source":"@site/blog/2023-07-16-write-your-first-workflow-with-cadence/2023-07-16-write-your-first-workflow-with-cadence.md","title":"Write your first workflow with Cadence","description":"We have covered basic components of Cadence and how to implement a Cadence worker on local environment in previous blogs. In this blog, let\'s write your very first HelloWorld workflow with Cadence. I\'ve started the Cadence backend server in background and registered a domain named test-domain. You may use the code snippet for the worker service in this blog Let\'s first write a activity, which takes a single string argument and print a log in the console.","date":"2023-07-16T00:00:00.000Z","tags":[{"inline":false,"label":"Deep Dives","permalink":"/blog/tags/deep-dives","description":"Deep Dives tag description"},{"inline":false,"label":"Introduction to Cadence","permalink":"/blog/tags/introduction-to-cadence","description":"Introduction to Cadence tag description"}],"readingTime":2.075,"hasTruncateMarker":true,"authors":[{"name":"Chris Qin","title":"Applications Developer @ Uber","url":"https://www.linkedin.com/in/chrisqin0610/","page":{"permalink":"/blog/authors/chopincode"},"socials":{"linkedin":"https://www.linkedin.com/in/chrisqin0610/","github":"https://github.com/chopincode"},"imageURL":"https://github.com/chopincode.png","key":"chopincode"}],"frontMatter":{"title":"Write your first workflow with Cadence","date":"2023-07-16T00:00:00.000Z","authors":"chopincode","tags":["deep-dive","introduction-to-cadence"]},"unlisted":false,"prevItem":{"title":"Cadence Community Spotlight Update - July 2023","permalink":"/blog/2023/07/31/community-spotlight-july-2023"},"nextItem":{"title":"Bad practices and Anti-patterns with Cadence (Part 1)","permalink":"/blog/2023/07/10/cadence-bad-practices-part-1"}},"content":"We have covered [basic components of Cadence](/blog/2023-06-28-components-of-cadence-application-setup.md) and [how to implement a Cadence worker on local environment](/blog/2023-07-05-implement-cadence-worker-from-scratch.md) in previous blogs. In this blog, let\'s write your very first HelloWorld workflow with Cadence. I\'ve started the Cadence backend server in background and registered a domain named `test-domain`. You may use the code snippet for the worker service in [this blog](/blog/2023-07-05-implement-cadence-worker-from-scratch.md) Let\'s first write a activity, which takes a single string argument and print a log in the console.\\n\\n```go\\nfunc helloWorldActivity(ctx context.Context, name string) (string, error) {\\n\\tlogger := activity.GetLogger(ctx)\\n\\tlogger.Info(\\"helloworld activity started\\")\\n\\treturn \\"Hello \\" + name + \\"!\\", nil\\n}\\n```\\n\\n\x3c!-- truncate --\x3e\\n\\nThen let\'s write a workflow that invokes this activity\\n```go\\nfunc helloWorldWorkflow(ctx workflow.Context, name string) error {\\n\\tao := workflow.ActivityOptions{\\n\\t\\tScheduleToStartTimeout: time.Minute,\\n\\t\\tStartToCloseTimeout: time.Minute,\\n\\t\\tHeartbeatTimeout: time.Second * 20,\\n\\t}\\n\\tctx = workflow.WithActivityOptions(ctx, ao)\\n\\n\\tlogger := workflow.GetLogger(ctx)\\n\\tlogger.Info(\\"helloworld workflow started\\")\\n\\tvar helloworldResult string\\n\\terr := workflow.ExecuteActivity(ctx, helloWorldActivity, name).Get(ctx, &helloworldResult)\\n\\tif err != nil {\\n\\t\\tlogger.Error(\\"Activity failed.\\", zap.Error(err))\\n\\t\\treturn err\\n\\t}\\n\\n\\tlogger.Info(\\"Workflow completed.\\", zap.String(\\"Result\\", helloworldResult))\\n\\n\\treturn nil\\n}\\n```\\n\\nDon\'t forget to register your workflow and activity to your worker in the `init` function.\\n```go\\nfunc init() {\\n workflow.Register(helloWorldWorkflow)\\n activity.Register(helloWorldActivity)\\n}\\n```\\n\\nNow restart your worker and you will only see logs like\\n```bash\\n2023-07-16T12:07:33.165-0700 INFO internal/internal_worker.go:834 Started Workflow Worker {\\"Domain\\": \\"test-domain\\", \\"TaskList\\": \\"test-worker\\", \\"WorkerID\\": \\"13585@uber-C02F18EQMD6R@test-worker@42f8a76f-cc42-4a0d-a001-7f7959d5d623\\"}\\n2023-07-16T12:07:33.175-0700 INFO internal/internal_worker.go:859 Started Activity Worker {\\"Domain\\": \\"test-domain\\", \\"TaskList\\": \\"test-worker\\", \\"WorkerID\\": \\"13585@uber-C02F18EQMD6R@test-worker@42f8a76f-cc42-4a0d-a001-7f7959d5d623\\"}\\n2023-07-16T12:07:33.175-0700 INFO cadence-worker/code.go:84 Started Worker. {\\"worker\\": \\"test-worker\\"}\\n```\\n\\nLet\'s try to run a Cadence workflow using Cadence CLI.\\n```bash\\ncadence --env development --domain test-domain workflow start --et 60 --tl test-worker --workflow_type main.helloWorldWorkflow --input \'\\"World\\"\'\\n```\\n\\nYou should see the Hello World log such like\\n```bash\\n2023-07-16T12:09:11.858-0700 INFO cadence-worker/code.go:104 Workflow completed. {\\"Domain\\": \\"test-domain\\", \\"TaskList\\": \\"test-worker\\", \\"WorkerID\\": \\"13585@uber-C02F18EQMD6R@test-worker@42f8a76f-cc42-4a0d-a001-7f7959d5d623\\", \\"WorkflowType\\": \\"main.helloWorldWorkflow\\", \\"WorkflowID\\": \\"8cb7fb2a-243b-43f8-82d9-48d758c9d62f\\", \\"RunID\\": \\"3c070007-89c3-4e00-a039-19a86b2f9224\\", \\"Result\\": \\"Hello World!\\"}\\n```\\n\\nCongratulations, you have successfully run your very first Cadence workflow.\\n\\nFor a bonus point, the Cadence team has also developed a demonstrative web dashboard to visualize the history of all workflows you have run when you start the Cadence server. Check http://localhost:8088 to see the dashboard like this.\\n\\n![cadencde-ui](./cadence_ui.png)\\n\\nThis web portal persists all historical workflow you have run recently. Search for the domain you used for this tutorial. In our case, type `test-domain` and hit enter. You may see a list of workflows with detailed information. Feel free to explore the web UI and raise your suggestions to our [Github repo](https://github.com/cadence-workflow/cadence-web).\\n\\n![cadence-ui-detailed](./cadence_ui_detailed.png)\\n\\nFor the incoming blogs, we will cover more advanced topics and use cases with Cadence."},{"id":"/2023/07/10/cadence-bad-practices-part-1","metadata":{"permalink":"/blog/2023/07/10/cadence-bad-practices-part-1","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2023-07-10-cadence-bad-practices-part-1.md","source":"@site/blog/2023-07-10-cadence-bad-practices-part-1.md","title":"Bad practices and Anti-patterns with Cadence (Part 1)","description":"In the upcoming blog series, we will delve into a discussion about common bad practices and anti-patterns related to Cadence. As diverse teams often encounter distinct business use cases, it becomes imperative to address the most frequently reported issues in Cadence workflows. To provide valuable insights and guidance, the Cadence team has meticulously compiled these common challenges based on customer feedback.","date":"2023-07-10T00:00:00.000Z","tags":[{"inline":false,"label":"Introduction to Cadence","permalink":"/blog/tags/introduction-to-cadence","description":"Introduction to Cadence tag description"},{"inline":false,"label":"Deep Dives","permalink":"/blog/tags/deep-dives","description":"Deep Dives tag description"}],"readingTime":2.065,"hasTruncateMarker":true,"authors":[{"name":"Chris Qin","title":"Applications Developer @ Uber","url":"https://www.linkedin.com/in/chrisqin0610/","page":{"permalink":"/blog/authors/chopincode"},"socials":{"linkedin":"https://www.linkedin.com/in/chrisqin0610/","github":"https://github.com/chopincode"},"imageURL":"https://github.com/chopincode.png","key":"chopincode"}],"frontMatter":{"title":"Bad practices and Anti-patterns with Cadence (Part 1)","date":"2023-07-10T00:00:00.000Z","authors":"chopincode","tags":["introduction-to-cadence","deep-dive"]},"unlisted":false,"prevItem":{"title":"Write your first workflow with Cadence","permalink":"/blog/2023/07/16/2023-07-16-write-your-first-workflow-with-cadence/write-your-first-workflow-with-cadence"},"nextItem":{"title":"Implement a Cadence worker service from scratch","permalink":"/blog/2023/07/05/implement-cadence-worker-from-scratch"}},"content":"In the upcoming blog series, we will delve into a discussion about common bad practices and anti-patterns related to Cadence. As diverse teams often encounter distinct business use cases, it becomes imperative to address the most frequently reported issues in Cadence workflows. To provide valuable insights and guidance, the Cadence team has meticulously compiled these common challenges based on customer feedback.\\n\\n* Reusing the same workflow ID for very active/continuous running workflows\\n\\nCadence organizes workflows based on their unique IDs, using a process called <b>partitioning</b>. If a workflow receives a large number of updates in a short period of time or frequently starts new runs using the `continueAsNew` function, all these updates will be directed to the same shard. Unfortunately, the Cadence backend is not equipped to handle this concentrated workload efficiently. As a result, a situation known as a \\"hot shard\\" arises, overloading the Cadence backend and worsening the problem.\\n\\nSolution:\\nWell, the best way to avoid this is simply just design your workflow in the way such that each workflow owns a uniformly distributed workflow ID across your Cadence domain. This will make sure that Cadence backend is able to evenly distribute the traffic with proper partition on your workflowIDs.\\n\\n\x3c!-- truncate --\x3e\\n\\n* Excessive batch jobs or an enormous number of timers triggered at the same time\\n\\nCadence has the capability to handle a large number of concurrent tasks initiated simultaneously, but tampering with this feature can lead to issues within the Cadence system. Consider a scenario where millions of jobs are scheduled to start at the same time and are expected to finish within a specific time interval. Cadence faces the challenge of understanding the desired behavior of customers in such cases. It is uncertain whether the intention is to complete all jobs simultaneously, provide progressive updates in parallel, or finish all jobs before a given deadline. This ambiguity arises due to the independent nature of each job and the difficulty in predicting their outcomes.\\n\\nMoreover, Cadence workers utilize a sticky cache by default to optimize the runtime of workflows. However, when an overwhelming number of parallel workflows cannot fit into the cache, it can result in <b>cache thrashing</b>. This, in turn, leads to a quadratic increase in runtime complexity, specifically O(n^2), exacerbating the overall performance of the system.\\n\\nSolution:\\nThere are multiple ways to address this issue. Customers can either run jobs in a smaller batch or use start workflow jitter to randomly distribute timers within certain timeframe."},{"id":"/2023/07/05/implement-cadence-worker-from-scratch","metadata":{"permalink":"/blog/2023/07/05/implement-cadence-worker-from-scratch","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2023-07-05-implement-cadence-worker-from-scratch.md","source":"@site/blog/2023-07-05-implement-cadence-worker-from-scratch.md","title":"Implement a Cadence worker service from scratch","description":"In the previous blog, we have introduced three critical components for a Cadence application: the Cadence backend, domain, and worker. Among these, the worker service is the most crucial focus for developers as it hosts the activities and workflows of a Cadence application. In this blog, I will provide a short tutorial on how to implement a simple worker service from scratch in Go.","date":"2023-07-05T00:00:00.000Z","tags":[{"inline":false,"label":"Deep Dives","permalink":"/blog/tags/deep-dives","description":"Deep Dives tag description"},{"inline":false,"label":"Introduction to Cadence","permalink":"/blog/tags/introduction-to-cadence","description":"Introduction to Cadence tag description"}],"readingTime":3.69,"hasTruncateMarker":true,"authors":[{"name":"Chris Qin","title":"Applications Developer @ Uber","url":"https://www.linkedin.com/in/chrisqin0610/","page":{"permalink":"/blog/authors/chopincode"},"socials":{"linkedin":"https://www.linkedin.com/in/chrisqin0610/","github":"https://github.com/chopincode"},"imageURL":"https://github.com/chopincode.png","key":"chopincode"}],"frontMatter":{"title":"Implement a Cadence worker service from scratch","date":"2023-07-05T00:00:00.000Z","authors":"chopincode","tags":["deep-dive","introduction-to-cadence"]},"unlisted":false,"prevItem":{"title":"Bad practices and Anti-patterns with Cadence (Part 1)","permalink":"/blog/2023/07/10/cadence-bad-practices-part-1"},"nextItem":{"title":"Understanding components of Cadence application","permalink":"/blog/2023/06/28/components-of-cadence-application-setup"}},"content":"In the previous [blog](/blog/2023-06-28-components-of-cadence-application-setup.md), we have introduced three critical components for a Cadence application: the Cadence backend, domain, and worker. Among these, the worker service is the most crucial focus for developers as it hosts the activities and workflows of a Cadence application. In this blog, I will provide a short tutorial on how to implement a simple worker service from scratch in Go.\\n\\nTo finish this tutorial, there are two prerequisites you need to finish first\\n1. Register a Cadence domain for your worker. For this tutorial, I\'ve already registered a domain named `test-domain`\\n2. Start the Cadence backend server in background.\\n\\nTo get started, let\'s simply use the native HTTP package built in Go to start a process listening to port 3000. You may customize the port for your worker, but the port you choose should not conflict with existing port for your Cadence backend.\\n\\n```go\\npackage main\\n\\nimport (\\n\\t\\"fmt\\"\\n\\t\\"net/http\\"\\n)\\n\\nfunc main(){\\n\\tfmt.Println(\\"Cadence worker started at port 3000\\")\\n\\thttp.ListenAndServe(\\":3000\\", nil)\\n}\\n```\\n\x3c!-- truncate --\x3e\\n\\nNext, let\'s define some basic configurations for the worker. In real production environment, you may need to implement them in configurational languages, but in this tutorial, let\'s just hard code them for now.\\n\\n```go\\nvar HostPort = \\"127.0.0.1:7933\\"\\nvar Domain = \\"test-domain\\"\\nvar TaskListName = \\"test-worker\\"\\nvar ClientName = \\"test-worker\\"\\nvar CadenceService = \\"cadence-frontend\\"\\n```\\n\\nNote that the domain is what we\'ve already registered in advance. We will need to use this domain to interact with Cadence CLI tool.\\n\\nThen let\'s write a simple function to build a Cadence client on gRPC in your worker, which will communicate with the Cadence backend continuously.\\n\\n```go\\nfunc buildCadenceClient() workflowserviceclient.Interface {\\n dispatcher := yarpc.NewDispatcher(yarpc.Config{\\n\\t\\tName: ClientName,\\n\\t\\tOutbounds: yarpc.Outbounds{\\n\\t\\t CadenceService: {Unary: grpc.NewTransport().NewSingleOutbound(HostPort)},\\n\\t\\t},\\n\\t })\\n\\t if err := dispatcher.Start(); err != nil {\\n\\t\\tpanic(\\"Failed to start dispatcher\\")\\n\\t }\\n\\n\\t clientConfig := dispatcher.ClientConfig(CadenceService)\\n\\n\\t return compatibility.NewThrift2ProtoAdapter(\\n\\t\\tapiv1.NewDomainAPIYARPCClient(clientConfig),\\n\\t\\tapiv1.NewWorkflowAPIYARPCClient(clientConfig),\\n\\t\\tapiv1.NewWorkerAPIYARPCClient(clientConfig),\\n\\t\\tapiv1.NewVisibilityAPIYARPCClient(clientConfig),\\n\\t )\\n}\\n```\\n\\nLet\'s also build a logger to help us debug our application\\n\\n```go\\nfunc buildLogger() *zap.Logger {\\n config := zap.NewDevelopmentConfig()\\n config.Level.SetLevel(zapcore.InfoLevel)\\n\\n var err error\\n logger, err := config.Build()\\n if err != nil {\\n panic(\\"Failed to setup logger\\")\\n }\\n\\n return logger\\n}\\n```\\n\\nWith both client and logger helper function ready, let\'s write the function that starts our worker.\\n\\n```go\\nfunc startWorker(logger *zap.Logger, service workflowserviceclient.Interface) {\\n // TaskListName identifies set of client workflows, activities, and workers.\\n // It could be your group or client or application name.\\n workerOptions := worker.Options{\\n Logger: logger,\\n MetricsScope: tally.NewTestScope(TaskListName, map[string]string{}),\\n }\\n\\n worker := worker.New(\\n service,\\n Domain,\\n TaskListName,\\n workerOptions)\\n err := worker.Start()\\n if err != nil {\\n panic(\\"Failed to start worker\\")\\n }\\n\\n logger.Info(\\"Started Worker.\\", zap.String(\\"worker\\", TaskListName))\\n}\\n```\\n\\nNow we have all components ready for the worker, let\'s put them together.\\n\\n```Go\\nimport (\\n \\"net/http\\"\\n \\"go.uber.org/cadence/.gen/go/cadence/workflowserviceclient\\"\\n \\"go.uber.org/cadence/compatibility\\"\\n \\"go.uber.org/cadence/worker\\"\\n\\n apiv1 \\"github.com/cadence-workflow/cadence-idl/go/proto/api/v1\\"\\n \\"github.com/uber-go/tally\\"\\n \\"go.uber.org/zap\\"\\n \\"go.uber.org/zap/zapcore\\"\\n \\"go.uber.org/yarpc\\"\\n \\"go.uber.org/yarpc/transport/grpc\\"\\n)\\n\\nvar HostPort = \\"127.0.0.1:7933\\"\\nvar Domain = \\"test-domain\\"\\nvar TaskListName = \\"test-worker\\"\\nvar ClientName = \\"test-worker\\"\\nvar CadenceService = \\"cadence-frontend\\"\\n\\nfunc main() {\\n startWorker(buildLogger(), buildCadenceClient())\\n http.ListenAndServe(\\":3000\\", nil)\\n}\\n\\nfunc buildLogger() *zap.Logger {\\n config := zap.NewDevelopmentConfig()\\n config.Level.SetLevel(zapcore.InfoLevel)\\n\\n var err error\\n logger, err := config.Build()\\n if err != nil {\\n panic(\\"Failed to setup logger\\")\\n }\\n\\n return logger\\n}\\n\\nfunc buildCadenceClient() workflowserviceclient.Interface {\\n dispatcher := yarpc.NewDispatcher(yarpc.Config{\\n\\t\\tName: ClientName,\\n\\t\\tOutbounds: yarpc.Outbounds{\\n\\t\\t CadenceService: {Unary: grpc.NewTransport().NewSingleOutbound(HostPort)},\\n\\t\\t},\\n\\t })\\n\\t if err := dispatcher.Start(); err != nil {\\n\\t\\tpanic(\\"Failed to start dispatcher\\")\\n\\t }\\n\\n\\t clientConfig := dispatcher.ClientConfig(CadenceService)\\n\\n\\t return compatibility.NewThrift2ProtoAdapter(\\n\\t\\tapiv1.NewDomainAPIYARPCClient(clientConfig),\\n\\t\\tapiv1.NewWorkflowAPIYARPCClient(clientConfig),\\n\\t\\tapiv1.NewWorkerAPIYARPCClient(clientConfig),\\n\\t\\tapiv1.NewVisibilityAPIYARPCClient(clientConfig),\\n\\t )\\n}\\n\\nfunc startWorker(logger *zap.Logger, service workflowserviceclient.Interface) {\\n // TaskListName identifies set of client workflows, activities, and workers.\\n // It could be your group or client or application name.\\n workerOptions := worker.Options{\\n Logger: logger,\\n MetricsScope: tally.NewTestScope(TaskListName, map[string]string{}),\\n }\\n\\n worker := worker.New(\\n service,\\n Domain,\\n TaskListName,\\n workerOptions)\\n err := worker.Start()\\n if err != nil {\\n panic(\\"Failed to start worker\\")\\n }\\n\\n logger.Info(\\"Started Worker.\\", zap.String(\\"worker\\", TaskListName))\\n}\\n```\\n\\nOpen a new terminal and start this server, you should see logs like\\n```shell\\n2023-07-03T11:46:46.266-0700 INFO internal/internal_worker.go:826 Worker has no workflows registered, so workflow worker will not be started. {\\"Domain\\": \\"test-domain\\", \\"TaskList\\": \\"test-worker\\", \\"WorkerID\\": \\"35987@uber-C02F18EQMD6R@test-worker@90c0260e-ba5c-4652-9f10-c6d1f9e29c1d\\"}\\n2023-07-03T11:46:46.267-0700 INFO internal/internal_worker.go:834 Started Workflow Worker {\\"Domain\\": \\"test-domain\\", \\"TaskList\\": \\"test-worker\\", \\"WorkerID\\": \\"35987@uber-C02F18EQMD6R@test-worker@90c0260e-ba5c-4652-9f10-c6d1f9e29c1d\\"}\\n2023-07-03T11:46:46.267-0700 INFO internal/internal_worker.go:838 Worker has no activities registered, so activity worker will not be started. {\\"Domain\\": \\"test-domain\\", \\"TaskList\\": \\"test-worker\\", \\"WorkerID\\": \\"35987@uber-C02F18EQMD6R@test-worker@90c0260e-ba5c-4652-9f10-c6d1f9e29c1d\\"}\\n2023-07-03T11:46:46.267-0700 INFO cadence-worker/main.go:75 Started Worker. {\\"worker\\": \\"test-worker\\"}\\n```\\n\\nYou may see these logs because your worker is successfully running but we haven\'t registered any workflows or activities to the worker. In the next tutorial, we will learn how to write a simple hello world workflow for your Cadence application."},{"id":"/2023/06/28/components-of-cadence-application-setup","metadata":{"permalink":"/blog/2023/06/28/components-of-cadence-application-setup","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2023-06-28-components-of-cadence-application-setup.md","source":"@site/blog/2023-06-28-components-of-cadence-application-setup.md","title":"Understanding components of Cadence application","description":"Cadence is a powerful, scalable, and fault-tolerant workflow orchestration framework that helps developers implement and manage complex workflow tasks. In most cases, developers contribute activities and workflows directly to their codebases, and they may not have a full understanding of the components behind a running Cadence application. We receive numerous inquiries about setting up Cadence in a local environment from scratch for testing. Therefore, in this article, we will explore the components that power a Cadence cluster.","date":"2023-07-01T00:00:00.000Z","tags":[{"inline":false,"label":"Deep Dives","permalink":"/blog/tags/deep-dives","description":"Deep Dives tag description"},{"inline":false,"label":"Introduction to Cadence","permalink":"/blog/tags/introduction-to-cadence","description":"Introduction to Cadence tag description"}],"readingTime":1.615,"hasTruncateMarker":true,"authors":[{"name":"Chris Qin","title":"Applications Developer @ Uber","url":"https://www.linkedin.com/in/chrisqin0610/","page":{"permalink":"/blog/authors/chopincode"},"socials":{"linkedin":"https://www.linkedin.com/in/chrisqin0610/","github":"https://github.com/chopincode"},"imageURL":"https://github.com/chopincode.png","key":"chopincode"}],"frontMatter":{"title":"Understanding components of Cadence application","date":"2023-07-01T00:00:00.000Z","authors":"chopincode","tags":["deep-dive","introduction-to-cadence"]},"unlisted":false,"prevItem":{"title":"Implement a Cadence worker service from scratch","permalink":"/blog/2023/07/05/implement-cadence-worker-from-scratch"},"nextItem":{"title":"Cadence Community Spotlight Update - June 2023","permalink":"/blog/2023/06/30/community-spotlight-june-2023"}},"content":"Cadence is a powerful, scalable, and fault-tolerant workflow orchestration framework that helps developers implement and manage complex workflow tasks. In most cases, developers contribute activities and workflows directly to their codebases, and they may not have a full understanding of the components behind a running Cadence application. We receive numerous inquiries about setting up Cadence in a local environment from scratch for testing. Therefore, in this article, we will explore the components that power a Cadence cluster.\\n\\nThere are three critical components that are essential for any Cadence application:\\n1. A running Cadence backend server.\\n2. A registered Cadence domain.\\n3. A running Cadence worker that registers all workflows and activities.\\n\\nLet\'s go over these components in more details.\\n\\n\x3c!-- truncate --\x3e\\n\\nThe Cadence backend serves as the heart of your Cadence application. It is responsible for processing and scheduling your workflows and activities. While the backend relies on various dependencies, our team has conveniently packaged them into a single Docker image. You can follow the instructions provided [here](/docs/get-started/server-installation).\\n\\nThe Cadence domain functions as the namespace for your Cadence workflows. It helps segregate your workflows into manageable groups. When running workflows, you must specify the domain on which you want to execute them.\\n\\nThe Cadence worker, also known as the worker service, is a separate binary process that you need to implement in order to host your workflows and activities. When developing a worker, ensure that all your workflows and activities are properly registered with it. The worker is an actively running application, and you have the freedom to choose the hosting technologies that best suit your needs, such as a simple HTTP or gRPC application.\\n\\nUltimately, you will need to set up two running processes on your local machine: the Cadence server and the worker. Additionally, you must register the Cadence domain as a resource. Our team has packaged all these components into user-friendly tools, which you can find on our website."},{"id":"/2023/06/30/community-spotlight-june-2023","metadata":{"permalink":"/blog/2023/06/30/community-spotlight-june-2023","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2023-06-30-community-spotlight-june-2023.md","source":"@site/blog/2023-06-30-community-spotlight-june-2023.md","title":"Cadence Community Spotlight Update - June 2023","description":"We\'ve had a short break but now we are back. Welcome to the latest of our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!","date":"2023-06-30T00:00:00.000Z","tags":[{"inline":false,"label":"Community Spotlight","permalink":"/blog/tags/community-spotlights","description":"Community Spotlight tag description"},{"inline":false,"label":"Releases","permalink":"/blog/tags/releases","description":"Releases tag description"}],"readingTime":2.725,"hasTruncateMarker":true,"authors":[{"name":"Sharan Foga","title":"Director of Operations & Customer Success @ Encube Technologies","url":"https://www.linkedin.com/in/sfoga/","page":{"permalink":"/blog/authors/sharanf"},"socials":{"linkedin":"https://www.linkedin.com/in/sfoga/","github":"https://github.com/sharanf"},"imageURL":"https://github.com/sharanf.png","key":"sharanf"}],"frontMatter":{"title":"Cadence Community Spotlight Update - June 2023","date":"2023-06-30T00:00:00.000Z","authors":"sharanf","tags":["community-spotlight","release"]},"unlisted":false,"prevItem":{"title":"Understanding components of Cadence application","permalink":"/blog/2023/06/28/components-of-cadence-application-setup"},"nextItem":{"title":"2023 Cadence Community Survey Results","permalink":"/blog/2023/06/08/2023-06-08-survey-results/survey-results"}},"content":"We\'ve had a short break but now we are back. Welcome to the latest of our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!\\n\\nPlease see below for a roundup of the highlights:\\n\\n## Cadence Release 1.0 ##\\n\\nJust in case you missed it - at the end of April [Cadence v1.0](https://github.com/cadence-workflow/cadence/releases/tag/v1.0.0) was officially released. This release is a significant milestone for the project and the community. It indicates that we are confident in the stability of the code that we can recommend it and promote it widely to more users. Kudos to everyone that worked together to make this release happen.\\n\\nAnd the Uber team also gave Cadence a writeup on the [Uber Engineering Blog](https://www.uber.com/en-SE/blog/announcing-cadence/) so please take a look.\\n\\n\x3c!-- truncate --\x3e\\n\\n## Community Survey Results ##\\n\\nThe results of our Community Survey have been published and you can find [the details right here on our blog](https://cadenceworkflow.io/blog/2023/06/08/survey-results/). From the results we can see that:\\n\\n- our community is a good mix of people using, evaluating, testing or thinking about migrating to Cadence\\n- Software Engineers featured highly as a community user profile\\n- Europe seems to be the most common community timezone\\n- People prefer using our Slack channel for questions\\n- Debugging is what most people need help with\\n\\nThank you to Ender for compiling the data and to everyone who participated.\\n\\n## Cadence Video Open Source Summit, North America ##\\nIn May [Ender Demirkaya](https://www.linkedin.com/in/enderdemirkaya/) gave a talk called on Cadence at the Linux Foundation\'s [Open Source Summit, North America](https://events.linuxfoundation.org/open-source-summit-north-america/) in Vancouver. The presentation attracted a sizeable audience and was very well received. There was also a lot of questions from the audience which is a sign that Cadence sounded potentially useful to them.\\n\\nA recording of the talk [Cadence: The New Open Source Project for Building Complex Distributed Applications](https://www.youtube.com/watch?v=vFPJlE6d4xs) is now available.\\n\\n## Overcoming Potential Workflow Versioning Maintenance Challenges ##\\n\\nCommunity member [Quanzheng Long](https://www.linkedin.com/in/prclqz/) has written a [detailed article on Medium](https://medium.com/@qlong/how-to-overcome-some-maintenance-challenges-of-temporal-cadence-workflow-versioning-f893815dd18d) about some of the potential maintenance challenges of workflow versioning. It\'s a short read and has some good examples that explains the potential problems and identifies some approaches for dealing with them.\\n\\nThanks Long for sharing this knowledge with the community!\\n\\n## Cadence in the News!\\n\\nBelow are a selection of Cadence related articles, blogs and whitepapers. Please take a look and feel free to share via your own social media channels.\\n\\n- [Announcing Cadence 1.0: The Powerful Workflow Platform Built for Scale and Reliability](https://www.uber.com/en-SE/blog/announcing-cadence/)\\n\\n- [Cadence 1.0 Released on the Instaclustr Managed Platform](https://www.instaclustr.com/blog/cadence-1-0-released-on-the-instaclustr-managed-platform/)\\n\\n- [How to Overcome Some Maintenance Challenges of Temporal/Cadence Workflow Versioning](https://medium.com/@qlong/how-to-overcome-some-maintenance-challenges-of-temporal-cadence-workflow-versioning-f893815dd18d)\\n\\n- [Video: Cadence - The New Open Source Project for Building Complex Distributed Applications](https://www.youtube.com/watch?v=vFPJlE6d4xs)\\n\\n- [Instaclustr Releases Multi-Region Cadence Workflow](https://www.instaclustr.com/blog/instaclustr-releases-multi-region-cadence-workflow-2/)\\n\\n- [Understanding Components of Cadence Application](https://cadenceworkflow.io/blog/2023/07/01/components-of-cadence-application-setup/)\\n\\n- [Improving the Reliability of Cadence Search Queries That Use OpenSearch/Elasticsearch](https://www.instaclustr.com/blog/improving-the-reliability-of-cadence-search-queries/)\\n\\n- [Instaclustr Cadence Workflow Developer Offering Hits General Availability](https://www.instaclustr.com/blog/instaclustr-cadence-workflow-developer/)\\n\\n## Upcoming Events\\n\\n- None\\n\\nIf you have any news or topics you\'d like us to include in our next update then please join our [Slack](http://t.uber.com/cadence-slack)#community channel.\\n\\nPlease remember that this update is for you - so if you have any comments or feedback that could help us improve it then please share it with us in the #community [Slack](http://t.uber.com/cadence-slack) channel."},{"id":"/2023/06/08/2023-06-08-survey-results/survey-results","metadata":{"permalink":"/blog/2023/06/08/2023-06-08-survey-results/survey-results","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2023-06-08-survey-results/2023-06-08-survey-results.md","source":"@site/blog/2023-06-08-survey-results/2023-06-08-survey-results.md","title":"2023 Cadence Community Survey Results","description":"We released a user survey earlier this year to learn about who our users are, how they use Cadence, and how we can help them. It was shared from our Slack workspace, cadenceworkflow.io Blog and LinkedIn. After collecting the feedback, we wanted to share the results with our community. Thank you everyone for filling it out! Your feedback is invaluable and it helps us shape our roadmap for the future.","date":"2023-06-08T00:00:00.000Z","tags":[{"inline":false,"label":"Announcement","permalink":"/blog/tags/announcements","description":"Announcement tag description"}],"readingTime":3.255,"hasTruncateMarker":true,"authors":[{"name":"Ender Demirkaya","title":"Senior Manager at Uber, Cadence. Author of the Software Engineering Handbook","url":"https://www.linkedin.com/in/enderdemirkaya/","page":{"permalink":"/blog/authors/enderdemirkaya"},"socials":{"linkedin":"https://www.linkedin.com/in/enderdemirkaya/","github":"https://github.com/demirkayaender"},"imageURL":"https://github.com/demirkayaender.png","key":"enderdemirkaya"}],"frontMatter":{"title":"2023 Cadence Community Survey Results","date":"2023-06-08T00:00:00.000Z","authors":"enderdemirkaya","tags":["announcement"]},"unlisted":false,"prevItem":{"title":"Cadence Community Spotlight Update - June 2023","permalink":"/blog/2023/06/30/community-spotlight-june-2023"},"nextItem":{"title":"Cadence Community Spotlight Update - March 2023","permalink":"/blog/2023/03/31/community-spotlight-march-2023"}},"content":"We released a user survey earlier this year to learn about who our users are, how they use Cadence, and how we can help them. It was shared from our [Slack workspace](https://uber-cadence.slack.com/), [cadenceworkflow.io](https://cadenceworkflow.io) Blog and [LinkedIn](https://www.linkedin.com/company/cadenceworkflow/). After collecting the feedback, we wanted to share the results with our community. Thank you everyone for filling it out! Your feedback is invaluable and it helps us shape our roadmap for the future.\\n\\n\\nHere are some highlights in text and you can check out the visuals to get more details:\\n\\n![using.png](./2023-survey-results/using.png)\\n\\n![job_role.png](./2023-survey-results/job_role.png)\\n\\nMost of the people who replied to our survey were engineers who were already using Cadence, actively evaluating, or migrating from a similar technology. This was exciting to hear! Some of you have contacted us to learn more about benchmarks, scale, and ideal use cases. We will share more guidelines about this but until then, feel free to contact us over our Slack workspace for guidance.\\n\\n\x3c!-- truncate --\x3e\\n\\n![scale.png](./2023-survey-results/scale.png)\\n\\nThe scale our users operating Cadence varies from thousands to billions of workflows per month. It was exciting to see it being used in both small and large scale companies.\\n\\n![time_zone.png](./2023-survey-results/time_zone.png)\\n\\nMost survey responders were from Europe compared to any other place. This is in-line with the Cadence team growing its presence in Europe. Users from different places also contacted us to contribute to Cadence as a follow up to the survey. We will start putting up-for-grabs and new-starter tasks on Github. Several of them wanted to meet with a Zoom call and to discuss their use cases and best practices. As the Cadence team has presence in both the EU and the US, we welcome all our users to contact us anytime. Slack is the fastest way to reach us.\\n\\n![following.png](./2023-survey-results/following.png)\\n\\n![channels.png](./2023-survey-results/channels.png)\\n\\nCadence is followed in [Slack](https://uber-cadence.slack.com/) the most, then [Github](https://github.com/cadence-workflow/cadence) and [LinkedIn](https://www.linkedin.com/company/cadenceworkflow/). We are the most active in Slack and we plan to be more active in other mediums as well.\\n\\n![scenarios.png](./2023-survey-results/scenarios.png)\\nAll of our main use cases were used across the board. While we mentioned the most common cases, several others were mentioned as a comment: enhanced timers, leader election etc.\\n\\nWe found out that Cadence has been used in several science communities. Some of them were using community built clients and were asking if we are going to support more languages. We are planning to take ownership of the Python and Javascript/Typescript clients and support them officially.\\n\\n![improvement.png](./2023-survey-results/improvement.png)\\n\\nDocumentation is by far what our users wanted improvements on. We are revamping our documentation soon and there will be major changes on our website soon.\\n\\n![help_stage.png](./2023-survey-results/help_stage.png)\\n\\nOther requests were about observability, debuggability, operability, and usability. These areas have been our main focus this year and we are planning to release updates and blogs about them.\\n\\n![support.png](./2023-survey-results/support.png)\\n\\nWe noticed most of our users need help once a month or more. While we welcome questions and discussions over the mediums mentioned above, we plan to make more public posts about the common issues using our blog, StackOverflow, LinkedIn, or Twitter.\\n\\nMany users wanted to hear more from Cadence about the roadmap and its growth. Our posts about these will be released soon. Expect more posts about upcoming features, investments, scale, and community updates. Follow us at [LinkedIn](https://www.linkedin.com/company/cadenceworkflow/) for such updates.\\n\\nOur users are interested in learning more about guidelines, capacity expectations in on-prem and in managed solutions. While we have been providing feedback per user basis before, we plan to release more generic guidelines with our observability updates mentioned above.\\n\\nWe also would like to thank our community for the increased interest and engagement with us! Cadence has been more active in different mediums (LinkedIn, Slack, blog, etc.) this year. In the first quarter, we observed that our user base and activities has almost doubled (+96% and +90% respectively) through both new and returning users. Based on such immediate positive reactions, we will keep increasing our community investments in different channels."},{"id":"/2023/03/31/community-spotlight-march-2023","metadata":{"permalink":"/blog/2023/03/31/community-spotlight-march-2023","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2023-03-31-community-spotlight-march-2023.md","source":"@site/blog/2023-03-31-community-spotlight-march-2023.md","title":"Cadence Community Spotlight Update - March 2023","description":"Welcome to the latest of our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!","date":"2023-03-31T00:00:00.000Z","tags":[{"inline":false,"label":"Community Spotlight","permalink":"/blog/tags/community-spotlights","description":"Community Spotlight tag description"}],"readingTime":1.885,"hasTruncateMarker":true,"authors":[{"name":"Sharan Foga","title":"Director of Operations & Customer Success @ Encube Technologies","url":"https://www.linkedin.com/in/sfoga/","page":{"permalink":"/blog/authors/sharanf"},"socials":{"linkedin":"https://www.linkedin.com/in/sfoga/","github":"https://github.com/sharanf"},"imageURL":"https://github.com/sharanf.png","key":"sharanf"}],"frontMatter":{"title":"Cadence Community Spotlight Update - March 2023","date":"2023-03-31T00:00:00.000Z","authors":"sharanf","tags":["community-spotlight"]},"unlisted":false,"prevItem":{"title":"2023 Cadence Community Survey Results","permalink":"/blog/2023/06/08/2023-06-08-survey-results/survey-results"},"nextItem":{"title":"Cadence Community Spotlight Update - March 2024","permalink":"/blog/2024/3/11/community-spotlight-update-march-2024"}},"content":"Welcome to the latest of our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!\\n\\nPlease see below for a roundup of the highlights:\\n\\n## Cadence at Open Source Summit, North America ##\\nWe are very pleased to let you know that a talk on Cadence has been accepted for the Linux Foundation\'s [Open Source Summit, North America](https://events.linuxfoundation.org/open-source-summit-north-america/) in Vancouver on 10th - 12th May 2023.\\n\\nThe talk called [Cadence: The New Open Source Project for Building Complex Distributed Applications](https://ossna2023.sched.com/event/1K5B1) will be given by [Ender Demirkaya](https://www.linkedin.com/in/enderdemirkaya/) and [Emrah Seker](https://www.linkedin.com/in/emrahseker/) If you are planning to attend the Open Source Summit then please don\'t forget to attend the talk and take time catch up with Ender and Emrah!\\n\\n## Community Activity ##\\nOur Slack #support channel has been very active over the last few months as we continue to get an continual stream of questions. Here are the stats:\\n\\n- February 2023 : 16 questions asked\\n- March 2023 : 12 questions asked\\n\\nAll of these questions are being answered collaboratively by the community. Thanks everyone for sharing your knowledge and we are looking forward to receiving more of your questions!\\n\\n\x3c!-- truncate --\x3e\\n\\n## Cadence Developer Advocate ##\\nPlease welcome Yizhe Qin - the new Cadence Developer Advocate from Uber team that will be working to help support the community.\\n\\nYizhe\'s role will involve responding to support questions, organising documentation and anything else that will help keep the community running smoothly.\\n\\nPlease feel free to say Hi to Yizhe on the Slack channel!\\n\\n## Cadence in the News!\\n\\nBelow are a selection of Cadence related articles, blogs and whitepapers. Please take a look and feel free to share via your own social media channels.\\n\\n- [Instaclustr Cadence Developer Offering - General Availability](https://www.instaclustr.com/blog/instaclustr-cadence-workflow-developer/)\\n\\n- [Improving Reliability of Cadence Search Queries That Use OpenSearch/Elasticsearch](https://www.instaclustr.com/blog/improving-the-reliability-of-cadence-search-queries/)\\n\\n## Upcoming Events\\n\\n- [Webinar: Microservices - A Modern Orchestration Approach with Cadence](https://netapp.zoom.us/webinar/register/WN__5fuwxmNQuWeZ6DiI5wUqg)\\n\\nIf you have any news or topics you\'d like us to include in our next update then please join our [Slack](http://t.uber.com/cadence-slack)#community channel.\\n\\nPlease remember that this update is for you - so if you have any comments or feedback that could help us improve it then please share it with us in the #community [Slack](http://t.uber.com/cadence-slack) channel."},{"id":"/2024/3/11/community-spotlight-update-march-2024","metadata":{"permalink":"/blog/2024/3/11/community-spotlight-update-march-2024","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2024-3-11-community-spotlight-update-march-2024.md","source":"@site/blog/2024-3-11-community-spotlight-update-march-2024.md","title":"Cadence Community Spotlight Update - March 2024","description":"Welcome back to the latest in our regular Cadence community spotlight updates where we aim to deliver you news from in and around the Cadence community!","date":"2023-03-11T00:00:00.000Z","tags":[{"inline":false,"label":"Community Spotlight","permalink":"/blog/tags/community-spotlights","description":"Community Spotlight tag description"}],"readingTime":2.91,"hasTruncateMarker":true,"authors":[{"name":"Kevin Corbett","title":"Open Source Community Manager | @instaclustr @NetApp","url":"https://github.com/kcorbett-netapp","page":{"permalink":"/blog/authors/kcorbett-netapp"},"socials":{"linkedin":"https://www.linkedin.com/in/kcorb95/","github":"https://github.com/kcorbett-netapp"},"imageURL":"https://github.com/kcorbett-netapp.png","key":"kcorbett-netapp"}],"frontMatter":{"title":"Cadence Community Spotlight Update - March 2024","date":"2023-03-11T00:00:00.000Z","authors":"kcorbett-netapp","tags":["community-spotlight"]},"unlisted":false,"prevItem":{"title":"Cadence Community Spotlight Update - March 2023","permalink":"/blog/2023/03/31/community-spotlight-march-2023"},"nextItem":{"title":"Cadence Community Spotlight Update - February 2023","permalink":"/blog/2023/02/28/community-spotlight-february"}},"content":"Welcome back to the latest in our regular Cadence community spotlight updates where we aim to deliver you news from in and around the Cadence community!\\nIt\u2019s been a few months since our [last update](https://cadenceworkflow.io/blog/2023/11/30/community-spotlight-update-november-2023/), so I have a bunch of exciting updates to share.\\n\\nLet\u2019s get started!\\n\\n## Proposal for Cadence Plugin System ##\\nCommunity member [Mantas Sidlauskas](https://lt.linkedin.com/in/mantassidlauskas) drafted a thorough proposal around putting together a plugin system in Cadence. Aimed at enhancing the flexibility of integrating various components like storage, document search, and archival, this system encourages the use of external plugins, promoting innovation and reducing dependency complications. Your insights and feedback are crucial; learn more and contribute your thoughts at the link below:\\n\\n- [Cadence Plugin System Proposal](https://github.com/cadence-workflow/cadence/issues/5593)\\n\\nA huge thank you to Mantas for initiating this work. This is an excellent example of how we can collaborate together to bring about new features that benefit us all.\\n\\n\x3c!-- truncate --\x3e\\n\\n## Admin API Permissions Rethinking ##\\nThe community is deliberating on the permission requirements for the Admin API DescribeCluster endpoint. This vital discussion aims to ensure Cadence web\'s accessibility across different user levels. We\'re exploring various solutions and your participation would greatly influence the decision-making process. Feel free to chime in [here](https://github.com/cadence-workflow/cadence/issues/5683)!\\n\\n## New Java Samples for Cadence: Signal Workflow Interactions ##\\nIn some exciting news for Java enthusiasts, a new sample has been added to the Cadence Java Samples repository, demonstrating how to initiate and interact with a signal workflow using the Cadence client. This practical example is a huge win for developers looking to deepen their understanding of workflow signaling in Java. Explore the new sample and expand your Cadence toolkit [here](https://github.com/cadence-workflow/cadence-java-samples/pull/78).\\n\\n## New GoLang client & Cadence Web Enhancements ##\\nUpdates to the Cadence GoLang Client and Cadence Web have been rolled out, bringing new features and improvements that streamline user experiences. Highlights include upgraded Cassandra images, refined workflow interceptors, and more intuitive Cadence Web interfaces. Discover the full scope of updates on our GitHub repositories.\\n\\n- [GoLang Client Releases](https://github.com/cadence-workflow/cadence-go-client/releases)\\n- [Cadence Web Releases](https://github.com/cadence-workflow/cadence-web/releases)\\n\\n## Release Updates: v1.2.6 & v1.2.7 ##\\nCadence recently saw the release of versions v1.2.6 and v1.2.7, featuring significant improvements and fixes that enhance the overall Cadence experience. These updates reflect a commitment to respond to the community\'s valuable feedback. Check out the detailed release notes on the [GitHub releases page](https://github.com/cadence-workflow/cadence/releases)!\\n\\n## Cadence in the News! ##\\nBelow is a selection of Cadence related articles and blogs. Take a look and feel free to share your own with us via your own social media channels!\\n\\n- [How to Avoid \u201cDomain update too frequent\u201d Error in Multi-Region Cadence](https://www.instaclustr.com/blog/how-to-avoid-domain-update-too-frequent-error-in-multi-region-cadence/)\\n- [Build a Digital Collectibles Portal Using Flow and Cadence (Part 1)](https://levelup.gitconnected.com/build-a-digital-collectibles-portal-using-flow-and-cadence-part-1-2783f2902ef6)\\n\\n## Recent Events ##\\nCheck out this recent webinar, \\"Building with Cadence: Quantifiable Efficiency,\\" available on-demand now. Discover the robust features of Cadence and how it can streamline the development of distributed applications through an engaging demonstration by [John Del Castillo](https://au.linkedin.com/in/john-del-castillo-28b87b90?trk=people-guest_people_search-card).\\n\\n- [On Demand: Building with Cadence: Quantifiable Efficiency](https://netapp.zoom.us/webinar/register/WN_jT5fxSldRhuzV0NSllBd7g#/registration)\\n\\n\\n\\\\\\n\\\\\\n\\\\\\nThat\u2019s all for this month!\\n\\nYour engagement and contributions are what make the Cadence community thrive. Whether you have innovative ideas, insightful feedback, or just want to chat about Cadence, we encourage you to join our [Slack #community channel](http://t.uber.com/cadence-slack).\\n\\nWe\'re committed to making this update as useful and informative as possible, so please share any feedback or suggestions you might have. Let\u2019s keep building a vibrant and collaborative Cadence community together!\\n\\nLooking forward to sharing more exciting updates next month!"},{"id":"/2023/02/28/community-spotlight-february","metadata":{"permalink":"/blog/2023/02/28/community-spotlight-february","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2023-02-28-community-spotlight-february.md","source":"@site/blog/2023-02-28-community-spotlight-february.md","title":"Cadence Community Spotlight Update - February 2023","description":"Here\u2019s the latest in our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!","date":"2023-02-28T00:00:00.000Z","tags":[{"inline":false,"label":"Community Spotlight","permalink":"/blog/tags/community-spotlights","description":"Community Spotlight tag description"}],"readingTime":1.875,"hasTruncateMarker":true,"authors":[{"name":"Sharan Foga","title":"Director of Operations & Customer Success @ Encube Technologies","url":"https://www.linkedin.com/in/sfoga/","page":{"permalink":"/blog/authors/sharanf"},"socials":{"linkedin":"https://www.linkedin.com/in/sfoga/","github":"https://github.com/sharanf"},"imageURL":"https://github.com/sharanf.png","key":"sharanf"}],"frontMatter":{"title":"Cadence Community Spotlight Update - February 2023","date":"2023-02-28T00:00:00.000Z","authors":"sharanf","tags":["community-spotlight"]},"unlisted":false,"prevItem":{"title":"Cadence Community Spotlight Update - March 2024","permalink":"/blog/2024/3/11/community-spotlight-update-march-2024"},"nextItem":{"title":"Cadence Community Spotlight Update - January 2023","permalink":"/blog/2023/01/31/community-spotlight-january-2023"}},"content":"Here\u2019s the latest in our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!\\n\\nPlease see below for a roundup of the highlights:\\n\\n## Community Survey ##\\nWe\'ve been talking about doing a community survey for a while and during February we sent it out. We are still collating the results so it\'s not too late to send in your response.\\n\\nThe survey takes 5 minutes and is your opportunity to provide feedback to the project and highlight areas you think we need to focus on.\\n\\nUse this [Survey Link](https://uber.surveymonkey.com/r/ZS83WJW)\\n\\nPlease take a few minutes to give us your opinion.\\n\\n\x3c!-- truncate --\x3e\\n\\n## Cadence and Temporal ##\\nDuring user surveys we\'ve had a few queries about whether Cadence and [Temporal](https://temporal.io/) are the same project. The answer is No - they are not the same project but they do share the same origin. At a high level Temporal is a fork of the Cadence project. Both Temporal and Cadence are now being developed by different communities so are independent.\\n\\n## Cadence at DoorDash ##\\nAlthough published a few months ago we missed including an article by [DoorDash](https://doordash.engineering/) about how they are using Cadence to build real time event processing with [Apache Flink](https://flink.apache.org/) and [Apache Kafka](https://kafka.apache.org/).\\n\\nHere is the link to the article: [Building Scalable Real Time Event Processing with Kafka and Flink](https://doordash.engineering/2022/08/02/building-scalable-real-time-event-processing-with-kafka-and-flink/)\\n\\nRemember to let us know if you have news, articles or blog posts about Cadence that you\'d like us to include in these monthly updates.\\n\\n## Cadence in the News!\\n\\nBelow are a selection of Cadence related articles, blogs and whitepapers. Please take a look and feel free to share via your own social media channels.\\n\\n- [Getting Started with Cadence, an Open Source Workflow Engine](https://opensource.com/article/22/6/cadence-open-source-workflow-engine)\\n\\n- [Meet Cadence: Workflow Engine for Taming Complex Processes](https://thenewstack.io/meet-cadence-workflow-engine-for-taming-complex-processes/)\\n\\n## Upcoming Events\\n\\n- [On Demand Webinar: Spinning Your Drones with Cadence and Apache Kafka](https://info.instaclustr.com/webinar-spinning-drones-cadence-kafka.html)\\n\\nIf you have any news or topics you\'d like us to include in our next update then please join our [Slack](http://t.uber.com/cadence-slack)#community channel.\\n\\nPlease remember that this update is for you - so if you have any comments or feedback that could help us improve it then please share it with us in the #community [Slack](http://t.uber.com/cadence-slack) channel."},{"id":"/2023/01/31/community-spotlight-january-2023","metadata":{"permalink":"/blog/2023/01/31/community-spotlight-january-2023","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2023-01-31-community-spotlight-january-2023.md","source":"@site/blog/2023-01-31-community-spotlight-january-2023.md","title":"Cadence Community Spotlight Update - January 2023","description":"Happy New Year everyone! Here\u2019s the latest in our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!","date":"2023-01-31T00:00:00.000Z","tags":[{"inline":false,"label":"Community Spotlight","permalink":"/blog/tags/community-spotlights","description":"Community Spotlight tag description"}],"readingTime":2.06,"hasTruncateMarker":true,"authors":[{"name":"Sharan Foga","title":"Director of Operations & Customer Success @ Encube Technologies","url":"https://www.linkedin.com/in/sfoga/","page":{"permalink":"/blog/authors/sharanf"},"socials":{"linkedin":"https://www.linkedin.com/in/sfoga/","github":"https://github.com/sharanf"},"imageURL":"https://github.com/sharanf.png","key":"sharanf"}],"frontMatter":{"title":"Cadence Community Spotlight Update - January 2023","date":"2023-01-31T00:00:00.000Z","authors":"sharanf","tags":["community-spotlight"]},"unlisted":false,"prevItem":{"title":"Cadence Community Spotlight Update - February 2023","permalink":"/blog/2023/02/28/community-spotlight-february"},"nextItem":{"title":"Cadence Community Spotlight Update - December 2022","permalink":"/blog/2022/12/23/community-spotlight-december-2022"}},"content":"Happy New Year everyone! Here\u2019s the latest in our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!\\n\\nPlease see below for a roundup of the highlights:\\n\\n## Closing Down Cadence Office Hours ##\\nWe have been running Office Hours sessions every month since May last year. The aim was to give the community an opportunity to speak directly with some of the Cadence core developers and experts to answer questions on particular issues you may be having. We have found that the most preferred method for community questions has been the support Slack channel so have decided to stop this monthly call.\\n\\nThanks very much to [Ender Demirkaya](https://www.linkedin.com/in/enderdemirkaya/)and the Uber team for making themselves available for these sessions.\\n\\nPlease remember that if you have question about Cadence or are facing a specific issue then you can post your question in our #support [Slack](http://t.uber.com/cadence-slack) channel. If you also post the details on StackOverflow with the cadence workflow tag then there will be a searchable history for others who encounter the same issue to find a solution.\\n\\n\x3c!-- truncate --\x3e\\n\\n## Update on iWF Support for Cadence ##\\nLast October we featured an update in our monthly blog about [iWF - Interpreter for Workflow](https://github.com/indeedeng/iwf), a project built on top of Cadence by community member [Quanzheng Long](https://www.linkedin.com/in/prclqz/). It was announced recently that iWF has released a [Golang SDK](https://github.com/iworkflowio/iwf-golang-sdk) and updated versions of the [Java SDK and server](https://github.com/indeedeng/iwf).\\n\\nLong is really keen to get feedback so please take a look at iWF, try them out and presented him any feedback.\\nLong has also created a couple of blog posts about iWF that we have featured in the Cadence in the News section below so please take a look.\\n\\n## Cadence in the News!\\n\\nBelow are a selection of Cadence related articles, blogs and whitepapers. Please take a look and feel free to share via your own social media channels.\\n\\n- [A Letter to Cadence/Temporal and Workflow Tech Community](https://medium.com/@qlong/a-letter-to-cadence-temporal-and-workflow-tech-community-b32e9fa97a0c)\\n\\n- [iWF vs Cadence/Temporal](https://medium.com/@qlong/iwf-vs-cadence-temporal-1e11b35960fe)\\n\\n- [AWS PrivateLink Connectivity Is Now Available with Instaclustr for Cadence](https://www.instaclustr.com/blog/aws-privatelink-for-cadence-on-instaclustr-by-netapp/)\\n\\n## Upcoming Events\\n\\nNo upcoming events at the moment.\\n\\nIf you have any news or topics you\'d like us to include in our next update then please join our [Slack](http://t.uber.com/cadence-slack)#community channel.\\n\\nPlease remember that this update is for you - so if you have any comments or feedback that could help us improve it then please share it with us in the #community [Slack](http://t.uber.com/cadence-slack) channel."},{"id":"/2022/12/23/community-spotlight-december-2022","metadata":{"permalink":"/blog/2022/12/23/community-spotlight-december-2022","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2022-12-23-community-spotlight-december-2022.md","source":"@site/blog/2022-12-23-community-spotlight-december-2022.md","title":"Cadence Community Spotlight Update - December 2022","description":"I know we are a little early this month as many people will be taking some time out for holidays.","date":"2022-12-23T00:00:00.000Z","tags":[{"inline":false,"label":"Community Spotlight","permalink":"/blog/tags/community-spotlights","description":"Community Spotlight tag description"}],"readingTime":1.08,"hasTruncateMarker":true,"authors":[{"name":"Sharan Foga","title":"Director of Operations & Customer Success @ Encube Technologies","url":"https://www.linkedin.com/in/sfoga/","page":{"permalink":"/blog/authors/sharanf"},"socials":{"linkedin":"https://www.linkedin.com/in/sfoga/","github":"https://github.com/sharanf"},"imageURL":"https://github.com/sharanf.png","key":"sharanf"}],"frontMatter":{"title":"Cadence Community Spotlight Update - December 2022","date":"2022-12-23T00:00:00.000Z","authors":"sharanf","tags":["community-spotlight"]},"unlisted":false,"prevItem":{"title":"Cadence Community Spotlight Update - January 2023","permalink":"/blog/2023/01/31/community-spotlight-january-2023"},"nextItem":{"title":"Cadence Community Spotlight Update - November 2022","permalink":"/blog/2022/11/30/community-spotlight-november-2022"}},"content":"I know we are a little early this month as many people will be taking some time out for holidays.\\n\\n## Happy Holidays ##\\n\\nWe\'d like to wish everyone happy holidays and to thank you for being part of the Cadence community. It\'s been a busy year for Cadence as we have continued to build a strong, active community that works together to solve issues and generally support each other.\\n\\nLet\'s keep going!...This is a great way to build a sustainable community.\\n\\nWe are sure that 2023 will be even more exciting as we continue to develop Cadence.\\n\\n## Cadence in the News!\\n\\nBelow are a selection of Cadence related articles, blogs and whitepapers. Please take a look and feel free to share via your own social media channels.\\n\\n- [Cadence iWF](https://www.instaclustr.com/blog/cadence-iwf)\\n\\n- [Child Workflow Cookbook](https://github.com/instaclustr/cadence-cookbooks-instafood/blob/main/cookbooks/child-workflows/child-workflows-megafood.md)\\n\\n- [Cadence Connection Examples Using TLS](https://www.instaclustr.com/blog/cadence-connection-examples-using-tls/)\\n\\n\x3c!-- truncate --\x3e\\n\\n## Upcoming Events\\n\\n- [Cadence Technical Office Hours - 30th January 2023 @ 9am PT](https://calendar.google.com/calendar/u/0/embed?src=e6r40gp3c2r01054id7e99dlac@group.calendar.google.com&ctz=America/Los_Angeles)\\n\\nIf you have any news or topics you\'d like us to include in our next update then please join our [Slack](http://t.uber.com/cadence-slack)#community channel.\\n\\nPlease remember that this update is for you - so if you have any comments or feedback that could help us improve it then please share it with us in the #community [Slack](http://t.uber.com/cadence-slack) channel."},{"id":"/2022/11/30/community-spotlight-november-2022","metadata":{"permalink":"/blog/2022/11/30/community-spotlight-november-2022","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2022-11-30-community-spotlight-november-2022.md","source":"@site/blog/2022-11-30-community-spotlight-november-2022.md","title":"Cadence Community Spotlight Update - November 2022","description":"Here\u2019s the latest in our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!","date":"2022-11-30T00:00:00.000Z","tags":[{"inline":false,"label":"Community Spotlight","permalink":"/blog/tags/community-spotlights","description":"Community Spotlight tag description"}],"readingTime":1.91,"hasTruncateMarker":true,"authors":[{"name":"Sharan Foga","title":"Director of Operations & Customer Success @ Encube Technologies","url":"https://www.linkedin.com/in/sfoga/","page":{"permalink":"/blog/authors/sharanf"},"socials":{"linkedin":"https://www.linkedin.com/in/sfoga/","github":"https://github.com/sharanf"},"imageURL":"https://github.com/sharanf.png","key":"sharanf"}],"frontMatter":{"title":"Cadence Community Spotlight Update - November 2022","date":"2022-11-30T00:00:00.000Z","authors":"sharanf","tags":["community-spotlight"]},"unlisted":false,"prevItem":{"title":"Cadence Community Spotlight Update - December 2022","permalink":"/blog/2022/12/23/community-spotlight-december-2022"},"nextItem":{"title":"Cadence Community Spotlight Update - October 2022","permalink":"/blog/2022/10/31/community-spotlight-october-2022"}},"content":"Here\u2019s the latest in our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!\\n\\nPlease see below for a roundup of the highlights:\\n\\n## Cadence @ Uber ##\\n\\nThis month Uber Engineering published a really nice article on one of the ways they are using Cadence. The article is called [How Uber Optimizes the Timing of Push Notifications using ML and Linear Programming](https://www.uber.com/en-US/blog/how-uber-optimizes-push-notifications-using-ml/).\\n\\nThe Uber team take you through the details of the problem that they are looking to solve, so you can understand the scope limitations and depedencies - so please take a look.\\n\\n## Cadence @ DeveloperWeek Enterprise ##\\n\\nDevNetwork run a series of conferences and during November Cadence was featured in at [DeveloperWeek Enterprise](https://www.developerweek.com/global/conference/enterprise/). [Ender Demirkaya](https://www.linkedin.com/in/enderdemirkaya/) and [Ben Slater](https://www.linkedin.com/in/ben-slater-2720562/) presented a talk called [Espress Complex Business Logic as Code with Open Source Cadence!](https://embed.emamo.com/event/developerweek-enterprise-2022/s/express-complex-business-logic-as-code-with-open-source-cadence-WKLMvo).\\n\\nIt is good to see that we are finding new channels for us to present the benefits of using Cadence. Huge hanks to Ben and Ender for the presentation and to everyone that attended.\\n\\n\x3c!-- truncate --\x3e\\n\\n## Cadence at W-JAX ##\\n\\nIt must be presentation month as we have had yet another Cadence presentation! Earlier this month a Cadence talk was featured at the [W-JAX Conference](https://jax.de/munich/) in Munich, Germany. [Merlin Walter](https://www.linkedin.com/in/merlin-walter/) presented a talk called [Microservices - Modern Orchestration with Cadence](https://jax.de/microservices/microservices-modern-orchestration-approach-with-cadence/)\\n\\nSession feedback received was very positive and it\'s great to see that new audiences are interested in learning more about Cadence and seeing how it works.\\n\\n## Cadence in the News!\\n\\nBelow are a selection of Cadence related articles, blogs and whitepapers. Please take a look and feel free to share via your own social media channels.\\n\\n- [How Uber Optimizes the Timing of Push Notifications using ML and Linear Programming](https://www.uber.com/en-US/blog/how-uber-optimizes-push-notifications-using-ml/)\\n\\n- [Building with Cadence: Quantifiable Efficiency](https://www.instaclustr.com/blog/building-with-cadence-quantifiable-efficiency/)\\n\\n## Upcoming Events\\n\\n**PLEASE NOTE:** No Office Hours on 26th December 2022\\n\\n- [Cadence Technical Office Hours - 30th January 2023 @ 9am PT](https://calendar.google.com/calendar/u/0/embed?src=e6r40gp3c2r01054id7e99dlac@group.calendar.google.com&ctz=America/Los_Angeles)\\n\\nIf you have any news or topics you\'d like us to include in our next update then please join our [Slack](http://t.uber.com/cadence-slack)#community channel.\\n\\nPlease remember that this update is for you - so if you have any comments or feedback that could help us improve it then please share it with us in the #community [Slack](http://t.uber.com/cadence-slack) channel."},{"id":"/2022/10/31/community-spotlight-october-2022","metadata":{"permalink":"/blog/2022/10/31/community-spotlight-october-2022","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2022-10-31-community-spotlight-october-2022.md","source":"@site/blog/2022-10-31-community-spotlight-october-2022.md","title":"Cadence Community Spotlight Update - October 2022","description":"Here\u2019s the latest in our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!","date":"2022-10-31T00:00:00.000Z","tags":[{"inline":false,"label":"Community Spotlight","permalink":"/blog/tags/community-spotlights","description":"Community Spotlight tag description"}],"readingTime":1.93,"hasTruncateMarker":true,"authors":[{"name":"Sharan Foga","title":"Director of Operations & Customer Success @ Encube Technologies","url":"https://www.linkedin.com/in/sfoga/","page":{"permalink":"/blog/authors/sharanf"},"socials":{"linkedin":"https://www.linkedin.com/in/sfoga/","github":"https://github.com/sharanf"},"imageURL":"https://github.com/sharanf.png","key":"sharanf"}],"frontMatter":{"title":"Cadence Community Spotlight Update - October 2022","date":"2022-10-31T00:00:00.000Z","authors":"sharanf","tags":["community-spotlight"]},"unlisted":false,"prevItem":{"title":"Cadence Community Spotlight Update - November 2022","permalink":"/blog/2022/11/30/community-spotlight-november-2022"},"nextItem":{"title":"Cadence Community Spotlight Update - September 2022","permalink":"/blog/2022/09/30/community-spotlight-september-2022"}},"content":"Here\u2019s the latest in our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!\\n\\nPlease see below for a roundup of the highlights:\\n\\n## Cadence Meetup Postponed ##\\n\\nIt\'s always great to get the community together and we had planned to run another Cadence Meetup in early November. Unfortunately we didn\'t have enough time to get things organised so we\'ve decided to postpone it. So please watch out for an announcement for the new Cadence meetup date.\\n\\n## Doordash Technnical Showcase Featuring Cadence\\n\\nWe have had some great feedback from people who attended Technical Showcase that was run this month by Doordash. It featured their financial products but also highlighted some of the key technologies they use...and guess what Cadence is one of them!\\n\\nIf you missed the session then you will be happy to know that it was recorded and we\'ve inlcuded a link to the [the recording on Youtube](https://www.youtube.com/watch?v=uNwbdQyLpns).\\n\\nThanks to the Doordash team for running the session and helping support Cadence by sharing their knowledge.\\n\\n\x3c!-- truncate --\x3e\\n\\n## iWF Support for Cadence ##\\n\\nCommunity member [Quanzheng Long](https://www.linkedin.com/in/prclqz/) has been busy working on a new project that has been built on top of Cadence. The project is called [iWF - Interpreter for Workflow](https://github.com/indeedeng/iwf). It\'s great to see that Cadence is now growing it\'s own ecosystem!\\n\\nPlease feel free to take a look and let Long know what you think!\\n\\n## Cadence in the News!\\n\\nBelow are a selection of Cadence related articles, blogs and whitepapers. Please take a look and feel free to share via your own social media channels.\\n\\n\\n- [Apache Airflow vs Cadence: A Side by Side Comparison](https://www.instaclustr.com/blog/airflow-vs-cadence-a-side-to-side-comparison/)\\n\\n- [Managing Custom Search Attributes for Advance Visibility Cadence](https://www.instaclustr.com/blog/managing-custom-search-attributes-for-advanced-visibility-cadence/)\\n\\n## Upcoming Events\\n\\n- [Webinar: Spinning Your Drones with Cadence and Apache Kafka - 15th November 2022](https://info.instaclustr.com/webinar-spinning-drones-cadence-kafka.html)\\n\\n- [Webinar: Fitting Cadence in Your Corporate Architecture - 24th November 2022](https://info.instaclustr.com/webinar-emea-fitting-cadence.html)\\n\\n- [Cadence Technical Office Hours - 28th November 2022 @ 9am PT](https://calendar.google.com/calendar/u/0/embed?src=e6r40gp3c2r01054id7e99dlac@group.calendar.google.com&ctz=America/Los_Angeles)\\n\\n\\nIf you have any news or topics you\'d like us to include in our next update then please join our [Slack](http://t.uber.com/cadence-slack)#community channel.\\n\\nPlease remember that this update is for you - so if you have any comments or feedback that could help us improve it then please share it with us in the #community [Slack](http://t.uber.com/cadence-slack) channel."},{"id":"/2022/09/30/community-spotlight-september-2022","metadata":{"permalink":"/blog/2022/09/30/community-spotlight-september-2022","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2022-09-30-community-spotlight-september-2022.md","source":"@site/blog/2022-09-30-community-spotlight-september-2022.md","title":"Cadence Community Spotlight Update - September 2022","description":"Here\u2019s the latest in our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!","date":"2022-10-11T00:00:00.000Z","tags":[{"inline":false,"label":"Community Spotlight","permalink":"/blog/tags/community-spotlights","description":"Community Spotlight tag description"}],"readingTime":1.585,"hasTruncateMarker":true,"authors":[{"name":"Sharan Foga","title":"Director of Operations & Customer Success @ Encube Technologies","url":"https://www.linkedin.com/in/sfoga/","page":{"permalink":"/blog/authors/sharanf"},"socials":{"linkedin":"https://www.linkedin.com/in/sfoga/","github":"https://github.com/sharanf"},"imageURL":"https://github.com/sharanf.png","key":"sharanf"}],"frontMatter":{"title":"Cadence Community Spotlight Update - September 2022","date":"2022-10-11T00:00:00.000Z","authors":"sharanf","tags":["community-spotlight"]},"unlisted":false,"prevItem":{"title":"Cadence Community Spotlight Update - October 2022","permalink":"/blog/2022/10/31/community-spotlight-october-2022"},"nextItem":{"title":"Cadence Community Spotlight Update - August 2022","permalink":"/blog/2022/08/31/community-spotlight-august-2022"}},"content":"Here\u2019s the latest in our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!\\n\\nPlease see below for a roundup of the highlights:\\n\\n# Cadence at Developer Week\\n\\nA Cadence talk by [Ender Demirkaya](https://www.linkedin.com/in/enderdemirkaya/) and [Ben Slater](https://www.linkedin.com/in/ben-slater-2720562/) has been accepted for [Developer Week Enterprise](https://www.developerweek.com/global/conference/enterprise/).\\n\\nThe talk is scheduled to for 16th November so please make a note in your calendars.\\n\\n# Sharing Knowledge\\n\\nOver the last few months we have had a continual stream of Cadence questions in our [Slack](http://t.uber.com/cadence-slack) #support channel or on [StackOverflow](https://stackoverflow.com/questions/tagged/cadence-workflow). As a result of the increased interest some members from the Cadence core team have decided to spend some time each day responding to your questions.\\n\\nRemember that if you have received a response that has solved your problem especially on StackOverflow then please don\'t forget to accept answer!\\n\\n\x3c!-- truncate --\x3e\\n\\n## Cadence in the News!\\n\\nBelow are a selection of Cadence related articles, blogs and whitepapers. Please take a look and feel free to share via your own social media channels.\\n\\n- [Technical Showcase Event: DoorDash\'s Financial Products and Platforms\\n](https://www.youtube.com/watch?v=uNwbdQyLpns)\\n\\n- [Airflow vs Cadence: A Side by Side Comparison](https://www.instaclustr.com/blog/airflow-vs-cadence-a-side-to-side-comparison/)\\n\\n- [New Offering for Cadence Developers](https://www.instaclustr.com/blog/new-instaclustr-offering-for-cadence-developers/)\\n\\n- [Open Source Cadence Is Built for the Developer Experience \u2013 Here\u2019s How to Take Advantage](https://devm.io/open-source/open-source-cadence)\\n\\n## Upcoming Events\\n\\n- [Fitting Cadence in Your Corporate Architecture - 18th October 2022 @ 10am PT](https://info.instaclustr.com/webinar-fitting-cadence-in-corporate-architecture.html)\\n\\n- [Migrating Your Workflow Solution from Temporal to Cadence - 25th October 2022 @ 10am PT](https://info.instaclustr.com/webinar-fitting-cadence-in-corporate-architecture.html)\\n\\n- [Cadence Technical Office Hours - 31st October 2022 @ 9am PT](https://calendar.google.com/calendar/u/0/embed?src=e6r40gp3c2r01054id7e99dlac@group.calendar.google.com&ctz=America/Los_Angeles)\\n\\n\\nIf you have any news or topics you\'d like us to include in our next update then please join our [Slack](http://t.uber.com/cadence-slack)#community channel.\\n\\nPlease remember that this update is for you - so if you have any comments or feedback that could help us improve it then please share it with us in the #community [Slack](http://t.uber.com/cadence-slack) channel."},{"id":"/2022/08/31/community-spotlight-august-2022","metadata":{"permalink":"/blog/2022/08/31/community-spotlight-august-2022","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2022-08-31-community-spotlight-august-2022.md","source":"@site/blog/2022-08-31-community-spotlight-august-2022.md","title":"Cadence Community Spotlight Update - August 2022","description":"Here\u2019s the latest in our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!","date":"2022-08-31T00:00:00.000Z","tags":[{"inline":false,"label":"Community Spotlight","permalink":"/blog/tags/community-spotlights","description":"Community Spotlight tag description"}],"readingTime":2.83,"hasTruncateMarker":true,"authors":[{"name":"Sharan Foga","title":"Director of Operations & Customer Success @ Encube Technologies","url":"https://www.linkedin.com/in/sfoga/","page":{"permalink":"/blog/authors/sharanf"},"socials":{"linkedin":"https://www.linkedin.com/in/sfoga/","github":"https://github.com/sharanf"},"imageURL":"https://github.com/sharanf.png","key":"sharanf"}],"frontMatter":{"title":"Cadence Community Spotlight Update - August 2022","date":"2022-08-31T00:00:00.000Z","authors":"sharanf","tags":["community-spotlight"]},"unlisted":false,"prevItem":{"title":"Cadence Community Spotlight Update - September 2022","permalink":"/blog/2022/09/30/community-spotlight-september-2022"},"nextItem":{"title":"Cadence Community Spotlight Update - July 2022","permalink":"/blog/2022/07/31/community-spotlight-update-july-2022"}},"content":"Here\u2019s the latest in our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!\\n\\nPlease see below for a roundup of the highlights:\\n\\n## Community Survey\\n\\nWe are working on putting together our first community survey to find out a bit more about our community. We would like to get your feedback about on a few things such as:\\n\\n- how you are using Cadence\\n- any specific experiences you have had where you\'d like to see new features\\n- any special use cases not yet covered\\n- and of course whatever other feedback you\'d like to give us\\n\\nSo please watch out for the survey which will be coming out to you via the Slack channel soon!\\n\\n\x3c!-- truncate --\x3e\\n\\n## Support Activity\\n\\nWe have noticed that community activity is increasing and that we are continuing to respond to questions in our Slack #support channel. Eight questions have been posted in the channel this month and another seven questions have been posted on StackOverflow. We encourage people to post their questions on StackOverflow so that the response can be shared. You can also post a link to the StackOverflow question in the support channel to be extra sure it gets seen by our community members.\\n\\nWe are looking always forward to receiving more of your questions!\\n\\n## GitHub Activity\\n\\nDo you remember our GitHub Statistics from last month? Don\'t worry if you don\'t! In July we had 28 pull requests (PRs) merged into the code repository. This month we have had 43 PRs merged (nearly double!)- so you can see the level of activity is also increasing in terms of the project code.\\n\\nIf you are interested in contributing to Cadence then please take a look at our [Contribution Guidelines](https://github.com/cadence-workflow/cadence/blob/86f645da952e15d7a7415cdf9fcd2726f28063a6/CONTRIBUTING.md) and also our list of [good first issues](https://github.com/cadence-workflow/cadence/contribute) to work on.\\n\\n## Come Along to Our Next Cadence Meetup!\\n\\nIt\'s been a while since we had a Cadence meetup so we have decided to organise another one. This time we are planning to do an in-person meetup in the San Francisco Bay area in early November. We are looking for any companies using Cadence to come along and speak about how they are using it. We\'d also like to hear about any interesting use cases that you have used Cadence for.\\n\\nIf you are interested in speaking at our next meetup then please contact [Ender Demirkaya](https://www.linkedin.com/in/enderdemirkaya/)\\n\\n## Looking for a Cadence Role?\\n\\nThe Cadence teeam at Uber are recruiting for a Fullstack Engineer. If you are interested then please contact [Ender Demirkaya](https://www.linkedin.com/in/enderdemirkaya/) for more details.\\n\\n## Cadence in the News!\\n\\nBelow are a selection of Cadence related articles, blogs and whitepapers. Please take a look and feel free to share via your own social media channels.\\n\\n- [Cadence Advanced Visibility: Enhance Your Workflows with Searchability](https://www.instaclustr.com/blog/cadence-advanced-visibility-enhance-your-workflows-with-searchability/)\\n\\n- [New Features for Instaclustr Managed Cadence](https://www.instaclustr.com/blog/new-features-for-instaclustr-managed-cadence/)\\n\\n## Upcoming Events\\n\\n- [Webinar: Building Your First Cadence Workflow with Java and Go - 1st September 2022](https://info.instaclustr.com/webinar-emea-building-cadence-workflow.html)\\n\\n- [Cadence Technical Office Hours - 26th September 2022 @ 9am PT](https://calendar.google.com/calendar/u/0/embed?src=e6r40gp3c2r01054id7e99dlac@group.calendar.google.com&ctz=America/Los_Angeles)\\n\\n\\nIf you have any news or topics you\'d like us to include in our next update then please join our [Slack](http://t.uber.com/cadence-slack)#community channel.\\n\\nPlease remember that this update is for you - so if you have any comments or feedback that could help us improve it then please share it with us in the #community [Slack](http://t.uber.com/cadence-slack) channel."},{"id":"/2022/07/31/community-spotlight-update-july-2022","metadata":{"permalink":"/blog/2022/07/31/community-spotlight-update-july-2022","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2022-07-31-community-spotlight-update-july-2022.md","source":"@site/blog/2022-07-31-community-spotlight-update-july-2022.md","title":"Cadence Community Spotlight Update - July 2022","description":"Here\u2019s our monthly Community Spotlight update that gives you news from in and around the Cadence community!","date":"2022-07-31T00:00:00.000Z","tags":[{"inline":false,"label":"Community Spotlight","permalink":"/blog/tags/community-spotlights","description":"Community Spotlight tag description"}],"readingTime":1.885,"hasTruncateMarker":true,"authors":[{"name":"Sharan Foga","title":"Director of Operations & Customer Success @ Encube Technologies","url":"https://www.linkedin.com/in/sfoga/","page":{"permalink":"/blog/authors/sharanf"},"socials":{"linkedin":"https://www.linkedin.com/in/sfoga/","github":"https://github.com/sharanf"},"imageURL":"https://github.com/sharanf.png","key":"sharanf"}],"frontMatter":{"title":"Cadence Community Spotlight Update - July 2022","date":"2022-07-31T00:00:00.000Z","authors":"sharanf","tags":["community-spotlight"]},"unlisted":false,"prevItem":{"title":"Cadence Community Spotlight Update - August 2022","permalink":"/blog/2022/08/31/community-spotlight-august-2022"},"nextItem":{"title":"Cadence Community Spotlight Update - June 2022","permalink":"/blog/2022/06/30/community-spotlight-update-june-2022"}},"content":"Here\u2019s our monthly Community Spotlight update that gives you news from in and around the Cadence community!\\n\\nPlease see below for a roundup of the highlights:\\n\\n## Flying Drones with Cadence\\n\\nCommunity member [Paul Brebner](https://www.linkedin.com/in/paul-brebner-0a547b4/) has released [another blog](https://www.instaclustr.com/blog/spinning-your-drones-with-cadence-and-apache-kafka-how-many-drones-can-we-fly/) in the series of using Cadence to manage a drone delivery service. You can see a [simulated view of it in action](https://www.youtube.com/watch?v=YgQeFSqzprk)\\n\\nDon\u2019t forget to try out the code yourself and remember if you have used Cadence to do something interesting then please let us know so we can feature it in our next update.\\n\\n## GitHub Statistics\\n\\nDuring July the main Cadence branch had 28 pull requests (PRs) merged. There were 214 files changed by 11 different authors. You can find more details [here](https://github.com/cadence-workflow/cadence/pulse/monthly)\\n\\nThe Cadence documentation repository was not as busy with only 2 PRs merged in July, 5 commits and 3 authors active. More details can be found [here](https://github.com/cadence-workflow/Cadence-Docs/pulse/monthly )\\n\\n\x3c!-- truncate --\x3e\\n\\n## Cadence Roadmap\\n\\nThe Cadence Core team has been busy this month looking at the various community feedback for potential improvements and features for Cadence. Planning is already in place for a development roadmap and it is still a little too early to say what will be included so please watch out for future updates. All I know is that it\u2019s going to be exciting!\\n\\n## Cadence in the News!\\n\\nBelow are a selection of Cadence related articles, blogs and whitepapers. Please take a look and feel free to share via your own social media channels.\\n\\n- [Migrate to Cadence From Temporal](https://www.instaclustr.com/blog/migrate-to-cadence-from-temporal/)\\n\\n- [Spinning Your Drones With Cadence and Apache Kafka\xae: How Many Drones Can We Fly?](https://www.instaclustr.com/blog/spinning-your-drones-with-cadence-and-apache-kafka-how-many-drones-can-we-fly/)\\n\\n## Upcoming Events\\n\\n- [Cadence Technical Office Hours - 29th August 2022 @ 9am PT](https://calendar.google.com/calendar/u/0/embed?src=e6r40gp3c2r01054id7e99dlac@group.calendar.google.com&ctz=America/Los_Angeles)\\n\\n- [Webinar: Cadence Fundamentals: Event Sourcing - Two sessions one on 16th and one on 18th August 2022\\n](https://info.instaclustr.com/webinar-cadence-fundamentals-event-sourcing/)\\n\\n- [Webinar: Building Your First Cadence Workflow with Java and Go - 1st September 2022](https://info.instaclustr.com/webinar-emea-building-cadence-workflow.html)\\n\\nIf you have any news or topics you\'d like us to include in our next update then please join our [Slack](http://t.uber.com/cadence-slack)#community channel.\\n\\nPlease remember that this update is for you - so if you have any comments or feedback that could help us improve it then please share it with us in the #community [Slack](http://t.uber.com/cadence-slack) channel."},{"id":"/2022/06/30/community-spotlight-update-june-2022","metadata":{"permalink":"/blog/2022/06/30/community-spotlight-update-june-2022","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2022-06-30-community-spotlight-update-june-2022.md","source":"@site/blog/2022-06-30-community-spotlight-update-june-2022.md","title":"Cadence Community Spotlight Update - June 2022","description":"It\u2019s time for our monthly Cadence Community Spotlight update with news from in and around the Cadence community!","date":"2022-06-30T00:00:00.000Z","tags":[{"inline":false,"label":"Community Spotlight","permalink":"/blog/tags/community-spotlights","description":"Community Spotlight tag description"}],"readingTime":2.285,"hasTruncateMarker":true,"authors":[{"name":"Sharan Foga","title":"Director of Operations & Customer Success @ Encube Technologies","url":"https://www.linkedin.com/in/sfoga/","page":{"permalink":"/blog/authors/sharanf"},"socials":{"linkedin":"https://www.linkedin.com/in/sfoga/","github":"https://github.com/sharanf"},"imageURL":"https://github.com/sharanf.png","key":"sharanf"}],"frontMatter":{"title":"Cadence Community Spotlight Update - June 2022","date":"2022-06-30T00:00:00.000Z","authors":"sharanf","tags":["community-spotlight"]},"unlisted":false,"prevItem":{"title":"Cadence Community Spotlight Update - July 2022","permalink":"/blog/2022/07/31/community-spotlight-update-july-2022"},"nextItem":{"title":"Cadence Community Spotlight Update - May 2022","permalink":"/blog/2022/05/31/community-spotlight-update-may-2022"}},"content":"It\u2019s time for our monthly Cadence Community Spotlight update with news from in and around the Cadence community!\\n\\nPlease see below for a roundup of the highlights:\\n\\n## Knowledge Sharing and Support\\n\\nOur Slack #support channel has been busy this month with 13 questions asked this month by 12 different community members. Six community members took time to respond to those questions which clearly shows our community is growing, collaborating and keen to share knowledge.\\n\\nPlease don\u2019t forget that we encourage everyone to post questions on StackOverflow using the **cadence-workflow** and **uber-cadence** tags so that others with similar questions or issues can easily search for and find an answer.\\n\\n## Improving Technical Office Hours\\n\\nOver the last few months we have been holding regular monthly Office Hours meetings but they have not attracted as many participants as we would like. We would like to understand if there is something preventing people from attending (e.g perhaps the timing or dates are not convenient) so we are planning to send out a short community survey.\\n\\nIf you have any ideas or comments about how we can improve our community office hours sessions then please include this in your feedback or contact us in the #community Slack channel.\\n\\n\x3c!-- truncate --\x3e\\n\\n## Cadence Stability Improvements\\n\\nIs Cadence getting better? Yes it is! Many of you may have noticed that Cadence is improving.That is because of the amount of work being done behind the scenes. The Cadence core team has been doing a lot of work to stabilise Cadence functionality. Keep watching out for even more improvements!\\n\\n## Sprechen Sie Deutsch?\\n\\nDo you speak German? If you do speak then we have some good news for you. A couple of Cadence blog posts have been translated into German to help promote it to a wider audience. The links are as below and we hope you find them useful!\\n\\n- [Workflows mit Cadence optimieren!](https://www.credativ.de/blog/howtos/workflows-mit-cadence-optimieren/)\\n- [Apache Kafka\xae Microservices mit Cadence-Workflows optimieren](https://www.credativ.de/blog/howtos/apache-kafka-microservices-mit-cadence-workflows-optimieren/)\\n\\n## Cadence in the News!\\n\\nBelow are a selection of Cadence related articles, blogs and whitepapers. Please take a look and feel free to share via your own social media channels.\\n\\n- [Workflow Comparison: Uber Cadence vs Netflix Conductor](https://www.instaclustr.com/blog/workflow-comparison-uber-cadence-vs-netflix-conductor/)\\n\\n- [Securing Cadence Web Using NGINX](https://www.instaclustr.com/blog/securing-cadence-web-using-nginx/)\\n\\n## Upcoming Events\\n\\n- [Cadence Technical Office Hours - 25th July 2022 @ 9am PT](https://calendar.google.com/calendar/u/0/embed?src=e6r40gp3c2r01054id7e99dlac@group.calendar.google.com&ctz=America/Los_Angeles)\\n\\n- [Webinar: Building Your First Cadence Workflow with Java and Go - 19th July 2022](https://info.instaclustr.com/webinar-building-cadence-workflow)\\n\\nIf you have any news or topics you\'d like us to include in our next update then please join our [Slack](http://t.uber.com/cadence-slack)#community channel.\\n\\nPlease remember that this update is for you - so if you have any comments or feedback that could help us improve it then please share it with us in the #community [Slack](http://t.uber.com/cadence-slack) channel."},{"id":"/2022/05/31/community-spotlight-update-may-2022","metadata":{"permalink":"/blog/2022/05/31/community-spotlight-update-may-2022","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2022-05-31-community-spotlight-update-may-2022.md","source":"@site/blog/2022-05-31-community-spotlight-update-may-2022.md","title":"Cadence Community Spotlight Update - May 2022","description":"Welcome to our regular Cadence Community Spotlight update!","date":"2022-05-31T00:00:00.000Z","tags":[{"inline":false,"label":"Community Spotlight","permalink":"/blog/tags/community-spotlights","description":"Community Spotlight tag description"}],"readingTime":2.905,"hasTruncateMarker":true,"authors":[{"name":"Sharan Foga","title":"Director of Operations & Customer Success @ Encube Technologies","url":"https://www.linkedin.com/in/sfoga/","page":{"permalink":"/blog/authors/sharanf"},"socials":{"linkedin":"https://www.linkedin.com/in/sfoga/","github":"https://github.com/sharanf"},"imageURL":"https://github.com/sharanf.png","key":"sharanf"}],"frontMatter":{"title":"Cadence Community Spotlight Update - May 2022","date":"2022-05-31T00:00:00.000Z","authors":"sharanf","tags":["community-spotlight"]},"unlisted":false,"prevItem":{"title":"Cadence Community Spotlight Update - June 2022","permalink":"/blog/2022/06/30/community-spotlight-update-june-2022"},"nextItem":{"title":"Cadence Community Spotlight Update - April 2022","permalink":"/blog/2022/04/30/community-spotlight-update-april-2022"}},"content":"Welcome to our regular Cadence Community Spotlight update!\\n\\nThis is our monthly blog post series focused on news from in and around the Cadence community.\\n\\nPlease see below for a short activity roundup of what has happened recently in the community.\\n\\n## Cadence Polling Cookbook\\n\\nDo you want to understand polling work and have an example of how to set it up in Cadence? Well a brand new [Cadence Polling cookbook](https://info.instaclustr.com/rs/620-JHM-287/images/Cadence_Cookbook.pdf) is now available that gives you all the details you need. The cookbook was created by several members of the [Instaclustr](https://www.instaclustr.com/) team and they are keen to share it with the community. The pdf version of the cookbook can found on the Cadence website under the *Polling an external API for a specific resource to become available* section of the [Polling Use cases](https://cadenceworkflow.io/docs/use-cases/polling/).\\n\\nA [Github repository](https://github.com/instaclustr/cadence-cookbooks-instafood) has also been created with the sample cookbook code for you to try out for yourself.\\n\\nSo please go ahead and try out the cookbook and don\u2019t forget to let us have your feedback.\\n\\n\x3c!-- truncate --\x3e\\n\\n## Congratulations to a First Time Contributor\\n\\nWe are always looking for ways to encourage project participation. It doesn\'t matter how large the contribution is or whether it is coding or non coding related. This month one of our community members had [their first PR merged](https://github.com/cadence-workflow/Cadence-Docs/pull/107)- so congratulations and many thanks for the contribution [tonyxrandall](https://github.com/tonyxrandall)!\\n\\n## Share Your News!\\n\\nOur #support [Slack](http://t.uber.com/cadence-slack) channel is always full of questions and activity so we know that there are are lot of people out there exploring, trying out and setting up Cadence. We are always interested in hearing about what the community are doing so if you have something to you want to share as a blog post or part of this montly update then please contact us in the #community [Slack](http://t.uber.com/cadence-slack) channel.\\n\\n## Next Cadence Technical Office Hours: 3rd and 27th June 2022\\n\\nWe will be having two Technical Office Hours sessions this month. As 30th May was a US holiday we have moved May\u2019s Technical Office Hours to Friday 3rd June at 11am PT. And we will be having our June call on 27th.\\n\\nRemember that in these Zoom sessions you can speak directly with some of our Cadence experts so if you have a question about Cadence or are facing a particular issue getting it setup then please come along and chat to one of our experts!\\n\\n## Cadence in the News!\\n\\nBelow are a selection of Cadence related articles, blogs and whitepapers. Please take a look and feel free to share via your own social media channels.\\n\\n- [Spinning Your Drones With Cadence and Apache Kafka \u2013 Integration Patterns and New Cadence Features](https://www.instaclustr.com/blog/spinning-your-drones-with-cadence-and-apache-kafka-integration-patterns-and-new-cadence-features/)\\n\\n- [Enabling Faster Financial Partnership Integrations Using Cadence](https://doordash.engineering/2022/05/18/enabling-faster-financial-partnership-integrations-using-cadence/)\\n\\n- [Spinning Your Drones With Cadence and Apache Kafka\xae \u2013 Architecture, Order and Delivery Workflows](https://www.instaclustr.com/blog/spinning-your-drones-with-cadence-and-apache-kafka-architecture-order-and-delivery-workflows/)\\n\\n## Upcoming Events\\n\\n- [Cadence Technical Office Hours - 3rd June 2022 @ 11am PT](https://calendar.google.com/calendar/u/0/embed?src=e6r40gp3c2r01054id7e99dlac@group.calendar.google.com&ctz=America/Los_Angeles)\\n\\n- [Webinar : Spinning up Your Workflows with Cadence : 20th June](https://info.instaclustr.com/webinar-emea-spinning-workflows-cadence.html)\\n\\n- [Cadence Technical Office Hours - 27th June 2022 @ 9am PT](https://calendar.google.com/calendar/u/0/embed?src=e6r40gp3c2r01054id7e99dlac@group.calendar.google.com&ctz=America/Los_Angeles)\\n\\n- [Webinar: Building Your First Cadence Workflow with Java and Go - 19th July 2022](https://info.instaclustr.com/webinar-building-cadence-workflow)\\n\\nIf you have any news or topics you\'d like us to include in our next update then please join our [Slack](http://t.uber.com/cadence-slack)#community channel.\\n\\nPlease remember that this update is for you - so if you have any comments or feedback that could help us improve it then please share it with us in the #community [Slack](http://t.uber.com/cadence-slack) channel."},{"id":"/2022/04/30/community-spotlight-update-april-2022","metadata":{"permalink":"/blog/2022/04/30/community-spotlight-update-april-2022","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2022-04-30-community-spotlight-update-april-2022.md","source":"@site/blog/2022-04-30-community-spotlight-update-april-2022.md","title":"Cadence Community Spotlight Update - April 2022","description":"Welcome to our Cadence Community Spotlight update!","date":"2022-04-30T00:00:00.000Z","tags":[{"inline":false,"label":"Community Spotlight","permalink":"/blog/tags/community-spotlights","description":"Community Spotlight tag description"}],"readingTime":2.955,"hasTruncateMarker":true,"authors":[{"name":"Sharan Foga","title":"Director of Operations & Customer Success @ Encube Technologies","url":"https://www.linkedin.com/in/sfoga/","page":{"permalink":"/blog/authors/sharanf"},"socials":{"linkedin":"https://www.linkedin.com/in/sfoga/","github":"https://github.com/sharanf"},"imageURL":"https://github.com/sharanf.png","key":"sharanf"}],"frontMatter":{"title":"Cadence Community Spotlight Update - April 2022","date":"2022-04-30T00:00:00.000Z","authors":"sharanf","tags":["community-spotlight"]},"unlisted":false,"prevItem":{"title":"Cadence Community Spotlight Update - May 2022","permalink":"/blog/2022/05/31/community-spotlight-update-may-2022"},"nextItem":{"title":"Cadence Community Spotlight Update - March 2022","permalink":"/blog/2022/03/31/community-spotlight-update-march-2022"}},"content":"Welcome to our Cadence Community Spotlight update!\\n\\nThis is our monthly blog post series focused on news from in and around the Cadence community.\\n\\nPlease see below for a short activity roundup of what has happened recently in the community.\\n\\n## SD Times Names Cadence Open Source Project of the Week\\n\\nIn April Cadence was named as open source project of the week by the SD Times. Being named gives the project some great publicity and means the project is getting noticed. You can find a link to the article in the *Cadence in the News* section below.\\n\\n## Follow Us on LinkedIn and Twitter!\\n\\nWe have now set up Cadence accounts on [LinkedIn](https://www.linkedin.com/company/cadenceworkflow/) and [Twitter](https://twitter.com/cadenceworkflow) where you can keep up to date with what is happening in the community. We will be using these social media accounts to share news, articles, stories and links related to Cadence - so please follow us!\\n\\nAnd don\u2019t forget to share your news with us. We are looking forward to receiving your feedback and comments. The more we interact - the more we build our community!\\n\\n\x3c!-- truncate --\x3e\\n\\n## Proposal to Change the Way We Write Workflows\\n\\nIf you haven\u2019t seen the proposal from community member [Quanzheng Long](https://www.linkedin.com/in/prclqz/) about creating a new way to write Cadence workflows then please take a look:[https://github.com/cadence-workflow/cadence/issues/4785](https://github.com/cadence-workflow/cadence/issues/4785). He has already received some initial feedback and is currently working on putting together a proof of concept demo to show the community. As soon as we have more news about it - we will let you know!\\n\\n\\n## Help Us Improve Cadence\\n\\nDo you want to help us improve Cadence? We are always looking for contributors so any contribution you can make - however small is welcome. If you would like to start contributing then please take a look at the list of [Cadence Issues on Github](https://github.com/cadence-workflow/cadence/issues). We have some issues flagged with a tag of *\u2018good first issue\'* that would be a great place to start.\\n\\nRemember that we are not only looking for code contributions but also non coding ones such as documentation improvements so please take a look and select something to work on.\\n\\n## Next Cadence Technical Office Hours: 30th May 2022\\n\\nEvery month we hold a Technical Office Hours session via Zoom where you can speak directly with some of our Cadence experts. If you have a question about Cadence or are facing a particular issue getting it setup then please come along and chat to one of our experts!\\n\\nMeetings are held on the last Monday of every month so please make sure you mark the dates in your calendars. Our next session will be on the 30th May at 9am PT so hope to see you there!\\n\\n## Cadence in the News!\\n\\nBelow are a selection of Cadence related articles, blogs and whitepapers. Please take a look and feel free to share via your own social media channels.\\n\\n- [SD Times Open Source Project of the Week : Cadence](https://sdtimes.com/softwaredev/sd-times-open-source-project-of-the-week-cadence/)\\n\\n- [The New Stack Interview: Meet Cadence: The Open-Source Orchestration Workflow Engine](https://www.youtube.com/watch?v=-f1m5EI4cRo)\\n\\n- [The New Stack: Instaclustr Adds Managed Cadence to Its Platform](https://thenewstack.io/instaclustr-adds-managed-cadence-to-its-platform/)\\n\\n## Upcoming Events\\n\\n- [Cadence Technical Office Hours - 30th May 2022 @ 9am PT](https://calendar.google.com/calendar/u/0/embed?src=e6r40gp3c2r01054id7e99dlac@group.calendar.google.com&ctz=America/Los_Angeles)\\n\\n\\nIf you have any news or topics you\'d like us to include in our next update then please join our [Slack](http://t.uber.com/cadence-slack)#community channel.\\n\\nPlease remember that this update is for you - so if you have any comments or feedback that could help us improve it then please share it with us in the #community [Slack](http://t.uber.com/cadence-slack) channel."},{"id":"/2022/03/31/community-spotlight-update-march-2022","metadata":{"permalink":"/blog/2022/03/31/community-spotlight-update-march-2022","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2022-03-31-community-spotlight-update-march-2022.md","source":"@site/blog/2022-03-31-community-spotlight-update-march-2022.md","title":"Cadence Community Spotlight Update - March 2022","description":"Welcome to our Cadence Community Spotlight update!","date":"2022-03-31T00:00:00.000Z","tags":[{"inline":false,"label":"Community Spotlight","permalink":"/blog/tags/community-spotlights","description":"Community Spotlight tag description"}],"readingTime":3.235,"hasTruncateMarker":true,"authors":[{"name":"Sharan Foga","title":"Director of Operations & Customer Success @ Encube Technologies","url":"https://www.linkedin.com/in/sfoga/","page":{"permalink":"/blog/authors/sharanf"},"socials":{"linkedin":"https://www.linkedin.com/in/sfoga/","github":"https://github.com/sharanf"},"imageURL":"https://github.com/sharanf.png","key":"sharanf"}],"frontMatter":{"title":"Cadence Community Spotlight Update - March 2022","date":"2022-03-31T00:00:00.000Z","authors":"sharanf","tags":["community-spotlight"]},"unlisted":false,"prevItem":{"title":"Cadence Community Spotlight Update - April 2022","permalink":"/blog/2022/04/30/community-spotlight-update-april-2022"},"nextItem":{"title":"Cadence Community Spotlight Update - February 2022","permalink":"/blog/2022/02/28/community-spotlight-february-2022"}},"content":"Welcome to our Cadence Community Spotlight update!\\n\\nThis is the latest in our series of monthly blog posts focused on the Cadence community and news about what you have been doing with Cadence.\\n\\nPlease see below for a short activity roundup of what has happened recently in the community.\\n\\n## Updated Cadence Topology Diagram\\n\\nDid you know that we have an updated Cadence Service diagram on the website? Well we do - and you can find it on our [Deployment Topology](https://cadenceworkflow.io/docs/concepts/topology/#overview) page. We are always looking for information that helps makes it easier for people to understand how Cadence works.\\n\\nSpecial thanks to Ben Slater for updating the diagram and also to Ender, Emrah and Long for helping review it.\\n\\n\x3c!-- truncate --\x3e\\n\\n## Monthly Cadence Technical Office Hours\\n\\nEvery month we hold a Technical Office Hours session via Zoom where you can speak directly with some of our Cadence experts. If you have a question about Cadence or are facing a particular issue getting it setup then please come along and chat to one of our experts!\\n\\nMeetings are held on the last Monday of every month so make sure you mark the dates in your calendars. Our next session will be on the 25th April at 9am PT so hope to see you there!\\n\\nThe [Cadence Community Calendar](https://calendar.google.com/calendar/u/0/embed?src=e6r40gp3c2r01054id7e99dlac@group.calendar.google.com&ctz=America/Los_Angeles) contains the Zoom link for the meeting and details of any other events planned so please check it regularly.\\n\\n## Some Cadence Statistics\\n\\nThis month we thought it would be interesting to post some statistics about the Cadence community.\\n\\n- 1722 - the number of members in our #general Slack channel\\n- 24 - the number of questions asked in our #support Slack channel during the month\\n- 5 - the number of questions asked about Cadence in StackOverflow during the month\\n- 105 - the number of contributors to the Cadence git repo\\n- 9 - the number of community members who responded to a question during the month\\n\\n## Using StackOverflow to Respond to Support Questions\\n\\nWe have over 1700 members in our #support channel on our Cadence Slack where some of you have been asking questions about Cadence. The community has been responding and provided some great answers that we don\u2019t want to lose!\\n\\nIt can be difficult searching the Slack #support channel for a specific problem and we want to make sure that we capture all these great answers so that they can help others in the community.\\n\\nSo if possible we would like you to start posting your Cadence questions on [StackOverflow](https://stackoverflow.com/).\\n\\n- Create your question in StackOverflow\\n- Post the StackOverflow question link in the Cadence Slack #support channel\\n- A response to your question will be posted to StackOverflow\\n\\nOther community members will be able to search StackOverflow for the details of the your question and see the response. We hope that this will make it easier for people to find answers to common questions.\\n\\n## Cadence in the News!\\n\\nBelow are a selection of Cadence related articles, blogs and whitepapers. Please take a look and feel free to share via your own social media channels.\\n\\n- [Create Distributed, Scalable, Durable, and Highly Available Software\u2014 With Cadence](https://betterprogramming.pub/create-distributed-scalable-durable-and-highly-available-software-with-cadence-9f4fa6b1376b)\\n\\n- [Spinning Your Drones with Cadence - Introduction](https://www.instaclustr.com/blog/spinning-your-drones-with-cadence-introduction/)\\n\\n- [Instaclustr Announces General Availability of Managed Cadence](https://www.globenewswire.com/news-release/2022/04/04/2415472/0/en/Instaclustr-Announces-General-Availability-of-Instaclustr-Managed-Cadence.html)\\n\\n- [Introducing Managed Cadence on the Instaclustr Platform](https://www.youtube.com/watch?v=Vzc_LWmJ8lE&feature=youtu.be)\\n\\n- [Whitepaper: Understanding Cadence for Ops and SREs](https://info.instaclustr.com/rs/620-JHM-287/images/Understanding_Cadence_for%20Ops_and_SRE_WhitePaper.pdf)\\n\\n## Upcoming Events\\n\\n- [Cadence Technical Office Hours - 25th April 2022 @ 9am PT\\n](https://calendar.google.com/calendar/u/0/embed?src=e6r40gp3c2r01054id7e99dlac@group.calendar.google.com&ctz=America/Los_Angeles)\\n\\n- [Webinar : Spinning up Your Workflows with Cadence](https://info.instaclustr.com/webinar-spinning-workflows-cadence.html)\\n\\nIf you have any news or topics you\'d like us to include in our next update then please join our [Slack](http://t.uber.com/cadence-slack)#community channel.\\n\\nPlease remember that this update is for you - so if you have any comments or feedback that could help us improve it then please share it with us in the #community [Slack](http://t.uber.com/cadence-slack) channel."},{"id":"/2022/02/28/community-spotlight-february-2022","metadata":{"permalink":"/blog/2022/02/28/community-spotlight-february-2022","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2022-02-28-community-spotlight-february-2022.md","source":"@site/blog/2022-02-28-community-spotlight-february-2022.md","title":"Cadence Community Spotlight Update - February 2022","description":"Welcome to the Cadence Community Spotlight update!","date":"2022-02-28T00:00:00.000Z","tags":[{"inline":false,"label":"Community Spotlight","permalink":"/blog/tags/community-spotlights","description":"Community Spotlight tag description"}],"readingTime":2.99,"hasTruncateMarker":true,"authors":[{"name":"Sharan Foga","title":"Director of Operations & Customer Success @ Encube Technologies","url":"https://www.linkedin.com/in/sfoga/","page":{"permalink":"/blog/authors/sharanf"},"socials":{"linkedin":"https://www.linkedin.com/in/sfoga/","github":"https://github.com/sharanf"},"imageURL":"https://github.com/sharanf.png","key":"sharanf"}],"frontMatter":{"title":"Cadence Community Spotlight Update - February 2022","date":"2022-02-28T00:00:00.000Z","authors":"sharanf","tags":["community-spotlight"]},"unlisted":false,"prevItem":{"title":"Cadence Community Spotlight Update - March 2022","permalink":"/blog/2022/03/31/community-spotlight-update-march-2022"},"nextItem":{"title":"Cadence Community Spotlight Update - January 2022","permalink":"/blog/2022/01/31/community-spotlight-january-2022"}},"content":"Welcome to the Cadence Community Spotlight update!\\n\\nThis is the second in our series of monthly updates focused on the Cadence community and news about what you have been doing with Cadence. We hope that you enjoyed last month\'s update and are keen to find out what has been happening.\\n\\nPlease see below for a short activity roundup of what has happened recently in the community.\\n\\n## Announcements\\n\\nJust in case you missed it the alpha version of the Cadence notification service has been released. Details can be found at the following link:\\n[Cadence Notification Service](https://github.com/cadence-oss/cadence-notification/releases/tag/v0.0.1)\\n\\nThanks very much to everyone that worked on this!\\n\\n\x3c!-- truncate --\x3e\\n\\n## Community Supporting the Community\\n\\nDuring February 16 questions were posted in the Cadence #support [Slack](http://t.uber.com/cadence-slack) channel from new Cadence users and existing community members looking for help and guidance. A very big thank you to the following community members who took the time to help others: Ali, David, Tamas Weisz, Liang Mei, Quanzheng Long, peaceChoi, Emrah Seker, Ben Slater and Sathyaraju Sekaran.\\n\\nIt\u2019s great to see that we are supporting each other - and that is exactly what communities do!\\n\\n\\n## Please Subscribe to our Youtube Channel\\n\\nDid you know that we have a Youtube channel where you can find Cadence related videos and even the recording of our last meetup? Well we do and you can find it here:\\n[Cadence Youtube](https://www.youtube.com/channel/UC6H9Jsq4ZQ74g8coDgJu9ZA/videos)\\nPlease subscribe and let us know what other videos you\u2019d like to see there.\\n\\n## Help us to Make Cadence even better\\n\\nAre you interested in helping us improve Cadence? We are always looking for contributors to help share the workload. If you\u2019d like to help then you can start by taking a look at our list of [open issues](https://github.com/cadence-workflow/cadence/issues) on Github. We currently have 320 of them that need to be worked on so if you want to learn more about Cadence and solve some of the reported issues then please take a look and volunteer to fix it.\\n\\nIf you are new to Cadence or you\u2019d like to try something simple then we have some issues labelled as \u2018good first issue\u2019. These are a great place to start to get more Cadence experience.\\n\\n## Cadence Calendar\\n\\nWe have created a [Cadence public calendar](https://calendar.google.com/calendar/embed?src=e6r40gp3c2r01054id7e99dlac%40group.calendar.google.com&ctz=America%2FLos_Angeles) where we can highlight events, meetings, webinars etc that are planned around Cadence. The calendar will soon be available on the [Cadence website](https://cadenceworkflow.io/) so please make sure that you check it regularly.\\nThis means that you can easily find out if there are any Cadence events planned that you would like to attend.\\n\\n## Cadence Technical Office Hours\\n\\nOur second Technical Office Hours event took place on February 28th, Monday at 9AM PST. The main objective was provide Cadence support, respond to any questions about and to share any knowledge that you have learned. We always encourage community members to come along - and thanks very much to everyone who participated.\\n\\n## Cadence in the News!\\n\\nBelow are a selection of Cadence related articles, blogs and whitepapers. Please take a look and feel free to share via your own social media channels.\\n\\n- [Spinning Apache Kafka\xae Microservices With Cadence Workflows](https://www.instaclustr.com/blog/spinning-apache-kafka-microservices-with-cadence-workflows/)\\n\\n## Upcoming Events\\n\\n- [Webinar : What is Cadence? And is it right for you? (APAC)](https://info.instaclustr.com/webinar-apac-what-is-cadence.html)\\n\\nIf you have any news or topics you\'d like us to include in our next update then please join our [Slack](http://t.uber.com/cadence-slack)#community channel.\\n\\nPlease remember that this update is for you - so if you have any comments or feedback that could help us improve it then please share it with us in the #community [Slack](http://t.uber.com/cadence-slack) channel."},{"id":"/2022/01/31/community-spotlight-january-2022","metadata":{"permalink":"/blog/2022/01/31/community-spotlight-january-2022","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2022-01-31-community-spotlight-january-2022.md","source":"@site/blog/2022-01-31-community-spotlight-january-2022.md","title":"Cadence Community Spotlight Update - January 2022","description":"Welcome to our very first Cadence Community Spotlight update!","date":"2022-01-31T00:00:00.000Z","tags":[{"inline":false,"label":"Community Spotlight","permalink":"/blog/tags/community-spotlights","description":"Community Spotlight tag description"},{"inline":false,"label":"Roadmap","permalink":"/blog/tags/roadmap","description":"Roadmap tag description"}],"readingTime":2.04,"hasTruncateMarker":true,"authors":[{"name":"Sharan Foga","title":"Director of Operations & Customer Success @ Encube Technologies","url":"https://www.linkedin.com/in/sfoga/","page":{"permalink":"/blog/authors/sharanf"},"socials":{"linkedin":"https://www.linkedin.com/in/sfoga/","github":"https://github.com/sharanf"},"imageURL":"https://github.com/sharanf.png","key":"sharanf"}],"frontMatter":{"title":"Cadence Community Spotlight Update - January 2022","date":"2022-01-31T00:00:00.000Z","authors":"sharanf","tags":["community-spotlight","roadmap"]},"unlisted":false,"prevItem":{"title":"Cadence Community Spotlight Update - February 2022","permalink":"/blog/2022/02/28/community-spotlight-february-2022"},"nextItem":{"title":"Moving to gRPC","permalink":"/blog/2021/10/19/2021-10-19-moving-to-grpc/moving-to-grpc"}},"content":"Welcome to our very first Cadence Community Spotlight update!\\n\\nThis monthly update focuses on news from the wider Cadence community and is all about what you have been doing with Cadence. Do you have an interesting project that uses Cadence? If so then we want to hear from you. Also if you have any news items, blogs, articles, videos or events where Cadence has been mentioned then that is good too. We want to showcase that our community is active and is doing exciting and interesting things.\\n\\nPlease see below for a short round up of things that have happened recently in the community.\\n\\n\x3c!-- truncate --\x3e\\n\\n## Community Related Office Hours\\n\\nOn the 12th January 2022 we held our first Cadence Community Related Office Hours. This session was focused on discussing how we plan and organise things for the community. This includes things such as Code of Conduct, managing social media and making sure we regularly communicate project news and events.\\n\\nAnd you can see that this monthly update is the result of the feedback from that session! We are happy to get any feedback for comments you may have. Please remember that this update is for you so getting your feedback will help us improve it.\\n\\nWe will be planning other Community Related Office Hour sessions so please watch out for updates.\\n\\n## Adopting a Cadence Community Code of Conduct\\n\\nSome of you may already know that our community has adopted this version of the [Contributor Covenant](https://github.com/uber/.github/blob/dcd96c52f2d1d839208315a2572cf37f48e52e96/CODE_OF_CONDUCT.md) as our Code of Conduct. We want our community to be an open, welcoming and supportive place where everyone can collaborate.\\n\\n## Recording from Cadence Meetup Available\\n\\nPlease don\'t worry if you missed our online [November Cadence meetup](https://www.meetup.com/UberEvents/events/281975343/) because the recording is now available. You can find out more details about the meetup and get access to recordings [here](https://www.youtube.com/watch?v=pXgCd1BilLQ)\\n\\n## Cadence in the News!\\n\\nBelow are a selection of Cadence related articles, blogs and whitepapers. Please take a look and feel free to share via your own social media channels.\\n\\n- [Meet Cadence: Workflow Engine for Taming Complex Processes](https://thenewstack.io/meet-cadence-workflow-engine-for-taming-complex-processes/)\\n- [Spinning Your Workflows with Cadence](https://www.instaclustr.com/blog/spinning-your-workflows-with-cadence/)\\n- [Instaclustr Joins the Engineering Team at Uber in Supporting Cadence, the Powerful Open Source Orchestration Engine](https://www.globenewswire.com/news-release/2021/12/07/2347314/0/en/Instaclustr-Joins-the-Engineering-Team-at-Uber-in-Supporting-Cadence-the-Powerful-Open-Source-Orchestration-Engine.html)\\n\\n## Upcoming Events\\n\\n- [Webinar : What is Cadence? And is it right for you?](https://info.instaclustr.com/webinar-emea-what-is-cadence.html?_ga=2.191041518.510582234.1643223308-2138855655.1638190316)\\n\\nIf you have any news or topics you\'d like us to include in our next update then please join our [slack](http://t.uber.com/cadence-slack)#community channel."},{"id":"/2021/10/19/2021-10-19-moving-to-grpc/moving-to-grpc","metadata":{"permalink":"/blog/2021/10/19/2021-10-19-moving-to-grpc/moving-to-grpc","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2021-10-19-moving-to-grpc/2021-10-19-moving-to-grpc.md","source":"@site/blog/2021-10-19-moving-to-grpc/2021-10-19-moving-to-grpc.md","title":"Moving to gRPC","description":"Background","date":"2021-10-19T00:00:00.000Z","tags":[{"inline":false,"label":"Deep Dives","permalink":"/blog/tags/deep-dives","description":"Deep Dives tag description"},{"inline":false,"label":"Cadence Operations","permalink":"/blog/tags/cadence-operations","description":"Cadence Operations tag description"}],"readingTime":4.795,"hasTruncateMarker":true,"authors":[{"name":"Vytautas Karpavicius","title":"Software Engineer @ Uber","url":"https://www.linkedin.com/in/vytautas-karpavicius","page":{"permalink":"/blog/authors/vytautas-karpavicius"},"socials":{"linkedin":"https://www.linkedin.com/in/vytautas-karpavicius","github":"https://github.com/vytautas-karpavicius"},"imageURL":"https://github.com/vytautas-karpavicius.png","key":"vytautas-karpavicius"}],"frontMatter":{"title":"Moving to gRPC","date":"2021-10-19T00:00:00.000Z","authors":"vytautas-karpavicius","tags":["deep-dive","cadence-operations"]},"unlisted":false,"prevItem":{"title":"Cadence Community Spotlight Update - January 2022","permalink":"/blog/2022/01/31/community-spotlight-january-2022"},"nextItem":{"title":"Announcing Cadence OSS office hours and community sync up","permalink":"/blog/2021/10/13/announcing-cadence-oss-office-hours-and-community-sync-up"}},"content":"## Background\\nCadence historically has been using TChannel transport with Thrift encoding for both internal RPC calls and communication with client SDKs. gRPC is becoming a de-facto industry standard with much better adoption and community support. It offers features such as authentication and streaming that are very relevant for Cadence. Moreover, TChannel is being deprecated within Uber itself, pushing an effort for this migration. During the last year we\u2019ve implemented multiple changes in server and SDK that allows users to use gRPC in Cadence, as well as to upgrade their existing Cadence cluster in a backward compatible way. This post tracks the completed work items and our future plans.\\n\\n## Our Approach\\nWith ~500 services using Cadence at Uber and many more open source customers around the world, we had to think about the gRPC transition in a backwards compatible way. We couldn\u2019t simply flip transport and encoding everywhere. Instead we needed to support both protocols as an intermediate step to ensure a smooth transition for our users.\\n\\nCadence was using Thrift/TChannel not just for the API with client SDKs. They were also used for RPC calls between internal Cadence server components and also between different data centers. When starting this migration we had a choice of either starting with public APIs first or all the internal things within the server. We chose the latter one, so that we could gain experience and iterate faster within the server without disruption to the clients. With server side done and listening for both protocols, dynamic config flag was exposed to switch traffic internally. It allowed gradual deployment and provided an option to rollback if needed.\\n\\n\x3c!-- truncate --\x3e\\n\\nThe next step - client migration. We have more users for the Go SDK at Uber, that is why we started with it. Current version of SDK exposes Thrift types via public API, therefore we can not remove them without breaking changes. While we have plans for revamped v2 SDK, current users are able to use gRPC as well - with the help of a [translation adapter](https://github.com/cadence-workflow/cadence-go-client/blob/v0.18.2/compatibility/thrift2proto.go). Migration is underway starting with [cadence canary service](https://github.com/cadence-workflow/cadence/tree/master/canary), and then onboarding user services one by one.\\n\\nWe plan to support TChannel for a few more releases and then eventually drop it in a future.\\n\\n## System overview\\n![gRPC migration overview](./grpc-migration.svg)\\n\\n1. The frontend of [Cadence Server](https://github.com/cadence-workflow/cadence) exposes two inbounds for both gRPC and TChannel starting [v0.21.0 release](https://github.com/cadence-workflow/cadence/releases/tag/v0.21.0). gRPC traffic is being served on a different port that can be configured [here](https://github.com/cadence-workflow/cadence/blob/v0.21.0/config/development.yaml#L25). For gRPC API we introduced [proto IDL](https://github.com/cadence-workflow/cadence-idl/tree/master/proto/cadence-workflow/cadence/api/v1) definitions. We will keep TChannel open on frontend for some time to allow gradual client migration.\\n2. Starting with [v0.21.0](https://github.com/cadence-workflow/cadence/releases/tag/v0.21.0) internal components of Cadence Server (history & matching) also started accepting gRPC traffic. Sending traffic via gRPC is off by default and could be enabled with a flag in [dynamic config](https://github.com/cadence-workflow/cadence/blob/v0.21.0/config/dynamicconfig/development.yaml#L10). Planned for v0.24.0 it will be enabled by default, with an option to opt-out.\\n3. Starting with v0.23.0 communication between different Cadence clusters can be switched to gRPC via this [configuration](https://github.com/cadence-workflow/cadence/blob/0.23.x/config/development_active.yaml#L82). It is used for replication and request redirection to different DC.\\n4. [Go SDK](https://github.com/cadence-workflow/cadence-go-client) has exposed generated Thrift types via its public API. This complicated migration, because switching them to proto types (or rpc agnostic types) means breaking changes. Because of this we are pursuing two alternatives:\\n 1. (A) Short term: starting with [v0.18.2](https://github.com/cadence-workflow/cadence-go-client/releases/tag/v0.18.2) a [compatibility layer](https://github.com/cadence-workflow/cadence-go-client/blob/v0.18.2/compatibility/thrift2proto.go) is available which makes translation between thrift-proto types underneath. It allows using gRPC communication while still using Thrift based API. [Usage example](https://github.com/cadence-workflow/cadence-samples/pull/52).\\n 2. (B) Long term: we are currently designing v2 SDK that will support gRPC directly. Its API will be RPC agnostic and will include other usability improvements. You can check some ideas that are being considered [here](https://github.com/cadence-workflow/cadence-go-client/issues/1133).\\n5. [Java SDK](https://github.com/cadence-workflow/cadence-java-client) is currently on TChannel only. Move to gRPC is planned for 2022 H1.\\n6. It is now possible to communicate with gRPC from other languages as well. Use [proto IDLs](https://github.com/cadence-workflow/cadence-idl/tree/master/proto/cadence-workflow/cadence/api/v1) to generate bindings for your preferred language. [Minimal example](https://github.com/vytautas-karpavicius/cadence-python) for doing it in python.\\n7. WebUI and CLI are currently on TChannel. They are planned to be switched to gRPC for 2022 H1.\\n\\n## Migration steps\\n### Upgrading Cadence server\\nIn order to start using gRPC please upgrade Cadence server to **[v0.22.0](https://github.com/cadence-workflow/cadence/releases/tag/v0.22.0) or later**.\\n1. If you are using an older version (before v0.21.0), make sure to disable internal gRPC communication at first. Needed to ensure that all nodes in the cluster are ready to accept gRPC traffic, before switching it on. This is controlled by the [system.enableGRPCOutbound](https://github.com/cadence-workflow/cadence/blob/v0.21.0/config/dynamicconfig/development.yaml#L10) flag in dynamic config.\\n2. Once deployed, flip system.enableGRPCOutbound to true. It will require a cluster restart for setting to take effect.\\n3. If you are operating in more than one DC - recommended server version to upgrade to is v0.23.0 or newer. Once individual clusters with gRPC support are deployed, please update [config](https://github.com/cadence-workflow/cadence/blob/0.23.x/config/development_active.yaml#L82) to switch cross DC traffic to gRPC. Don\u2019t forget to update ports as well. We also recommend increasing [grpcMaxMsgSize](https://github.com/cadence-workflow/cadence/blob/0.23.x/config/development.yaml#L29) to 32MB which is needed to ensure smooth replication. After config change you will need a restart for setting to take effect.\\n4. Do not forget that gRPC runs on a different port, therefore you might need to open it on docker containers, firewalls, etc.\\n\\n### Upgrading clients\\n1. GoSDK - Follow an [example](https://github.com/cadence-workflow/cadence-samples/pull/52) to inject Thrift-to-proto adapter during client initialization and update your config to use the gRPC port.\\n\\n### Status at Uber\\n* All clusters run gRPC traffic internally for 4 months without any issues.\\n* Cross DC traffic has been switched to gRPC this month.\\n* With internal tooling updated, we are starting to onboard services to use the Go SDK gRPC compatibility layer.\\n\\n---\\nDo not hesitate to reach out to us ([cadence-oss@googlegroups.com](mailto:cadence-oss@googlegroups.com)\xa0or\xa0[slack](http://t.uber.com/cadence-slack)) if you have any questions.\\n\\nThe Uber Cadence team"},{"id":"/2021/10/13/announcing-cadence-oss-office-hours-and-community-sync-up","metadata":{"permalink":"/blog/2021/10/13/announcing-cadence-oss-office-hours-and-community-sync-up","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2021-10-13-announcing-cadence-oss-office-hours-and-community-sync-up.md","source":"@site/blog/2021-10-13-announcing-cadence-oss-office-hours-and-community-sync-up.md","title":"Announcing Cadence OSS office hours and community sync up","description":"Are you a current Cadence user, do you operate Cadence services, or are you interested in learning about workflow technologies and wonder what problems Cadence could solve for you? We would like to talk to you!","date":"2021-10-13T00:00:00.000Z","tags":[{"inline":false,"label":"Announcement","permalink":"/blog/tags/announcements","description":"Announcement tag description"},{"inline":false,"label":"Roadmap","permalink":"/blog/tags/roadmap","description":"Roadmap tag description"}],"readingTime":1.83,"hasTruncateMarker":true,"authors":[{"name":"Liang Mei","title":"Engineering Manager @ Uber","url":"https://www.linkedin.com/in/meiliang86/","page":{"permalink":"/blog/authors/meiliang-86"},"socials":{"linkedin":"https://www.linkedin.com/in/meiliang86/","github":"https://github.com/meiliang86"},"imageURL":"https://github.com/meiliang86.png","key":"meiliang86"}],"frontMatter":{"title":"Announcing Cadence OSS office hours and community sync up","date":"2021-10-13T00:00:00.000Z","authors":"meiliang86","tags":["announcement","roadmap"]},"unlisted":false,"prevItem":{"title":"Moving to gRPC","permalink":"/blog/2021/10/19/2021-10-19-moving-to-grpc/moving-to-grpc"},"nextItem":{"title":"Long-term commitment and support for the Cadence project, and its community","permalink":"/blog/2021/09/30/long-term-commitment-and-support-for-the-cadence-project-and-its-community"}},"content":"Are you a current Cadence user, do you operate Cadence services, or are you interested in learning about workflow technologies and wonder what problems Cadence could solve for you? We would like to talk to you!\\n\\n\\nOur team has spent a significant amount of time working with users and partner teams at Uber to design, scale and operate their workflows. This helps our users understand the technology better, smooth their learning curve and ramp up experience, and at the same time allows us to get fast and direct feedback so we can improve the developer experience and close feature gaps. As our product and community grows, we would like to expand this practice to our users in the OSS community. **For the first time ever, members of the Cadence team along with core contributors from the community will host bi-weekly office hours to answer any questions you have about Cadence, or workflow technology in general.** We can also dedicate future sessions to specific topics that have a common interest. Please don\u2019t hesitate to let us know your thoughts.\\n\\n\\nPlease join a session if you would like to talk about any of the following topics:\\n<ol>\\n<li>Understand what Cadence is and why it might be useful for you and your company</li>\\n<li>Guidance about running Cadence services and workers in production</li>\\n<li>Workflow design and operation consultation</li>\\n<li>Product update, future roadmaps as well as collaboration opportunities</li>\\n</ol>\\n\\n\\nBuilding and maintaining a healthy and growing community is the key to the success of Cadence, and one of the top priorities for our team. We would like to use the office hours as an opportunity to understand and help our customers, seek feedback, and forge partnerships. We look forward to seeing you in one of the meetings.\\n\\n\\n**Upcoming Office Hours**\\n\\n\\nAs we have a geo-distributed userbase, we are still trying to figure out a time that works for most of the people. In the meanwhile, we will manually schedule the first few instances of the meeting until we settle on a fixed schedule. Our next office hours will take place on **Thursday, October 21 2pm-3pm PT/5pm-6pm EST/9pm-10pm GMT**. Please join via [this zoom link](https://uber.zoom.us/j/92356466350?pwd=RFVTc2pwV0xoVTdlK3VxN3N2eU5UZz09).\\n\\n\x3c!-- truncate --\x3e\\n\\nThe Uber Cadence team"},{"id":"/2021/09/30/long-term-commitment-and-support-for-the-cadence-project-and-its-community","metadata":{"permalink":"/blog/2021/09/30/long-term-commitment-and-support-for-the-cadence-project-and-its-community","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2021-09-30-long-term-commitment-and-support-for-the-cadence-project-and-its-community.md","source":"@site/blog/2021-09-30-long-term-commitment-and-support-for-the-cadence-project-and-its-community.md","title":"Long-term commitment and support for the Cadence project, and its community","description":"Dear valued Cadence users and developers,","date":"2021-09-30T00:00:00.000Z","tags":[{"inline":false,"label":"Announcement","permalink":"/blog/tags/announcements","description":"Announcement tag description"}],"readingTime":2.545,"hasTruncateMarker":true,"authors":[{"name":"Liang Mei","title":"Engineering Manager @ Uber","url":"https://www.linkedin.com/in/meiliang86/","page":{"permalink":"/blog/authors/meiliang-86"},"socials":{"linkedin":"https://www.linkedin.com/in/meiliang86/","github":"https://github.com/meiliang86"},"imageURL":"https://github.com/meiliang86.png","key":"meiliang86"}],"frontMatter":{"title":"Long-term commitment and support for the Cadence project, and its community","date":"2021-09-30T00:00:00.000Z","authors":"meiliang86","tags":["announcement"]},"unlisted":false,"prevItem":{"title":"Announcing Cadence OSS office hours and community sync up","permalink":"/blog/2021/10/13/announcing-cadence-oss-office-hours-and-community-sync-up"}},"content":"Dear valued Cadence users and developers,\\n\\n\\nSome of you might have read Temporal\u2019s recent announcement about their decision to drop the support for the Cadence project. This message caused some confusion in the community, so we would like to take this opportunity to clear things out.\\n\\n\\nFirst of all, **Uber is committed to the long-term success of the Cadence project**. Since its inception 5 years ago, use cases built on Cadence and their scale have grown significantly at Uber. Today, Cadence powers a variety of our most business-critical use cases (some public stories are available [here](https://eng.uber.com/hadoop-container-blog/) and [here](https://eng.uber.com/meet-sao-paulo-tech/)). At the same time, the Cadence development team at Uber has enjoyed rapid growth with the product and has been driving innovations of workflow technology across the board, from new features (e.g. [graceful failover](https://github.com/cadence-workflow/cadence/pulls?q=is%3Apr+graceful+failover), [workflow shadowing](https://cadenceworkflow.io/docs/java-client/workflow-replay-shadowing/#workflow-replayer), [UI improvements](https://github.com/cadence-workflow/cadence-web/commits/master)) to better engineering foundations (e.g. [gRPC support](https://github.com/cadence-workflow/cadence/pulls?q=is%3Apr+grpc), [multi-tenancy support](https://github.com/cadence-workflow/cadence/pulls?q=is%3Apr+label%3A%22cadence+multi-tenancy%22+)), all in a backwards compatible manner. Neither Uber\u2019s use nor support of Cadence is going to change with Temporal\u2019s announcement. We have a long list of features and exciting roadmaps ahead of us, and we will share more details in our next meetup in November \u201821. As always we will continue to push the boundaries of scale and reliability as our usage within Uber grows.\\n\\n\x3c!-- truncate --\x3e\\n\\nSecondly, **we are committed to maintaining and growing a healthy and collaborative community**. Cadence continues to attract attention as a [popular open source platform](https://star-history.t9t.io/#cadence-workflow/cadence), with more than 100 contributors to our project, and more than 1500 developers in our [open source Slack support channel](https://t.uber.com/cadence-slack). The Uber Cadence team, along with our open source partners like [Long](https://www.linkedin.com/in/prclqz/) from Indeed, have been behind the management and support of the Cadence open source community for the past 2 years. Moving forward, we are going to work even more closely with our community, through a series of online and offline channels including meetups, office hours, tech deep dives, and design consultations. We would also like to scale the way we operate, by creating a **Cadence OSS Committee** that allows us to maintain a closer relationship with its members, so that we can learn from each other\'s Cadence experiences and grow together. Please definitely let us know your suggestions on the type of engagements that you would like to see with the core team.\\n\\n\\n**About Temporal and its \u201cEOL announcement\u201d**\\n\\nTemporal is a startup that was started 2 years ago based on a Cadence fork by some of the original Cadence team members. We are always grateful for their original contribution to the Cadence project and wish them the best of luck in their future endeavours. That said the announcement from Temporal only means that their team will focus on Temporal (which has always been the case for the last 2 years), and not an official stance on Cadence since they have not been involved with the project for quite some time now.\\n\\n\\nFeel free to reach out to us ([cadence-oss@googlegroups.com](mailto:cadence-oss@googlegroups.com) or [slack](http://t.uber.com/cadence-slack)) if you have any questions. And we look forward to your contribution and collaboration.\\n\\n\\nThe Uber Cadence team"}]}}')}}]); \ No newline at end of file diff --git a/assets/js/f81e7c5e.77858357.js b/assets/js/f81e7c5e.77858357.js new file mode 100644 index 000000000..3b651fdb3 --- /dev/null +++ b/assets/js/f81e7c5e.77858357.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[5351],{9540:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>c,contentTitle:()=>l,default:()=>d,frontMatter:()=>r,metadata:()=>i,toc:()=>a});const i=JSON.parse('{"id":"go-client/workflow-testing","title":"Testing","description":"The Cadence Go client library provides a test framework to facilitate testing implementations.","source":"@site/docs/05-go-client/13-workflow-testing.md","sourceDirName":"05-go-client","slug":"/go-client/workflow-testing","permalink":"/Cadence-Docs/docs/go-client/workflow-testing","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/05-go-client/13-workflow-testing.md","tags":[],"version":"current","sidebarPosition":13,"frontMatter":{"layout":"default","title":"Testing","permalink":"/docs/go-client/workflow-testing"},"sidebar":"docsSidebar","previous":{"title":"Async activity completion","permalink":"/Cadence-Docs/docs/go-client/activity-async-completion"},"next":{"title":"Versioning","permalink":"/Cadence-Docs/docs/go-client/workflow-versioning"}}');var s=n(4848),o=n(8453);const r={layout:"default",title:"Testing",permalink:"/docs/go-client/workflow-testing"},l="Testing",c={},a=[{value:"Setup",id:"setup",level:2},{value:"A Simple Test",id:"a-simple-test",level:2},{value:"Activity mocking and overriding",id:"activity-mocking-and-overriding",level:2},{value:"Testing signals",id:"testing-signals",level:2}];function u(e){const t={a:"a",blockquote:"blockquote",code:"code",em:"em",h1:"h1",h2:"h2",header:"header",p:"p",pre:"pre",...(0,o.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(t.header,{children:(0,s.jsx)(t.h1,{id:"testing",children:"Testing"})}),"\n",(0,s.jsx)(t.p,{children:"The Cadence Go client library provides a test framework to facilitate testing workflow implementations.\nThe framework is suited for implementing unit tests as well as functional tests of the workflow logic."}),"\n",(0,s.jsxs)(t.p,{children:["The following code implements unit tests for the ",(0,s.jsx)(t.code,{children:"SimpleWorkflow"})," sample:"]}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-go",children:'package sample\n\nimport (\n "errors"\n "testing"\n\n "github.com/stretchr/testify/mock"\n "github.com/stretchr/testify/suite"\n\n "go.uber.org/cadence"\n "go.uber.org/cadence/testsuite"\n)\n\ntype UnitTestSuite struct {\n suite.Suite\n testsuite.WorkflowTestSuite\n\n env *testsuite.TestWorkflowEnvironment\n}\n\nfunc (s *UnitTestSuite) SetupTest() {\n s.env = s.NewTestWorkflowEnvironment()\n}\n\nfunc (s *UnitTestSuite) AfterTest(suiteName, testName string) {\n s.env.AssertExpectations(s.T())\n}\n\nfunc (s *UnitTestSuite) Test_SimpleWorkflow_Success() {\n s.env.ExecuteWorkflow(SimpleWorkflow, "test_success")\n\n s.True(s.env.IsWorkflowCompleted())\n s.NoError(s.env.GetWorkflowError())\n}\n\nfunc (s *UnitTestSuite) Test_SimpleWorkflow_ActivityParamCorrect() {\n s.env.OnActivity(SimpleActivity, mock.Anything, mock.Anything).Return(\n func(ctx context.Context, value string) (string, error) {\n s.Equal("test_success", value)\n return value, nil\n }\n )\n s.env.ExecuteWorkflow(SimpleWorkflow, "test_success")\n\n s.True(s.env.IsWorkflowCompleted())\n s.NoError(s.env.GetWorkflowError())\n}\n\nfunc (s *UnitTestSuite) Test_SimpleWorkflow_ActivityFails() {\n s.env.OnActivity(SimpleActivity, mock.Anything, mock.Anything).Return(\n "", errors.New("SimpleActivityFailure"))\n s.env.ExecuteWorkflow(SimpleWorkflow, "test_failure")\n\n s.True(s.env.IsWorkflowCompleted())\n\n s.NotNil(s.env.GetWorkflowError())\n s.True(cadence.IsGenericError(s.env.GetWorkflowError()))\n s.Equal("SimpleActivityFailure", s.env.GetWorkflowError().Error())\n}\n\nfunc TestUnitTestSuite(t *testing.T) {\n suite.Run(t, new(UnitTestSuite))\n}\n'})}),"\n",(0,s.jsx)(t.h2,{id:"setup",children:"Setup"}),"\n",(0,s.jsxs)(t.p,{children:['To run unit tests, we first define a "test suite" struct that absorbs both the\nbasic suite functionality from ',(0,s.jsx)(t.a,{href:"https://godoc.org/github.com/stretchr/testify/suite",children:"testify"}),"\nvia ",(0,s.jsx)(t.code,{children:"suite.Suite"})," and the suite functionality from the Cadence test framework via\n",(0,s.jsx)(t.code,{children:"cadence.WorkflowTestSuite"}),". Because every test in this test suite will test our workflow, we\nadd a property to our struct to hold an instance of the test environment. This allows us to initialize\nthe test environment in a setup method. For testing workflows, we use a ",(0,s.jsx)(t.code,{children:"cadence.TestWorkflowEnvironment"}),"."]}),"\n",(0,s.jsxs)(t.p,{children:["Next, we implement a ",(0,s.jsx)(t.code,{children:"SetupTest"})," method to setup a new test environment before each test. Doing so\nensures that each test runs in its own isolated sandbox. We also implement an ",(0,s.jsx)(t.code,{children:"AfterTest"})," function\nwhere we assert that all mocks we set up were indeed called by invoking ",(0,s.jsx)(t.code,{children:"s.env.AssertExpectations(s.T())"}),"."]}),"\n",(0,s.jsxs)(t.p,{children:['Finally, we create a regular test function recognized by "go test" and pass the struct to ',(0,s.jsx)(t.code,{children:"suite.Run"}),"."]}),"\n",(0,s.jsx)(t.h2,{id:"a-simple-test",children:"A Simple Test"}),"\n",(0,s.jsx)(t.p,{children:"The most simple test case we can write is to have the test environment execute the workflow and then\nevaluate the results."}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-go",children:'func (s *UnitTestSuite) Test_SimpleWorkflow_Success() {\n s.env.ExecuteWorkflow(SimpleWorkflow, "test_success")\n\n s.True(s.env.IsWorkflowCompleted())\n s.NoError(s.env.GetWorkflowError())\n}\n'})}),"\n",(0,s.jsxs)(t.p,{children:["Calling ",(0,s.jsx)(t.code,{children:"s.env.ExecuteWorkflow(...)"})," executes the workflow logic and any invoked activities inside the\ntest process. The first parameter of ",(0,s.jsx)(t.code,{children:"s.env.ExecuteWorkflow(...)"})," contains the workflow functions,\nand any subsequent parameters contain values for custom input parameters declared by the workflow\nfunction."]}),"\n",(0,s.jsxs)(t.blockquote,{children:["\n",(0,s.jsxs)(t.p,{children:["Note that unless the activity invocations are mocked or activity implementation\nreplaced (see ",(0,s.jsx)(t.a,{href:"#activity-mocking-and-overriding",children:"Activity mocking and overriding"}),"), the test environment\nwill execute the actual activity code including any calls to outside services."]}),"\n"]}),"\n",(0,s.jsxs)(t.p,{children:["After executing the workflow in the above example, we assert that the workflow ran through completion\nvia the call to ",(0,s.jsx)(t.code,{children:"s.env.IsWorkflowComplete()"}),". We also assert that no errors were returned by asserting\non the return value of ",(0,s.jsx)(t.code,{children:"s.env.GetWorkflowError()"}),". If our workflow returned a value, we could have\nretrieved that value via a call to ",(0,s.jsx)(t.code,{children:"s.env.GetWorkflowResult(&value)"})," and had additional asserts on that\nvalue."]}),"\n",(0,s.jsx)(t.h2,{id:"activity-mocking-and-overriding",children:"Activity mocking and overriding"}),"\n",(0,s.jsx)(t.p,{children:"When running unit tests on workflows, we want to test the workflow logic in isolation. Additionally,\nwe want to inject activity errors during our test runs. The test framework provides two mechanisms\nthat support these scenarios: activity mocking and activity overriding. Both of these mechanisms allow\nyou to change the behavior of activities invoked by your workflow without the need to modify the actual\nworkflow code."}),"\n",(0,s.jsx)(t.p,{children:'Let\'s take a look at a test that simulates a test that fails via the "activity mocking" mechanism.'}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-go",children:'func (s *UnitTestSuite) Test_SimpleWorkflow_ActivityFails() {\n s.env.OnActivity(SimpleActivity, mock.Anything, mock.Anything).Return(\n "", errors.New("SimpleActivityFailure"))\n s.env.ExecuteWorkflow(SimpleWorkflow, "test_failure")\n\n s.True(s.env.IsWorkflowCompleted())\n\n s.NotNil(s.env.GetWorkflowError())\n _, ok := s.env.GetWorkflowError().(*cadence.GenericError)\n s.True(ok)\n s.Equal("SimpleActivityFailure", s.env.GetWorkflowError().Error())\n}\n'})}),"\n",(0,s.jsxs)(t.p,{children:["This test simulates the execution of the activity ",(0,s.jsx)(t.code,{children:"SimpleActivity"})," that is invoked by our workflow\n",(0,s.jsx)(t.code,{children:"SimpleWorkflow"})," returning an error. We accomplish this by setting up a mock on the test environment\nfor the ",(0,s.jsx)(t.code,{children:"SimpleActivity"})," that returns an error."]}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-go",children:'s.env.OnActivity(SimpleActivity, mock.Anything, mock.Anything).Return(\n "", errors.New("SimpleActivityFailure"))\n'})}),"\n",(0,s.jsx)(t.p,{children:"With the mock set up we can now execute the workflow via the s.env.ExecuteWorkflow(...) method and\nassert that the workflow completed successfully and returned the expected error."}),"\n",(0,s.jsx)(t.p,{children:"Simply mocking the execution to return a desired value or error is a pretty powerful mechanism to\nisolate workflow logic. However, sometimes we want to replace the activity with an alternate implementation\nto support a more complex test scenario. Let's assume we want to validate that the activity gets called\nwith the correct parameters."}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-go",children:'func (s *UnitTestSuite) Test_SimpleWorkflow_ActivityParamCorrect() {\n s.env.OnActivity(SimpleActivity, mock.Anything, mock.Anything).Return(\n func(ctx context.Context, value string) (string, error) {\n s.Equal("test_success", value)\n return value, nil\n }\n )\n s.env.ExecuteWorkflow(SimpleWorkflow, "test_success")\n\n s.True(s.env.IsWorkflowCompleted())\n s.NoError(s.env.GetWorkflowError())\n}\n'})}),"\n",(0,s.jsxs)(t.p,{children:["In this example, we provide a function implementation as the parameter to ",(0,s.jsx)(t.code,{children:"Return"}),". This allows us to\nprovide an alternate implementation for the activity ",(0,s.jsx)(t.code,{children:"SimpleActivity"}),". The framework will execute this\nfunction whenever the activity is invoked and pass on the return value from the function as the result\nof the activity invocation. Additionally, the framework will validate that the signature of the \u201cmock\u201d\nfunction matches the signature of the original activity function."]}),"\n",(0,s.jsx)(t.p,{children:"Since this can be an entire function, there is no limitation as to what we can do here. In this\nexample, we assert that the \u201cvalue\u201d param has the same content as the value param we passed to the workflow."}),"\n",(0,s.jsx)(t.h2,{id:"testing-signals",children:"Testing signals"}),"\n",(0,s.jsxs)(t.p,{children:["To test signals we can use the functions ",(0,s.jsx)(t.code,{children:"s.env.SignalWorkflow"}),", and ",(0,s.jsx)(t.code,{children:"s.env.SignalWorkflowByID"}),". These\nfunctions needs to be called inside ",(0,s.jsx)(t.code,{children:"s.env.RegisterDelayedCallback"}),", as the signal should be send while the\nworkflow is running. It is important to register the signal before calling ",(0,s.jsx)(t.code,{children:"s.env.ExecuteWorkflow"}),", otherwise\nthe signal will not be send."]}),"\n",(0,s.jsxs)(t.p,{children:["If our workflow is waiting for a signal with name ",(0,s.jsx)(t.code,{children:"signalName"})," we can register\nto send this signal ",(0,s.jsx)(t.em,{children:"before"})," the workflow is executed like this:"]}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-go",children:'func (s *UnitTestSuite) Test_SimpleWorkflow_Signal() {\n // Send the signal\n\ts.env.RegisterDelayedCallback(func() {\n\t\ts.env.SignalWorkflow(signalName, signalData)\n\t}, time.Minute*10)\n\n // Execute the workflow\n s.env.ExecuteWorkflow(SimpleWorkflow, "test_success")\n\n s.True(s.env.IsWorkflowCompleted())\n s.NoError(s.env.GetWorkflowError())\n}\n'})}),"\n",(0,s.jsxs)(t.p,{children:["Note that the ",(0,s.jsx)(t.code,{children:"s.env.RegisterDelayedCallback"})," function does not actually wait 10 minutes in the unit test\ninstead the cadence test framework uses an internal clock which knows which event is the next, and executes it\nimmediately."]})]})}function d(e={}){const{wrapper:t}={...(0,o.R)(),...e.components};return t?(0,s.jsx)(t,{...e,children:(0,s.jsx)(u,{...e})}):u(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>r,x:()=>l});var i=n(6540);const s={},o=i.createContext(s);function r(e){const t=i.useContext(o);return i.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function l(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:r(e.components),i.createElement(o.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/f81e7c5e.a97005a8.js b/assets/js/f81e7c5e.a97005a8.js deleted file mode 100644 index e27f9af85..000000000 --- a/assets/js/f81e7c5e.a97005a8.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[5351],{9540:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>c,contentTitle:()=>l,default:()=>d,frontMatter:()=>r,metadata:()=>i,toc:()=>a});const i=JSON.parse('{"id":"go-client/workflow-testing","title":"Testing","description":"The Cadence Go client library provides a test framework to facilitate testing implementations.","source":"@site/docs/05-go-client/13-workflow-testing.md","sourceDirName":"05-go-client","slug":"/go-client/workflow-testing","permalink":"/docs/go-client/workflow-testing","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/05-go-client/13-workflow-testing.md","tags":[],"version":"current","sidebarPosition":13,"frontMatter":{"layout":"default","title":"Testing","permalink":"/docs/go-client/workflow-testing"},"sidebar":"docsSidebar","previous":{"title":"Async activity completion","permalink":"/docs/go-client/activity-async-completion"},"next":{"title":"Versioning","permalink":"/docs/go-client/workflow-versioning"}}');var s=n(4848),o=n(8453);const r={layout:"default",title:"Testing",permalink:"/docs/go-client/workflow-testing"},l="Testing",c={},a=[{value:"Setup",id:"setup",level:2},{value:"A Simple Test",id:"a-simple-test",level:2},{value:"Activity mocking and overriding",id:"activity-mocking-and-overriding",level:2},{value:"Testing signals",id:"testing-signals",level:2}];function u(e){const t={a:"a",blockquote:"blockquote",code:"code",em:"em",h1:"h1",h2:"h2",header:"header",p:"p",pre:"pre",...(0,o.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(t.header,{children:(0,s.jsx)(t.h1,{id:"testing",children:"Testing"})}),"\n",(0,s.jsx)(t.p,{children:"The Cadence Go client library provides a test framework to facilitate testing workflow implementations.\nThe framework is suited for implementing unit tests as well as functional tests of the workflow logic."}),"\n",(0,s.jsxs)(t.p,{children:["The following code implements unit tests for the ",(0,s.jsx)(t.code,{children:"SimpleWorkflow"})," sample:"]}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-go",children:'package sample\n\nimport (\n "errors"\n "testing"\n\n "github.com/stretchr/testify/mock"\n "github.com/stretchr/testify/suite"\n\n "go.uber.org/cadence"\n "go.uber.org/cadence/testsuite"\n)\n\ntype UnitTestSuite struct {\n suite.Suite\n testsuite.WorkflowTestSuite\n\n env *testsuite.TestWorkflowEnvironment\n}\n\nfunc (s *UnitTestSuite) SetupTest() {\n s.env = s.NewTestWorkflowEnvironment()\n}\n\nfunc (s *UnitTestSuite) AfterTest(suiteName, testName string) {\n s.env.AssertExpectations(s.T())\n}\n\nfunc (s *UnitTestSuite) Test_SimpleWorkflow_Success() {\n s.env.ExecuteWorkflow(SimpleWorkflow, "test_success")\n\n s.True(s.env.IsWorkflowCompleted())\n s.NoError(s.env.GetWorkflowError())\n}\n\nfunc (s *UnitTestSuite) Test_SimpleWorkflow_ActivityParamCorrect() {\n s.env.OnActivity(SimpleActivity, mock.Anything, mock.Anything).Return(\n func(ctx context.Context, value string) (string, error) {\n s.Equal("test_success", value)\n return value, nil\n }\n )\n s.env.ExecuteWorkflow(SimpleWorkflow, "test_success")\n\n s.True(s.env.IsWorkflowCompleted())\n s.NoError(s.env.GetWorkflowError())\n}\n\nfunc (s *UnitTestSuite) Test_SimpleWorkflow_ActivityFails() {\n s.env.OnActivity(SimpleActivity, mock.Anything, mock.Anything).Return(\n "", errors.New("SimpleActivityFailure"))\n s.env.ExecuteWorkflow(SimpleWorkflow, "test_failure")\n\n s.True(s.env.IsWorkflowCompleted())\n\n s.NotNil(s.env.GetWorkflowError())\n s.True(cadence.IsGenericError(s.env.GetWorkflowError()))\n s.Equal("SimpleActivityFailure", s.env.GetWorkflowError().Error())\n}\n\nfunc TestUnitTestSuite(t *testing.T) {\n suite.Run(t, new(UnitTestSuite))\n}\n'})}),"\n",(0,s.jsx)(t.h2,{id:"setup",children:"Setup"}),"\n",(0,s.jsxs)(t.p,{children:['To run unit tests, we first define a "test suite" struct that absorbs both the\nbasic suite functionality from ',(0,s.jsx)(t.a,{href:"https://godoc.org/github.com/stretchr/testify/suite",children:"testify"}),"\nvia ",(0,s.jsx)(t.code,{children:"suite.Suite"})," and the suite functionality from the Cadence test framework via\n",(0,s.jsx)(t.code,{children:"cadence.WorkflowTestSuite"}),". Because every test in this test suite will test our workflow, we\nadd a property to our struct to hold an instance of the test environment. This allows us to initialize\nthe test environment in a setup method. For testing workflows, we use a ",(0,s.jsx)(t.code,{children:"cadence.TestWorkflowEnvironment"}),"."]}),"\n",(0,s.jsxs)(t.p,{children:["Next, we implement a ",(0,s.jsx)(t.code,{children:"SetupTest"})," method to setup a new test environment before each test. Doing so\nensures that each test runs in its own isolated sandbox. We also implement an ",(0,s.jsx)(t.code,{children:"AfterTest"})," function\nwhere we assert that all mocks we set up were indeed called by invoking ",(0,s.jsx)(t.code,{children:"s.env.AssertExpectations(s.T())"}),"."]}),"\n",(0,s.jsxs)(t.p,{children:['Finally, we create a regular test function recognized by "go test" and pass the struct to ',(0,s.jsx)(t.code,{children:"suite.Run"}),"."]}),"\n",(0,s.jsx)(t.h2,{id:"a-simple-test",children:"A Simple Test"}),"\n",(0,s.jsx)(t.p,{children:"The most simple test case we can write is to have the test environment execute the workflow and then\nevaluate the results."}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-go",children:'func (s *UnitTestSuite) Test_SimpleWorkflow_Success() {\n s.env.ExecuteWorkflow(SimpleWorkflow, "test_success")\n\n s.True(s.env.IsWorkflowCompleted())\n s.NoError(s.env.GetWorkflowError())\n}\n'})}),"\n",(0,s.jsxs)(t.p,{children:["Calling ",(0,s.jsx)(t.code,{children:"s.env.ExecuteWorkflow(...)"})," executes the workflow logic and any invoked activities inside the\ntest process. The first parameter of ",(0,s.jsx)(t.code,{children:"s.env.ExecuteWorkflow(...)"})," contains the workflow functions,\nand any subsequent parameters contain values for custom input parameters declared by the workflow\nfunction."]}),"\n",(0,s.jsxs)(t.blockquote,{children:["\n",(0,s.jsxs)(t.p,{children:["Note that unless the activity invocations are mocked or activity implementation\nreplaced (see ",(0,s.jsx)(t.a,{href:"#activity-mocking-and-overriding",children:"Activity mocking and overriding"}),"), the test environment\nwill execute the actual activity code including any calls to outside services."]}),"\n"]}),"\n",(0,s.jsxs)(t.p,{children:["After executing the workflow in the above example, we assert that the workflow ran through completion\nvia the call to ",(0,s.jsx)(t.code,{children:"s.env.IsWorkflowComplete()"}),". We also assert that no errors were returned by asserting\non the return value of ",(0,s.jsx)(t.code,{children:"s.env.GetWorkflowError()"}),". If our workflow returned a value, we could have\nretrieved that value via a call to ",(0,s.jsx)(t.code,{children:"s.env.GetWorkflowResult(&value)"})," and had additional asserts on that\nvalue."]}),"\n",(0,s.jsx)(t.h2,{id:"activity-mocking-and-overriding",children:"Activity mocking and overriding"}),"\n",(0,s.jsx)(t.p,{children:"When running unit tests on workflows, we want to test the workflow logic in isolation. Additionally,\nwe want to inject activity errors during our test runs. The test framework provides two mechanisms\nthat support these scenarios: activity mocking and activity overriding. Both of these mechanisms allow\nyou to change the behavior of activities invoked by your workflow without the need to modify the actual\nworkflow code."}),"\n",(0,s.jsx)(t.p,{children:'Let\'s take a look at a test that simulates a test that fails via the "activity mocking" mechanism.'}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-go",children:'func (s *UnitTestSuite) Test_SimpleWorkflow_ActivityFails() {\n s.env.OnActivity(SimpleActivity, mock.Anything, mock.Anything).Return(\n "", errors.New("SimpleActivityFailure"))\n s.env.ExecuteWorkflow(SimpleWorkflow, "test_failure")\n\n s.True(s.env.IsWorkflowCompleted())\n\n s.NotNil(s.env.GetWorkflowError())\n _, ok := s.env.GetWorkflowError().(*cadence.GenericError)\n s.True(ok)\n s.Equal("SimpleActivityFailure", s.env.GetWorkflowError().Error())\n}\n'})}),"\n",(0,s.jsxs)(t.p,{children:["This test simulates the execution of the activity ",(0,s.jsx)(t.code,{children:"SimpleActivity"})," that is invoked by our workflow\n",(0,s.jsx)(t.code,{children:"SimpleWorkflow"})," returning an error. We accomplish this by setting up a mock on the test environment\nfor the ",(0,s.jsx)(t.code,{children:"SimpleActivity"})," that returns an error."]}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-go",children:'s.env.OnActivity(SimpleActivity, mock.Anything, mock.Anything).Return(\n "", errors.New("SimpleActivityFailure"))\n'})}),"\n",(0,s.jsx)(t.p,{children:"With the mock set up we can now execute the workflow via the s.env.ExecuteWorkflow(...) method and\nassert that the workflow completed successfully and returned the expected error."}),"\n",(0,s.jsx)(t.p,{children:"Simply mocking the execution to return a desired value or error is a pretty powerful mechanism to\nisolate workflow logic. However, sometimes we want to replace the activity with an alternate implementation\nto support a more complex test scenario. Let's assume we want to validate that the activity gets called\nwith the correct parameters."}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-go",children:'func (s *UnitTestSuite) Test_SimpleWorkflow_ActivityParamCorrect() {\n s.env.OnActivity(SimpleActivity, mock.Anything, mock.Anything).Return(\n func(ctx context.Context, value string) (string, error) {\n s.Equal("test_success", value)\n return value, nil\n }\n )\n s.env.ExecuteWorkflow(SimpleWorkflow, "test_success")\n\n s.True(s.env.IsWorkflowCompleted())\n s.NoError(s.env.GetWorkflowError())\n}\n'})}),"\n",(0,s.jsxs)(t.p,{children:["In this example, we provide a function implementation as the parameter to ",(0,s.jsx)(t.code,{children:"Return"}),". This allows us to\nprovide an alternate implementation for the activity ",(0,s.jsx)(t.code,{children:"SimpleActivity"}),". The framework will execute this\nfunction whenever the activity is invoked and pass on the return value from the function as the result\nof the activity invocation. Additionally, the framework will validate that the signature of the \u201cmock\u201d\nfunction matches the signature of the original activity function."]}),"\n",(0,s.jsx)(t.p,{children:"Since this can be an entire function, there is no limitation as to what we can do here. In this\nexample, we assert that the \u201cvalue\u201d param has the same content as the value param we passed to the workflow."}),"\n",(0,s.jsx)(t.h2,{id:"testing-signals",children:"Testing signals"}),"\n",(0,s.jsxs)(t.p,{children:["To test signals we can use the functions ",(0,s.jsx)(t.code,{children:"s.env.SignalWorkflow"}),", and ",(0,s.jsx)(t.code,{children:"s.env.SignalWorkflowByID"}),". These\nfunctions needs to be called inside ",(0,s.jsx)(t.code,{children:"s.env.RegisterDelayedCallback"}),", as the signal should be send while the\nworkflow is running. It is important to register the signal before calling ",(0,s.jsx)(t.code,{children:"s.env.ExecuteWorkflow"}),", otherwise\nthe signal will not be send."]}),"\n",(0,s.jsxs)(t.p,{children:["If our workflow is waiting for a signal with name ",(0,s.jsx)(t.code,{children:"signalName"})," we can register\nto send this signal ",(0,s.jsx)(t.em,{children:"before"})," the workflow is executed like this:"]}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-go",children:'func (s *UnitTestSuite) Test_SimpleWorkflow_Signal() {\n // Send the signal\n\ts.env.RegisterDelayedCallback(func() {\n\t\ts.env.SignalWorkflow(signalName, signalData)\n\t}, time.Minute*10)\n\n // Execute the workflow\n s.env.ExecuteWorkflow(SimpleWorkflow, "test_success")\n\n s.True(s.env.IsWorkflowCompleted())\n s.NoError(s.env.GetWorkflowError())\n}\n'})}),"\n",(0,s.jsxs)(t.p,{children:["Note that the ",(0,s.jsx)(t.code,{children:"s.env.RegisterDelayedCallback"})," function does not actually wait 10 minutes in the unit test\ninstead the cadence test framework uses an internal clock which knows which event is the next, and executes it\nimmediately."]})]})}function d(e={}){const{wrapper:t}={...(0,o.R)(),...e.components};return t?(0,s.jsx)(t,{...e,children:(0,s.jsx)(u,{...e})}):u(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>r,x:()=>l});var i=n(6540);const s={},o=i.createContext(s);function r(e){const t=i.useContext(o);return i.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function l(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:r(e.components),i.createElement(o.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/f8f32361.60809238.js b/assets/js/f8f32361.60809238.js deleted file mode 100644 index e89f6bd5d..000000000 --- a/assets/js/f8f32361.60809238.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[734],{5913:(e,n,o)=>{o.r(n),o.d(n,{assets:()=>l,contentTitle:()=>t,default:()=>h,frontMatter:()=>i,metadata:()=>r,toc:()=>c});const r=JSON.parse('{"id":"cli/index","title":"Introduction","description":"The Cadence is a command-line tool you can use to perform varioustasks: on a Cadence server. It can perform","source":"@site/docs/06-cli/index.md","sourceDirName":"06-cli","slug":"/cli/","permalink":"/docs/cli/","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/06-cli/index.md","tags":[],"version":"current","frontMatter":{"layout":"default","title":"Introduction","permalink":"/docs/cli"},"sidebar":"docsSidebar","previous":{"title":"Workflow Replay and Shadowing","permalink":"/docs/go-client/workflow-replay-shadowing"},"next":{"title":"Overview","permalink":"/docs/operation-guide/"}}');var s=o(4848),a=o(8453);const i={layout:"default",title:"Introduction",permalink:"/docs/cli"},t="Command Line Interface",l={},c=[{value:"Using the CLI",id:"using-the-cli",level:2},{value:"Homebrew",id:"homebrew",level:3},{value:"Docker",id:"docker",level:3},{value:"Build it yourself",id:"build-it-yourself",level:3},{value:"Documentation",id:"documentation",level:2},{value:"Environment variables",id:"environment-variables",level:2},{value:"Quick Start",id:"quick-start",level:2},{value:"Domain operation examples",id:"domain-operation-examples",level:3},{value:"Workflow operation examples",id:"workflow-operation-examples",level:3},{value:"Run workflow",id:"run-workflow",level:4},{value:"Show running workers of a tasklist",id:"show-running-workers-of-a-tasklist",level:4},{value:"Start workflow",id:"start-workflow",level:4},{value:"Reuse the same workflow id when starting/running a workflow",id:"reuse-the-same-workflow-id-when-startingrunning-a-workflow",level:5},{value:"Start a workflow with a memo",id:"start-a-workflow-with-a-memo",level:5},{value:"Show workflow history",id:"show-workflow-history",level:4},{value:"Show workflow execution information",id:"show-workflow-execution-information",level:4},{value:"List closed or open workflow executions",id:"list-closed-or-open-workflow-executions",level:4},{value:"Query workflow execution",id:"query-workflow-execution",level:4},{value:"Signal, cancel, terminate workflow",id:"signal-cancel-terminate-workflow",level:4},{value:"Signal, cancel, terminate workflows as a batch job",id:"signal-cancel-terminate-workflows-as-a-batch-job",level:4},{value:"Restart, reset workflow",id:"restart-reset-workflow",level:4},{value:"Recovery from bad deployment -- auto-reset workflow",id:"recovery-from-bad-deployment----auto-reset-workflow",level:4}];function d(e){const n={a:"a",code:"code",em:"em",h1:"h1",h2:"h2",h3:"h3",h4:"h4",h5:"h5",header:"header",li:"li",ol:"ol",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,a.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(n.header,{children:(0,s.jsx)(n.h1,{id:"command-line-interface",children:"Command Line Interface"})}),"\n",(0,s.jsx)(n.p,{children:"The Cadence CLI is a command-line tool you can use to perform various tasks on a Cadence server. It can perform\ndomain operations such as register, update, and describe as well as workflow operations like start\nworkflow, show workflow history, and signal workflow."}),"\n",(0,s.jsx)(n.h2,{id:"using-the-cli",children:"Using the CLI"}),"\n",(0,s.jsx)(n.h3,{id:"homebrew",children:"Homebrew"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"brew install cadence-workflow\n"})}),"\n",(0,s.jsx)(n.p,{children:"After the installation is done, you can use CLI:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"cadence --help\n"})}),"\n",(0,s.jsxs)(n.p,{children:["This will always install the latest version. Follow ",(0,s.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence/discussions/4457",children:"this instructions"})," if you need to install older versions of Cadence CLI."]}),"\n",(0,s.jsx)(n.h3,{id:"docker",children:"Docker"}),"\n",(0,s.jsxs)(n.p,{children:["The Cadence CLI can be used directly from the Docker Hub image ",(0,s.jsx)(n.em,{children:"ubercadence/cli"})," or by building the CLI tool\nlocally."]}),"\n",(0,s.jsx)(n.p,{children:"Example of using the docker image to describe a "}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"docker run -it --rm ubercadence/cli:master --address <frontendAddress> --domain samples-domain domain describe\n"})}),"\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.code,{children:"master"})," will be the latest CLI binary from the project. But you can specify a version to best match your server version:"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"docker run -it --rm ubercadence/cli:<version> --address <frontendAddress> --domain samples-domain domain describe\n"})}),"\n",(0,s.jsxs)(n.p,{children:["For example ",(0,s.jsx)(n.code,{children:"docker run --rm ubercadence/cli:0.21.3 --domain samples-domain domain describe"})," will be the CLI that is released as part of the ",(0,s.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence/releases/tag/v0.21.3",children:"v0.21.3 release"}),".\nSee ",(0,s.jsx)(n.a,{href:"https://hub.docker.com/r/ubercadence/cli/tags?page=1&ordering=last_updated",children:"docker hub page"})," for all the CLI image tags.\nNote that CLI versions of 0.20.0 works for all server versions of 0.12 to 0.19 as well. That's because ",(0,s.jsx)(n.a,{href:"https://stackoverflow.com/questions/68217385/what-is-clientversionnotsupportederror-and-how-to-resolve-it",children:"the CLI version doesn't change in those versions"}),"."]}),"\n",(0,s.jsxs)(n.p,{children:['NOTE: On Docker versions 18.03 and later, you may get a "connection refused" error when connecting to local server. You can work around this by setting the host to "host.docker.internal" (see ',(0,s.jsx)(n.a,{href:"https://docs.docker.com/docker-for-mac/networking/#use-cases-and-workarounds",children:"here"})," for more info)."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"docker run -it --rm ubercadence/cli:master --address host.docker.internal:7933 --domain samples-domain domain describe\n"})}),"\n",(0,s.jsxs)(n.p,{children:["NOTE: Be sure to update your image when you want to try new features: ",(0,s.jsx)(n.code,{children:"docker pull ubercadence/cli:master "})]}),"\n",(0,s.jsx)(n.p,{children:"NOTE: If you are running docker-compose Cadence server, you can also logon to the container to execute CLI:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-sh-session",children:"# this logs you onto the Cadence docker container\n$ docker exec -it docker_cadence_1 /bin/bash\n\n# this command runs within the container\n% cadence --address $(hostname -i):7933 --do samples domain register\n"})}),"\n",(0,s.jsx)(n.h3,{id:"build-it-yourself",children:"Build it yourself"}),"\n",(0,s.jsxs)(n.p,{children:["To build the CLI tool locally, clone the ",(0,s.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence",children:"Cadence server repo"}),", check out the version tag (e.g. ",(0,s.jsx)(n.code,{children:"git checkout v0.21.3"}),") and run\n",(0,s.jsx)(n.code,{children:"make tools"}),". This produces an executable called ",(0,s.jsx)(n.code,{children:"cadence"}),". With a local build, the same command to\ndescribe a domain would look like this:"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"cadence --domain samples-domain domain describe\n"})}),"\n",(0,s.jsxs)(n.p,{children:["Alternatively, you can build the CLI image, see ",(0,s.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence/blob/master/docker/README.md#diy-building-an-image-for-any-tag-or-branch",children:"instructions"})]}),"\n",(0,s.jsx)(n.h2,{id:"documentation",children:"Documentation"}),"\n",(0,s.jsxs)(n.p,{children:["CLI are documented by ",(0,s.jsx)(n.code,{children:"--help"})," or ",(0,s.jsx)(n.code,{children:"-h"})," in ANY tab of all levels:"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-sh-session",children:"$ cadence --help\nNAME:\n cadence - A command-line tool for cadence users\n\nUSAGE:\n cadence [global options] command [command options] [arguments...]\n\nVERSION:\n 0.18.4\n\nCOMMANDS:\n domain, d Operate cadence domain\n workflow, wf Operate cadence workflow\n tasklist, tl Operate cadence tasklist\n admin, adm Run admin operation\n cluster, cl Operate cadence cluster\n help, h Shows a list of commands or help for one command\n\nGLOBAL OPTIONS:\n --address value, --ad value host:port for cadence frontend service [$CADENCE_CLI_ADDRESS]\n --domain value, --do value cadence workflow domain [$CADENCE_CLI_DOMAIN]\n --context_timeout value, --ct value optional timeout for context of RPC call in seconds (default: 5) [$CADENCE_CONTEXT_TIMEOUT]\n --help, -h show help\n --version, -v print the version\n"})}),"\n",(0,s.jsx)(n.p,{children:"And"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-sh-session",children:"$ cadence workflow -h\nNAME:\n cadence workflow - Operate cadence workflow\n\nUSAGE:\n cadence workflow command [command options] [arguments...]\n\nCOMMANDS:\n activity, act operate activities of workflow\n show show workflow history\n showid show workflow history with given workflow_id and run_id (a shortcut of `show -w <wid> -r <rid>`). run_id is only required for archived history\n start start a new workflow execution\n run start a new workflow execution and get workflow progress\n cancel, c cancel a workflow execution\n signal, s signal a workflow execution\n signalwithstart signal the current open workflow if exists, or attempt to start a new run based on IDResuePolicy and signals it\n terminate, term terminate a new workflow execution\n list, l list open or closed workflow executions\n listall, la list all open or closed workflow executions\n listarchived list archived workflow executions\n scan, sc, scanall scan workflow executions (need to enable Cadence server on ElasticSearch). It will be faster than listall, but result are not sorted.\n count, cnt count number of workflow executions (need to enable Cadence server on ElasticSearch)\n query query workflow execution\n stack query workflow execution with __stack_trace as query type\n describe, desc show information of workflow execution\n describeid, descid show information of workflow execution with given workflow_id and optional run_id (a shortcut of `describe -w <wid> -r <rid>`)\n observe, ob show the progress of workflow history\n observeid, obid show the progress of workflow history with given workflow_id and optional run_id (a shortcut of `observe -w <wid> -r <rid>`)\n reset, rs reset the workflow, by either eventID or resetType.\n reset-batch reset workflow in batch by resetType: LastDecisionCompleted,LastContinuedAsNew,BadBinary,DecisionCompletedTime,FirstDecisionScheduled,LastDecisionScheduled,FirstDecisionCompletedTo get base workflowIDs/runIDs to reset, source is from input file or visibility query.\n batch batch operation on a list of workflows from query.\n\nOPTIONS:\n --help, -h show help\n"})}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-sh-session",children:"$ cadence wf signal -h\nNAME:\n cadence workflow signal - signal a workflow execution\n\nUSAGE:\n cadence workflow signal [command options] [arguments...]\n\nOPTIONS:\n --workflow_id value, --wid value, -w value WorkflowID\n --run_id value, --rid value, -r value RunID\n --name value, -n value SignalName\n --input value, -i value Input for the signal, in JSON format.\n --input_file value, --if value Input for the signal from JSON file.\n\n"})}),"\n",(0,s.jsx)(n.p,{children:"And etc."}),"\n",(0,s.jsxs)(n.p,{children:["The example commands below will use ",(0,s.jsx)(n.code,{children:"cadence"})," for brevity."]}),"\n",(0,s.jsx)(n.h2,{id:"environment-variables",children:"Environment variables"}),"\n",(0,s.jsx)(n.p,{children:"Setting environment variables for repeated parameters can shorten the CLI commands."}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.strong,{children:"CADENCE_CLI_ADDRESS"})," - host",":port"," for Cadence frontend service, the default is for the local server"]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.strong,{children:"CADENCE_CLI_DOMAIN"})," - default workflow domain, so you don't need to specify ",(0,s.jsx)(n.code,{children:"--domain"})]}),"\n"]}),"\n",(0,s.jsx)(n.h2,{id:"quick-start",children:"Quick Start"}),"\n",(0,s.jsxs)(n.p,{children:["Run ",(0,s.jsx)(n.code,{children:"cadence"})," for help on top level commands and global options\nRun ",(0,s.jsx)(n.code,{children:"cadence domain"})," for help on domain operations\nRun ",(0,s.jsx)(n.code,{children:"cadence workflow"})," for help on workflow operations\nRun ",(0,s.jsx)(n.code,{children:"cadence tasklist"})," for help on tasklist operations\n(",(0,s.jsx)(n.code,{children:"cadence help"}),", ",(0,s.jsx)(n.code,{children:"cadence help [domain|workflow]"})," will also print help messages)"]}),"\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.strong,{children:"Note:"})," make sure you have a Cadence server running before using CLI"]}),"\n",(0,s.jsx)(n.h3,{id:"domain-operation-examples",children:"Domain operation examples"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:'Register a new domain named "samples-domain":'}),"\n"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"cadence --domain samples-domain domain register\n# OR using short alias\ncadence --do samples-domain d re\n"})}),"\n",(0,s.jsxs)(n.p,{children:["If your Cadence cluster has enable ",(0,s.jsx)(n.a,{href:"https://cadenceworkflow.io/docs/concepts/cross-dc-replication/",children:"global domain(XDC replication)"}),", then you have to specify the replicaiton settings when registering a domain:"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"cadence --domains amples-domain domain register --active_cluster clusterNameA --clusters clusterNameA clusterNameB\n"})}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:'View "samples-domain" details:'}),"\n"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"cadence --domain samples-domain domain describe\n"})}),"\n",(0,s.jsx)(n.h3,{id:"workflow-operation-examples",children:"Workflow operation examples"}),"\n",(0,s.jsx)(n.p,{children:"The following examples assume the CADENCE_CLI_DOMAIN environment variable is set."}),"\n",(0,s.jsx)(n.h4,{id:"run-workflow",children:"Run workflow"}),"\n",(0,s.jsx)(n.p,{children:"Start a workflow and see its progress. This command doesn't finish until workflow completes."}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"cadence workflow run --tl helloWorldGroup --wt main.Workflow --et 60 -i '\"cadence\"'\n\n# view help messages for workflow run\ncadence workflow run -h\n"})}),"\n",(0,s.jsx)(n.p,{children:"Brief explanation:\nTo run a workflow, the user must specify the following:"}),"\n",(0,s.jsxs)(n.ol,{children:["\n",(0,s.jsx)(n.li,{children:"Tasklist name (--tl)"}),"\n",(0,s.jsx)(n.li,{children:"Workflow type (--wt)"}),"\n",(0,s.jsx)(n.li,{children:"Execution start to close timeout in seconds (--et)"}),"\n",(0,s.jsx)(n.li,{children:"Input in JSON format (--i) (optional)"}),"\n"]}),"\n",(0,s.jsxs)(n.p,{children:["s example uses ",(0,s.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence-samples/blob/master/cmd/samples/recipes/helloworld/helloworld_workflow.go",children:"this cadence-samples workflow"}),"\nand takes a string as input with the ",(0,s.jsx)(n.code,{children:"-i '\"cadence\"'"})," parameter. Single quotes (",(0,s.jsx)(n.code,{children:"''"}),") are used to wrap input as JSON."]}),"\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.strong,{children:"Note:"})," You need to start the worker so that the workflow can make progress.\n(Run ",(0,s.jsx)(n.code,{children:"make && ./bin/helloworld -m worker"})," in cadence-samples to start the worker)"]}),"\n",(0,s.jsx)(n.h4,{id:"show-running-workers-of-a-tasklist",children:"Show running workers of a tasklist"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"cadence tasklist desc --tl helloWorldGroup\n"})}),"\n",(0,s.jsx)(n.h4,{id:"start-workflow",children:"Start workflow"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:'cadence workflow start --tl helloWorldGroup --wt main.Workflow --et 60 -i \'"cadence"\'\n\n# view help messages for workflow start\ncadence workflow start -h\n\n# for a workflow with multiple inputs, separate each json with space/newline like\ncadence workflow start --tl helloWorldGroup --wt main.WorkflowWith3Args --et 60 -i \'"your_input_string" 123 {"Name":"my-string", "Age":12345}\'\n'})}),"\n",(0,s.jsxs)(n.p,{children:["The workflow ",(0,s.jsx)(n.code,{children:"start"})," command is similar to the ",(0,s.jsx)(n.code,{children:"run"})," command, but immediately returns the workflow_id and\nrun_id after starting the workflow. Use the ",(0,s.jsx)(n.code,{children:"show"})," command to view the workflow's history/progress."]}),"\n",(0,s.jsx)(n.h5,{id:"reuse-the-same-workflow-id-when-startingrunning-a-workflow",children:"Reuse the same workflow id when starting/running a workflow"}),"\n",(0,s.jsxs)(n.p,{children:["Use option ",(0,s.jsx)(n.code,{children:"--workflowidreusepolicy"})," or ",(0,s.jsx)(n.code,{children:"--wrp"})," to configure the workflow_ID reuse policy.\n",(0,s.jsx)(n.strong,{children:"Option 0 AllowDuplicateFailedOnly:"})," Allow starting a workflow_execution using the same workflow_ID when a workflow with the same workflow_ID is not already running and the last execution close state is one of ",(0,s.jsx)(n.em,{children:"[terminated, cancelled, timedout, failed]"}),".\n",(0,s.jsx)(n.strong,{children:"Option 1 AllowDuplicate:"})," Allow starting a workflow_execution using the same workflow_ID when a workflow with the same workflow_ID is not already running.\n",(0,s.jsx)(n.strong,{children:"Option 2 RejectDuplicate:"})," Do not allow starting a workflow_execution using the same workflow_ID as a previous workflow."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:'# use AllowDuplicateFailedOnly option to start a workflow\ncadence workflow start --tl helloWorldGroup --wt main.Workflow --et 60 -i \'"cadence"\' --wid "<duplicated workflow id>" --wrp 0\n\n# use AllowDuplicate option to run a workflow\ncadence workflow run --tl helloWorldGroup --wt main.Workflow --et 60 -i \'"cadence"\' --wid "<duplicated workflow id>" --wrp 1\n'})}),"\n",(0,s.jsx)(n.h5,{id:"start-a-workflow-with-a-memo",children:"Start a workflow with a memo"}),"\n",(0,s.jsxs)(n.p,{children:["Memos are immutable key/value pairs that can be attached to a workflow run when starting the workflow. These are\nvisible when listing workflows. More information on memos can be found\n",(0,s.jsx)(n.a,{href:"/docs/concepts/search-workflows/#memo-vs-search-attributes",children:"here"}),"."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"cadence wf start -tl helloWorldGroup -wt main.Workflow -et 60 -i '\"cadence\"' -memo_key \u2018\u201cService\u201d \u201cEnv\u201d \u201cInstance\u201d\u2019 -memo \u2018\u201cserverName1\u201d \u201ctest\u201d 5\u2019\n"})}),"\n",(0,s.jsx)(n.h4,{id:"show-workflow-history",children:"Show workflow history"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"cadence workflow show -w 3ea6b242-b23c-4279-bb13-f215661b4717 -r 866ae14c-88cf-4f1e-980f-571e031d71b0\n# a shortcut of this is (without -w -r flag)\ncadence workflow showid 3ea6b242-b23c-4279-bb13-f215661b4717 866ae14c-88cf-4f1e-980f-571e031d71b0\n\n# if run_id is not provided, it will show the latest run history of that workflow_id\ncadence workflow show -w 3ea6b242-b23c-4279-bb13-f215661b4717\n# a shortcut of this is\ncadence workflow showid 3ea6b242-b23c-4279-bb13-f215661b4717\n"})}),"\n",(0,s.jsx)(n.h4,{id:"show-workflow-execution-information",children:"Show workflow execution information"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"cadence workflow describe -w 3ea6b242-b23c-4279-bb13-f215661b4717 -r 866ae14c-88cf-4f1e-980f-571e031d71b0\n# a shortcut of this is (without -w -r flag)\ncadence workflow describeid 3ea6b242-b23c-4279-bb13-f215661b4717 866ae14c-88cf-4f1e-980f-571e031d71b0\n\n# if run_id is not provided, it will show the latest workflow execution of that workflow_id\ncadence workflow describe -w 3ea6b242-b23c-4279-bb13-f215661b4717\n# a shortcut of this is\ncadence workflow describeid 3ea6b242-b23c-4279-bb13-f215661b4717\n"})}),"\n",(0,s.jsx)(n.h4,{id:"list-closed-or-open-workflow-executions",children:"List closed or open workflow executions"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"cadence workflow list\n\n# default will only show one page, to view more items, use --more flag\ncadence workflow list -m\n"})}),"\n",(0,s.jsxs)(n.p,{children:["Use ",(0,s.jsx)(n.strong,{children:"--query"})," to list workflows with SQL like "]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"cadence workflow list --query \"WorkflowType='main.SampleParentWorkflow' AND CloseTime = missing \"\n"})}),"\n",(0,s.jsx)(n.p,{children:'This will return all open workflows with workflowType as "main.SampleParentWorkflow".'}),"\n",(0,s.jsx)(n.h4,{id:"query-workflow-execution",children:"Query workflow execution"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:'# use custom query type\ncadence workflow query -w <wid> -r <rid> --qt <query-type>\n\n# use build-in query type "__stack_trace" which is supported by Cadence client library\ncadence workflow query -w <wid> -r <rid> --qt __stack_trace\n# a shortcut to query using __stack_trace is (without --qt flag)\ncadence workflow stack -w <wid> -r <rid>\n'})}),"\n",(0,s.jsx)(n.h4,{id:"signal-cancel-terminate-workflow",children:"Signal, cancel, terminate workflow"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"# signal\ncadence workflow signal -w <wid> -r <rid> -n <signal-name> -i '\"signal-value\"'\n\n# cancel\ncadence workflow cancel -w <wid> -r <rid>\n\n# terminate\ncadence workflow terminate -w <wid> -r <rid> --reason\n"})}),"\n",(0,s.jsx)(n.p,{children:"Terminating a running workflow_execution will record a WorkflowExecutionTerminated event as the closing event in the history. No more decision_tasks will be scheduled for a terminated workflow_execution.\nCanceling a running workflow_execution will record a WorkflowExecutionCancelRequested event in the history, and a new decision_task will be scheduled. The workflow has a chance to do some clean up work after cancellation."}),"\n",(0,s.jsx)(n.h4,{id:"signal-cancel-terminate-workflows-as-a-batch-job",children:"Signal, cancel, terminate workflows as a batch job"}),"\n",(0,s.jsxs)(n.p,{children:["Batch job is based on List Workflow Query(",(0,s.jsx)(n.strong,{children:"--query"}),"). It supports signal, cancel and terminate as batch job type.\nFor terminating workflows as batch job, it will terminte the children recursively."]}),"\n",(0,s.jsx)(n.p,{children:"Start a batch job(using signal as batch type):"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:'cadence --do samples-domain wf batch start --query "WorkflowType=\'main.SampleParentWorkflow\' AND CloseTime=missing" --reason "test" --bt signal --sig testname\nThis batch job will be operating on 5 workflows.\nPlease confirm[Yes/No]:yes\n{\n "jobID": "<batch-job-id>",\n "msg": "batch job is started"\n}\n\n'})}),"\n",(0,s.jsx)(n.p,{children:"You need to remember the JobID or use List command to get all your batch jobs:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"cadence --do samples-domain wf batch list\n"})}),"\n",(0,s.jsx)(n.p,{children:"Describe the progress of a batch job:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"cadence --do samples-domain wf batch desc -jid <batch-job-id>\n"})}),"\n",(0,s.jsx)(n.p,{children:"Terminate a batch job:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"cadence --do samples-domain wf batch terminate -jid <batch-job-id>\n"})}),"\n",(0,s.jsx)(n.p,{children:"Note that the operation performed by a batch will not be rolled back by terminating the batch. However, you can use reset to rollback your workflows."}),"\n",(0,s.jsx)(n.h4,{id:"restart-reset-workflow",children:"Restart, reset workflow"}),"\n",(0,s.jsx)(n.p,{children:"The Reset command allows resetting a workflow to a particular point and continue running from there.\nThere are a lot of use cases:"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:"Rerun a failed workflow from the beginning with the same start parameters."}),"\n",(0,s.jsx)(n.li,{children:"Rerun a failed workflow from the failing point without losing the achieved progress(history)."}),"\n",(0,s.jsx)(n.li,{children:"After deploying new code, reset an open workflow to let the workflow run to different flows."}),"\n"]}),"\n",(0,s.jsx)(n.p,{children:"You can reset to some predefined event types:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:'cadence workflow reset -w <wid> -r <rid> --reset_type <reset_type> --reason "some_reason"\n'})}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:"FirstDecisionCompleted: reset to the beginning of the history."}),"\n",(0,s.jsx)(n.li,{children:"LastDecisionCompleted: reset to the end of the history."}),"\n",(0,s.jsx)(n.li,{children:"LastContinuedAsNew: reset to the end of the history for the previous run."}),"\n"]}),"\n",(0,s.jsx)(n.p,{children:"If you are familiar with the Cadence history event, You can also reset to any decision finish event by using:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:'cadence workflow reset -w <wid> -r <rid> --event_id <decision_finish_event_id> --reason "some_reason"\n'})}),"\n",(0,s.jsx)(n.p,{children:"Some things to note:"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:"When reset, a new run will be kicked off with the same workflowID. But if there is a running execution for the workflow(workflowID), the current run will be terminated."}),"\n",(0,s.jsx)(n.li,{children:"decision_finish_event_id is the ID of events of the type: DecisionTaskComplete/DecisionTaskFailed/DecisionTaskTimeout."}),"\n",(0,s.jsx)(n.li,{children:"To restart a workflow from the beginning, reset to the first decision_task finish event."}),"\n"]}),"\n",(0,s.jsx)(n.p,{children:"To reset multiple workflows, you can use batch reset command:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:'cadence workflow reset-batch --input_file <file_of_workflows_to_reset> --reset_type <reset_type> --reason "some_reason"\n'})}),"\n",(0,s.jsx)(n.h4,{id:"recovery-from-bad-deployment----auto-reset-workflow",children:"Recovery from bad deployment -- auto-reset workflow"}),"\n",(0,s.jsx)(n.p,{children:"If a bad deployment lets a workflow run into a wrong state, you might want to reset the workflow to the point that the bad deployment started to run. But usually it is not easy to find out all the workflows impacted, and every reset point for each workflow. In this case, auto-reset will automatically reset all the workflows given a bad deployment identifier."}),"\n",(0,s.jsxs)(n.p,{children:["Let's get familiar with some concepts. Each deployment will have an identifier, we call it \"",(0,s.jsx)(n.strong,{children:"Binary Checksum"}),'" as it is usually generated by the md5sum of a binary file. For a workflow, each binary checksum will be associated with an ',(0,s.jsx)(n.strong,{children:"auto-reset point"}),", which contains a ",(0,s.jsx)(n.strong,{children:"runID"}),", an ",(0,s.jsx)(n.strong,{children:"eventID"}),", and the ",(0,s.jsx)(n.strong,{children:"created_time"})," that binary/deployment made the first decision for the workflow."]}),"\n",(0,s.jsxs)(n.p,{children:["To find out which ",(0,s.jsx)(n.strong,{children:"binary checksum"})," of the bad deployment to reset, you should be aware of at least one workflow running into a bad state. Use the describe command with ",(0,s.jsx)(n.strong,{children:"--reset_points_only"})," option to show all the reset points:"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"cadence wf desc -w <WorkflowID> --reset_points_only\n+----------------------------------+--------------------------------+--------------------------------------+---------+\n| BINARY CHECKSUM | CREATE TIME | RUNID | EVENTID |\n+----------------------------------+--------------------------------+--------------------------------------+---------+\n| c84c5afa552613a83294793f4e664a7f | 2019-05-24 10:01:00.398455019 | 2dd29ab7-2dd8-4668-83e0-89cae261cfb1 | 4 |\n| aae748fdc557a3f873adbe1dd066713f | 2019-05-24 11:01:00.067691445 | d42d21b8-2adb-4313-b069-3837d44d6ce6 | 4 |\n...\n...\n"})}),"\n",(0,s.jsx)(n.p,{children:"Then use this command to tell Cadence to auto-reset all workflows impacted by the bad deployment. The command will store the bad binary checksum into domain info and trigger a process to reset all your workflows."}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:'cadence --do <YourDomainName> domain update --add_bad_binary aae748fdc557a3f873adbe1dd066713f --reason "rollback bad deployment"\n'})}),"\n",(0,s.jsx)(n.p,{children:"As you add the bad binary checksum to your domain, Cadence will not dispatch any decision_tasks to the bad binary. So make sure that you have rolled back to a good deployment(or roll out new bits with bug fixes). Otherwise your workflow can't make any progress after auto-reset."})]})}function h(e={}){const{wrapper:n}={...(0,a.R)(),...e.components};return n?(0,s.jsx)(n,{...e,children:(0,s.jsx)(d,{...e})}):d(e)}},8453:(e,n,o)=>{o.d(n,{R:()=>i,x:()=>t});var r=o(6540);const s={},a=r.createContext(s);function i(e){const n=r.useContext(a);return r.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function t(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:i(e.components),r.createElement(a.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/f8f32361.65347fb7.js b/assets/js/f8f32361.65347fb7.js new file mode 100644 index 000000000..a5ed31e4d --- /dev/null +++ b/assets/js/f8f32361.65347fb7.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[734],{5913:(e,n,o)=>{o.r(n),o.d(n,{assets:()=>l,contentTitle:()=>t,default:()=>h,frontMatter:()=>i,metadata:()=>r,toc:()=>c});const r=JSON.parse('{"id":"cli/index","title":"Introduction","description":"The Cadence is a command-line tool you can use to perform varioustasks: on a Cadence server. It can perform","source":"@site/docs/06-cli/index.md","sourceDirName":"06-cli","slug":"/cli/","permalink":"/Cadence-Docs/docs/cli/","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/06-cli/index.md","tags":[],"version":"current","frontMatter":{"layout":"default","title":"Introduction","permalink":"/docs/cli"},"sidebar":"docsSidebar","previous":{"title":"Workflow Replay and Shadowing","permalink":"/Cadence-Docs/docs/go-client/workflow-replay-shadowing"},"next":{"title":"Overview","permalink":"/Cadence-Docs/docs/operation-guide/"}}');var s=o(4848),a=o(8453);const i={layout:"default",title:"Introduction",permalink:"/docs/cli"},t="Command Line Interface",l={},c=[{value:"Using the CLI",id:"using-the-cli",level:2},{value:"Homebrew",id:"homebrew",level:3},{value:"Docker",id:"docker",level:3},{value:"Build it yourself",id:"build-it-yourself",level:3},{value:"Documentation",id:"documentation",level:2},{value:"Environment variables",id:"environment-variables",level:2},{value:"Quick Start",id:"quick-start",level:2},{value:"Domain operation examples",id:"domain-operation-examples",level:3},{value:"Workflow operation examples",id:"workflow-operation-examples",level:3},{value:"Run workflow",id:"run-workflow",level:4},{value:"Show running workers of a tasklist",id:"show-running-workers-of-a-tasklist",level:4},{value:"Start workflow",id:"start-workflow",level:4},{value:"Reuse the same workflow id when starting/running a workflow",id:"reuse-the-same-workflow-id-when-startingrunning-a-workflow",level:5},{value:"Start a workflow with a memo",id:"start-a-workflow-with-a-memo",level:5},{value:"Show workflow history",id:"show-workflow-history",level:4},{value:"Show workflow execution information",id:"show-workflow-execution-information",level:4},{value:"List closed or open workflow executions",id:"list-closed-or-open-workflow-executions",level:4},{value:"Query workflow execution",id:"query-workflow-execution",level:4},{value:"Signal, cancel, terminate workflow",id:"signal-cancel-terminate-workflow",level:4},{value:"Signal, cancel, terminate workflows as a batch job",id:"signal-cancel-terminate-workflows-as-a-batch-job",level:4},{value:"Restart, reset workflow",id:"restart-reset-workflow",level:4},{value:"Recovery from bad deployment -- auto-reset workflow",id:"recovery-from-bad-deployment----auto-reset-workflow",level:4}];function d(e){const n={a:"a",code:"code",em:"em",h1:"h1",h2:"h2",h3:"h3",h4:"h4",h5:"h5",header:"header",li:"li",ol:"ol",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,a.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(n.header,{children:(0,s.jsx)(n.h1,{id:"command-line-interface",children:"Command Line Interface"})}),"\n",(0,s.jsx)(n.p,{children:"The Cadence CLI is a command-line tool you can use to perform various tasks on a Cadence server. It can perform\ndomain operations such as register, update, and describe as well as workflow operations like start\nworkflow, show workflow history, and signal workflow."}),"\n",(0,s.jsx)(n.h2,{id:"using-the-cli",children:"Using the CLI"}),"\n",(0,s.jsx)(n.h3,{id:"homebrew",children:"Homebrew"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"brew install cadence-workflow\n"})}),"\n",(0,s.jsx)(n.p,{children:"After the installation is done, you can use CLI:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"cadence --help\n"})}),"\n",(0,s.jsxs)(n.p,{children:["This will always install the latest version. Follow ",(0,s.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence/discussions/4457",children:"this instructions"})," if you need to install older versions of Cadence CLI."]}),"\n",(0,s.jsx)(n.h3,{id:"docker",children:"Docker"}),"\n",(0,s.jsxs)(n.p,{children:["The Cadence CLI can be used directly from the Docker Hub image ",(0,s.jsx)(n.em,{children:"ubercadence/cli"})," or by building the CLI tool\nlocally."]}),"\n",(0,s.jsx)(n.p,{children:"Example of using the docker image to describe a "}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"docker run -it --rm ubercadence/cli:master --address <frontendAddress> --domain samples-domain domain describe\n"})}),"\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.code,{children:"master"})," will be the latest CLI binary from the project. But you can specify a version to best match your server version:"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"docker run -it --rm ubercadence/cli:<version> --address <frontendAddress> --domain samples-domain domain describe\n"})}),"\n",(0,s.jsxs)(n.p,{children:["For example ",(0,s.jsx)(n.code,{children:"docker run --rm ubercadence/cli:0.21.3 --domain samples-domain domain describe"})," will be the CLI that is released as part of the ",(0,s.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence/releases/tag/v0.21.3",children:"v0.21.3 release"}),".\nSee ",(0,s.jsx)(n.a,{href:"https://hub.docker.com/r/ubercadence/cli/tags?page=1&ordering=last_updated",children:"docker hub page"})," for all the CLI image tags.\nNote that CLI versions of 0.20.0 works for all server versions of 0.12 to 0.19 as well. That's because ",(0,s.jsx)(n.a,{href:"https://stackoverflow.com/questions/68217385/what-is-clientversionnotsupportederror-and-how-to-resolve-it",children:"the CLI version doesn't change in those versions"}),"."]}),"\n",(0,s.jsxs)(n.p,{children:['NOTE: On Docker versions 18.03 and later, you may get a "connection refused" error when connecting to local server. You can work around this by setting the host to "host.docker.internal" (see ',(0,s.jsx)(n.a,{href:"https://docs.docker.com/docker-for-mac/networking/#use-cases-and-workarounds",children:"here"})," for more info)."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"docker run -it --rm ubercadence/cli:master --address host.docker.internal:7933 --domain samples-domain domain describe\n"})}),"\n",(0,s.jsxs)(n.p,{children:["NOTE: Be sure to update your image when you want to try new features: ",(0,s.jsx)(n.code,{children:"docker pull ubercadence/cli:master "})]}),"\n",(0,s.jsx)(n.p,{children:"NOTE: If you are running docker-compose Cadence server, you can also logon to the container to execute CLI:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-sh-session",children:"# this logs you onto the Cadence docker container\n$ docker exec -it docker_cadence_1 /bin/bash\n\n# this command runs within the container\n% cadence --address $(hostname -i):7933 --do samples domain register\n"})}),"\n",(0,s.jsx)(n.h3,{id:"build-it-yourself",children:"Build it yourself"}),"\n",(0,s.jsxs)(n.p,{children:["To build the CLI tool locally, clone the ",(0,s.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence",children:"Cadence server repo"}),", check out the version tag (e.g. ",(0,s.jsx)(n.code,{children:"git checkout v0.21.3"}),") and run\n",(0,s.jsx)(n.code,{children:"make tools"}),". This produces an executable called ",(0,s.jsx)(n.code,{children:"cadence"}),". With a local build, the same command to\ndescribe a domain would look like this:"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"cadence --domain samples-domain domain describe\n"})}),"\n",(0,s.jsxs)(n.p,{children:["Alternatively, you can build the CLI image, see ",(0,s.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence/blob/master/docker/README.md#diy-building-an-image-for-any-tag-or-branch",children:"instructions"})]}),"\n",(0,s.jsx)(n.h2,{id:"documentation",children:"Documentation"}),"\n",(0,s.jsxs)(n.p,{children:["CLI are documented by ",(0,s.jsx)(n.code,{children:"--help"})," or ",(0,s.jsx)(n.code,{children:"-h"})," in ANY tab of all levels:"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-sh-session",children:"$ cadence --help\nNAME:\n cadence - A command-line tool for cadence users\n\nUSAGE:\n cadence [global options] command [command options] [arguments...]\n\nVERSION:\n 0.18.4\n\nCOMMANDS:\n domain, d Operate cadence domain\n workflow, wf Operate cadence workflow\n tasklist, tl Operate cadence tasklist\n admin, adm Run admin operation\n cluster, cl Operate cadence cluster\n help, h Shows a list of commands or help for one command\n\nGLOBAL OPTIONS:\n --address value, --ad value host:port for cadence frontend service [$CADENCE_CLI_ADDRESS]\n --domain value, --do value cadence workflow domain [$CADENCE_CLI_DOMAIN]\n --context_timeout value, --ct value optional timeout for context of RPC call in seconds (default: 5) [$CADENCE_CONTEXT_TIMEOUT]\n --help, -h show help\n --version, -v print the version\n"})}),"\n",(0,s.jsx)(n.p,{children:"And"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-sh-session",children:"$ cadence workflow -h\nNAME:\n cadence workflow - Operate cadence workflow\n\nUSAGE:\n cadence workflow command [command options] [arguments...]\n\nCOMMANDS:\n activity, act operate activities of workflow\n show show workflow history\n showid show workflow history with given workflow_id and run_id (a shortcut of `show -w <wid> -r <rid>`). run_id is only required for archived history\n start start a new workflow execution\n run start a new workflow execution and get workflow progress\n cancel, c cancel a workflow execution\n signal, s signal a workflow execution\n signalwithstart signal the current open workflow if exists, or attempt to start a new run based on IDResuePolicy and signals it\n terminate, term terminate a new workflow execution\n list, l list open or closed workflow executions\n listall, la list all open or closed workflow executions\n listarchived list archived workflow executions\n scan, sc, scanall scan workflow executions (need to enable Cadence server on ElasticSearch). It will be faster than listall, but result are not sorted.\n count, cnt count number of workflow executions (need to enable Cadence server on ElasticSearch)\n query query workflow execution\n stack query workflow execution with __stack_trace as query type\n describe, desc show information of workflow execution\n describeid, descid show information of workflow execution with given workflow_id and optional run_id (a shortcut of `describe -w <wid> -r <rid>`)\n observe, ob show the progress of workflow history\n observeid, obid show the progress of workflow history with given workflow_id and optional run_id (a shortcut of `observe -w <wid> -r <rid>`)\n reset, rs reset the workflow, by either eventID or resetType.\n reset-batch reset workflow in batch by resetType: LastDecisionCompleted,LastContinuedAsNew,BadBinary,DecisionCompletedTime,FirstDecisionScheduled,LastDecisionScheduled,FirstDecisionCompletedTo get base workflowIDs/runIDs to reset, source is from input file or visibility query.\n batch batch operation on a list of workflows from query.\n\nOPTIONS:\n --help, -h show help\n"})}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-sh-session",children:"$ cadence wf signal -h\nNAME:\n cadence workflow signal - signal a workflow execution\n\nUSAGE:\n cadence workflow signal [command options] [arguments...]\n\nOPTIONS:\n --workflow_id value, --wid value, -w value WorkflowID\n --run_id value, --rid value, -r value RunID\n --name value, -n value SignalName\n --input value, -i value Input for the signal, in JSON format.\n --input_file value, --if value Input for the signal from JSON file.\n\n"})}),"\n",(0,s.jsx)(n.p,{children:"And etc."}),"\n",(0,s.jsxs)(n.p,{children:["The example commands below will use ",(0,s.jsx)(n.code,{children:"cadence"})," for brevity."]}),"\n",(0,s.jsx)(n.h2,{id:"environment-variables",children:"Environment variables"}),"\n",(0,s.jsx)(n.p,{children:"Setting environment variables for repeated parameters can shorten the CLI commands."}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.strong,{children:"CADENCE_CLI_ADDRESS"})," - host",":port"," for Cadence frontend service, the default is for the local server"]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.strong,{children:"CADENCE_CLI_DOMAIN"})," - default workflow domain, so you don't need to specify ",(0,s.jsx)(n.code,{children:"--domain"})]}),"\n"]}),"\n",(0,s.jsx)(n.h2,{id:"quick-start",children:"Quick Start"}),"\n",(0,s.jsxs)(n.p,{children:["Run ",(0,s.jsx)(n.code,{children:"cadence"})," for help on top level commands and global options\nRun ",(0,s.jsx)(n.code,{children:"cadence domain"})," for help on domain operations\nRun ",(0,s.jsx)(n.code,{children:"cadence workflow"})," for help on workflow operations\nRun ",(0,s.jsx)(n.code,{children:"cadence tasklist"})," for help on tasklist operations\n(",(0,s.jsx)(n.code,{children:"cadence help"}),", ",(0,s.jsx)(n.code,{children:"cadence help [domain|workflow]"})," will also print help messages)"]}),"\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.strong,{children:"Note:"})," make sure you have a Cadence server running before using CLI"]}),"\n",(0,s.jsx)(n.h3,{id:"domain-operation-examples",children:"Domain operation examples"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:'Register a new domain named "samples-domain":'}),"\n"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"cadence --domain samples-domain domain register\n# OR using short alias\ncadence --do samples-domain d re\n"})}),"\n",(0,s.jsxs)(n.p,{children:["If your Cadence cluster has enable ",(0,s.jsx)(n.a,{href:"https://cadenceworkflow.io/docs/concepts/cross-dc-replication/",children:"global domain(XDC replication)"}),", then you have to specify the replicaiton settings when registering a domain:"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"cadence --domains amples-domain domain register --active_cluster clusterNameA --clusters clusterNameA clusterNameB\n"})}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:'View "samples-domain" details:'}),"\n"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"cadence --domain samples-domain domain describe\n"})}),"\n",(0,s.jsx)(n.h3,{id:"workflow-operation-examples",children:"Workflow operation examples"}),"\n",(0,s.jsx)(n.p,{children:"The following examples assume the CADENCE_CLI_DOMAIN environment variable is set."}),"\n",(0,s.jsx)(n.h4,{id:"run-workflow",children:"Run workflow"}),"\n",(0,s.jsx)(n.p,{children:"Start a workflow and see its progress. This command doesn't finish until workflow completes."}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"cadence workflow run --tl helloWorldGroup --wt main.Workflow --et 60 -i '\"cadence\"'\n\n# view help messages for workflow run\ncadence workflow run -h\n"})}),"\n",(0,s.jsx)(n.p,{children:"Brief explanation:\nTo run a workflow, the user must specify the following:"}),"\n",(0,s.jsxs)(n.ol,{children:["\n",(0,s.jsx)(n.li,{children:"Tasklist name (--tl)"}),"\n",(0,s.jsx)(n.li,{children:"Workflow type (--wt)"}),"\n",(0,s.jsx)(n.li,{children:"Execution start to close timeout in seconds (--et)"}),"\n",(0,s.jsx)(n.li,{children:"Input in JSON format (--i) (optional)"}),"\n"]}),"\n",(0,s.jsxs)(n.p,{children:["s example uses ",(0,s.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence-samples/blob/master/cmd/samples/recipes/helloworld/helloworld_workflow.go",children:"this cadence-samples workflow"}),"\nand takes a string as input with the ",(0,s.jsx)(n.code,{children:"-i '\"cadence\"'"})," parameter. Single quotes (",(0,s.jsx)(n.code,{children:"''"}),") are used to wrap input as JSON."]}),"\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.strong,{children:"Note:"})," You need to start the worker so that the workflow can make progress.\n(Run ",(0,s.jsx)(n.code,{children:"make && ./bin/helloworld -m worker"})," in cadence-samples to start the worker)"]}),"\n",(0,s.jsx)(n.h4,{id:"show-running-workers-of-a-tasklist",children:"Show running workers of a tasklist"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"cadence tasklist desc --tl helloWorldGroup\n"})}),"\n",(0,s.jsx)(n.h4,{id:"start-workflow",children:"Start workflow"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:'cadence workflow start --tl helloWorldGroup --wt main.Workflow --et 60 -i \'"cadence"\'\n\n# view help messages for workflow start\ncadence workflow start -h\n\n# for a workflow with multiple inputs, separate each json with space/newline like\ncadence workflow start --tl helloWorldGroup --wt main.WorkflowWith3Args --et 60 -i \'"your_input_string" 123 {"Name":"my-string", "Age":12345}\'\n'})}),"\n",(0,s.jsxs)(n.p,{children:["The workflow ",(0,s.jsx)(n.code,{children:"start"})," command is similar to the ",(0,s.jsx)(n.code,{children:"run"})," command, but immediately returns the workflow_id and\nrun_id after starting the workflow. Use the ",(0,s.jsx)(n.code,{children:"show"})," command to view the workflow's history/progress."]}),"\n",(0,s.jsx)(n.h5,{id:"reuse-the-same-workflow-id-when-startingrunning-a-workflow",children:"Reuse the same workflow id when starting/running a workflow"}),"\n",(0,s.jsxs)(n.p,{children:["Use option ",(0,s.jsx)(n.code,{children:"--workflowidreusepolicy"})," or ",(0,s.jsx)(n.code,{children:"--wrp"})," to configure the workflow_ID reuse policy.\n",(0,s.jsx)(n.strong,{children:"Option 0 AllowDuplicateFailedOnly:"})," Allow starting a workflow_execution using the same workflow_ID when a workflow with the same workflow_ID is not already running and the last execution close state is one of ",(0,s.jsx)(n.em,{children:"[terminated, cancelled, timedout, failed]"}),".\n",(0,s.jsx)(n.strong,{children:"Option 1 AllowDuplicate:"})," Allow starting a workflow_execution using the same workflow_ID when a workflow with the same workflow_ID is not already running.\n",(0,s.jsx)(n.strong,{children:"Option 2 RejectDuplicate:"})," Do not allow starting a workflow_execution using the same workflow_ID as a previous workflow."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:'# use AllowDuplicateFailedOnly option to start a workflow\ncadence workflow start --tl helloWorldGroup --wt main.Workflow --et 60 -i \'"cadence"\' --wid "<duplicated workflow id>" --wrp 0\n\n# use AllowDuplicate option to run a workflow\ncadence workflow run --tl helloWorldGroup --wt main.Workflow --et 60 -i \'"cadence"\' --wid "<duplicated workflow id>" --wrp 1\n'})}),"\n",(0,s.jsx)(n.h5,{id:"start-a-workflow-with-a-memo",children:"Start a workflow with a memo"}),"\n",(0,s.jsxs)(n.p,{children:["Memos are immutable key/value pairs that can be attached to a workflow run when starting the workflow. These are\nvisible when listing workflows. More information on memos can be found\n",(0,s.jsx)(n.a,{href:"/docs/concepts/search-workflows/#memo-vs-search-attributes",children:"here"}),"."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"cadence wf start -tl helloWorldGroup -wt main.Workflow -et 60 -i '\"cadence\"' -memo_key \u2018\u201cService\u201d \u201cEnv\u201d \u201cInstance\u201d\u2019 -memo \u2018\u201cserverName1\u201d \u201ctest\u201d 5\u2019\n"})}),"\n",(0,s.jsx)(n.h4,{id:"show-workflow-history",children:"Show workflow history"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"cadence workflow show -w 3ea6b242-b23c-4279-bb13-f215661b4717 -r 866ae14c-88cf-4f1e-980f-571e031d71b0\n# a shortcut of this is (without -w -r flag)\ncadence workflow showid 3ea6b242-b23c-4279-bb13-f215661b4717 866ae14c-88cf-4f1e-980f-571e031d71b0\n\n# if run_id is not provided, it will show the latest run history of that workflow_id\ncadence workflow show -w 3ea6b242-b23c-4279-bb13-f215661b4717\n# a shortcut of this is\ncadence workflow showid 3ea6b242-b23c-4279-bb13-f215661b4717\n"})}),"\n",(0,s.jsx)(n.h4,{id:"show-workflow-execution-information",children:"Show workflow execution information"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"cadence workflow describe -w 3ea6b242-b23c-4279-bb13-f215661b4717 -r 866ae14c-88cf-4f1e-980f-571e031d71b0\n# a shortcut of this is (without -w -r flag)\ncadence workflow describeid 3ea6b242-b23c-4279-bb13-f215661b4717 866ae14c-88cf-4f1e-980f-571e031d71b0\n\n# if run_id is not provided, it will show the latest workflow execution of that workflow_id\ncadence workflow describe -w 3ea6b242-b23c-4279-bb13-f215661b4717\n# a shortcut of this is\ncadence workflow describeid 3ea6b242-b23c-4279-bb13-f215661b4717\n"})}),"\n",(0,s.jsx)(n.h4,{id:"list-closed-or-open-workflow-executions",children:"List closed or open workflow executions"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"cadence workflow list\n\n# default will only show one page, to view more items, use --more flag\ncadence workflow list -m\n"})}),"\n",(0,s.jsxs)(n.p,{children:["Use ",(0,s.jsx)(n.strong,{children:"--query"})," to list workflows with SQL like "]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"cadence workflow list --query \"WorkflowType='main.SampleParentWorkflow' AND CloseTime = missing \"\n"})}),"\n",(0,s.jsx)(n.p,{children:'This will return all open workflows with workflowType as "main.SampleParentWorkflow".'}),"\n",(0,s.jsx)(n.h4,{id:"query-workflow-execution",children:"Query workflow execution"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:'# use custom query type\ncadence workflow query -w <wid> -r <rid> --qt <query-type>\n\n# use build-in query type "__stack_trace" which is supported by Cadence client library\ncadence workflow query -w <wid> -r <rid> --qt __stack_trace\n# a shortcut to query using __stack_trace is (without --qt flag)\ncadence workflow stack -w <wid> -r <rid>\n'})}),"\n",(0,s.jsx)(n.h4,{id:"signal-cancel-terminate-workflow",children:"Signal, cancel, terminate workflow"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"# signal\ncadence workflow signal -w <wid> -r <rid> -n <signal-name> -i '\"signal-value\"'\n\n# cancel\ncadence workflow cancel -w <wid> -r <rid>\n\n# terminate\ncadence workflow terminate -w <wid> -r <rid> --reason\n"})}),"\n",(0,s.jsx)(n.p,{children:"Terminating a running workflow_execution will record a WorkflowExecutionTerminated event as the closing event in the history. No more decision_tasks will be scheduled for a terminated workflow_execution.\nCanceling a running workflow_execution will record a WorkflowExecutionCancelRequested event in the history, and a new decision_task will be scheduled. The workflow has a chance to do some clean up work after cancellation."}),"\n",(0,s.jsx)(n.h4,{id:"signal-cancel-terminate-workflows-as-a-batch-job",children:"Signal, cancel, terminate workflows as a batch job"}),"\n",(0,s.jsxs)(n.p,{children:["Batch job is based on List Workflow Query(",(0,s.jsx)(n.strong,{children:"--query"}),"). It supports signal, cancel and terminate as batch job type.\nFor terminating workflows as batch job, it will terminte the children recursively."]}),"\n",(0,s.jsx)(n.p,{children:"Start a batch job(using signal as batch type):"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:'cadence --do samples-domain wf batch start --query "WorkflowType=\'main.SampleParentWorkflow\' AND CloseTime=missing" --reason "test" --bt signal --sig testname\nThis batch job will be operating on 5 workflows.\nPlease confirm[Yes/No]:yes\n{\n "jobID": "<batch-job-id>",\n "msg": "batch job is started"\n}\n\n'})}),"\n",(0,s.jsx)(n.p,{children:"You need to remember the JobID or use List command to get all your batch jobs:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"cadence --do samples-domain wf batch list\n"})}),"\n",(0,s.jsx)(n.p,{children:"Describe the progress of a batch job:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"cadence --do samples-domain wf batch desc -jid <batch-job-id>\n"})}),"\n",(0,s.jsx)(n.p,{children:"Terminate a batch job:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"cadence --do samples-domain wf batch terminate -jid <batch-job-id>\n"})}),"\n",(0,s.jsx)(n.p,{children:"Note that the operation performed by a batch will not be rolled back by terminating the batch. However, you can use reset to rollback your workflows."}),"\n",(0,s.jsx)(n.h4,{id:"restart-reset-workflow",children:"Restart, reset workflow"}),"\n",(0,s.jsx)(n.p,{children:"The Reset command allows resetting a workflow to a particular point and continue running from there.\nThere are a lot of use cases:"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:"Rerun a failed workflow from the beginning with the same start parameters."}),"\n",(0,s.jsx)(n.li,{children:"Rerun a failed workflow from the failing point without losing the achieved progress(history)."}),"\n",(0,s.jsx)(n.li,{children:"After deploying new code, reset an open workflow to let the workflow run to different flows."}),"\n"]}),"\n",(0,s.jsx)(n.p,{children:"You can reset to some predefined event types:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:'cadence workflow reset -w <wid> -r <rid> --reset_type <reset_type> --reason "some_reason"\n'})}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:"FirstDecisionCompleted: reset to the beginning of the history."}),"\n",(0,s.jsx)(n.li,{children:"LastDecisionCompleted: reset to the end of the history."}),"\n",(0,s.jsx)(n.li,{children:"LastContinuedAsNew: reset to the end of the history for the previous run."}),"\n"]}),"\n",(0,s.jsx)(n.p,{children:"If you are familiar with the Cadence history event, You can also reset to any decision finish event by using:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:'cadence workflow reset -w <wid> -r <rid> --event_id <decision_finish_event_id> --reason "some_reason"\n'})}),"\n",(0,s.jsx)(n.p,{children:"Some things to note:"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:"When reset, a new run will be kicked off with the same workflowID. But if there is a running execution for the workflow(workflowID), the current run will be terminated."}),"\n",(0,s.jsx)(n.li,{children:"decision_finish_event_id is the ID of events of the type: DecisionTaskComplete/DecisionTaskFailed/DecisionTaskTimeout."}),"\n",(0,s.jsx)(n.li,{children:"To restart a workflow from the beginning, reset to the first decision_task finish event."}),"\n"]}),"\n",(0,s.jsx)(n.p,{children:"To reset multiple workflows, you can use batch reset command:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:'cadence workflow reset-batch --input_file <file_of_workflows_to_reset> --reset_type <reset_type> --reason "some_reason"\n'})}),"\n",(0,s.jsx)(n.h4,{id:"recovery-from-bad-deployment----auto-reset-workflow",children:"Recovery from bad deployment -- auto-reset workflow"}),"\n",(0,s.jsx)(n.p,{children:"If a bad deployment lets a workflow run into a wrong state, you might want to reset the workflow to the point that the bad deployment started to run. But usually it is not easy to find out all the workflows impacted, and every reset point for each workflow. In this case, auto-reset will automatically reset all the workflows given a bad deployment identifier."}),"\n",(0,s.jsxs)(n.p,{children:["Let's get familiar with some concepts. Each deployment will have an identifier, we call it \"",(0,s.jsx)(n.strong,{children:"Binary Checksum"}),'" as it is usually generated by the md5sum of a binary file. For a workflow, each binary checksum will be associated with an ',(0,s.jsx)(n.strong,{children:"auto-reset point"}),", which contains a ",(0,s.jsx)(n.strong,{children:"runID"}),", an ",(0,s.jsx)(n.strong,{children:"eventID"}),", and the ",(0,s.jsx)(n.strong,{children:"created_time"})," that binary/deployment made the first decision for the workflow."]}),"\n",(0,s.jsxs)(n.p,{children:["To find out which ",(0,s.jsx)(n.strong,{children:"binary checksum"})," of the bad deployment to reset, you should be aware of at least one workflow running into a bad state. Use the describe command with ",(0,s.jsx)(n.strong,{children:"--reset_points_only"})," option to show all the reset points:"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"cadence wf desc -w <WorkflowID> --reset_points_only\n+----------------------------------+--------------------------------+--------------------------------------+---------+\n| BINARY CHECKSUM | CREATE TIME | RUNID | EVENTID |\n+----------------------------------+--------------------------------+--------------------------------------+---------+\n| c84c5afa552613a83294793f4e664a7f | 2019-05-24 10:01:00.398455019 | 2dd29ab7-2dd8-4668-83e0-89cae261cfb1 | 4 |\n| aae748fdc557a3f873adbe1dd066713f | 2019-05-24 11:01:00.067691445 | d42d21b8-2adb-4313-b069-3837d44d6ce6 | 4 |\n...\n...\n"})}),"\n",(0,s.jsx)(n.p,{children:"Then use this command to tell Cadence to auto-reset all workflows impacted by the bad deployment. The command will store the bad binary checksum into domain info and trigger a process to reset all your workflows."}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:'cadence --do <YourDomainName> domain update --add_bad_binary aae748fdc557a3f873adbe1dd066713f --reason "rollback bad deployment"\n'})}),"\n",(0,s.jsx)(n.p,{children:"As you add the bad binary checksum to your domain, Cadence will not dispatch any decision_tasks to the bad binary. So make sure that you have rolled back to a good deployment(or roll out new bits with bug fixes). Otherwise your workflow can't make any progress after auto-reset."})]})}function h(e={}){const{wrapper:n}={...(0,a.R)(),...e.components};return n?(0,s.jsx)(n,{...e,children:(0,s.jsx)(d,{...e})}):d(e)}},8453:(e,n,o)=>{o.d(n,{R:()=>i,x:()=>t});var r=o(6540);const s={},a=r.createContext(s);function i(e){const n=r.useContext(a);return r.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function t(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:i(e.components),r.createElement(a.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/f997f9c8.18a43177.js b/assets/js/f997f9c8.18a43177.js deleted file mode 100644 index a547742c5..000000000 --- a/assets/js/f997f9c8.18a43177.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[5138],{9691:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>s,contentTitle:()=>a,default:()=>l,frontMatter:()=>c,metadata:()=>o,toc:()=>d});const o=JSON.parse('{"id":"operation-guide/index","title":"Overview","description":"This document will cover things that you need to know to run a Cadence cluster in production. Topics including: setup, monitoring, maintenance and troubleshooting.","source":"@site/docs/07-operation-guide/index.md","sourceDirName":"07-operation-guide","slug":"/operation-guide/","permalink":"/docs/operation-guide/","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/07-operation-guide/index.md","tags":[],"version":"current","frontMatter":{"layout":"default","title":"Overview","permalink":"/docs/operation-guide"},"sidebar":"docsSidebar","previous":{"title":"Introduction","permalink":"/docs/cli/"},"next":{"title":"Cluster Configuration","permalink":"/docs/operation-guide/setup"}}');var i=n(4848),r=n(8453);const c={layout:"default",title:"Overview",permalink:"/docs/operation-guide"},a="Operation Guide Overview",s={},d=[];function u(e){const t={h1:"h1",header:"header",p:"p",...(0,r.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(t.header,{children:(0,i.jsx)(t.h1,{id:"operation-guide-overview",children:"Operation Guide Overview"})}),"\n",(0,i.jsx)(t.p,{children:"This document will cover things that you need to know to run a Cadence cluster in production. Topics including: setup, monitoring, maintenance and troubleshooting."})]})}function l(e={}){const{wrapper:t}={...(0,r.R)(),...e.components};return t?(0,i.jsx)(t,{...e,children:(0,i.jsx)(u,{...e})}):u(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>c,x:()=>a});var o=n(6540);const i={},r=o.createContext(i);function c(e){const t=o.useContext(r);return o.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function a(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:c(e.components),o.createElement(r.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/f997f9c8.413e3664.js b/assets/js/f997f9c8.413e3664.js new file mode 100644 index 000000000..0eaff96af --- /dev/null +++ b/assets/js/f997f9c8.413e3664.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[5138],{9691:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>s,contentTitle:()=>a,default:()=>l,frontMatter:()=>c,metadata:()=>o,toc:()=>d});const o=JSON.parse('{"id":"operation-guide/index","title":"Overview","description":"This document will cover things that you need to know to run a Cadence cluster in production. Topics including: setup, monitoring, maintenance and troubleshooting.","source":"@site/docs/07-operation-guide/index.md","sourceDirName":"07-operation-guide","slug":"/operation-guide/","permalink":"/Cadence-Docs/docs/operation-guide/","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/07-operation-guide/index.md","tags":[],"version":"current","frontMatter":{"layout":"default","title":"Overview","permalink":"/docs/operation-guide"},"sidebar":"docsSidebar","previous":{"title":"Introduction","permalink":"/Cadence-Docs/docs/cli/"},"next":{"title":"Cluster Configuration","permalink":"/Cadence-Docs/docs/operation-guide/setup"}}');var i=t(4848),r=t(8453);const c={layout:"default",title:"Overview",permalink:"/docs/operation-guide"},a="Operation Guide Overview",s={},d=[];function u(e){const n={h1:"h1",header:"header",p:"p",...(0,r.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.header,{children:(0,i.jsx)(n.h1,{id:"operation-guide-overview",children:"Operation Guide Overview"})}),"\n",(0,i.jsx)(n.p,{children:"This document will cover things that you need to know to run a Cadence cluster in production. Topics including: setup, monitoring, maintenance and troubleshooting."})]})}function l(e={}){const{wrapper:n}={...(0,r.R)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(u,{...e})}):u(e)}},8453:(e,n,t)=>{t.d(n,{R:()=>c,x:()=>a});var o=t(6540);const i={},r=o.createContext(i);function c(e){const n=o.useContext(r);return o.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function a(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:c(e.components),o.createElement(r.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/fa0e6b45.273bd646.js b/assets/js/fa0e6b45.273bd646.js deleted file mode 100644 index 12019d38a..000000000 --- a/assets/js/fa0e6b45.273bd646.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[1328],{8094:(e,t,a)=>{a.r(t),a.d(t,{assets:()=>i,contentTitle:()=>c,default:()=>u,frontMatter:()=>r,metadata:()=>s,toc:()=>l});const s=JSON.parse('{"id":"use-cases/batch-job","title":"Batch job","description":"A lot of batch jobs are not pure data manipulation programs. For those, the existing big data frameworks are the best fit.","source":"@site/docs/02-use-cases/06-batch-job.md","sourceDirName":"02-use-cases","slug":"/use-cases/batch-job","permalink":"/docs/use-cases/batch-job","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/02-use-cases/06-batch-job.md","tags":[],"version":"current","sidebarPosition":6,"frontMatter":{"layout":"default","title":"Batch job","permalink":"/docs/use-cases/batch-job"},"sidebar":"docsSidebar","previous":{"title":"Storage scan","permalink":"/docs/use-cases/partitioned-scan"},"next":{"title":"Infrastructure provisioning","permalink":"/docs/use-cases/provisioning"}}');var n=a(4848),o=a(8453);const r={layout:"default",title:"Batch job",permalink:"/docs/use-cases/batch-job"},c="Batch job",i={},l=[];function d(e){const t={h1:"h1",header:"header",p:"p",...(0,o.R)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(t.header,{children:(0,n.jsx)(t.h1,{id:"batch-job",children:"Batch job"})}),"\n",(0,n.jsx)(t.p,{children:"A lot of batch jobs are not pure data manipulation programs. For those, the existing big data frameworks are the best fit.\nBut if processing a record requires external API calls that might fail and potentially take a long time, Cadence might be preferable."}),"\n",(0,n.jsx)(t.p,{children:"One of our internal Uber customer uses Cadence for end of month statement generation. Each statement requires calls to multiple\nmicroservices and some statements can be really large. Cadence was chosen because it provides hard guarantees around durability of the financial data and seamlessly deals with long running operations, retries, and intermittent failures."})]})}function u(e={}){const{wrapper:t}={...(0,o.R)(),...e.components};return t?(0,n.jsx)(t,{...e,children:(0,n.jsx)(d,{...e})}):d(e)}},8453:(e,t,a)=>{a.d(t,{R:()=>r,x:()=>c});var s=a(6540);const n={},o=s.createContext(n);function r(e){const t=s.useContext(o);return s.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function c(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(n):e.components||n:r(e.components),s.createElement(o.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/fa0e6b45.97bcdd1c.js b/assets/js/fa0e6b45.97bcdd1c.js new file mode 100644 index 000000000..27a6d0362 --- /dev/null +++ b/assets/js/fa0e6b45.97bcdd1c.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[1328],{8094:(e,t,a)=>{a.r(t),a.d(t,{assets:()=>i,contentTitle:()=>c,default:()=>u,frontMatter:()=>r,metadata:()=>s,toc:()=>d});const s=JSON.parse('{"id":"use-cases/batch-job","title":"Batch job","description":"A lot of batch jobs are not pure data manipulation programs. For those, the existing big data frameworks are the best fit.","source":"@site/docs/02-use-cases/06-batch-job.md","sourceDirName":"02-use-cases","slug":"/use-cases/batch-job","permalink":"/Cadence-Docs/docs/use-cases/batch-job","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/02-use-cases/06-batch-job.md","tags":[],"version":"current","sidebarPosition":6,"frontMatter":{"layout":"default","title":"Batch job","permalink":"/docs/use-cases/batch-job"},"sidebar":"docsSidebar","previous":{"title":"Storage scan","permalink":"/Cadence-Docs/docs/use-cases/partitioned-scan"},"next":{"title":"Infrastructure provisioning","permalink":"/Cadence-Docs/docs/use-cases/provisioning"}}');var n=a(4848),o=a(8453);const r={layout:"default",title:"Batch job",permalink:"/docs/use-cases/batch-job"},c="Batch job",i={},d=[];function l(e){const t={h1:"h1",header:"header",p:"p",...(0,o.R)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(t.header,{children:(0,n.jsx)(t.h1,{id:"batch-job",children:"Batch job"})}),"\n",(0,n.jsx)(t.p,{children:"A lot of batch jobs are not pure data manipulation programs. For those, the existing big data frameworks are the best fit.\nBut if processing a record requires external API calls that might fail and potentially take a long time, Cadence might be preferable."}),"\n",(0,n.jsx)(t.p,{children:"One of our internal Uber customer uses Cadence for end of month statement generation. Each statement requires calls to multiple\nmicroservices and some statements can be really large. Cadence was chosen because it provides hard guarantees around durability of the financial data and seamlessly deals with long running operations, retries, and intermittent failures."})]})}function u(e={}){const{wrapper:t}={...(0,o.R)(),...e.components};return t?(0,n.jsx)(t,{...e,children:(0,n.jsx)(l,{...e})}):l(e)}},8453:(e,t,a)=>{a.d(t,{R:()=>r,x:()=>c});var s=a(6540);const n={},o=s.createContext(n);function r(e){const t=s.useContext(o);return s.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function c(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(n):e.components||n:r(e.components),s.createElement(o.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/fcdcf093.5cc5644d.js b/assets/js/fcdcf093.5cc5644d.js deleted file mode 100644 index ac84c443d..000000000 --- a/assets/js/fcdcf093.5cc5644d.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[9051],{4271:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>c,contentTitle:()=>o,default:()=>u,frontMatter:()=>r,metadata:()=>s,toc:()=>l});const s=JSON.parse('{"id":"use-cases/event-driven","title":"Event driven application","description":"Many applications listen to multiple sources, update the state of correspondent business entities,","source":"@site/docs/02-use-cases/04-event-driven.md","sourceDirName":"02-use-cases","slug":"/use-cases/event-driven","permalink":"/docs/use-cases/event-driven","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/02-use-cases/04-event-driven.md","tags":[],"version":"current","sidebarPosition":4,"frontMatter":{"layout":"default","title":"Event driven application","permalink":"/docs/use-cases/event-driven"},"sidebar":"docsSidebar","previous":{"title":"Polling","permalink":"/docs/use-cases/polling"},"next":{"title":"Storage scan","permalink":"/docs/use-cases/partitioned-scan"}}');var a=n(4848),i=n(8453);const r={layout:"default",title:"Event driven application",permalink:"/docs/use-cases/event-driven"},o="Event driven application",c={},l=[];function d(e){const t={h1:"h1",header:"header",li:"li",p:"p",ul:"ul",...(0,i.R)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(t.header,{children:(0,a.jsx)(t.h1,{id:"event-driven-application",children:"Event driven application"})}),"\n",(0,a.jsx)(t.p,{children:"Many applications listen to multiple event sources, update the state of correspondent business entities,\nand have to execute actions if some state is reached.\nCadence is a good fit for many of these. It has direct support for asynchronous events (aka signals),\nhas a simple programming model that obscures a lot of complexity\naround state persistence, and ensures external action execution through built-in retries."}),"\n",(0,a.jsx)(t.p,{children:"Real-world examples:"}),"\n",(0,a.jsxs)(t.ul,{children:["\n",(0,a.jsx)(t.li,{children:"Fraud detection where workflow reacts to events generated by consumer behavior"}),"\n",(0,a.jsx)(t.li,{children:"Customer loyalty program where the workflow accumulates reward points and applies them when requested"}),"\n"]})]})}function u(e={}){const{wrapper:t}={...(0,i.R)(),...e.components};return t?(0,a.jsx)(t,{...e,children:(0,a.jsx)(d,{...e})}):d(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>r,x:()=>o});var s=n(6540);const a={},i=s.createContext(a);function r(e){const t=s.useContext(i);return s.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function o(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:r(e.components),s.createElement(i.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/fcdcf093.652e25f3.js b/assets/js/fcdcf093.652e25f3.js new file mode 100644 index 000000000..2465d90d0 --- /dev/null +++ b/assets/js/fcdcf093.652e25f3.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[9051],{4271:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>c,contentTitle:()=>r,default:()=>u,frontMatter:()=>i,metadata:()=>s,toc:()=>d});const s=JSON.parse('{"id":"use-cases/event-driven","title":"Event driven application","description":"Many applications listen to multiple sources, update the state of correspondent business entities,","source":"@site/docs/02-use-cases/04-event-driven.md","sourceDirName":"02-use-cases","slug":"/use-cases/event-driven","permalink":"/Cadence-Docs/docs/use-cases/event-driven","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/02-use-cases/04-event-driven.md","tags":[],"version":"current","sidebarPosition":4,"frontMatter":{"layout":"default","title":"Event driven application","permalink":"/docs/use-cases/event-driven"},"sidebar":"docsSidebar","previous":{"title":"Polling","permalink":"/Cadence-Docs/docs/use-cases/polling"},"next":{"title":"Storage scan","permalink":"/Cadence-Docs/docs/use-cases/partitioned-scan"}}');var a=n(4848),o=n(8453);const i={layout:"default",title:"Event driven application",permalink:"/docs/use-cases/event-driven"},r="Event driven application",c={},d=[];function l(e){const t={h1:"h1",header:"header",li:"li",p:"p",ul:"ul",...(0,o.R)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(t.header,{children:(0,a.jsx)(t.h1,{id:"event-driven-application",children:"Event driven application"})}),"\n",(0,a.jsx)(t.p,{children:"Many applications listen to multiple event sources, update the state of correspondent business entities,\nand have to execute actions if some state is reached.\nCadence is a good fit for many of these. It has direct support for asynchronous events (aka signals),\nhas a simple programming model that obscures a lot of complexity\naround state persistence, and ensures external action execution through built-in retries."}),"\n",(0,a.jsx)(t.p,{children:"Real-world examples:"}),"\n",(0,a.jsxs)(t.ul,{children:["\n",(0,a.jsx)(t.li,{children:"Fraud detection where workflow reacts to events generated by consumer behavior"}),"\n",(0,a.jsx)(t.li,{children:"Customer loyalty program where the workflow accumulates reward points and applies them when requested"}),"\n"]})]})}function u(e={}){const{wrapper:t}={...(0,o.R)(),...e.components};return t?(0,a.jsx)(t,{...e,children:(0,a.jsx)(l,{...e})}):l(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>i,x:()=>r});var s=n(6540);const a={},o=s.createContext(a);function i(e){const t=s.useContext(o);return s.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function r(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:i(e.components),s.createElement(o.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/fda2e45a.b7d575ef.js b/assets/js/fda2e45a.b7d575ef.js new file mode 100644 index 000000000..22a2adba5 --- /dev/null +++ b/assets/js/fda2e45a.b7d575ef.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[1653],{8856:(e,n,o)=>{o.r(n),o.d(n,{assets:()=>c,contentTitle:()=>r,default:()=>d,frontMatter:()=>s,metadata:()=>t,toc:()=>u});var t=o(4131),a=o(4848),i=o(8453);const s={title:"Announcing Cadence OSS office hours and community sync up",date:new Date("2021-10-13T00:00:00.000Z"),authors:"meiliang86",tags:["announcement","roadmap"]},r=void 0,c={authorsImageUrls:[void 0]},u=[];function l(e){const n={a:"a",p:"p",strong:"strong",...(0,i.R)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(n.p,{children:"Are you a current Cadence user, do you operate Cadence services, or are you interested in learning about workflow technologies and wonder what problems Cadence could solve for you? We would like to talk to you!"}),"\n",(0,a.jsxs)(n.p,{children:["Our team has spent a significant amount of time working with users and partner teams at Uber to design, scale and operate their workflows. This helps our users understand the technology better, smooth their learning curve and ramp up experience, and at the same time allows us to get fast and direct feedback so we can improve the developer experience and close feature gaps. As our product and community grows, we would like to expand this practice to our users in the OSS community. ",(0,a.jsx)(n.strong,{children:"For the first time ever, members of the Cadence team along with core contributors from the community will host bi-weekly office hours to answer any questions you have about Cadence, or workflow technology in general."})," We can also dedicate future sessions to specific topics that have a common interest. Please don\u2019t hesitate to let us know your thoughts."]}),"\n",(0,a.jsx)(n.p,{children:"Please join a session if you would like to talk about any of the following topics:"}),"\n",(0,a.jsxs)("ol",{children:[(0,a.jsx)("li",{children:"Understand what Cadence is and why it might be useful for you and your company"}),(0,a.jsx)("li",{children:"Guidance about running Cadence services and workers in production"}),(0,a.jsx)("li",{children:"Workflow design and operation consultation"}),(0,a.jsx)("li",{children:"Product update, future roadmaps as well as collaboration opportunities"})]}),"\n",(0,a.jsx)(n.p,{children:"Building and maintaining a healthy and growing community is the key to the success of Cadence, and one of the top priorities for our team. We would like to use the office hours as an opportunity to understand and help our customers, seek feedback, and forge partnerships. We look forward to seeing you in one of the meetings."}),"\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.strong,{children:"Upcoming Office Hours"})}),"\n",(0,a.jsxs)(n.p,{children:["As we have a geo-distributed userbase, we are still trying to figure out a time that works for most of the people. In the meanwhile, we will manually schedule the first few instances of the meeting until we settle on a fixed schedule. Our next office hours will take place on ",(0,a.jsx)(n.strong,{children:"Thursday, October 21 2pm-3pm PT/5pm-6pm EST/9pm-10pm GMT"}),". Please join via ",(0,a.jsx)(n.a,{href:"https://uber.zoom.us/j/92356466350?pwd=RFVTc2pwV0xoVTdlK3VxN3N2eU5UZz09",children:"this zoom link"}),"."]})]})}function d(e={}){const{wrapper:n}={...(0,i.R)(),...e.components};return n?(0,a.jsx)(n,{...e,children:(0,a.jsx)(l,{...e})}):l(e)}},8453:(e,n,o)=>{o.d(n,{R:()=>s,x:()=>r});var t=o(6540);const a={},i=t.createContext(a);function s(e){const n=t.useContext(i);return t.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function r(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:s(e.components),t.createElement(i.Provider,{value:n},e.children)}},4131:e=>{e.exports=JSON.parse('{"permalink":"/Cadence-Docs/blog/2021/10/13/announcing-cadence-oss-office-hours-and-community-sync-up","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2021-10-13-announcing-cadence-oss-office-hours-and-community-sync-up.md","source":"@site/blog/2021-10-13-announcing-cadence-oss-office-hours-and-community-sync-up.md","title":"Announcing Cadence OSS office hours and community sync up","description":"Are you a current Cadence user, do you operate Cadence services, or are you interested in learning about workflow technologies and wonder what problems Cadence could solve for you? We would like to talk to you!","date":"2021-10-13T00:00:00.000Z","tags":[{"inline":false,"label":"Announcement","permalink":"/Cadence-Docs/blog/tags/announcements","description":"Announcement tag description"},{"inline":false,"label":"Roadmap","permalink":"/Cadence-Docs/blog/tags/roadmap","description":"Roadmap tag description"}],"readingTime":1.83,"hasTruncateMarker":true,"authors":[{"name":"Liang Mei","title":"Engineering Manager @ Uber","url":"https://www.linkedin.com/in/meiliang86/","page":{"permalink":"/Cadence-Docs/blog/authors/meiliang-86"},"socials":{"linkedin":"https://www.linkedin.com/in/meiliang86/","github":"https://github.com/meiliang86"},"imageURL":"https://github.com/meiliang86.png","key":"meiliang86"}],"frontMatter":{"title":"Announcing Cadence OSS office hours and community sync up","date":"2021-10-13T00:00:00.000Z","authors":"meiliang86","tags":["announcement","roadmap"]},"unlisted":false,"prevItem":{"title":"Moving to gRPC","permalink":"/Cadence-Docs/blog/2021/10/19/2021-10-19-moving-to-grpc/moving-to-grpc"},"nextItem":{"title":"Long-term commitment and support for the Cadence project, and its community","permalink":"/Cadence-Docs/blog/2021/09/30/long-term-commitment-and-support-for-the-cadence-project-and-its-community"}}')}}]); \ No newline at end of file diff --git a/assets/js/fda2e45a.d2d91c08.js b/assets/js/fda2e45a.d2d91c08.js deleted file mode 100644 index c122bf63a..000000000 --- a/assets/js/fda2e45a.d2d91c08.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[1653],{8856:(e,n,o)=>{o.r(n),o.d(n,{assets:()=>c,contentTitle:()=>s,default:()=>d,frontMatter:()=>r,metadata:()=>t,toc:()=>u});var t=o(4131),i=o(4848),a=o(8453);const r={title:"Announcing Cadence OSS office hours and community sync up",date:new Date("2021-10-13T00:00:00.000Z"),authors:"meiliang86",tags:["announcement","roadmap"]},s=void 0,c={authorsImageUrls:[void 0]},u=[];function l(e){const n={a:"a",p:"p",strong:"strong",...(0,a.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.p,{children:"Are you a current Cadence user, do you operate Cadence services, or are you interested in learning about workflow technologies and wonder what problems Cadence could solve for you? We would like to talk to you!"}),"\n",(0,i.jsxs)(n.p,{children:["Our team has spent a significant amount of time working with users and partner teams at Uber to design, scale and operate their workflows. This helps our users understand the technology better, smooth their learning curve and ramp up experience, and at the same time allows us to get fast and direct feedback so we can improve the developer experience and close feature gaps. As our product and community grows, we would like to expand this practice to our users in the OSS community. ",(0,i.jsx)(n.strong,{children:"For the first time ever, members of the Cadence team along with core contributors from the community will host bi-weekly office hours to answer any questions you have about Cadence, or workflow technology in general."})," We can also dedicate future sessions to specific topics that have a common interest. Please don\u2019t hesitate to let us know your thoughts."]}),"\n",(0,i.jsx)(n.p,{children:"Please join a session if you would like to talk about any of the following topics:"}),"\n",(0,i.jsxs)("ol",{children:[(0,i.jsx)("li",{children:"Understand what Cadence is and why it might be useful for you and your company"}),(0,i.jsx)("li",{children:"Guidance about running Cadence services and workers in production"}),(0,i.jsx)("li",{children:"Workflow design and operation consultation"}),(0,i.jsx)("li",{children:"Product update, future roadmaps as well as collaboration opportunities"})]}),"\n",(0,i.jsx)(n.p,{children:"Building and maintaining a healthy and growing community is the key to the success of Cadence, and one of the top priorities for our team. We would like to use the office hours as an opportunity to understand and help our customers, seek feedback, and forge partnerships. We look forward to seeing you in one of the meetings."}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.strong,{children:"Upcoming Office Hours"})}),"\n",(0,i.jsxs)(n.p,{children:["As we have a geo-distributed userbase, we are still trying to figure out a time that works for most of the people. In the meanwhile, we will manually schedule the first few instances of the meeting until we settle on a fixed schedule. Our next office hours will take place on ",(0,i.jsx)(n.strong,{children:"Thursday, October 21 2pm-3pm PT/5pm-6pm EST/9pm-10pm GMT"}),". Please join via ",(0,i.jsx)(n.a,{href:"https://uber.zoom.us/j/92356466350?pwd=RFVTc2pwV0xoVTdlK3VxN3N2eU5UZz09",children:"this zoom link"}),"."]})]})}function d(e={}){const{wrapper:n}={...(0,a.R)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(l,{...e})}):l(e)}},8453:(e,n,o)=>{o.d(n,{R:()=>r,x:()=>s});var t=o(6540);const i={},a=t.createContext(i);function r(e){const n=t.useContext(a);return t.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function s(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:r(e.components),t.createElement(a.Provider,{value:n},e.children)}},4131:e=>{e.exports=JSON.parse('{"permalink":"/blog/2021/10/13/announcing-cadence-oss-office-hours-and-community-sync-up","editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/blog/2021-10-13-announcing-cadence-oss-office-hours-and-community-sync-up.md","source":"@site/blog/2021-10-13-announcing-cadence-oss-office-hours-and-community-sync-up.md","title":"Announcing Cadence OSS office hours and community sync up","description":"Are you a current Cadence user, do you operate Cadence services, or are you interested in learning about workflow technologies and wonder what problems Cadence could solve for you? We would like to talk to you!","date":"2021-10-13T00:00:00.000Z","tags":[{"inline":false,"label":"Announcement","permalink":"/blog/tags/announcements","description":"Announcement tag description"},{"inline":false,"label":"Roadmap","permalink":"/blog/tags/roadmap","description":"Roadmap tag description"}],"readingTime":1.83,"hasTruncateMarker":true,"authors":[{"name":"Liang Mei","title":"Engineering Manager @ Uber","url":"https://www.linkedin.com/in/meiliang86/","page":{"permalink":"/blog/authors/meiliang-86"},"socials":{"linkedin":"https://www.linkedin.com/in/meiliang86/","github":"https://github.com/meiliang86"},"imageURL":"https://github.com/meiliang86.png","key":"meiliang86"}],"frontMatter":{"title":"Announcing Cadence OSS office hours and community sync up","date":"2021-10-13T00:00:00.000Z","authors":"meiliang86","tags":["announcement","roadmap"]},"unlisted":false,"prevItem":{"title":"Moving to gRPC","permalink":"/blog/2021/10/19/2021-10-19-moving-to-grpc/moving-to-grpc"},"nextItem":{"title":"Long-term commitment and support for the Cadence project, and its community","permalink":"/blog/2021/09/30/long-term-commitment-and-support-for-the-cadence-project-and-its-community"}}')}}]); \ No newline at end of file diff --git a/assets/js/fde82b69.993e17e6.js b/assets/js/fde82b69.993e17e6.js new file mode 100644 index 000000000..d8b1a21d9 --- /dev/null +++ b/assets/js/fde82b69.993e17e6.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[6185],{5410:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>a,contentTitle:()=>l,default:()=>h,frontMatter:()=>o,metadata:()=>s,toc:()=>c});const s=JSON.parse('{"id":"concepts/search-workflows","title":"Search workflows(Advanced visibility)","description":"Introduction","source":"@site/docs/03-concepts/09-search-workflows.md","sourceDirName":"03-concepts","slug":"/concepts/search-workflows","permalink":"/Cadence-Docs/docs/concepts/search-workflows","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/03-concepts/09-search-workflows.md","tags":[],"version":"current","sidebarPosition":9,"frontMatter":{"layout":"default","title":"Search workflows(Advanced visibility)","permalink":"/docs/concepts/search-workflows"},"sidebar":"docsSidebar","previous":{"title":"Cross DC replication","permalink":"/Cadence-Docs/docs/concepts/cross-dc-replication"},"next":{"title":"HTTP API","permalink":"/Cadence-Docs/docs/concepts/http-api"}}');var r=t(4848),i=t(8453);const o={layout:"default",title:"Search workflows(Advanced visibility)",permalink:"/docs/concepts/search-workflows"},l="Searching Workflows(Advanced visibility)",a={},c=[{value:"Introduction",id:"introduction",level:2},{value:"Memo vs Search Attributes",id:"memo-vs-search-attributes",level:2},{value:"Search Attributes (Go Client Usage)",id:"search-attributes-go-client-usage",level:2},{value:"Allow Listing Search Attributes",id:"allow-listing-search-attributes",level:3},{value:"Keyword vs String(Text)",id:"keyword-vs-stringtext",level:4},{value:"Value Types",id:"value-types",level:3},{value:"Limit",id:"limit",level:3},{value:"Upsert Search Attributes in Workflow",id:"upsert-search-attributes-in-workflow",level:3},{value:"ContinueAsNew and Cron",id:"continueasnew-and-cron",level:3},{value:"Query Capabilities",id:"query-capabilities",level:2},{value:"Supported Operators",id:"supported-operators",level:3},{value:"Default Attributes",id:"default-attributes",level:3},{value:"General Notes About Queries",id:"general-notes-about-queries",level:3},{value:"Tools Support",id:"tools-support",level:2},{value:"CLI",id:"cli",level:3},{value:"Start Workflow with Search Attributes",id:"start-workflow-with-search-attributes",level:4},{value:"Search Workflows with List API/Command",id:"search-workflows-with-list-apicommand",level:4},{value:"Count Workflows with Count API/Command",id:"count-workflows-with-count-apicommand",level:4},{value:"Web UI Support",id:"web-ui-support",level:3},{value:"TLS Support for connecting to Elasticsearch",id:"tls-support-for-connecting-to-elasticsearch",level:3},{value:"Running Locally",id:"running-locally",level:2},{value:"Running in Production",id:"running-in-production",level:2}];function d(e){const n={a:"a",code:"code",em:"em",h1:"h1",h2:"h2",h3:"h3",h4:"h4",header:"header",li:"li",ol:"ol",p:"p",pre:"pre",strong:"strong",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",ul:"ul",...(0,i.R)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(n.header,{children:(0,r.jsx)(n.h1,{id:"searching-workflowsadvanced-visibility",children:"Searching Workflows(Advanced visibility)"})}),"\n",(0,r.jsx)(n.h2,{id:"introduction",children:"Introduction"}),"\n",(0,r.jsxs)(n.p,{children:["Cadence supports creating workflows with customized key-value pairs, updating the information within the workflow code, and then listing/searching workflows with a SQL-like query. For example, you can create workflows with keys ",(0,r.jsx)(n.code,{children:"city"})," and ",(0,r.jsx)(n.code,{children:"age"}),", then search all workflows with ",(0,r.jsx)(n.code,{children:"city = seattle and age > 22"}),"."]}),"\n",(0,r.jsxs)(n.p,{children:["Also note that normal workflow properties like start time and workflow type can be queried as well. For example, the following query could be specified when ",(0,r.jsx)(n.a,{href:"/docs/cli#list-closed-or-open-workflow-executions",children:"listing workflows from the CLI"})," or using the list APIs (",(0,r.jsx)(n.a,{href:"https://godoc.org/go.uber.org/cadence/client#Client",children:"Go"}),", ",(0,r.jsx)(n.a,{href:"https://static.javadoc.io/com.uber.cadence/cadence-client/2.6.0/com/cadence-workflow/cadence/WorkflowService.Iface.html#ListWorkflowExecutions-com.uber.cadence.ListWorkflowExecutionsRequest-",children:"Java"}),"):"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-sql",children:'WorkflowType = "main.Workflow" AND CloseStatus != "completed" AND (StartTime >\n "2019-06-07T16:46:34-08:00" OR CloseTime > "2019-06-07T16:46:34-08:00")\n ORDER BY StartTime DESC\n'})}),"\n",(0,r.jsxs)(n.p,{children:["In other places, this is also called as ",(0,r.jsx)(n.code,{children:"advanced visibility"}),". While ",(0,r.jsx)(n.code,{children:"basic visibility"})," is referred to basic listing without being able to search."]}),"\n",(0,r.jsx)(n.h2,{id:"memo-vs-search-attributes",children:"Memo vs Search Attributes"}),"\n",(0,r.jsx)(n.p,{children:"Cadence offers two methods for creating workflows with key-value pairs: memo and search attributes. Memo can only be provided on workflow start. Also, memo data are not indexed, and are therefore not searchable. Memo data are visible when listing workflows using the list APIs. Search attributes data are indexed so you can search workflows by querying on these attributes. However, search attributes require the use of Elasticsearch."}),"\n",(0,r.jsxs)(n.p,{children:["Memo and search attributes are available in the Go client in ",(0,r.jsx)(n.a,{href:"https://godoc.org/go.uber.org/cadence/internal#StartWorkflowOptions",children:"StartWorkflowOptions"}),"."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-go",children:"type StartWorkflowOptions struct {\n // ...\n\n // Memo - Optional non-indexed info that will be shown in list workflow.\n Memo map[string]interface{}\n\n // SearchAttributes - Optional indexed info that can be used in query of List/Scan/Count workflow APIs (only\n // supported when Cadence server is using Elasticsearch). The key and value type must be registered on Cadence server side.\n // Use GetSearchAttributes API to get valid key and corresponding value type.\n SearchAttributes map[string]interface{}\n}\n"})}),"\n",(0,r.jsxs)(n.p,{children:["In the Java client, the ",(0,r.jsx)(n.em,{children:"WorkflowOptions.Builder"})," has similar methods for ",(0,r.jsx)(n.a,{href:"https://static.javadoc.io/com.uber.cadence/cadence-client/2.6.0/com/cadence-workflow/cadence/client/WorkflowOptions.Builder.html#setMemo-java.util.Map-",children:"memo"})," and ",(0,r.jsx)(n.a,{href:"https://static.javadoc.io/com.uber.cadence/cadence-client/2.6.0/com/cadence-workflow/cadence/client/WorkflowOptions.Builder.html#setSearchAttributes-java.util.Map-",children:"search attributes"}),"."]}),"\n",(0,r.jsx)(n.p,{children:"Some important distinctions between memo and search attributes:"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"Memo can support all data types because it is not indexed. Search attributes only support basic data types (including String(aka Text), Int, Float, Bool, Datetime) because it is indexed by Elasticsearch."}),"\n",(0,r.jsx)(n.li,{children:"Memo does not restrict on key names. Search attributes require that keys are allowlisted before using them because Elasticsearch has a limit on indexed keys."}),"\n",(0,r.jsx)(n.li,{children:"Memo doesn't require Cadence clusters to depend on Elasticsearch while search attributes only works with Elasticsearch."}),"\n"]}),"\n",(0,r.jsx)(n.h2,{id:"search-attributes-go-client-usage",children:"Search Attributes (Go Client Usage)"}),"\n",(0,r.jsxs)(n.p,{children:["When using the Cadence Go client, provide key-value pairs as SearchAttributes in ",(0,r.jsx)(n.a,{href:"https://godoc.org/go.uber.org/cadence/internal#StartWorkflowOptions",children:"StartWorkflowOptions"}),"."]}),"\n",(0,r.jsxs)(n.p,{children:["SearchAttributes is ",(0,r.jsx)(n.code,{children:"map[string]interface{}"})," where the keys need to be allowlisted so that Cadence knows the attribute key name and value type. The value provided in the map must be the same type as registered."]}),"\n",(0,r.jsx)(n.h3,{id:"allow-listing-search-attributes",children:"Allow Listing Search Attributes"}),"\n",(0,r.jsx)(n.p,{children:"Start by querying the list of search attributes using the "}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-bash",children:"$ cadence --domain samples-domain cl get-search-attr\n+---------------------+------------+\n| KEY | VALUE TYPE |\n+---------------------+------------+\n| CloseStatus | INT |\n| CloseTime | INT |\n| CustomBoolField | DOUBLE |\n| CustomDatetimeField | DATETIME |\n| CustomDomain | KEYWORD |\n| CustomDoubleField | BOOL |\n| CustomIntField | INT |\n| CustomKeywordField | KEYWORD |\n| CustomStringField | STRING |\n| DomainID | KEYWORD |\n| ExecutionTime | INT |\n| HistoryLength | INT |\n| RunID | KEYWORD |\n| StartTime | INT |\n| WorkflowID | KEYWORD |\n| WorkflowType | KEYWORD |\n+---------------------+------------+\n"})}),"\n",(0,r.jsx)(n.p,{children:"Use the admin CLI to add a new search attribute:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-bash",children:"cadence --domain samples-domain adm cl asa --search_attr_key NewKey --search_attr_type 1\n"})}),"\n",(0,r.jsx)(n.p,{children:"The numbers for the attribute types map as follows:"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"0 = String(Text)"}),"\n",(0,r.jsx)(n.li,{children:"1 = Keyword"}),"\n",(0,r.jsx)(n.li,{children:"2 = Int"}),"\n",(0,r.jsx)(n.li,{children:"3 = Double"}),"\n",(0,r.jsx)(n.li,{children:"4 = Bool"}),"\n",(0,r.jsx)(n.li,{children:"5 = DateTime"}),"\n"]}),"\n",(0,r.jsx)(n.h4,{id:"keyword-vs-stringtext",children:"Keyword vs String(Text)"}),"\n",(0,r.jsxs)(n.p,{children:["Note 1: ",(0,r.jsx)(n.strong,{children:"String"})," has been renamed to ",(0,r.jsx)(n.strong,{children:"Text"})," in ",(0,r.jsx)(n.a,{href:"https://www.elastic.co/blog/strings-are-dead-long-live-strings",children:"ElasticSearch"}),". Cadence is also ",(0,r.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence/issues/4604",children:"planning"})," to rename it."]}),"\n",(0,r.jsxs)(n.p,{children:["Note 2: ",(0,r.jsx)(n.strong,{children:"Keyword"})," and ",(0,r.jsx)(n.strong,{children:"String(Text)"})," are concepts taken from Elasticsearch. Each word in a ",(0,r.jsx)(n.strong,{children:"String(Text)"})," is considered a searchable keyword. For a UUID, that can be problematic as Elasticsearch will index each portion of the UUID separately. To have the whole string considered as a searchable keyword, use the ",(0,r.jsx)(n.strong,{children:"Keyword"})," type."]}),"\n",(0,r.jsx)(n.p,{children:'For example, key RunID with value "2dd29ab7-2dd8-4668-83e0-89cae261cfb1"'}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:["as a ",(0,r.jsx)(n.strong,{children:"Keyword"}),' will only be matched by RunID = "2dd29ab7-2dd8-4668-83e0-89cae261cfb1" (or in the future with ',(0,r.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence/issues/1137",children:"regular expressions"}),")"]}),"\n",(0,r.jsxs)(n.li,{children:["as a ",(0,r.jsx)(n.strong,{children:"String(Text)"}),' will be matched by RunID = "2dd8", which may cause unwanted matches']}),"\n"]}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.strong,{children:"Note:"})," String(Text) type can not be used in Order By query."]}),"\n",(0,r.jsx)(n.p,{children:"There are some pre-allowlisted search attributes that are handy for testing:"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"CustomKeywordField"}),"\n",(0,r.jsx)(n.li,{children:"CustomIntField"}),"\n",(0,r.jsx)(n.li,{children:"CustomDoubleField"}),"\n",(0,r.jsx)(n.li,{children:"CustomBoolField"}),"\n",(0,r.jsx)(n.li,{children:"CustomDatetimeField"}),"\n",(0,r.jsx)(n.li,{children:"CustomStringField"}),"\n"]}),"\n",(0,r.jsx)(n.p,{children:"Their types are indicated in their names."}),"\n",(0,r.jsx)(n.h3,{id:"value-types",children:"Value Types"}),"\n",(0,r.jsx)(n.p,{children:"Here are the Search Attribute value types and their correspondent Golang types:"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"Keyword = string"}),"\n",(0,r.jsx)(n.li,{children:"Int = int64"}),"\n",(0,r.jsx)(n.li,{children:"Double = float64"}),"\n",(0,r.jsx)(n.li,{children:"Bool = bool"}),"\n",(0,r.jsx)(n.li,{children:"Datetime = time.Time"}),"\n",(0,r.jsx)(n.li,{children:"String = string"}),"\n"]}),"\n",(0,r.jsx)(n.h3,{id:"limit",children:"Limit"}),"\n",(0,r.jsx)(n.p,{children:"We recommend limiting the number of Elasticsearch indexes by enforcing limits on the following:"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"Number of keys: 100 per workflow"}),"\n",(0,r.jsx)(n.li,{children:"Size of value: 2kb per value"}),"\n",(0,r.jsx)(n.li,{children:"Total size of key and values: 40kb per workflow"}),"\n"]}),"\n",(0,r.jsx)(n.p,{children:"Cadence reserves keys like DomainID, WorkflowID, and RunID. These can only be used in list queries. The values are not updatable."}),"\n",(0,r.jsx)(n.h3,{id:"upsert-search-attributes-in-workflow",children:"Upsert Search Attributes in Workflow"}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.a,{href:"https://godoc.org/go.uber.org/cadence/workflow#UpsertSearchAttributes",children:"UpsertSearchAttributes"})," is used to add or update search attributes from within the workflow code."]}),"\n",(0,r.jsxs)(n.p,{children:["Go samples for search attributes can be found at ",(0,r.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence-samples/tree/master/cmd/samples/recipes/searchattributes",children:"github.com/cadence-workflow/cadence-samples"}),"."]}),"\n",(0,r.jsx)(n.p,{children:"UpsertSearchAttributes will merge attributes to the existing map in the workflow. Consider this example workflow code:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-go",children:'func MyWorkflow(ctx workflow.Context, input string) error {\n\n attr1 := map[string]interface{}{\n "CustomIntField": 1,\n "CustomBoolField": true,\n }\n workflow.UpsertSearchAttributes(ctx, attr1)\n\n attr2 := map[string]interface{}{\n "CustomIntField": 2,\n "CustomKeywordField": "seattle",\n }\n workflow.UpsertSearchAttributes(ctx, attr2)\n}\n'})}),"\n",(0,r.jsx)(n.p,{children:"After the second call to UpsertSearchAttributes, the map will contain:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-go",children:'map[string]interface{}{\n "CustomIntField": 2,\n "CustomBoolField": true,\n "CustomKeywordField": "seattle",\n}\n'})}),"\n",(0,r.jsxs)(n.p,{children:["There is no support for removing a field. To achieve a similar effect, set the field to a sentinel value. For example, to remove \u201cCustomKeywordField\u201d, update it to \u201cimpossibleVal\u201d. Then searching ",(0,r.jsx)(n.code,{children:"CustomKeywordField != \u2018impossibleVal\u2019"}),' will match workflows with CustomKeywordField not equal to "impossibleVal", which ',(0,r.jsx)(n.strong,{children:"includes"})," workflows without the CustomKeywordField set."]}),"\n",(0,r.jsxs)(n.p,{children:["Use ",(0,r.jsx)(n.code,{children:"workflow.GetInfo"})," to get current search attributes."]}),"\n",(0,r.jsx)(n.h3,{id:"continueasnew-and-cron",children:"ContinueAsNew and Cron"}),"\n",(0,r.jsxs)(n.p,{children:["When performing a ",(0,r.jsx)(n.a,{href:"/docs/go-client/continue-as-new/",children:"ContinueAsNew"})," or using ",(0,r.jsx)(n.a,{href:"/docs/go-client/distributed-cron/",children:"Cron"}),", search attributes (and memo) will be carried over to the new run by default."]}),"\n",(0,r.jsx)(n.h2,{id:"query-capabilities",children:"Query Capabilities"}),"\n",(0,r.jsxs)(n.p,{children:["Query workflows by using a SQL-like where clause when ",(0,r.jsx)(n.a,{href:"/docs/cli#list-closed-or-open-workflow-executions",children:"listing workflows from the CLI"})," or using the list APIs (",(0,r.jsx)(n.a,{href:"https://godoc.org/go.uber.org/cadence/client#Client",children:"Go"}),", ",(0,r.jsx)(n.a,{href:"https://static.javadoc.io/com.uber.cadence/cadence-client/2.6.0/com/cadence-workflow/cadence/WorkflowService.Iface.html#ListWorkflowExecutions-com.uber.cadence.ListWorkflowExecutionsRequest-",children:"Java"}),")."]}),"\n",(0,r.jsx)(n.p,{children:"Note that you will only see workflows from one domain when querying."}),"\n",(0,r.jsx)(n.h3,{id:"supported-operators",children:"Supported Operators"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.code,{children:"AND"}),", ",(0,r.jsx)(n.code,{children:"OR"}),", ",(0,r.jsx)(n.code,{children:"()"})]}),"\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.code,{children:"="}),", ",(0,r.jsx)(n.code,{children:"!="}),", ",(0,r.jsx)(n.code,{children:">"}),", ",(0,r.jsx)(n.code,{children:">="}),", ",(0,r.jsx)(n.code,{children:"<"}),", ",(0,r.jsx)(n.code,{children:"<="})]}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.code,{children:"IN"})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.code,{children:"BETWEEN ... AND"})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.code,{children:"ORDER BY"})}),"\n"]}),"\n",(0,r.jsx)(n.h3,{id:"default-attributes",children:"Default Attributes"}),"\n",(0,r.jsx)(n.p,{children:"More and more default attributes are added in newer versions.\nPlease get the by using the CLI get-search-attr command or the GetSearchAttributes API.\nSome names and types are as follows:"}),"\n",(0,r.jsxs)(n.table,{children:[(0,r.jsx)(n.thead,{children:(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.th,{children:"KEY"}),(0,r.jsx)(n.th,{children:"VALUE TYPE"})]})}),(0,r.jsxs)(n.tbody,{children:[(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"CloseStatus"}),(0,r.jsx)(n.td,{children:"INT"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"CloseTime"}),(0,r.jsx)(n.td,{children:"INT"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"CustomBoolField"}),(0,r.jsx)(n.td,{children:"DOUBLE"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"CustomDatetimeField"}),(0,r.jsx)(n.td,{children:"DATETIME"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"CustomDomain"}),(0,r.jsx)(n.td,{children:"KEYWORD"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"CustomDoubleField"}),(0,r.jsx)(n.td,{children:"BOOL"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"CustomIntField"}),(0,r.jsx)(n.td,{children:"INT"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"CustomKeywordField"}),(0,r.jsx)(n.td,{children:"KEYWORD"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"CustomStringField"}),(0,r.jsx)(n.td,{children:"STRING"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"DomainID"}),(0,r.jsx)(n.td,{children:"KEYWORD"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"ExecutionTime"}),(0,r.jsx)(n.td,{children:"INT"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"HistoryLength"}),(0,r.jsx)(n.td,{children:"INT"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"RunID"}),(0,r.jsx)(n.td,{children:"KEYWORD"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"StartTime"}),(0,r.jsx)(n.td,{children:"INT"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"WorkflowID"}),(0,r.jsx)(n.td,{children:"KEYWORD"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"WorkflowType"}),(0,r.jsx)(n.td,{children:"KEYWORD"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"Tasklist"}),(0,r.jsx)(n.td,{children:"KEYWORD"})]})]})]}),"\n",(0,r.jsx)(n.p,{children:"There are some special considerations for these attributes:"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"CloseStatus, CloseTime, DomainID, ExecutionTime, HistoryLength, RunID, StartTime, WorkflowID, WorkflowType are reserved by Cadence and are read-only"}),"\n",(0,r.jsxs)(n.li,{children:["Starting from ",(0,r.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence/commit/6e69fa1a6e9ae5d2f683759820f09d1286ba7797",children:"v0.18.0"}),", Cadence automatically maps(case insensitive) string to CloseStatus so that you don't need to use integer in the query, to make it easier to use.","\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:'0 = "completed"'}),"\n",(0,r.jsx)(n.li,{children:'1 = "failed"'}),"\n",(0,r.jsx)(n.li,{children:'2 = "canceled"'}),"\n",(0,r.jsx)(n.li,{children:'3 = "terminated"'}),"\n",(0,r.jsx)(n.li,{children:'4 = "continued_as_new"'}),"\n",(0,r.jsx)(n.li,{children:'5 = "timed_out"'}),"\n"]}),"\n"]}),"\n",(0,r.jsxs)(n.li,{children:["StartTime, CloseTime and ExecutionTime are stored as INT, but support queries using both EpochTime in nanoseconds, and string in RFC3339 format (ex. ",(0,r.jsx)(n.code,{children:'"2006-01-02T15:04:05+07:00"'}),")"]}),"\n",(0,r.jsx)(n.li,{children:"CloseTime, CloseStatus, HistoryLength are only present in closed workflow"}),"\n",(0,r.jsx)(n.li,{children:"ExecutionTime is for Retry/Cron user to query a workflow that will run in the future"}),"\n",(0,r.jsxs)(n.li,{children:["To list only open workflows, add ",(0,r.jsx)(n.code,{children:"CloseTime = missing"})," to the end of the query."]}),"\n"]}),"\n",(0,r.jsxs)(n.p,{children:["If you use retry or the cron feature to query workflows that will start execution in a certain time range, you can add predicates on ExecutionTime. For example: ",(0,r.jsx)(n.code,{children:"ExecutionTime > 2019-01-01T10:00:00-07:00"}),". Note that if predicates on ExecutionTime are included, only cron or a workflow that needs to retry will be returned."]}),"\n",(0,r.jsx)(n.h3,{id:"general-notes-about-queries",children:"General Notes About Queries"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"Pagesize default is 1000, and cannot be larger than 10k"}),"\n",(0,r.jsx)(n.li,{children:"Range query on Cadence timestamp (StartTime, CloseTime, ExecutionTime) cannot be larger than 9223372036854775807 (maxInt64 - 1001)"}),"\n",(0,r.jsx)(n.li,{children:"Query by time range will have 1ms resolution"}),"\n",(0,r.jsx)(n.li,{children:"Query column names are case sensitive"}),"\n",(0,r.jsx)(n.li,{children:"ListWorkflow may take longer when retrieving a large number of workflows (10M+)"}),"\n",(0,r.jsx)(n.li,{children:"To retrieve a large number of workflows without caring about order, use the ScanWorkflow API"}),"\n",(0,r.jsx)(n.li,{children:"To efficiently count the number of workflows, use the CountWorkflow API"}),"\n"]}),"\n",(0,r.jsx)(n.h2,{id:"tools-support",children:"Tools Support"}),"\n",(0,r.jsx)(n.h3,{id:"cli",children:"CLI"}),"\n",(0,r.jsxs)(n.p,{children:["Support for search attributes is available as of version 0.6.0 of the Cadence server. You can also use the CLI from the latest ",(0,r.jsx)(n.a,{href:"https://hub.docker.com/r/ubercadence/cli",children:"CLI Docker image"})," (supported on 0.6.4 or later)."]}),"\n",(0,r.jsx)(n.h4,{id:"start-workflow-with-search-attributes",children:"Start Workflow with Search Attributes"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-bash",children:"cadence --do samples-domain workflow start --tl helloWorldGroup --wt main.Workflow --et 60 --dt 10 -i '\"vancexu\"' -search_attr_key 'CustomIntField | CustomKeywordField | CustomStringField | CustomBoolField | CustomDatetimeField' -search_attr_value '5 | keyword1 | vancexu test | true | 2019-06-07T16:16:36-08:00'\n"})}),"\n",(0,r.jsx)(n.h4,{id:"search-workflows-with-list-apicommand",children:"Search Workflows with List API/Command"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-bash",children:'cadence --do samples-domain wf list -q \'(CustomKeywordField = "keyword1" and CustomIntField >= 5) or CustomKeywordField = "keyword2"\' -psa\n'})}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-bash",children:'cadence --do samples-domain wf list -q \'CustomKeywordField in ("keyword2", "keyword1") and CustomIntField >= 5 and CloseTime between "2018-06-07T16:16:36-08:00" and "2019-06-07T16:46:34-08:00" order by CustomDatetimeField desc\' -psa\n'})}),"\n",(0,r.jsxs)(n.p,{children:["To list only open workflows, add ",(0,r.jsx)(n.code,{children:"CloseTime = missing"})," to the end of the query."]}),"\n",(0,r.jsx)(n.p,{children:"Note that queries can support more than one type of filter:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-bash",children:'cadence --do samples-domain wf list -q \'WorkflowType = "main.Workflow" and (WorkflowID = "1645a588-4772-4dab-b276-5f9db108b3a8" or RunID = "be66519b-5f09-40cd-b2e8-20e4106244dc")\'\n'})}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-bash",children:'cadence --do samples-domain wf list -q \'WorkflowType = "main.Workflow" StartTime > "2019-06-07T16:46:34-08:00" and CloseTime = missing\'\n'})}),"\n",(0,r.jsx)(n.p,{children:"All above command can be done with ListWorkflowExecutions API."}),"\n",(0,r.jsx)(n.h4,{id:"count-workflows-with-count-apicommand",children:"Count Workflows with Count API/Command"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-bash",children:'cadence --do samples-domain wf count -q \'(CustomKeywordField = "keyword1" and CustomIntField >= 5) or CustomKeywordField = "keyword2"\'\n'})}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-bash",children:"cadence --do samples-domain wf count -q 'CloseStatus=\"failed\"'\n"})}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-bash",children:"cadence --do samples-domain wf count -q 'CloseStatus!=\"completed\"'\n"})}),"\n",(0,r.jsx)(n.p,{children:"All above command can be done with CountWorkflowExecutions API."}),"\n",(0,r.jsx)(n.h3,{id:"web-ui-support",children:"Web UI Support"}),"\n",(0,r.jsxs)(n.p,{children:["Queries are supported in ",(0,r.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence-web",children:"Cadence Web"}),' as of release 3.4.0. Use the "Basic/Advanced" button to switch to "Advanced" mode and type the query in the search box.']}),"\n",(0,r.jsx)(n.h3,{id:"tls-support-for-connecting-to-elasticsearch",children:"TLS Support for connecting to Elasticsearch"}),"\n",(0,r.jsxs)(n.p,{children:["If your elasticsearch deployment requires TLS to connect to it, you can add the following to your config template.\nThe TLS config is optional and when not provided it defaults to tls.enabled to ",(0,r.jsx)(n.strong,{children:"false"})]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-yaml",children:'elasticsearch:\n url:\n scheme: "https"\n host: "127.0.0.1:9200"\n indices:\n visibility: cadence-visibility-dev\n tls:\n enabled: true\n caFile: /secrets/cadence/elasticsearch_cert.pem\n enableHostVerification: true\n serverName: myServerName\n certFile: /secrets/cadence/certfile.crt\n keyFile: /secrets/cadence/keyfile.key\n sslmode: false\n'})}),"\n",(0,r.jsx)(n.h2,{id:"running-locally",children:"Running Locally"}),"\n",(0,r.jsxs)(n.ol,{children:["\n",(0,r.jsx)(n.li,{children:"Increase Docker memory to higher than 6GB. Navigate to Docker -> Preferences -> Advanced -> Memory"}),"\n",(0,r.jsxs)(n.li,{children:["Get the Cadence Docker compose file. Run ",(0,r.jsx)(n.code,{children:"curl -O https://raw.githubusercontent.com/cadence-workflow/cadence/master/docker/docker-compose-es.yml"})]}),"\n",(0,r.jsxs)(n.li,{children:["Start Cadence Docker (which contains Apache Kafka, Apache Zookeeper, and Elasticsearch) using ",(0,r.jsx)(n.code,{children:"docker-compose -f docker-compose-es.yml up"})]}),"\n",(0,r.jsxs)(n.li,{children:["From the Docker output log, make sure Elasticsearch and Cadence started correctly. If you encounter an insufficient disk space error, try ",(0,r.jsx)(n.code,{children:"docker system prune -a --volumes"})]}),"\n",(0,r.jsxs)(n.li,{children:["Register a local domain and start using it. ",(0,r.jsx)(n.code,{children:"cadence --do samples-domain d re"})]}),"\n",(0,r.jsxs)(n.li,{children:["Add the key to ElasticSearch And also allowlist search attributes. ",(0,r.jsx)(n.code,{children:"cadence --do domain adm cl asa --search_attr_key NewKey --search_attr_type 1"})]}),"\n"]}),"\n",(0,r.jsx)(n.h2,{id:"running-in-production",children:"Running in Production"}),"\n",(0,r.jsx)(n.p,{children:"To enable this feature in a Cadence cluster:"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:["Register index schema on ElasticSearch. Run two CURL commands following this ",(0,r.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence/blob/a05ce6b0328b89aa516ae09d5ff601e35df2cc4f/docker/start.sh#L59",children:"script"}),".","\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"Create a index template by using the schema , choose v6/v7 based on your ElasticSearch version"}),"\n",(0,r.jsx)(n.li,{children:"Create an index follow the index template, remember the name"}),"\n"]}),"\n"]}),"\n",(0,r.jsxs)(n.li,{children:["Register topic on Kafka, and remember the name","\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"Set up the right number of partitions based on your expected throughput(can be scaled up later)"}),"\n"]}),"\n"]}),"\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence/blob/master/docs/visibility-on-elasticsearch.md#configuration",children:"Configure Cadence for ElasticSearch + Kafka like this documentation"}),"\nBased on the full ",(0,r.jsx)(n.a,{href:"/docs/operation-guide/setup/#static-configuration",children:"static config"}),", you may add some other fields like AuthN.\nSimilarly for Kafka."]}),"\n"]}),"\n",(0,r.jsx)(n.p,{children:"To add new search attributes:"}),"\n",(0,r.jsxs)(n.ol,{children:["\n",(0,r.jsxs)(n.li,{children:["Add the key to ElasticSearch ",(0,r.jsx)(n.code,{children:"cadence --do domain adm cl asa --search_attr_key NewKey --search_attr_type 1"})]}),"\n",(0,r.jsxs)(n.li,{children:["Update the ",(0,r.jsx)(n.a,{href:"https://cadenceworkflow.io/docs/operation-guide/setup/#dynamic-configuration-overview",children:"dynamic configuration"})," to allowlist the new attribute"]}),"\n"]}),"\n",(0,r.jsx)(n.p,{children:"Note: starting a workflow with search attributes but without advanced visibility feature will succeed as normal, but will not be searchable and will not be shown in list results."})]})}function h(e={}){const{wrapper:n}={...(0,i.R)(),...e.components};return n?(0,r.jsx)(n,{...e,children:(0,r.jsx)(d,{...e})}):d(e)}},8453:(e,n,t)=>{t.d(n,{R:()=>o,x:()=>l});var s=t(6540);const r={},i=s.createContext(r);function o(e){const n=s.useContext(i);return s.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function l(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:o(e.components),s.createElement(i.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/fde82b69.e4eeae89.js b/assets/js/fde82b69.e4eeae89.js deleted file mode 100644 index bcbbb6e02..000000000 --- a/assets/js/fde82b69.e4eeae89.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[6185],{5410:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>a,contentTitle:()=>l,default:()=>h,frontMatter:()=>o,metadata:()=>s,toc:()=>c});const s=JSON.parse('{"id":"concepts/search-workflows","title":"Search workflows(Advanced visibility)","description":"Introduction","source":"@site/docs/03-concepts/09-search-workflows.md","sourceDirName":"03-concepts","slug":"/concepts/search-workflows","permalink":"/docs/concepts/search-workflows","draft":false,"unlisted":false,"editUrl":"https://github.com/cadence-workflow/Cadence-Docs/tree/master/docs/03-concepts/09-search-workflows.md","tags":[],"version":"current","sidebarPosition":9,"frontMatter":{"layout":"default","title":"Search workflows(Advanced visibility)","permalink":"/docs/concepts/search-workflows"},"sidebar":"docsSidebar","previous":{"title":"Cross DC replication","permalink":"/docs/concepts/cross-dc-replication"},"next":{"title":"HTTP API","permalink":"/docs/concepts/http-api"}}');var r=t(4848),i=t(8453);const o={layout:"default",title:"Search workflows(Advanced visibility)",permalink:"/docs/concepts/search-workflows"},l="Searching Workflows(Advanced visibility)",a={},c=[{value:"Introduction",id:"introduction",level:2},{value:"Memo vs Search Attributes",id:"memo-vs-search-attributes",level:2},{value:"Search Attributes (Go Client Usage)",id:"search-attributes-go-client-usage",level:2},{value:"Allow Listing Search Attributes",id:"allow-listing-search-attributes",level:3},{value:"Keyword vs String(Text)",id:"keyword-vs-stringtext",level:4},{value:"Value Types",id:"value-types",level:3},{value:"Limit",id:"limit",level:3},{value:"Upsert Search Attributes in Workflow",id:"upsert-search-attributes-in-workflow",level:3},{value:"ContinueAsNew and Cron",id:"continueasnew-and-cron",level:3},{value:"Query Capabilities",id:"query-capabilities",level:2},{value:"Supported Operators",id:"supported-operators",level:3},{value:"Default Attributes",id:"default-attributes",level:3},{value:"General Notes About Queries",id:"general-notes-about-queries",level:3},{value:"Tools Support",id:"tools-support",level:2},{value:"CLI",id:"cli",level:3},{value:"Start Workflow with Search Attributes",id:"start-workflow-with-search-attributes",level:4},{value:"Search Workflows with List API/Command",id:"search-workflows-with-list-apicommand",level:4},{value:"Count Workflows with Count API/Command",id:"count-workflows-with-count-apicommand",level:4},{value:"Web UI Support",id:"web-ui-support",level:3},{value:"TLS Support for connecting to Elasticsearch",id:"tls-support-for-connecting-to-elasticsearch",level:3},{value:"Running Locally",id:"running-locally",level:2},{value:"Running in Production",id:"running-in-production",level:2}];function d(e){const n={a:"a",code:"code",em:"em",h1:"h1",h2:"h2",h3:"h3",h4:"h4",header:"header",li:"li",ol:"ol",p:"p",pre:"pre",strong:"strong",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",ul:"ul",...(0,i.R)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(n.header,{children:(0,r.jsx)(n.h1,{id:"searching-workflowsadvanced-visibility",children:"Searching Workflows(Advanced visibility)"})}),"\n",(0,r.jsx)(n.h2,{id:"introduction",children:"Introduction"}),"\n",(0,r.jsxs)(n.p,{children:["Cadence supports creating workflows with customized key-value pairs, updating the information within the workflow code, and then listing/searching workflows with a SQL-like query. For example, you can create workflows with keys ",(0,r.jsx)(n.code,{children:"city"})," and ",(0,r.jsx)(n.code,{children:"age"}),", then search all workflows with ",(0,r.jsx)(n.code,{children:"city = seattle and age > 22"}),"."]}),"\n",(0,r.jsxs)(n.p,{children:["Also note that normal workflow properties like start time and workflow type can be queried as well. For example, the following query could be specified when ",(0,r.jsx)(n.a,{href:"/docs/cli#list-closed-or-open-workflow-executions",children:"listing workflows from the CLI"})," or using the list APIs (",(0,r.jsx)(n.a,{href:"https://godoc.org/go.uber.org/cadence/client#Client",children:"Go"}),", ",(0,r.jsx)(n.a,{href:"https://static.javadoc.io/com.uber.cadence/cadence-client/2.6.0/com/cadence-workflow/cadence/WorkflowService.Iface.html#ListWorkflowExecutions-com.uber.cadence.ListWorkflowExecutionsRequest-",children:"Java"}),"):"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-sql",children:'WorkflowType = "main.Workflow" AND CloseStatus != "completed" AND (StartTime >\n "2019-06-07T16:46:34-08:00" OR CloseTime > "2019-06-07T16:46:34-08:00")\n ORDER BY StartTime DESC\n'})}),"\n",(0,r.jsxs)(n.p,{children:["In other places, this is also called as ",(0,r.jsx)(n.code,{children:"advanced visibility"}),". While ",(0,r.jsx)(n.code,{children:"basic visibility"})," is referred to basic listing without being able to search."]}),"\n",(0,r.jsx)(n.h2,{id:"memo-vs-search-attributes",children:"Memo vs Search Attributes"}),"\n",(0,r.jsx)(n.p,{children:"Cadence offers two methods for creating workflows with key-value pairs: memo and search attributes. Memo can only be provided on workflow start. Also, memo data are not indexed, and are therefore not searchable. Memo data are visible when listing workflows using the list APIs. Search attributes data are indexed so you can search workflows by querying on these attributes. However, search attributes require the use of Elasticsearch."}),"\n",(0,r.jsxs)(n.p,{children:["Memo and search attributes are available in the Go client in ",(0,r.jsx)(n.a,{href:"https://godoc.org/go.uber.org/cadence/internal#StartWorkflowOptions",children:"StartWorkflowOptions"}),"."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-go",children:"type StartWorkflowOptions struct {\n // ...\n\n // Memo - Optional non-indexed info that will be shown in list workflow.\n Memo map[string]interface{}\n\n // SearchAttributes - Optional indexed info that can be used in query of List/Scan/Count workflow APIs (only\n // supported when Cadence server is using Elasticsearch). The key and value type must be registered on Cadence server side.\n // Use GetSearchAttributes API to get valid key and corresponding value type.\n SearchAttributes map[string]interface{}\n}\n"})}),"\n",(0,r.jsxs)(n.p,{children:["In the Java client, the ",(0,r.jsx)(n.em,{children:"WorkflowOptions.Builder"})," has similar methods for ",(0,r.jsx)(n.a,{href:"https://static.javadoc.io/com.uber.cadence/cadence-client/2.6.0/com/cadence-workflow/cadence/client/WorkflowOptions.Builder.html#setMemo-java.util.Map-",children:"memo"})," and ",(0,r.jsx)(n.a,{href:"https://static.javadoc.io/com.uber.cadence/cadence-client/2.6.0/com/cadence-workflow/cadence/client/WorkflowOptions.Builder.html#setSearchAttributes-java.util.Map-",children:"search attributes"}),"."]}),"\n",(0,r.jsx)(n.p,{children:"Some important distinctions between memo and search attributes:"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"Memo can support all data types because it is not indexed. Search attributes only support basic data types (including String(aka Text), Int, Float, Bool, Datetime) because it is indexed by Elasticsearch."}),"\n",(0,r.jsx)(n.li,{children:"Memo does not restrict on key names. Search attributes require that keys are allowlisted before using them because Elasticsearch has a limit on indexed keys."}),"\n",(0,r.jsx)(n.li,{children:"Memo doesn't require Cadence clusters to depend on Elasticsearch while search attributes only works with Elasticsearch."}),"\n"]}),"\n",(0,r.jsx)(n.h2,{id:"search-attributes-go-client-usage",children:"Search Attributes (Go Client Usage)"}),"\n",(0,r.jsxs)(n.p,{children:["When using the Cadence Go client, provide key-value pairs as SearchAttributes in ",(0,r.jsx)(n.a,{href:"https://godoc.org/go.uber.org/cadence/internal#StartWorkflowOptions",children:"StartWorkflowOptions"}),"."]}),"\n",(0,r.jsxs)(n.p,{children:["SearchAttributes is ",(0,r.jsx)(n.code,{children:"map[string]interface{}"})," where the keys need to be allowlisted so that Cadence knows the attribute key name and value type. The value provided in the map must be the same type as registered."]}),"\n",(0,r.jsx)(n.h3,{id:"allow-listing-search-attributes",children:"Allow Listing Search Attributes"}),"\n",(0,r.jsx)(n.p,{children:"Start by querying the list of search attributes using the "}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-bash",children:"$ cadence --domain samples-domain cl get-search-attr\n+---------------------+------------+\n| KEY | VALUE TYPE |\n+---------------------+------------+\n| CloseStatus | INT |\n| CloseTime | INT |\n| CustomBoolField | DOUBLE |\n| CustomDatetimeField | DATETIME |\n| CustomDomain | KEYWORD |\n| CustomDoubleField | BOOL |\n| CustomIntField | INT |\n| CustomKeywordField | KEYWORD |\n| CustomStringField | STRING |\n| DomainID | KEYWORD |\n| ExecutionTime | INT |\n| HistoryLength | INT |\n| RunID | KEYWORD |\n| StartTime | INT |\n| WorkflowID | KEYWORD |\n| WorkflowType | KEYWORD |\n+---------------------+------------+\n"})}),"\n",(0,r.jsx)(n.p,{children:"Use the admin CLI to add a new search attribute:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-bash",children:"cadence --domain samples-domain adm cl asa --search_attr_key NewKey --search_attr_type 1\n"})}),"\n",(0,r.jsx)(n.p,{children:"The numbers for the attribute types map as follows:"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"0 = String(Text)"}),"\n",(0,r.jsx)(n.li,{children:"1 = Keyword"}),"\n",(0,r.jsx)(n.li,{children:"2 = Int"}),"\n",(0,r.jsx)(n.li,{children:"3 = Double"}),"\n",(0,r.jsx)(n.li,{children:"4 = Bool"}),"\n",(0,r.jsx)(n.li,{children:"5 = DateTime"}),"\n"]}),"\n",(0,r.jsx)(n.h4,{id:"keyword-vs-stringtext",children:"Keyword vs String(Text)"}),"\n",(0,r.jsxs)(n.p,{children:["Note 1: ",(0,r.jsx)(n.strong,{children:"String"})," has been renamed to ",(0,r.jsx)(n.strong,{children:"Text"})," in ",(0,r.jsx)(n.a,{href:"https://www.elastic.co/blog/strings-are-dead-long-live-strings",children:"ElasticSearch"}),". Cadence is also ",(0,r.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence/issues/4604",children:"planning"})," to rename it."]}),"\n",(0,r.jsxs)(n.p,{children:["Note 2: ",(0,r.jsx)(n.strong,{children:"Keyword"})," and ",(0,r.jsx)(n.strong,{children:"String(Text)"})," are concepts taken from Elasticsearch. Each word in a ",(0,r.jsx)(n.strong,{children:"String(Text)"})," is considered a searchable keyword. For a UUID, that can be problematic as Elasticsearch will index each portion of the UUID separately. To have the whole string considered as a searchable keyword, use the ",(0,r.jsx)(n.strong,{children:"Keyword"})," type."]}),"\n",(0,r.jsx)(n.p,{children:'For example, key RunID with value "2dd29ab7-2dd8-4668-83e0-89cae261cfb1"'}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:["as a ",(0,r.jsx)(n.strong,{children:"Keyword"}),' will only be matched by RunID = "2dd29ab7-2dd8-4668-83e0-89cae261cfb1" (or in the future with ',(0,r.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence/issues/1137",children:"regular expressions"}),")"]}),"\n",(0,r.jsxs)(n.li,{children:["as a ",(0,r.jsx)(n.strong,{children:"String(Text)"}),' will be matched by RunID = "2dd8", which may cause unwanted matches']}),"\n"]}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.strong,{children:"Note:"})," String(Text) type can not be used in Order By query."]}),"\n",(0,r.jsx)(n.p,{children:"There are some pre-allowlisted search attributes that are handy for testing:"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"CustomKeywordField"}),"\n",(0,r.jsx)(n.li,{children:"CustomIntField"}),"\n",(0,r.jsx)(n.li,{children:"CustomDoubleField"}),"\n",(0,r.jsx)(n.li,{children:"CustomBoolField"}),"\n",(0,r.jsx)(n.li,{children:"CustomDatetimeField"}),"\n",(0,r.jsx)(n.li,{children:"CustomStringField"}),"\n"]}),"\n",(0,r.jsx)(n.p,{children:"Their types are indicated in their names."}),"\n",(0,r.jsx)(n.h3,{id:"value-types",children:"Value Types"}),"\n",(0,r.jsx)(n.p,{children:"Here are the Search Attribute value types and their correspondent Golang types:"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"Keyword = string"}),"\n",(0,r.jsx)(n.li,{children:"Int = int64"}),"\n",(0,r.jsx)(n.li,{children:"Double = float64"}),"\n",(0,r.jsx)(n.li,{children:"Bool = bool"}),"\n",(0,r.jsx)(n.li,{children:"Datetime = time.Time"}),"\n",(0,r.jsx)(n.li,{children:"String = string"}),"\n"]}),"\n",(0,r.jsx)(n.h3,{id:"limit",children:"Limit"}),"\n",(0,r.jsx)(n.p,{children:"We recommend limiting the number of Elasticsearch indexes by enforcing limits on the following:"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"Number of keys: 100 per workflow"}),"\n",(0,r.jsx)(n.li,{children:"Size of value: 2kb per value"}),"\n",(0,r.jsx)(n.li,{children:"Total size of key and values: 40kb per workflow"}),"\n"]}),"\n",(0,r.jsx)(n.p,{children:"Cadence reserves keys like DomainID, WorkflowID, and RunID. These can only be used in list queries. The values are not updatable."}),"\n",(0,r.jsx)(n.h3,{id:"upsert-search-attributes-in-workflow",children:"Upsert Search Attributes in Workflow"}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.a,{href:"https://godoc.org/go.uber.org/cadence/workflow#UpsertSearchAttributes",children:"UpsertSearchAttributes"})," is used to add or update search attributes from within the workflow code."]}),"\n",(0,r.jsxs)(n.p,{children:["Go samples for search attributes can be found at ",(0,r.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence-samples/tree/master/cmd/samples/recipes/searchattributes",children:"github.com/cadence-workflow/cadence-samples"}),"."]}),"\n",(0,r.jsx)(n.p,{children:"UpsertSearchAttributes will merge attributes to the existing map in the workflow. Consider this example workflow code:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-go",children:'func MyWorkflow(ctx workflow.Context, input string) error {\n\n attr1 := map[string]interface{}{\n "CustomIntField": 1,\n "CustomBoolField": true,\n }\n workflow.UpsertSearchAttributes(ctx, attr1)\n\n attr2 := map[string]interface{}{\n "CustomIntField": 2,\n "CustomKeywordField": "seattle",\n }\n workflow.UpsertSearchAttributes(ctx, attr2)\n}\n'})}),"\n",(0,r.jsx)(n.p,{children:"After the second call to UpsertSearchAttributes, the map will contain:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-go",children:'map[string]interface{}{\n "CustomIntField": 2,\n "CustomBoolField": true,\n "CustomKeywordField": "seattle",\n}\n'})}),"\n",(0,r.jsxs)(n.p,{children:["There is no support for removing a field. To achieve a similar effect, set the field to a sentinel value. For example, to remove \u201cCustomKeywordField\u201d, update it to \u201cimpossibleVal\u201d. Then searching ",(0,r.jsx)(n.code,{children:"CustomKeywordField != \u2018impossibleVal\u2019"}),' will match workflows with CustomKeywordField not equal to "impossibleVal", which ',(0,r.jsx)(n.strong,{children:"includes"})," workflows without the CustomKeywordField set."]}),"\n",(0,r.jsxs)(n.p,{children:["Use ",(0,r.jsx)(n.code,{children:"workflow.GetInfo"})," to get current search attributes."]}),"\n",(0,r.jsx)(n.h3,{id:"continueasnew-and-cron",children:"ContinueAsNew and Cron"}),"\n",(0,r.jsxs)(n.p,{children:["When performing a ",(0,r.jsx)(n.a,{href:"/docs/go-client/continue-as-new/",children:"ContinueAsNew"})," or using ",(0,r.jsx)(n.a,{href:"/docs/go-client/distributed-cron/",children:"Cron"}),", search attributes (and memo) will be carried over to the new run by default."]}),"\n",(0,r.jsx)(n.h2,{id:"query-capabilities",children:"Query Capabilities"}),"\n",(0,r.jsxs)(n.p,{children:["Query workflows by using a SQL-like where clause when ",(0,r.jsx)(n.a,{href:"/docs/cli#list-closed-or-open-workflow-executions",children:"listing workflows from the CLI"})," or using the list APIs (",(0,r.jsx)(n.a,{href:"https://godoc.org/go.uber.org/cadence/client#Client",children:"Go"}),", ",(0,r.jsx)(n.a,{href:"https://static.javadoc.io/com.uber.cadence/cadence-client/2.6.0/com/cadence-workflow/cadence/WorkflowService.Iface.html#ListWorkflowExecutions-com.uber.cadence.ListWorkflowExecutionsRequest-",children:"Java"}),")."]}),"\n",(0,r.jsx)(n.p,{children:"Note that you will only see workflows from one domain when querying."}),"\n",(0,r.jsx)(n.h3,{id:"supported-operators",children:"Supported Operators"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.code,{children:"AND"}),", ",(0,r.jsx)(n.code,{children:"OR"}),", ",(0,r.jsx)(n.code,{children:"()"})]}),"\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.code,{children:"="}),", ",(0,r.jsx)(n.code,{children:"!="}),", ",(0,r.jsx)(n.code,{children:">"}),", ",(0,r.jsx)(n.code,{children:">="}),", ",(0,r.jsx)(n.code,{children:"<"}),", ",(0,r.jsx)(n.code,{children:"<="})]}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.code,{children:"IN"})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.code,{children:"BETWEEN ... AND"})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.code,{children:"ORDER BY"})}),"\n"]}),"\n",(0,r.jsx)(n.h3,{id:"default-attributes",children:"Default Attributes"}),"\n",(0,r.jsx)(n.p,{children:"More and more default attributes are added in newer versions.\nPlease get the by using the CLI get-search-attr command or the GetSearchAttributes API.\nSome names and types are as follows:"}),"\n",(0,r.jsxs)(n.table,{children:[(0,r.jsx)(n.thead,{children:(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.th,{children:"KEY"}),(0,r.jsx)(n.th,{children:"VALUE TYPE"})]})}),(0,r.jsxs)(n.tbody,{children:[(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"CloseStatus"}),(0,r.jsx)(n.td,{children:"INT"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"CloseTime"}),(0,r.jsx)(n.td,{children:"INT"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"CustomBoolField"}),(0,r.jsx)(n.td,{children:"DOUBLE"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"CustomDatetimeField"}),(0,r.jsx)(n.td,{children:"DATETIME"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"CustomDomain"}),(0,r.jsx)(n.td,{children:"KEYWORD"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"CustomDoubleField"}),(0,r.jsx)(n.td,{children:"BOOL"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"CustomIntField"}),(0,r.jsx)(n.td,{children:"INT"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"CustomKeywordField"}),(0,r.jsx)(n.td,{children:"KEYWORD"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"CustomStringField"}),(0,r.jsx)(n.td,{children:"STRING"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"DomainID"}),(0,r.jsx)(n.td,{children:"KEYWORD"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"ExecutionTime"}),(0,r.jsx)(n.td,{children:"INT"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"HistoryLength"}),(0,r.jsx)(n.td,{children:"INT"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"RunID"}),(0,r.jsx)(n.td,{children:"KEYWORD"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"StartTime"}),(0,r.jsx)(n.td,{children:"INT"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"WorkflowID"}),(0,r.jsx)(n.td,{children:"KEYWORD"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"WorkflowType"}),(0,r.jsx)(n.td,{children:"KEYWORD"})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"Tasklist"}),(0,r.jsx)(n.td,{children:"KEYWORD"})]})]})]}),"\n",(0,r.jsx)(n.p,{children:"There are some special considerations for these attributes:"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"CloseStatus, CloseTime, DomainID, ExecutionTime, HistoryLength, RunID, StartTime, WorkflowID, WorkflowType are reserved by Cadence and are read-only"}),"\n",(0,r.jsxs)(n.li,{children:["Starting from ",(0,r.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence/commit/6e69fa1a6e9ae5d2f683759820f09d1286ba7797",children:"v0.18.0"}),", Cadence automatically maps(case insensitive) string to CloseStatus so that you don't need to use integer in the query, to make it easier to use.","\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:'0 = "completed"'}),"\n",(0,r.jsx)(n.li,{children:'1 = "failed"'}),"\n",(0,r.jsx)(n.li,{children:'2 = "canceled"'}),"\n",(0,r.jsx)(n.li,{children:'3 = "terminated"'}),"\n",(0,r.jsx)(n.li,{children:'4 = "continued_as_new"'}),"\n",(0,r.jsx)(n.li,{children:'5 = "timed_out"'}),"\n"]}),"\n"]}),"\n",(0,r.jsxs)(n.li,{children:["StartTime, CloseTime and ExecutionTime are stored as INT, but support queries using both EpochTime in nanoseconds, and string in RFC3339 format (ex. ",(0,r.jsx)(n.code,{children:'"2006-01-02T15:04:05+07:00"'}),")"]}),"\n",(0,r.jsx)(n.li,{children:"CloseTime, CloseStatus, HistoryLength are only present in closed workflow"}),"\n",(0,r.jsx)(n.li,{children:"ExecutionTime is for Retry/Cron user to query a workflow that will run in the future"}),"\n",(0,r.jsxs)(n.li,{children:["To list only open workflows, add ",(0,r.jsx)(n.code,{children:"CloseTime = missing"})," to the end of the query."]}),"\n"]}),"\n",(0,r.jsxs)(n.p,{children:["If you use retry or the cron feature to query workflows that will start execution in a certain time range, you can add predicates on ExecutionTime. For example: ",(0,r.jsx)(n.code,{children:"ExecutionTime > 2019-01-01T10:00:00-07:00"}),". Note that if predicates on ExecutionTime are included, only cron or a workflow that needs to retry will be returned."]}),"\n",(0,r.jsx)(n.h3,{id:"general-notes-about-queries",children:"General Notes About Queries"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"Pagesize default is 1000, and cannot be larger than 10k"}),"\n",(0,r.jsx)(n.li,{children:"Range query on Cadence timestamp (StartTime, CloseTime, ExecutionTime) cannot be larger than 9223372036854775807 (maxInt64 - 1001)"}),"\n",(0,r.jsx)(n.li,{children:"Query by time range will have 1ms resolution"}),"\n",(0,r.jsx)(n.li,{children:"Query column names are case sensitive"}),"\n",(0,r.jsx)(n.li,{children:"ListWorkflow may take longer when retrieving a large number of workflows (10M+)"}),"\n",(0,r.jsx)(n.li,{children:"To retrieve a large number of workflows without caring about order, use the ScanWorkflow API"}),"\n",(0,r.jsx)(n.li,{children:"To efficiently count the number of workflows, use the CountWorkflow API"}),"\n"]}),"\n",(0,r.jsx)(n.h2,{id:"tools-support",children:"Tools Support"}),"\n",(0,r.jsx)(n.h3,{id:"cli",children:"CLI"}),"\n",(0,r.jsxs)(n.p,{children:["Support for search attributes is available as of version 0.6.0 of the Cadence server. You can also use the CLI from the latest ",(0,r.jsx)(n.a,{href:"https://hub.docker.com/r/ubercadence/cli",children:"CLI Docker image"})," (supported on 0.6.4 or later)."]}),"\n",(0,r.jsx)(n.h4,{id:"start-workflow-with-search-attributes",children:"Start Workflow with Search Attributes"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-bash",children:"cadence --do samples-domain workflow start --tl helloWorldGroup --wt main.Workflow --et 60 --dt 10 -i '\"vancexu\"' -search_attr_key 'CustomIntField | CustomKeywordField | CustomStringField | CustomBoolField | CustomDatetimeField' -search_attr_value '5 | keyword1 | vancexu test | true | 2019-06-07T16:16:36-08:00'\n"})}),"\n",(0,r.jsx)(n.h4,{id:"search-workflows-with-list-apicommand",children:"Search Workflows with List API/Command"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-bash",children:'cadence --do samples-domain wf list -q \'(CustomKeywordField = "keyword1" and CustomIntField >= 5) or CustomKeywordField = "keyword2"\' -psa\n'})}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-bash",children:'cadence --do samples-domain wf list -q \'CustomKeywordField in ("keyword2", "keyword1") and CustomIntField >= 5 and CloseTime between "2018-06-07T16:16:36-08:00" and "2019-06-07T16:46:34-08:00" order by CustomDatetimeField desc\' -psa\n'})}),"\n",(0,r.jsxs)(n.p,{children:["To list only open workflows, add ",(0,r.jsx)(n.code,{children:"CloseTime = missing"})," to the end of the query."]}),"\n",(0,r.jsx)(n.p,{children:"Note that queries can support more than one type of filter:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-bash",children:'cadence --do samples-domain wf list -q \'WorkflowType = "main.Workflow" and (WorkflowID = "1645a588-4772-4dab-b276-5f9db108b3a8" or RunID = "be66519b-5f09-40cd-b2e8-20e4106244dc")\'\n'})}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-bash",children:'cadence --do samples-domain wf list -q \'WorkflowType = "main.Workflow" StartTime > "2019-06-07T16:46:34-08:00" and CloseTime = missing\'\n'})}),"\n",(0,r.jsx)(n.p,{children:"All above command can be done with ListWorkflowExecutions API."}),"\n",(0,r.jsx)(n.h4,{id:"count-workflows-with-count-apicommand",children:"Count Workflows with Count API/Command"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-bash",children:'cadence --do samples-domain wf count -q \'(CustomKeywordField = "keyword1" and CustomIntField >= 5) or CustomKeywordField = "keyword2"\'\n'})}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-bash",children:"cadence --do samples-domain wf count -q 'CloseStatus=\"failed\"'\n"})}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-bash",children:"cadence --do samples-domain wf count -q 'CloseStatus!=\"completed\"'\n"})}),"\n",(0,r.jsx)(n.p,{children:"All above command can be done with CountWorkflowExecutions API."}),"\n",(0,r.jsx)(n.h3,{id:"web-ui-support",children:"Web UI Support"}),"\n",(0,r.jsxs)(n.p,{children:["Queries are supported in ",(0,r.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence-web",children:"Cadence Web"}),' as of release 3.4.0. Use the "Basic/Advanced" button to switch to "Advanced" mode and type the query in the search box.']}),"\n",(0,r.jsx)(n.h3,{id:"tls-support-for-connecting-to-elasticsearch",children:"TLS Support for connecting to Elasticsearch"}),"\n",(0,r.jsxs)(n.p,{children:["If your elasticsearch deployment requires TLS to connect to it, you can add the following to your config template.\nThe TLS config is optional and when not provided it defaults to tls.enabled to ",(0,r.jsx)(n.strong,{children:"false"})]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-yaml",children:'elasticsearch:\n url:\n scheme: "https"\n host: "127.0.0.1:9200"\n indices:\n visibility: cadence-visibility-dev\n tls:\n enabled: true\n caFile: /secrets/cadence/elasticsearch_cert.pem\n enableHostVerification: true\n serverName: myServerName\n certFile: /secrets/cadence/certfile.crt\n keyFile: /secrets/cadence/keyfile.key\n sslmode: false\n'})}),"\n",(0,r.jsx)(n.h2,{id:"running-locally",children:"Running Locally"}),"\n",(0,r.jsxs)(n.ol,{children:["\n",(0,r.jsx)(n.li,{children:"Increase Docker memory to higher than 6GB. Navigate to Docker -> Preferences -> Advanced -> Memory"}),"\n",(0,r.jsxs)(n.li,{children:["Get the Cadence Docker compose file. Run ",(0,r.jsx)(n.code,{children:"curl -O https://raw.githubusercontent.com/cadence-workflow/cadence/master/docker/docker-compose-es.yml"})]}),"\n",(0,r.jsxs)(n.li,{children:["Start Cadence Docker (which contains Apache Kafka, Apache Zookeeper, and Elasticsearch) using ",(0,r.jsx)(n.code,{children:"docker-compose -f docker-compose-es.yml up"})]}),"\n",(0,r.jsxs)(n.li,{children:["From the Docker output log, make sure Elasticsearch and Cadence started correctly. If you encounter an insufficient disk space error, try ",(0,r.jsx)(n.code,{children:"docker system prune -a --volumes"})]}),"\n",(0,r.jsxs)(n.li,{children:["Register a local domain and start using it. ",(0,r.jsx)(n.code,{children:"cadence --do samples-domain d re"})]}),"\n",(0,r.jsxs)(n.li,{children:["Add the key to ElasticSearch And also allowlist search attributes. ",(0,r.jsx)(n.code,{children:"cadence --do domain adm cl asa --search_attr_key NewKey --search_attr_type 1"})]}),"\n"]}),"\n",(0,r.jsx)(n.h2,{id:"running-in-production",children:"Running in Production"}),"\n",(0,r.jsx)(n.p,{children:"To enable this feature in a Cadence cluster:"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:["Register index schema on ElasticSearch. Run two CURL commands following this ",(0,r.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence/blob/a05ce6b0328b89aa516ae09d5ff601e35df2cc4f/docker/start.sh#L59",children:"script"}),".","\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"Create a index template by using the schema , choose v6/v7 based on your ElasticSearch version"}),"\n",(0,r.jsx)(n.li,{children:"Create an index follow the index template, remember the name"}),"\n"]}),"\n"]}),"\n",(0,r.jsxs)(n.li,{children:["Register topic on Kafka, and remember the name","\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"Set up the right number of partitions based on your expected throughput(can be scaled up later)"}),"\n"]}),"\n"]}),"\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.a,{href:"https://github.com/cadence-workflow/cadence/blob/master/docs/visibility-on-elasticsearch.md#configuration",children:"Configure Cadence for ElasticSearch + Kafka like this documentation"}),"\nBased on the full ",(0,r.jsx)(n.a,{href:"/docs/operation-guide/setup/#static-configuration",children:"static config"}),", you may add some other fields like AuthN.\nSimilarly for Kafka."]}),"\n"]}),"\n",(0,r.jsx)(n.p,{children:"To add new search attributes:"}),"\n",(0,r.jsxs)(n.ol,{children:["\n",(0,r.jsxs)(n.li,{children:["Add the key to ElasticSearch ",(0,r.jsx)(n.code,{children:"cadence --do domain adm cl asa --search_attr_key NewKey --search_attr_type 1"})]}),"\n",(0,r.jsxs)(n.li,{children:["Update the ",(0,r.jsx)(n.a,{href:"https://cadenceworkflow.io/docs/operation-guide/setup/#dynamic-configuration-overview",children:"dynamic configuration"})," to allowlist the new attribute"]}),"\n"]}),"\n",(0,r.jsx)(n.p,{children:"Note: starting a workflow with search attributes but without advanced visibility feature will succeed as normal, but will not be searchable and will not be shown in list results."})]})}function h(e={}){const{wrapper:n}={...(0,i.R)(),...e.components};return n?(0,r.jsx)(n,{...e,children:(0,r.jsx)(d,{...e})}):d(e)}},8453:(e,n,t)=>{t.d(n,{R:()=>o,x:()=>l});var s=t(6540);const r={},i=s.createContext(r);function o(e){const n=s.useContext(i);return s.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function l(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:o(e.components),s.createElement(i.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/main.6e1cf64a.js b/assets/js/main.6e1cf64a.js new file mode 100644 index 000000000..cb1c7f60a --- /dev/null +++ b/assets/js/main.6e1cf64a.js @@ -0,0 +1,2 @@ +/*! For license information please see main.6e1cf64a.js.LICENSE.txt */ +(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[8792],{3219:(e,t,n)=>{"use strict";n.d(t,{Bc:()=>j,E8:()=>Zn,a1:()=>Qn});var r=n(6540);n(961);function o(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n<t;n++)r[n]=e[n];return r}function a(e,t,n,r,o,a,i){try{var c=e[a](i),s=c.value}catch(e){return void n(e)}c.done?t(s):Promise.resolve(s).then(r,o)}function i(e){return function(){var t=this,n=arguments;return new Promise((function(r,o){var i=e.apply(t,n);function c(e){a(i,r,o,c,s,"next",e)}function s(e){a(i,r,o,c,s,"throw",e)}c(void 0)}))}}function c(e,t,n){return t=p(t),function(e,t){if(t&&("object"==typeof t||"function"==typeof t))return t;if(void 0!==t)throw new TypeError("Derived constructors may only return object or undefined");return function(e){if(void 0===e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return e}(e)}(e,m()?Reflect.construct(t,n||[],p(e).constructor):t.apply(e,n))}function s(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function l(e,t,n){return Object.defineProperty(e,"prototype",{writable:!1}),e}function u(e,t,n){return(t=function(e){var t=function(e){if("object"!=typeof e||!e)return e;var t=e[Symbol.toPrimitive];if(void 0!==t){var n=t.call(e,"string");if("object"!=typeof n)return n;throw new TypeError("@@toPrimitive must return a primitive value.")}return String(e)}(e);return"symbol"==typeof t?t:t+""}(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function d(){return d=Object.assign?Object.assign.bind():function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var r in n)({}).hasOwnProperty.call(n,r)&&(e[r]=n[r])}return e},d.apply(null,arguments)}function p(e){return p=Object.setPrototypeOf?Object.getPrototypeOf.bind():function(e){return e.__proto__||Object.getPrototypeOf(e)},p(e)}function f(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function");e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,writable:!0,configurable:!0}}),Object.defineProperty(e,"prototype",{writable:!1}),t&&v(e,t)}function m(){try{var e=!Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],(function(){})))}catch(e){}return(m=function(){return!!e})()}function g(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function h(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?g(Object(n),!0).forEach((function(t){u(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):g(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}function b(e,t){if(null==e)return{};var n,r,o=function(e,t){if(null==e)return{};var n={};for(var r in e)if({}.hasOwnProperty.call(e,r)){if(t.includes(r))continue;n[r]=e[r]}return n}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(r=0;r<a.length;r++)n=a[r],t.includes(n)||{}.propertyIsEnumerable.call(e,n)&&(o[n]=e[n])}return o}function y(){y=function(){return t};var e,t={},n=Object.prototype,r=n.hasOwnProperty,o=Object.defineProperty||function(e,t,n){e[t]=n.value},a="function"==typeof Symbol?Symbol:{},i=a.iterator||"@@iterator",c=a.asyncIterator||"@@asyncIterator",s=a.toStringTag||"@@toStringTag";function l(e,t,n){return Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}),e[t]}try{l({},"")}catch(e){l=function(e,t,n){return e[t]=n}}function u(e,t,n,r){var a=t&&t.prototype instanceof b?t:b,i=Object.create(a.prototype),c=new T(r||[]);return o(i,"_invoke",{value:D(e,n,c)}),i}function d(e,t,n){try{return{type:"normal",arg:e.call(t,n)}}catch(e){return{type:"throw",arg:e}}}t.wrap=u;var p="suspendedStart",f="suspendedYield",m="executing",g="completed",h={};function b(){}function v(){}function w(){}var S={};l(S,i,(function(){return this}));var k=Object.getPrototypeOf,x=k&&k(k(P([])));x&&x!==n&&r.call(x,i)&&(S=x);var _=w.prototype=b.prototype=Object.create(S);function C(e){["next","throw","return"].forEach((function(t){l(e,t,(function(e){return this._invoke(t,e)}))}))}function E(e,t){function n(o,a,i,c){var s=d(e[o],e,a);if("throw"!==s.type){var l=s.arg,u=l.value;return u&&"object"==typeof u&&r.call(u,"__await")?t.resolve(u.__await).then((function(e){n("next",e,i,c)}),(function(e){n("throw",e,i,c)})):t.resolve(u).then((function(e){l.value=e,i(l)}),(function(e){return n("throw",e,i,c)}))}c(s.arg)}var a;o(this,"_invoke",{value:function(e,r){function o(){return new t((function(t,o){n(e,r,t,o)}))}return a=a?a.then(o,o):o()}})}function D(t,n,r){var o=p;return function(a,i){if(o===m)throw Error("Generator is already running");if(o===g){if("throw"===a)throw i;return{value:e,done:!0}}for(r.method=a,r.arg=i;;){var c=r.delegate;if(c){var s=j(c,r);if(s){if(s===h)continue;return s}}if("next"===r.method)r.sent=r._sent=r.arg;else if("throw"===r.method){if(o===p)throw o=g,r.arg;r.dispatchException(r.arg)}else"return"===r.method&&r.abrupt("return",r.arg);o=m;var l=d(t,n,r);if("normal"===l.type){if(o=r.done?g:f,l.arg===h)continue;return{value:l.arg,done:r.done}}"throw"===l.type&&(o=g,r.method="throw",r.arg=l.arg)}}}function j(t,n){var r=n.method,o=t.iterator[r];if(o===e)return n.delegate=null,"throw"===r&&t.iterator.return&&(n.method="return",n.arg=e,j(t,n),"throw"===n.method)||"return"!==r&&(n.method="throw",n.arg=new TypeError("The iterator does not provide a '"+r+"' method")),h;var a=d(o,t.iterator,n.arg);if("throw"===a.type)return n.method="throw",n.arg=a.arg,n.delegate=null,h;var i=a.arg;return i?i.done?(n[t.resultName]=i.value,n.next=t.nextLoc,"return"!==n.method&&(n.method="next",n.arg=e),n.delegate=null,h):i:(n.method="throw",n.arg=new TypeError("iterator result is not an object"),n.delegate=null,h)}function O(e){var t={tryLoc:e[0]};1 in e&&(t.catchLoc=e[1]),2 in e&&(t.finallyLoc=e[2],t.afterLoc=e[3]),this.tryEntries.push(t)}function A(e){var t=e.completion||{};t.type="normal",delete t.arg,e.completion=t}function T(e){this.tryEntries=[{tryLoc:"root"}],e.forEach(O,this),this.reset(!0)}function P(t){if(t||""===t){var n=t[i];if(n)return n.call(t);if("function"==typeof t.next)return t;if(!isNaN(t.length)){var o=-1,a=function n(){for(;++o<t.length;)if(r.call(t,o))return n.value=t[o],n.done=!1,n;return n.value=e,n.done=!0,n};return a.next=a}}throw new TypeError(typeof t+" is not iterable")}return v.prototype=w,o(_,"constructor",{value:w,configurable:!0}),o(w,"constructor",{value:v,configurable:!0}),v.displayName=l(w,s,"GeneratorFunction"),t.isGeneratorFunction=function(e){var t="function"==typeof e&&e.constructor;return!!t&&(t===v||"GeneratorFunction"===(t.displayName||t.name))},t.mark=function(e){return Object.setPrototypeOf?Object.setPrototypeOf(e,w):(e.__proto__=w,l(e,s,"GeneratorFunction")),e.prototype=Object.create(_),e},t.awrap=function(e){return{__await:e}},C(E.prototype),l(E.prototype,c,(function(){return this})),t.AsyncIterator=E,t.async=function(e,n,r,o,a){void 0===a&&(a=Promise);var i=new E(u(e,n,r,o),a);return t.isGeneratorFunction(n)?i:i.next().then((function(e){return e.done?e.value:i.next()}))},C(_),l(_,s,"Generator"),l(_,i,(function(){return this})),l(_,"toString",(function(){return"[object Generator]"})),t.keys=function(e){var t=Object(e),n=[];for(var r in t)n.push(r);return n.reverse(),function e(){for(;n.length;){var r=n.pop();if(r in t)return e.value=r,e.done=!1,e}return e.done=!0,e}},t.values=P,T.prototype={constructor:T,reset:function(t){if(this.prev=0,this.next=0,this.sent=this._sent=e,this.done=!1,this.delegate=null,this.method="next",this.arg=e,this.tryEntries.forEach(A),!t)for(var n in this)"t"===n.charAt(0)&&r.call(this,n)&&!isNaN(+n.slice(1))&&(this[n]=e)},stop:function(){this.done=!0;var e=this.tryEntries[0].completion;if("throw"===e.type)throw e.arg;return this.rval},dispatchException:function(t){if(this.done)throw t;var n=this;function o(r,o){return c.type="throw",c.arg=t,n.next=r,o&&(n.method="next",n.arg=e),!!o}for(var a=this.tryEntries.length-1;a>=0;--a){var i=this.tryEntries[a],c=i.completion;if("root"===i.tryLoc)return o("end");if(i.tryLoc<=this.prev){var s=r.call(i,"catchLoc"),l=r.call(i,"finallyLoc");if(s&&l){if(this.prev<i.catchLoc)return o(i.catchLoc,!0);if(this.prev<i.finallyLoc)return o(i.finallyLoc)}else if(s){if(this.prev<i.catchLoc)return o(i.catchLoc,!0)}else{if(!l)throw Error("try statement without catch or finally");if(this.prev<i.finallyLoc)return o(i.finallyLoc)}}}},abrupt:function(e,t){for(var n=this.tryEntries.length-1;n>=0;--n){var o=this.tryEntries[n];if(o.tryLoc<=this.prev&&r.call(o,"finallyLoc")&&this.prev<o.finallyLoc){var a=o;break}}a&&("break"===e||"continue"===e)&&a.tryLoc<=t&&t<=a.finallyLoc&&(a=null);var i=a?a.completion:{};return i.type=e,i.arg=t,a?(this.method="next",this.next=a.finallyLoc,h):this.complete(i)},complete:function(e,t){if("throw"===e.type)throw e.arg;return"break"===e.type||"continue"===e.type?this.next=e.arg:"return"===e.type?(this.rval=this.arg=e.arg,this.method="return",this.next="end"):"normal"===e.type&&t&&(this.next=t),h},finish:function(e){for(var t=this.tryEntries.length-1;t>=0;--t){var n=this.tryEntries[t];if(n.finallyLoc===e)return this.complete(n.completion,n.afterLoc),A(n),h}},catch:function(e){for(var t=this.tryEntries.length-1;t>=0;--t){var n=this.tryEntries[t];if(n.tryLoc===e){var r=n.completion;if("throw"===r.type){var o=r.arg;A(n)}return o}}throw Error("illegal catch attempt")},delegateYield:function(t,n,r){return this.delegate={iterator:P(t),resultName:n,nextLoc:r},"next"===this.method&&(this.arg=e),h}},t}function v(e,t){return v=Object.setPrototypeOf?Object.setPrototypeOf.bind():function(e,t){return e.__proto__=t,e},v(e,t)}function w(e,t){return function(e){if(Array.isArray(e))return e}(e)||function(e,t){var n=null==e?null:"undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(null!=n){var r,o,a,i,c=[],s=!0,l=!1;try{if(a=(n=n.call(e)).next,0===t){if(Object(n)!==n)return;s=!1}else for(;!(s=(r=a.call(n)).done)&&(c.push(r.value),c.length!==t);s=!0);}catch(e){l=!0,o=e}finally{try{if(!s&&null!=n.return&&(i=n.return(),Object(i)!==i))return}finally{if(l)throw o}}return c}}(e,t)||k(e,t)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function S(e){return function(e){if(Array.isArray(e))return o(e)}(e)||function(e){if("undefined"!=typeof Symbol&&null!=e[Symbol.iterator]||null!=e["@@iterator"])return Array.from(e)}(e)||k(e)||function(){throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function k(e,t){if(e){if("string"==typeof e)return o(e,t);var n={}.toString.call(e).slice(8,-1);return"Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n?Array.from(e):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?o(e,t):void 0}}function x(e){var t="function"==typeof Map?new Map:void 0;return x=function(e){if(null===e||!function(e){try{return-1!==Function.toString.call(e).indexOf("[native code]")}catch(t){return"function"==typeof e}}(e))return e;if("function"!=typeof e)throw new TypeError("Super expression must either be null or a function");if(void 0!==t){if(t.has(e))return t.get(e);t.set(e,n)}function n(){return function(e,t,n){if(m())return Reflect.construct.apply(null,arguments);var r=[null];r.push.apply(r,t);var o=new(e.bind.apply(e,r));return n&&v(o,n.prototype),o}(e,arguments,p(this).constructor)}return n.prototype=Object.create(e.prototype,{constructor:{value:n,enumerable:!1,writable:!0,configurable:!0}}),v(n,e)},x(e)}function _(){return r.createElement("svg",{width:"15",height:"15",className:"DocSearch-Control-Key-Icon"},r.createElement("path",{d:"M4.505 4.496h2M5.505 5.496v5M8.216 4.496l.055 5.993M10 7.5c.333.333.5.667.5 1v2M12.326 4.5v5.996M8.384 4.496c1.674 0 2.116 0 2.116 1.5s-.442 1.5-2.116 1.5M3.205 9.303c-.09.448-.277 1.21-1.241 1.203C1 10.5.5 9.513.5 8V7c0-1.57.5-2.5 1.464-2.494.964.006 1.134.598 1.24 1.342M12.553 10.5h1.953",strokeWidth:"1.2",stroke:"currentColor",fill:"none",strokeLinecap:"square"}))}function C(){return r.createElement("svg",{width:"20",height:"20",className:"DocSearch-Search-Icon",viewBox:"0 0 20 20","aria-hidden":"true"},r.createElement("path",{d:"M14.386 14.386l4.0877 4.0877-4.0877-4.0877c-2.9418 2.9419-7.7115 2.9419-10.6533 0-2.9419-2.9418-2.9419-7.7115 0-10.6533 2.9418-2.9419 7.7115-2.9419 10.6533 0 2.9419 2.9418 2.9419 7.7115 0 10.6533z",stroke:"currentColor",fill:"none",fillRule:"evenodd",strokeLinecap:"round",strokeLinejoin:"round"}))}var E=["translations"],D="Ctrl",j=r.forwardRef((function(e,t){var n=e.translations,o=void 0===n?{}:n,a=b(e,E),i=o.buttonText,c=void 0===i?"Search":i,s=o.buttonAriaLabel,l=void 0===s?"Search":s,u=w((0,r.useState)(null),2),p=u[0],f=u[1];(0,r.useEffect)((function(){"undefined"!=typeof navigator&&(/(Mac|iPhone|iPod|iPad)/i.test(navigator.platform)?f("\u2318"):f(D))}),[]);var m=w(p===D?[D,"Ctrl",r.createElement(_,null)]:["Meta","Command",p],3),g=m[0],h=m[1],y=m[2];return r.createElement("button",d({type:"button",className:"DocSearch DocSearch-Button","aria-label":"".concat(l," (").concat(h,"+K)")},a,{ref:t}),r.createElement("span",{className:"DocSearch-Button-Container"},r.createElement(C,null),r.createElement("span",{className:"DocSearch-Button-Placeholder"},c)),r.createElement("span",{className:"DocSearch-Button-Keys"},null!==p&&r.createElement(r.Fragment,null,r.createElement(O,{reactsToKey:g},y),r.createElement(O,{reactsToKey:"k"},"K"))))}));function O(e){var t=e.reactsToKey,n=e.children,o=w((0,r.useState)(!1),2),a=o[0],i=o[1];return(0,r.useEffect)((function(){if(t)return window.addEventListener("keydown",e),window.addEventListener("keyup",n),function(){window.removeEventListener("keydown",e),window.removeEventListener("keyup",n)};function e(e){e.key===t&&i(!0)}function n(e){e.key!==t&&"Meta"!==e.key||i(!1)}}),[t]),r.createElement("kbd",{className:a?"DocSearch-Button-Key DocSearch-Button-Key--pressed":"DocSearch-Button-Key"},n)}function A(e,t){var n=void 0;return function(){for(var r=arguments.length,o=new Array(r),a=0;a<r;a++)o[a]=arguments[a];n&&clearTimeout(n),n=setTimeout((function(){return e.apply(void 0,o)}),t)}}function T(e){return e.reduce((function(e,t){return e.concat(t)}),[])}var P=0;function I(e){return 0===e.collections.length?0:e.collections.reduce((function(e,t){return e+t.items.length}),0)}function N(e){return e!==Object(e)}function R(e,t){if(e===t)return!0;if(N(e)||N(t)||"function"==typeof e||"function"==typeof t)return e===t;if(Object.keys(e).length!==Object.keys(t).length)return!1;for(var n=0,r=Object.keys(e);n<r.length;n++){var o=r[n];if(!(o in t))return!1;if(!R(e[o],t[o]))return!1}return!0}var L=function(){},M=[{segment:"autocomplete-core",version:"1.17.7"}];function F(e){var t=e.item,n=e.items,r=void 0===n?[]:n;return{index:t.__autocomplete_indexName,items:[t],positions:[1+r.findIndex((function(e){return e.objectID===t.objectID}))],queryID:t.__autocomplete_queryID,algoliaSource:["autocomplete"]}}function B(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=new Array(t);n<t;n++)r[n]=e[n];return r}var z=["items"],$=["items"];function U(e){return U="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},U(e)}function H(e){return function(e){if(Array.isArray(e))return q(e)}(e)||function(e){if("undefined"!=typeof Symbol&&null!=e[Symbol.iterator]||null!=e["@@iterator"])return Array.from(e)}(e)||function(e,t){if(e){if("string"==typeof e)return q(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);return"Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n?Array.from(e):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?q(e,t):void 0}}(e)||function(){throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function q(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=new Array(t);n<t;n++)r[n]=e[n];return r}function V(e,t){if(null==e)return{};var n,r,o=function(e,t){if(null==e)return{};var n,r,o={},a=Object.keys(e);for(r=0;r<a.length;r++)n=a[r],t.indexOf(n)>=0||(o[n]=e[n]);return o}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(r=0;r<a.length;r++)n=a[r],t.indexOf(n)>=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(o[n]=e[n])}return o}function W(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function G(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?W(Object(n),!0).forEach((function(t){K(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):W(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}function K(e,t,n){return(t=function(e){var t=function(e){if("object"!==U(e)||null===e)return e;var t=e[Symbol.toPrimitive];if(void 0!==t){var n=t.call(e,"string");if("object"!==U(n))return n;throw new TypeError("@@toPrimitive must return a primitive value.")}return String(e)}(e);return"symbol"===U(t)?t:String(t)}(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function Y(e){return e.map((function(e){var t=e.items,n=V(e,z);return G(G({},n),{},{objectIDs:(null==t?void 0:t.map((function(e){return e.objectID})))||n.objectIDs})}))}function Q(e){var t,n,r,o=(t=function(e,t){return function(e){if(Array.isArray(e))return e}(e)||function(e,t){var n=null==e?null:"undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(null!=n){var r,o,a,i,c=[],s=!0,l=!1;try{if(a=(n=n.call(e)).next,0===t);else for(;!(s=(r=a.call(n)).done)&&(c.push(r.value),c.length!==t);s=!0);}catch(e){l=!0,o=e}finally{try{if(!s&&null!=n.return&&(i=n.return(),Object(i)!==i))return}finally{if(l)throw o}}return c}}(e,t)||function(e,t){if(e){if("string"==typeof e)return B(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);return"Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n?Array.from(e):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?B(e,t):void 0}}(e,t)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}((e.version||"").split(".").map(Number),2),n=t[0],r=t[1],n>=3||2===n&&r>=4||1===n&&r>=10);function a(t,n,r){if(o&&void 0!==r){var a=r[0].__autocomplete_algoliaCredentials,i={"X-Algolia-Application-Id":a.appId,"X-Algolia-API-Key":a.apiKey};e.apply(void 0,[t].concat(H(n),[{headers:i}]))}else e.apply(void 0,[t].concat(H(n)))}return{init:function(t,n){e("init",{appId:t,apiKey:n})},setAuthenticatedUserToken:function(t){e("setAuthenticatedUserToken",t)},setUserToken:function(t){e("setUserToken",t)},clickedObjectIDsAfterSearch:function(){for(var e=arguments.length,t=new Array(e),n=0;n<e;n++)t[n]=arguments[n];t.length>0&&a("clickedObjectIDsAfterSearch",Y(t),t[0].items)},clickedObjectIDs:function(){for(var e=arguments.length,t=new Array(e),n=0;n<e;n++)t[n]=arguments[n];t.length>0&&a("clickedObjectIDs",Y(t),t[0].items)},clickedFilters:function(){for(var t=arguments.length,n=new Array(t),r=0;r<t;r++)n[r]=arguments[r];n.length>0&&e.apply(void 0,["clickedFilters"].concat(n))},convertedObjectIDsAfterSearch:function(){for(var e=arguments.length,t=new Array(e),n=0;n<e;n++)t[n]=arguments[n];t.length>0&&a("convertedObjectIDsAfterSearch",Y(t),t[0].items)},convertedObjectIDs:function(){for(var e=arguments.length,t=new Array(e),n=0;n<e;n++)t[n]=arguments[n];t.length>0&&a("convertedObjectIDs",Y(t),t[0].items)},convertedFilters:function(){for(var t=arguments.length,n=new Array(t),r=0;r<t;r++)n[r]=arguments[r];n.length>0&&e.apply(void 0,["convertedFilters"].concat(n))},viewedObjectIDs:function(){for(var e=arguments.length,t=new Array(e),n=0;n<e;n++)t[n]=arguments[n];t.length>0&&t.reduce((function(e,t){var n=t.items,r=V(t,$);return[].concat(H(e),H(function(e){for(var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:20,n=[],r=0;r<e.objectIDs.length;r+=t)n.push(G(G({},e),{},{objectIDs:e.objectIDs.slice(r,r+t)}));return n}(G(G({},r),{},{objectIDs:(null==n?void 0:n.map((function(e){return e.objectID})))||r.objectIDs})).map((function(e){return{items:n,payload:e}}))))}),[]).forEach((function(e){var t=e.items;return a("viewedObjectIDs",[e.payload],t)}))},viewedFilters:function(){for(var t=arguments.length,n=new Array(t),r=0;r<t;r++)n[r]=arguments[r];n.length>0&&e.apply(void 0,["viewedFilters"].concat(n))}}}function Z(e){var t=e.items.reduce((function(e,t){var n;return e[t.__autocomplete_indexName]=(null!==(n=e[t.__autocomplete_indexName])&&void 0!==n?n:[]).concat(t),e}),{});return Object.keys(t).map((function(e){return{index:e,items:t[e],algoliaSource:["autocomplete"]}}))}function X(e){return e.objectID&&e.__autocomplete_indexName&&e.__autocomplete_queryID}function J(e){return J="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},J(e)}function ee(e){return function(e){if(Array.isArray(e))return te(e)}(e)||function(e){if("undefined"!=typeof Symbol&&null!=e[Symbol.iterator]||null!=e["@@iterator"])return Array.from(e)}(e)||function(e,t){if(e){if("string"==typeof e)return te(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);return"Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n?Array.from(e):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?te(e,t):void 0}}(e)||function(){throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function te(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=new Array(t);n<t;n++)r[n]=e[n];return r}function ne(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function re(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?ne(Object(n),!0).forEach((function(t){oe(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):ne(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}function oe(e,t,n){return(t=function(e){var t=function(e){if("object"!==J(e)||null===e)return e;var t=e[Symbol.toPrimitive];if(void 0!==t){var n=t.call(e,"string");if("object"!==J(n))return n;throw new TypeError("@@toPrimitive must return a primitive value.")}return String(e)}(e);return"symbol"===J(t)?t:String(t)}(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}var ae="2.15.0",ie="https://cdn.jsdelivr.net/npm/search-insights@".concat(ae,"/dist/search-insights.min.js"),ce=A((function(e){var t=e.onItemsChange,n=e.items,r=e.insights,o=e.state;t({insights:r,insightsEvents:Z({items:n}).map((function(e){return re({eventName:"Items Viewed"},e)})),state:o})}),400);function se(e){var t=function(e){return re({onItemsChange:function(e){var t=e.insights,n=e.insightsEvents,r=e.state;t.viewedObjectIDs.apply(t,ee(n.map((function(e){return re(re({},e),{},{algoliaSource:le(e.algoliaSource,r.context)})}))))},onSelect:function(e){var t=e.insights,n=e.insightsEvents,r=e.state;t.clickedObjectIDsAfterSearch.apply(t,ee(n.map((function(e){return re(re({},e),{},{algoliaSource:le(e.algoliaSource,r.context)})}))))},onActive:L,__autocomplete_clickAnalytics:!0},e)}(e),n=t.insightsClient,r=t.insightsInitParams,o=t.onItemsChange,a=t.onSelect,i=t.onActive,c=t.__autocomplete_clickAnalytics,s=n;if(n||"undefined"!=typeof window&&function(e){var t=e.window,n=t.AlgoliaAnalyticsObject||"aa";"string"==typeof n&&(s=t[n]),s||(t.AlgoliaAnalyticsObject=n,t[n]||(t[n]=function(){t[n].queue||(t[n].queue=[]);for(var e=arguments.length,r=new Array(e),o=0;o<e;o++)r[o]=arguments[o];t[n].queue.push(r)}),t[n].version=ae,s=t[n],function(e){var t="[Autocomplete]: Could not load search-insights.js. Please load it manually following https://alg.li/insights-autocomplete";try{var n=e.document.createElement("script");n.async=!0,n.src=ie,n.onerror=function(){console.error(t)},document.body.appendChild(n)}catch(e){console.error(t)}}(t))}({window:window}),!s)return{};r&&s("init",re({partial:!0},r));var l=Q(s),u={current:[]},d=A((function(e){var t=e.state;if(t.isOpen){var n=t.collections.reduce((function(e,t){return[].concat(ee(e),ee(t.items))}),[]).filter(X);R(u.current.map((function(e){return e.objectID})),n.map((function(e){return e.objectID})))||(u.current=n,n.length>0&&ce({onItemsChange:o,items:n,insights:l,state:t}))}}),0);return{name:"aa.algoliaInsightsPlugin",subscribe:function(e){var t=e.setContext,n=e.onSelect,r=e.onActive,o=!1;function u(e){t({algoliaInsightsPlugin:{__algoliaSearchParameters:re(re({},c?{clickAnalytics:!0}:{}),e?{userToken:ue(e)}:{}),insights:l}})}s("addAlgoliaAgent","insights-plugin"),u(),s("onUserTokenChange",(function(e){o||u(e)})),s("getUserToken",null,(function(e,t){o||u(t)})),s("onAuthenticatedUserTokenChange",(function(e){e?(o=!0,u(e)):(o=!1,s("getUserToken",null,(function(e,t){return u(t)})))})),s("getAuthenticatedUserToken",null,(function(e,t){t&&(o=!0,u(t))})),n((function(e){var t=e.item,n=e.state,r=e.event,o=e.source;X(t)&&a({state:n,event:r,insights:l,item:t,insightsEvents:[re({eventName:"Item Selected"},F({item:t,items:o.getItems().filter(X)}))]})})),r((function(e){var t=e.item,n=e.source,r=e.state,o=e.event;X(t)&&i({state:r,event:o,insights:l,item:t,insightsEvents:[re({eventName:"Item Active"},F({item:t,items:n.getItems().filter(X)}))]})}))},onStateChange:function(e){var t=e.state;d({state:t})},__autocomplete_pluginOptions:e}}function le(){var e,t=arguments.length>1?arguments[1]:void 0;return[].concat(ee(arguments.length>0&&void 0!==arguments[0]?arguments[0]:[]),["autocomplete-internal"],ee(null!==(e=t.algoliaInsightsPlugin)&&void 0!==e&&e.__automaticInsights?["autocomplete-automatic"]:[]))}function ue(e){return"number"==typeof e?e.toString():e}function de(e,t){var n=t;return{then:function(t,r){return de(e.then(fe(t,n,e),fe(r,n,e)),n)},catch:function(t){return de(e.catch(fe(t,n,e)),n)},finally:function(t){return t&&n.onCancelList.push(t),de(e.finally(fe(t&&function(){return n.onCancelList=[],t()},n,e)),n)},cancel:function(){n.isCanceled=!0;var e=n.onCancelList;n.onCancelList=[],e.forEach((function(e){e()}))},isCanceled:function(){return!0===n.isCanceled}}}function pe(e){return de(e,{isCanceled:!1,onCancelList:[]})}function fe(e,t,n){return e?function(n){return t.isCanceled?n:e(n)}:n}function me(e,t,n,r){if(!n)return null;if(e<0&&(null===t||null!==r&&0===t))return n+e;var o=(null===t?-1:t)+e;return o<=-1||o>=n?null===r?null:0:o}function ge(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function he(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?ge(Object(n),!0).forEach((function(t){be(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):ge(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}function be(e,t,n){return(t=function(e){var t=function(e){if("object"!==ye(e)||null===e)return e;var t=e[Symbol.toPrimitive];if(void 0!==t){var n=t.call(e,"string");if("object"!==ye(n))return n;throw new TypeError("@@toPrimitive must return a primitive value.")}return String(e)}(e);return"symbol"===ye(t)?t:String(t)}(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function ye(e){return ye="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},ye(e)}function ve(e){var t=function(e){var t=e.collections.map((function(e){return e.items.length})).reduce((function(e,t,n){var r=(e[n-1]||0)+t;return e.push(r),e}),[]).reduce((function(t,n){return n<=e.activeItemId?t+1:t}),0);return e.collections[t]}(e);if(!t)return null;var n=t.items[function(e){for(var t=e.state,n=e.collection,r=!1,o=0,a=0;!1===r;){var i=t.collections[o];if(i===n){r=!0;break}a+=i.items.length,o++}return t.activeItemId-a}({state:e,collection:t})],r=t.source;return{item:n,itemInputValue:r.getItemInputValue({item:n,state:e}),itemUrl:r.getItemUrl({item:n,state:e}),source:r}}function we(e,t,n){return[e,null==n?void 0:n.sourceId,t].filter(Boolean).join("-").replace(/\s/g,"")}var Se=/((gt|sm)-|galaxy nexus)|samsung[- ]|samsungbrowser/i;function ke(e){return e.nativeEvent||e}function xe(e){return xe="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},xe(e)}function _e(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function Ce(e,t,n){return(t=function(e){var t=function(e){if("object"!==xe(e)||null===e)return e;var t=e[Symbol.toPrimitive];if(void 0!==t){var n=t.call(e,"string");if("object"!==xe(n))return n;throw new TypeError("@@toPrimitive must return a primitive value.")}return String(e)}(e);return"symbol"===xe(t)?t:String(t)}(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function Ee(e){return Ee="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},Ee(e)}function De(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function je(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?De(Object(n),!0).forEach((function(t){Oe(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):De(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}function Oe(e,t,n){return(t=function(e){var t=function(e){if("object"!==Ee(e)||null===e)return e;var t=e[Symbol.toPrimitive];if(void 0!==t){var n=t.call(e,"string");if("object"!==Ee(n))return n;throw new TypeError("@@toPrimitive must return a primitive value.")}return String(e)}(e);return"symbol"===Ee(t)?t:String(t)}(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function Ae(e){return Ae="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},Ae(e)}function Te(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=new Array(t);n<t;n++)r[n]=e[n];return r}function Pe(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function Ie(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?Pe(Object(n),!0).forEach((function(t){Ne(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):Pe(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}function Ne(e,t,n){return(t=function(e){var t=function(e){if("object"!==Ae(e)||null===e)return e;var t=e[Symbol.toPrimitive];if(void 0!==t){var n=t.call(e,"string");if("object"!==Ae(n))return n;throw new TypeError("@@toPrimitive must return a primitive value.")}return String(e)}(e);return"symbol"===Ae(t)?t:String(t)}(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function Re(e,t){var n,r="undefined"!=typeof window?window:{},o=e.plugins||[];return Ie(Ie({debug:!1,openOnFocus:!1,enterKeyHint:void 0,ignoreCompositionEvents:!1,placeholder:"",autoFocus:!1,defaultActiveItemId:null,stallThreshold:300,insights:void 0,environment:r,shouldPanelOpen:function(e){return I(e.state)>0},reshape:function(e){return e.sources}},e),{},{id:null!==(n=e.id)&&void 0!==n?n:"autocomplete-".concat(P++),plugins:o,initialState:Ie({activeItemId:null,query:"",completion:null,collections:[],isOpen:!1,status:"idle",context:{}},e.initialState),onStateChange:function(t){var n;null===(n=e.onStateChange)||void 0===n||n.call(e,t),o.forEach((function(e){var n;return null===(n=e.onStateChange)||void 0===n?void 0:n.call(e,t)}))},onSubmit:function(t){var n;null===(n=e.onSubmit)||void 0===n||n.call(e,t),o.forEach((function(e){var n;return null===(n=e.onSubmit)||void 0===n?void 0:n.call(e,t)}))},onReset:function(t){var n;null===(n=e.onReset)||void 0===n||n.call(e,t),o.forEach((function(e){var n;return null===(n=e.onReset)||void 0===n?void 0:n.call(e,t)}))},getSources:function(n){return Promise.all([].concat(function(e){return function(e){if(Array.isArray(e))return Te(e)}(e)||function(e){if("undefined"!=typeof Symbol&&null!=e[Symbol.iterator]||null!=e["@@iterator"])return Array.from(e)}(e)||function(e,t){if(e){if("string"==typeof e)return Te(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);return"Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n?Array.from(e):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?Te(e,t):void 0}}(e)||function(){throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}(o.map((function(e){return e.getSources}))),[e.getSources]).filter(Boolean).map((function(e){return function(e,t){var n=[];return Promise.resolve(e(t)).then((function(e){return Promise.all(e.filter((function(e){return Boolean(e)})).map((function(e){if(e.sourceId,n.includes(e.sourceId))throw new Error("[Autocomplete] The `sourceId` ".concat(JSON.stringify(e.sourceId)," is not unique."));n.push(e.sourceId);var t={getItemInputValue:function(e){return e.state.query},getItemUrl:function(){},onSelect:function(e){(0,e.setIsOpen)(!1)},onActive:L,onResolve:L};Object.keys(t).forEach((function(e){t[e].__default=!0}));var r=he(he({},t),e);return Promise.resolve(r)})))}))}(e,n)}))).then((function(e){return T(e)})).then((function(e){return e.map((function(e){return Ie(Ie({},e),{},{onSelect:function(n){e.onSelect(n),t.forEach((function(e){var t;return null===(t=e.onSelect)||void 0===t?void 0:t.call(e,n)}))},onActive:function(n){e.onActive(n),t.forEach((function(e){var t;return null===(t=e.onActive)||void 0===t?void 0:t.call(e,n)}))},onResolve:function(n){e.onResolve(n),t.forEach((function(e){var t;return null===(t=e.onResolve)||void 0===t?void 0:t.call(e,n)}))}})}))}))},navigator:Ie({navigate:function(e){var t=e.itemUrl;r.location.assign(t)},navigateNewTab:function(e){var t=e.itemUrl,n=r.open(t,"_blank","noopener");null==n||n.focus()},navigateNewWindow:function(e){var t=e.itemUrl;r.open(t,"_blank","noopener")}},e.navigator)})}function Le(e){return Le="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},Le(e)}function Me(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function Fe(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?Me(Object(n),!0).forEach((function(t){Be(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):Me(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}function Be(e,t,n){return(t=function(e){var t=function(e){if("object"!==Le(e)||null===e)return e;var t=e[Symbol.toPrimitive];if(void 0!==t){var n=t.call(e,"string");if("object"!==Le(n))return n;throw new TypeError("@@toPrimitive must return a primitive value.")}return String(e)}(e);return"symbol"===Le(t)?t:String(t)}(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function ze(e){return ze="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},ze(e)}function $e(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function Ue(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?$e(Object(n),!0).forEach((function(t){He(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):$e(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}function He(e,t,n){return(t=function(e){var t=function(e){if("object"!==ze(e)||null===e)return e;var t=e[Symbol.toPrimitive];if(void 0!==t){var n=t.call(e,"string");if("object"!==ze(n))return n;throw new TypeError("@@toPrimitive must return a primitive value.")}return String(e)}(e);return"symbol"===ze(t)?t:String(t)}(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function qe(e){return function(e){if(Array.isArray(e))return Ve(e)}(e)||function(e){if("undefined"!=typeof Symbol&&null!=e[Symbol.iterator]||null!=e["@@iterator"])return Array.from(e)}(e)||function(e,t){if(e){if("string"==typeof e)return Ve(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);return"Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n?Array.from(e):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?Ve(e,t):void 0}}(e)||function(){throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function Ve(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=new Array(t);n<t;n++)r[n]=e[n];return r}function We(e){return Boolean(e.execute)}function Ge(e){var t=e.reduce((function(e,t){if(!We(t))return e.push(t),e;var n=t.searchClient,r=t.execute,o=t.requesterId,a=t.requests,i=e.find((function(e){return We(t)&&We(e)&&e.searchClient===n&&Boolean(o)&&e.requesterId===o}));if(i){var c;(c=i.items).push.apply(c,qe(a))}else{var s={execute:r,requesterId:o,items:a,searchClient:n};e.push(s)}return e}),[]).map((function(e){if(!We(e))return Promise.resolve(e);var t=e,n=t.execute,r=t.items;return n({searchClient:t.searchClient,requests:r})}));return Promise.all(t).then((function(e){return T(e)}))}function Ke(e){return Ke="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},Ke(e)}var Ye=["event","nextState","props","query","refresh","store"];function Qe(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function Ze(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?Qe(Object(n),!0).forEach((function(t){Xe(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):Qe(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}function Xe(e,t,n){return(t=function(e){var t=function(e){if("object"!==Ke(e)||null===e)return e;var t=e[Symbol.toPrimitive];if(void 0!==t){var n=t.call(e,"string");if("object"!==Ke(n))return n;throw new TypeError("@@toPrimitive must return a primitive value.")}return String(e)}(e);return"symbol"===Ke(t)?t:String(t)}(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}var Je,et,tt,nt=null,rt=(Je=-1,et=-1,tt=void 0,function(e){var t=++Je;return Promise.resolve(e).then((function(e){return tt&&t<et?tt:(et=t,tt=e,e)}))});function ot(e){var t=e.event,n=e.nextState,r=void 0===n?{}:n,o=e.props,a=e.query,i=e.refresh,c=e.store,s=function(e,t){if(null==e)return{};var n,r,o=function(e,t){if(null==e)return{};var n,r,o={},a=Object.keys(e);for(r=0;r<a.length;r++)n=a[r],t.indexOf(n)>=0||(o[n]=e[n]);return o}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(r=0;r<a.length;r++)n=a[r],t.indexOf(n)>=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(o[n]=e[n])}return o}(e,Ye);nt&&o.environment.clearTimeout(nt);var l=s.setCollections,u=s.setIsOpen,d=s.setQuery,p=s.setActiveItemId,f=s.setStatus,m=s.setContext;if(d(a),p(o.defaultActiveItemId),!a&&!1===o.openOnFocus){var g,h=c.getState().collections.map((function(e){return Ze(Ze({},e),{},{items:[]})}));f("idle"),l(h),u(null!==(g=r.isOpen)&&void 0!==g?g:o.shouldPanelOpen({state:c.getState()}));var b=pe(rt(h).then((function(){return Promise.resolve()})));return c.pendingRequests.add(b)}f("loading"),nt=o.environment.setTimeout((function(){f("stalled")}),o.stallThreshold);var y=pe(rt(o.getSources(Ze({query:a,refresh:i,state:c.getState()},s)).then((function(e){return Promise.all(e.map((function(e){return Promise.resolve(e.getItems(Ze({query:a,refresh:i,state:c.getState()},s))).then((function(t){return function(e,t,n){if(o=e,Boolean(null==o?void 0:o.execute)){var r="algolia"===e.requesterId?Object.assign.apply(Object,[{}].concat(qe(Object.keys(n.context).map((function(e){var t;return null===(t=n.context[e])||void 0===t?void 0:t.__algoliaSearchParameters}))))):{};return Ue(Ue({},e),{},{requests:e.queries.map((function(n){return{query:"algolia"===e.requesterId?Ue(Ue({},n),{},{params:Ue(Ue({},r),n.params)}):n,sourceId:t,transformResponse:e.transformResponse}}))})}var o;return{items:e,sourceId:t}}(t,e.sourceId,c.getState())}))}))).then(Ge).then((function(t){var n,r=t.some((function(e){return function(e){return!Array.isArray(e)&&Boolean(null==e?void 0:e._automaticInsights)}(e.items)}));return r&&m({algoliaInsightsPlugin:Ze(Ze({},(null===(n=c.getState().context)||void 0===n?void 0:n.algoliaInsightsPlugin)||{}),{},{__automaticInsights:r})}),function(e,t,n){return t.map((function(t){var r,o=e.filter((function(e){return e.sourceId===t.sourceId})),a=o.map((function(e){return e.items})),i=o[0].transformResponse,c=i?i({results:r=a,hits:r.map((function(e){return e.hits})).filter(Boolean),facetHits:r.map((function(e){var t;return null===(t=e.facetHits)||void 0===t?void 0:t.map((function(e){return{label:e.value,count:e.count,_highlightResult:{label:{value:e.highlighted}}}}))})).filter(Boolean)}):a;return t.onResolve({source:t,results:a,items:c,state:n.getState()}),c.every(Boolean),'The `getItems` function from source "'.concat(t.sourceId,'" must return an array of items but returned ').concat(JSON.stringify(void 0),".\n\nDid you forget to return items?\n\nSee: https://www.algolia.com/doc/ui-libraries/autocomplete/core-concepts/sources/#param-getitems"),{source:t,items:c}}))}(t,e,c)})).then((function(e){return function(e){var t=e.props,n=e.state,r=e.collections.reduce((function(e,t){return Fe(Fe({},e),{},Be({},t.source.sourceId,Fe(Fe({},t.source),{},{getItems:function(){return T(t.items)}})))}),{}),o=t.plugins.reduce((function(e,t){return t.reshape?t.reshape(e):e}),{sourcesBySourceId:r,state:n}).sourcesBySourceId;return T(t.reshape({sourcesBySourceId:o,sources:Object.values(o),state:n})).filter(Boolean).map((function(e){return{source:e,items:e.getItems()}}))}({collections:e,props:o,state:c.getState()})}))})))).then((function(e){var n;f("idle"),l(e);var d=o.shouldPanelOpen({state:c.getState()});u(null!==(n=r.isOpen)&&void 0!==n?n:o.openOnFocus&&!a&&d||d);var p=ve(c.getState());if(null!==c.getState().activeItemId&&p){var m=p.item,g=p.itemInputValue,h=p.itemUrl,b=p.source;b.onActive(Ze({event:t,item:m,itemInputValue:g,itemUrl:h,refresh:i,source:b,state:c.getState()},s))}})).finally((function(){f("idle"),nt&&o.environment.clearTimeout(nt)}));return c.pendingRequests.add(y)}function at(e){return at="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},at(e)}var it=["event","props","refresh","store"];function ct(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function st(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?ct(Object(n),!0).forEach((function(t){lt(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):ct(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}function lt(e,t,n){return(t=function(e){var t=function(e){if("object"!==at(e)||null===e)return e;var t=e[Symbol.toPrimitive];if(void 0!==t){var n=t.call(e,"string");if("object"!==at(n))return n;throw new TypeError("@@toPrimitive must return a primitive value.")}return String(e)}(e);return"symbol"===at(t)?t:String(t)}(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function ut(e){return ut="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},ut(e)}var dt=["props","refresh","store"],pt=["inputElement","formElement","panelElement"],ft=["inputElement"],mt=["inputElement","maxLength"],gt=["source"],ht=["item","source"];function bt(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function yt(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?bt(Object(n),!0).forEach((function(t){vt(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):bt(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}function vt(e,t,n){return(t=function(e){var t=function(e){if("object"!==ut(e)||null===e)return e;var t=e[Symbol.toPrimitive];if(void 0!==t){var n=t.call(e,"string");if("object"!==ut(n))return n;throw new TypeError("@@toPrimitive must return a primitive value.")}return String(e)}(e);return"symbol"===ut(t)?t:String(t)}(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function wt(e,t){if(null==e)return{};var n,r,o=function(e,t){if(null==e)return{};var n,r,o={},a=Object.keys(e);for(r=0;r<a.length;r++)n=a[r],t.indexOf(n)>=0||(o[n]=e[n]);return o}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(r=0;r<a.length;r++)n=a[r],t.indexOf(n)>=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(o[n]=e[n])}return o}function St(e){var t=e.props,n=e.refresh,r=e.store,o=wt(e,dt);return{getEnvironmentProps:function(e){var n=e.inputElement,o=e.formElement,a=e.panelElement;function i(e){!r.getState().isOpen&&r.pendingRequests.isEmpty()||e.target===n||!1===[o,a].some((function(t){return(n=t)===(r=e.target)||n.contains(r);var n,r}))&&(r.dispatch("blur",null),t.debug||r.pendingRequests.cancelAll())}return yt({onTouchStart:i,onMouseDown:i,onTouchMove:function(e){!1!==r.getState().isOpen&&n===t.environment.document.activeElement&&e.target!==n&&n.blur()}},wt(e,pt))},getRootProps:function(e){return yt({role:"combobox","aria-expanded":r.getState().isOpen,"aria-haspopup":"listbox","aria-controls":r.getState().isOpen?r.getState().collections.map((function(e){var n=e.source;return we(t.id,"list",n)})).join(" "):void 0,"aria-labelledby":we(t.id,"label")},e)},getFormProps:function(e){return e.inputElement,yt({action:"",noValidate:!0,role:"search",onSubmit:function(a){var i;a.preventDefault(),t.onSubmit(yt({event:a,refresh:n,state:r.getState()},o)),r.dispatch("submit",null),null===(i=e.inputElement)||void 0===i||i.blur()},onReset:function(a){var i;a.preventDefault(),t.onReset(yt({event:a,refresh:n,state:r.getState()},o)),r.dispatch("reset",null),null===(i=e.inputElement)||void 0===i||i.focus()}},wt(e,ft))},getLabelProps:function(e){return yt({htmlFor:we(t.id,"input"),id:we(t.id,"label")},e)},getInputProps:function(e){var a;function i(e){(t.openOnFocus||Boolean(r.getState().query))&&ot(yt({event:e,props:t,query:r.getState().completion||r.getState().query,refresh:n,store:r},o)),r.dispatch("focus",null)}var c=e||{};c.inputElement;var s=c.maxLength,l=void 0===s?512:s,u=wt(c,mt),d=ve(r.getState()),p=function(e){return Boolean(e&&e.match(Se))}((null===(a=t.environment.navigator)||void 0===a?void 0:a.userAgent)||""),f=t.enterKeyHint||(null!=d&&d.itemUrl&&!p?"go":"search");return yt({"aria-autocomplete":"both","aria-activedescendant":r.getState().isOpen&&null!==r.getState().activeItemId?we(t.id,"item-".concat(r.getState().activeItemId),null==d?void 0:d.source):void 0,"aria-controls":r.getState().isOpen?r.getState().collections.map((function(e){var n=e.source;return we(t.id,"list",n)})).join(" "):void 0,"aria-labelledby":we(t.id,"label"),value:r.getState().completion||r.getState().query,id:we(t.id,"input"),autoComplete:"off",autoCorrect:"off",autoCapitalize:"off",enterKeyHint:f,spellCheck:"false",autoFocus:t.autoFocus,placeholder:t.placeholder,maxLength:l,type:"search",onChange:function(e){var a=e.currentTarget.value;t.ignoreCompositionEvents&&ke(e).isComposing?o.setQuery(a):ot(yt({event:e,props:t,query:a.slice(0,l),refresh:n,store:r},o))},onCompositionEnd:function(e){ot(yt({event:e,props:t,query:e.currentTarget.value.slice(0,l),refresh:n,store:r},o))},onKeyDown:function(e){ke(e).isComposing||function(e){var t=e.event,n=e.props,r=e.refresh,o=e.store,a=function(e,t){if(null==e)return{};var n,r,o=function(e,t){if(null==e)return{};var n,r,o={},a=Object.keys(e);for(r=0;r<a.length;r++)n=a[r],t.indexOf(n)>=0||(o[n]=e[n]);return o}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(r=0;r<a.length;r++)n=a[r],t.indexOf(n)>=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(o[n]=e[n])}return o}(e,it);if("ArrowUp"===t.key||"ArrowDown"===t.key){var i=function(){var e=ve(o.getState()),t=n.environment.document.getElementById(we(n.id,"item-".concat(o.getState().activeItemId),null==e?void 0:e.source));t&&(t.scrollIntoViewIfNeeded?t.scrollIntoViewIfNeeded(!1):t.scrollIntoView(!1))},c=function(){var e=ve(o.getState());if(null!==o.getState().activeItemId&&e){var n=e.item,i=e.itemInputValue,c=e.itemUrl,s=e.source;s.onActive(st({event:t,item:n,itemInputValue:i,itemUrl:c,refresh:r,source:s,state:o.getState()},a))}};t.preventDefault(),!1===o.getState().isOpen&&(n.openOnFocus||Boolean(o.getState().query))?ot(st({event:t,props:n,query:o.getState().query,refresh:r,store:o},a)).then((function(){o.dispatch(t.key,{nextActiveItemId:n.defaultActiveItemId}),c(),setTimeout(i,0)})):(o.dispatch(t.key,{}),c(),i())}else if("Escape"===t.key)t.preventDefault(),o.dispatch(t.key,null),o.pendingRequests.cancelAll();else if("Tab"===t.key)o.dispatch("blur",null),o.pendingRequests.cancelAll();else if("Enter"===t.key){if(null===o.getState().activeItemId||o.getState().collections.every((function(e){return 0===e.items.length})))return void(n.debug||o.pendingRequests.cancelAll());t.preventDefault();var s=ve(o.getState()),l=s.item,u=s.itemInputValue,d=s.itemUrl,p=s.source;if(t.metaKey||t.ctrlKey)void 0!==d&&(p.onSelect(st({event:t,item:l,itemInputValue:u,itemUrl:d,refresh:r,source:p,state:o.getState()},a)),n.navigator.navigateNewTab({itemUrl:d,item:l,state:o.getState()}));else if(t.shiftKey)void 0!==d&&(p.onSelect(st({event:t,item:l,itemInputValue:u,itemUrl:d,refresh:r,source:p,state:o.getState()},a)),n.navigator.navigateNewWindow({itemUrl:d,item:l,state:o.getState()}));else if(t.altKey);else{if(void 0!==d)return p.onSelect(st({event:t,item:l,itemInputValue:u,itemUrl:d,refresh:r,source:p,state:o.getState()},a)),void n.navigator.navigate({itemUrl:d,item:l,state:o.getState()});ot(st({event:t,nextState:{isOpen:!1},props:n,query:u,refresh:r,store:o},a)).then((function(){p.onSelect(st({event:t,item:l,itemInputValue:u,itemUrl:d,refresh:r,source:p,state:o.getState()},a))}))}}}(yt({event:e,props:t,refresh:n,store:r},o))},onFocus:i,onBlur:L,onClick:function(n){e.inputElement!==t.environment.document.activeElement||r.getState().isOpen||i(n)}},u)},getPanelProps:function(e){return yt({onMouseDown:function(e){e.preventDefault()},onMouseLeave:function(){r.dispatch("mouseleave",null)}},e)},getListProps:function(e){var n=e||{},r=n.source,o=wt(n,gt);return yt({role:"listbox","aria-labelledby":we(t.id,"label"),id:we(t.id,"list",r)},o)},getItemProps:function(e){var a=e.item,i=e.source,c=wt(e,ht);return yt({id:we(t.id,"item-".concat(a.__autocomplete_id),i),role:"option","aria-selected":r.getState().activeItemId===a.__autocomplete_id,onMouseMove:function(e){if(a.__autocomplete_id!==r.getState().activeItemId){r.dispatch("mousemove",a.__autocomplete_id);var t=ve(r.getState());if(null!==r.getState().activeItemId&&t){var i=t.item,c=t.itemInputValue,s=t.itemUrl,l=t.source;l.onActive(yt({event:e,item:i,itemInputValue:c,itemUrl:s,refresh:n,source:l,state:r.getState()},o))}}},onMouseDown:function(e){e.preventDefault()},onClick:function(e){var c=i.getItemInputValue({item:a,state:r.getState()}),s=i.getItemUrl({item:a,state:r.getState()});(s?Promise.resolve():ot(yt({event:e,nextState:{isOpen:!1},props:t,query:c,refresh:n,store:r},o))).then((function(){i.onSelect(yt({event:e,item:a,itemInputValue:c,itemUrl:s,refresh:n,source:i,state:r.getState()},o))}))}},c)}}}function kt(e){return kt="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},kt(e)}function xt(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function _t(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?xt(Object(n),!0).forEach((function(t){Ct(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):xt(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}function Ct(e,t,n){return(t=function(e){var t=function(e){if("object"!==kt(e)||null===e)return e;var t=e[Symbol.toPrimitive];if(void 0!==t){var n=t.call(e,"string");if("object"!==kt(n))return n;throw new TypeError("@@toPrimitive must return a primitive value.")}return String(e)}(e);return"symbol"===kt(t)?t:String(t)}(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function Et(e){var t,n,r,o,a=e.plugins,i=e.options,c=null===(t=((null===(n=i.__autocomplete_metadata)||void 0===n?void 0:n.userAgents)||[])[0])||void 0===t?void 0:t.segment,s=c?Ct({},c,Object.keys((null===(r=i.__autocomplete_metadata)||void 0===r?void 0:r.options)||{})):{};return{plugins:a.map((function(e){return{name:e.name,options:Object.keys(e.__autocomplete_pluginOptions||[])}})),options:_t({"autocomplete-core":Object.keys(i)},s),ua:M.concat((null===(o=i.__autocomplete_metadata)||void 0===o?void 0:o.userAgents)||[])}}function Dt(e){var t,n=e.state;return!1===n.isOpen||null===n.activeItemId?null:(null===(t=ve(n))||void 0===t?void 0:t.itemInputValue)||null}function jt(e){return jt="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},jt(e)}function Ot(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function At(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?Ot(Object(n),!0).forEach((function(t){Tt(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):Ot(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}function Tt(e,t,n){return(t=function(e){var t=function(e){if("object"!==jt(e)||null===e)return e;var t=e[Symbol.toPrimitive];if(void 0!==t){var n=t.call(e,"string");if("object"!==jt(n))return n;throw new TypeError("@@toPrimitive must return a primitive value.")}return String(e)}(e);return"symbol"===jt(t)?t:String(t)}(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}var Pt=function(e,t){switch(t.type){case"setActiveItemId":case"mousemove":return At(At({},e),{},{activeItemId:t.payload});case"setQuery":return At(At({},e),{},{query:t.payload,completion:null});case"setCollections":return At(At({},e),{},{collections:t.payload});case"setIsOpen":return At(At({},e),{},{isOpen:t.payload});case"setStatus":return At(At({},e),{},{status:t.payload});case"setContext":return At(At({},e),{},{context:At(At({},e.context),t.payload)});case"ArrowDown":var n=At(At({},e),{},{activeItemId:t.payload.hasOwnProperty("nextActiveItemId")?t.payload.nextActiveItemId:me(1,e.activeItemId,I(e),t.props.defaultActiveItemId)});return At(At({},n),{},{completion:Dt({state:n})});case"ArrowUp":var r=At(At({},e),{},{activeItemId:me(-1,e.activeItemId,I(e),t.props.defaultActiveItemId)});return At(At({},r),{},{completion:Dt({state:r})});case"Escape":return e.isOpen?At(At({},e),{},{activeItemId:null,isOpen:!1,completion:null}):At(At({},e),{},{activeItemId:null,query:"",status:"idle",collections:[]});case"submit":return At(At({},e),{},{activeItemId:null,isOpen:!1,status:"idle"});case"reset":return At(At({},e),{},{activeItemId:!0===t.props.openOnFocus?t.props.defaultActiveItemId:null,status:"idle",completion:null,query:""});case"focus":return At(At({},e),{},{activeItemId:t.props.defaultActiveItemId,isOpen:(t.props.openOnFocus||Boolean(e.query))&&t.props.shouldPanelOpen({state:e})});case"blur":return t.props.debug?e:At(At({},e),{},{isOpen:!1,activeItemId:null});case"mouseleave":return At(At({},e),{},{activeItemId:t.props.defaultActiveItemId});default:return"The reducer action ".concat(JSON.stringify(t.type)," is not supported."),e}};function It(e){return It="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},It(e)}function Nt(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function Rt(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?Nt(Object(n),!0).forEach((function(t){Lt(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):Nt(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}function Lt(e,t,n){return(t=function(e){var t=function(e){if("object"!==It(e)||null===e)return e;var t=e[Symbol.toPrimitive];if(void 0!==t){var n=t.call(e,"string");if("object"!==It(n))return n;throw new TypeError("@@toPrimitive must return a primitive value.")}return String(e)}(e);return"symbol"===It(t)?t:String(t)}(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function Mt(e){var t=[],n=Re(e,t),r=function(e,t,n){var r,o=t.initialState;return{getState:function(){return o},dispatch:function(r,a){var i=function(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?_e(Object(n),!0).forEach((function(t){Ce(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):_e(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}({},o);o=e(o,{type:r,props:t,payload:a}),n({state:o,prevState:i})},pendingRequests:(r=[],{add:function(e){return r.push(e),e.finally((function(){r=r.filter((function(t){return t!==e}))}))},cancelAll:function(){r.forEach((function(e){return e.cancel()}))},isEmpty:function(){return 0===r.length}})}}(Pt,n,(function(e){var t,r,a=e.prevState,l=e.state;if(n.onStateChange(Rt({prevState:a,state:l,refresh:i,navigator:n.navigator},o)),!s()&&null!==(t=l.context)&&void 0!==t&&null!==(r=t.algoliaInsightsPlugin)&&void 0!==r&&r.__automaticInsights&&!1!==n.insights){var u=se({__autocomplete_clickAnalytics:!1});n.plugins.push(u),c([u])}})),o=function(e){var t=e.store;return{setActiveItemId:function(e){t.dispatch("setActiveItemId",e)},setQuery:function(e){t.dispatch("setQuery",e)},setCollections:function(e){var n=0,r=e.map((function(e){return je(je({},e),{},{items:T(e.items).map((function(e){return je(je({},e),{},{__autocomplete_id:n++})}))})}));t.dispatch("setCollections",r)},setIsOpen:function(e){t.dispatch("setIsOpen",e)},setStatus:function(e){t.dispatch("setStatus",e)},setContext:function(e){t.dispatch("setContext",e)}}}({store:r}),a=St(Rt({props:n,refresh:i,store:r,navigator:n.navigator},o));function i(){return ot(Rt({event:new Event("input"),nextState:{isOpen:r.getState().isOpen},props:n,navigator:n.navigator,query:r.getState().query,refresh:i,store:r},o))}function c(e){e.forEach((function(e){var r;return null===(r=e.subscribe)||void 0===r?void 0:r.call(e,Rt(Rt({},o),{},{navigator:n.navigator,refresh:i,onSelect:function(e){t.push({onSelect:e})},onActive:function(e){t.push({onActive:e})},onResolve:function(e){t.push({onResolve:e})}}))}))}function s(){return n.plugins.some((function(e){return"aa.algoliaInsightsPlugin"===e.name}))}if(n.insights&&!s()){var l="boolean"==typeof n.insights?{}:n.insights;n.plugins.push(se(l))}return c(n.plugins),function(e){var t,n,r=e.metadata,o=e.environment;if(null===(t=o.navigator)||void 0===t||null===(n=t.userAgent)||void 0===n?void 0:n.includes("Algolia Crawler")){var a=o.document.createElement("meta"),i=o.document.querySelector("head");a.name="algolia:metadata",setTimeout((function(){a.content=JSON.stringify(r),i.appendChild(a)}),0)}}({metadata:Et({plugins:n.plugins,options:e}),environment:n.environment}),Rt(Rt({refresh:i,navigator:n.navigator},a),o)}function Ft(e){var t=e.translations,n=(void 0===t?{}:t).searchByText,o=void 0===n?"Search by":n;return r.createElement("a",{href:"https://www.algolia.com/ref/docsearch/?utm_source=".concat(window.location.hostname,"&utm_medium=referral&utm_content=powered_by&utm_campaign=docsearch"),target:"_blank",rel:"noopener noreferrer"},r.createElement("span",{className:"DocSearch-Label"},o),r.createElement("svg",{width:"77",height:"19","aria-label":"Algolia",role:"img",id:"Layer_1",xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 2196.2 500"},r.createElement("defs",null,r.createElement("style",null,".cls-1,.cls-2{fill:#003dff;}.cls-2{fill-rule:evenodd;}")),r.createElement("path",{className:"cls-2",d:"M1070.38,275.3V5.91c0-3.63-3.24-6.39-6.82-5.83l-50.46,7.94c-2.87,.45-4.99,2.93-4.99,5.84l.17,273.22c0,12.92,0,92.7,95.97,95.49,3.33,.1,6.09-2.58,6.09-5.91v-40.78c0-2.96-2.19-5.51-5.12-5.84-34.85-4.01-34.85-47.57-34.85-54.72Z"}),r.createElement("rect",{className:"cls-1",x:"1845.88",y:"104.73",width:"62.58",height:"277.9",rx:"5.9",ry:"5.9"}),r.createElement("path",{className:"cls-2",d:"M1851.78,71.38h50.77c3.26,0,5.9-2.64,5.9-5.9V5.9c0-3.62-3.24-6.39-6.82-5.83l-50.77,7.95c-2.87,.45-4.99,2.92-4.99,5.83v51.62c0,3.26,2.64,5.9,5.9,5.9Z"}),r.createElement("path",{className:"cls-2",d:"M1764.03,275.3V5.91c0-3.63-3.24-6.39-6.82-5.83l-50.46,7.94c-2.87,.45-4.99,2.93-4.99,5.84l.17,273.22c0,12.92,0,92.7,95.97,95.49,3.33,.1,6.09-2.58,6.09-5.91v-40.78c0-2.96-2.19-5.51-5.12-5.84-34.85-4.01-34.85-47.57-34.85-54.72Z"}),r.createElement("path",{className:"cls-2",d:"M1631.95,142.72c-11.14-12.25-24.83-21.65-40.78-28.31-15.92-6.53-33.26-9.85-52.07-9.85-18.78,0-36.15,3.17-51.92,9.85-15.59,6.66-29.29,16.05-40.76,28.31-11.47,12.23-20.38,26.87-26.76,44.03-6.38,17.17-9.24,37.37-9.24,58.36,0,20.99,3.19,36.87,9.55,54.21,6.38,17.32,15.14,32.11,26.45,44.36,11.29,12.23,24.83,21.62,40.6,28.46,15.77,6.83,40.12,10.33,52.4,10.48,12.25,0,36.78-3.82,52.7-10.48,15.92-6.68,29.46-16.23,40.78-28.46,11.29-12.25,20.05-27.04,26.25-44.36,6.22-17.34,9.24-33.22,9.24-54.21,0-20.99-3.34-41.19-10.03-58.36-6.38-17.17-15.14-31.8-26.43-44.03Zm-44.43,163.75c-11.47,15.75-27.56,23.7-48.09,23.7-20.55,0-36.63-7.8-48.1-23.7-11.47-15.75-17.21-34.01-17.21-61.2,0-26.89,5.59-49.14,17.06-64.87,11.45-15.75,27.54-23.52,48.07-23.52,20.55,0,36.63,7.78,48.09,23.52,11.47,15.57,17.36,37.98,17.36,64.87,0,27.19-5.72,45.3-17.19,61.2Z"}),r.createElement("path",{className:"cls-2",d:"M894.42,104.73h-49.33c-48.36,0-90.91,25.48-115.75,64.1-14.52,22.58-22.99,49.63-22.99,78.73,0,44.89,20.13,84.92,51.59,111.1,2.93,2.6,6.05,4.98,9.31,7.14,12.86,8.49,28.11,13.47,44.52,13.47,1.23,0,2.46-.03,3.68-.09,.36-.02,.71-.05,1.07-.07,.87-.05,1.75-.11,2.62-.2,.34-.03,.68-.08,1.02-.12,.91-.1,1.82-.21,2.73-.34,.21-.03,.42-.07,.63-.1,32.89-5.07,61.56-30.82,70.9-62.81v57.83c0,3.26,2.64,5.9,5.9,5.9h50.42c3.26,0,5.9-2.64,5.9-5.9V110.63c0-3.26-2.64-5.9-5.9-5.9h-56.32Zm0,206.92c-12.2,10.16-27.97,13.98-44.84,15.12-.16,.01-.33,.03-.49,.04-1.12,.07-2.24,.1-3.36,.1-42.24,0-77.12-35.89-77.12-79.37,0-10.25,1.96-20.01,5.42-28.98,11.22-29.12,38.77-49.74,71.06-49.74h49.33v142.83Z"}),r.createElement("path",{className:"cls-2",d:"M2133.97,104.73h-49.33c-48.36,0-90.91,25.48-115.75,64.1-14.52,22.58-22.99,49.63-22.99,78.73,0,44.89,20.13,84.92,51.59,111.1,2.93,2.6,6.05,4.98,9.31,7.14,12.86,8.49,28.11,13.47,44.52,13.47,1.23,0,2.46-.03,3.68-.09,.36-.02,.71-.05,1.07-.07,.87-.05,1.75-.11,2.62-.2,.34-.03,.68-.08,1.02-.12,.91-.1,1.82-.21,2.73-.34,.21-.03,.42-.07,.63-.1,32.89-5.07,61.56-30.82,70.9-62.81v57.83c0,3.26,2.64,5.9,5.9,5.9h50.42c3.26,0,5.9-2.64,5.9-5.9V110.63c0-3.26-2.64-5.9-5.9-5.9h-56.32Zm0,206.92c-12.2,10.16-27.97,13.98-44.84,15.12-.16,.01-.33,.03-.49,.04-1.12,.07-2.24,.1-3.36,.1-42.24,0-77.12-35.89-77.12-79.37,0-10.25,1.96-20.01,5.42-28.98,11.22-29.12,38.77-49.74,71.06-49.74h49.33v142.83Z"}),r.createElement("path",{className:"cls-2",d:"M1314.05,104.73h-49.33c-48.36,0-90.91,25.48-115.75,64.1-11.79,18.34-19.6,39.64-22.11,62.59-.58,5.3-.88,10.68-.88,16.14s.31,11.15,.93,16.59c4.28,38.09,23.14,71.61,50.66,94.52,2.93,2.6,6.05,4.98,9.31,7.14,12.86,8.49,28.11,13.47,44.52,13.47h0c17.99,0,34.61-5.93,48.16-15.97,16.29-11.58,28.88-28.54,34.48-47.75v50.26h-.11v11.08c0,21.84-5.71,38.27-17.34,49.36-11.61,11.08-31.04,16.63-58.25,16.63-11.12,0-28.79-.59-46.6-2.41-2.83-.29-5.46,1.5-6.27,4.22l-12.78,43.11c-1.02,3.46,1.27,7.02,4.83,7.53,21.52,3.08,42.52,4.68,54.65,4.68,48.91,0,85.16-10.75,108.89-32.21,21.48-19.41,33.15-48.89,35.2-88.52V110.63c0-3.26-2.64-5.9-5.9-5.9h-56.32Zm0,64.1s.65,139.13,0,143.36c-12.08,9.77-27.11,13.59-43.49,14.7-.16,.01-.33,.03-.49,.04-1.12,.07-2.24,.1-3.36,.1-1.32,0-2.63-.03-3.94-.1-40.41-2.11-74.52-37.26-74.52-79.38,0-10.25,1.96-20.01,5.42-28.98,11.22-29.12,38.77-49.74,71.06-49.74h49.33Z"}),r.createElement("path",{className:"cls-1",d:"M249.83,0C113.3,0,2,110.09,.03,246.16c-2,138.19,110.12,252.7,248.33,253.5,42.68,.25,83.79-10.19,120.3-30.03,3.56-1.93,4.11-6.83,1.08-9.51l-23.38-20.72c-4.75-4.21-11.51-5.4-17.36-2.92-25.48,10.84-53.17,16.38-81.71,16.03-111.68-1.37-201.91-94.29-200.13-205.96,1.76-110.26,92-199.41,202.67-199.41h202.69V407.41l-115-102.18c-3.72-3.31-9.42-2.66-12.42,1.31-18.46,24.44-48.53,39.64-81.93,37.34-46.33-3.2-83.87-40.5-87.34-86.81-4.15-55.24,39.63-101.52,94-101.52,49.18,0,89.68,37.85,93.91,85.95,.38,4.28,2.31,8.27,5.52,11.12l29.95,26.55c3.4,3.01,8.79,1.17,9.63-3.3,2.16-11.55,2.92-23.58,2.07-35.92-4.82-70.34-61.8-126.93-132.17-131.26-80.68-4.97-148.13,58.14-150.27,137.25-2.09,77.1,61.08,143.56,138.19,145.26,32.19,.71,62.03-9.41,86.14-26.95l150.26,133.2c6.44,5.71,16.61,1.14,16.61-7.47V9.48C499.66,4.25,495.42,0,490.18,0H249.83Z"})))}function Bt(e){return r.createElement("svg",{width:"15",height:"15","aria-label":e.ariaLabel,role:"img"},r.createElement("g",{fill:"none",stroke:"currentColor",strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:"1.2"},e.children))}function zt(e){var t=e.translations,n=void 0===t?{}:t,o=n.selectText,a=void 0===o?"to select":o,i=n.selectKeyAriaLabel,c=void 0===i?"Enter key":i,s=n.navigateText,l=void 0===s?"to navigate":s,u=n.navigateUpKeyAriaLabel,d=void 0===u?"Arrow up":u,p=n.navigateDownKeyAriaLabel,f=void 0===p?"Arrow down":p,m=n.closeText,g=void 0===m?"to close":m,h=n.closeKeyAriaLabel,b=void 0===h?"Escape key":h,y=n.searchByText,v=void 0===y?"Search by":y;return r.createElement(r.Fragment,null,r.createElement("div",{className:"DocSearch-Logo"},r.createElement(Ft,{translations:{searchByText:v}})),r.createElement("ul",{className:"DocSearch-Commands"},r.createElement("li",null,r.createElement("kbd",{className:"DocSearch-Commands-Key"},r.createElement(Bt,{ariaLabel:c},r.createElement("path",{d:"M12 3.53088v3c0 1-1 2-2 2H4M7 11.53088l-3-3 3-3"}))),r.createElement("span",{className:"DocSearch-Label"},a)),r.createElement("li",null,r.createElement("kbd",{className:"DocSearch-Commands-Key"},r.createElement(Bt,{ariaLabel:f},r.createElement("path",{d:"M7.5 3.5v8M10.5 8.5l-3 3-3-3"}))),r.createElement("kbd",{className:"DocSearch-Commands-Key"},r.createElement(Bt,{ariaLabel:d},r.createElement("path",{d:"M7.5 11.5v-8M10.5 6.5l-3-3-3 3"}))),r.createElement("span",{className:"DocSearch-Label"},l)),r.createElement("li",null,r.createElement("kbd",{className:"DocSearch-Commands-Key"},r.createElement(Bt,{ariaLabel:b},r.createElement("path",{d:"M13.6167 8.936c-.1065.3583-.6883.962-1.4875.962-.7993 0-1.653-.9165-1.653-2.1258v-.5678c0-1.2548.7896-2.1016 1.653-2.1016.8634 0 1.3601.4778 1.4875 1.0724M9 6c-.1352-.4735-.7506-.9219-1.46-.8972-.7092.0246-1.344.57-1.344 1.2166s.4198.8812 1.3445.9805C8.465 7.3992 8.968 7.9337 9 8.5c.032.5663-.454 1.398-1.4595 1.398C6.6593 9.898 6 9 5.963 8.4851m-1.4748.5368c-.2635.5941-.8099.876-1.5443.876s-1.7073-.6248-1.7073-2.204v-.4603c0-1.0416.721-2.131 1.7073-2.131.9864 0 1.6425 1.031 1.5443 2.2492h-2.956"}))),r.createElement("span",{className:"DocSearch-Label"},g))))}function $t(e){var t=e.hit,n=e.children;return r.createElement("a",{href:t.url},n)}function Ut(){return r.createElement("svg",{viewBox:"0 0 38 38",stroke:"currentColor",strokeOpacity:".5"},r.createElement("g",{fill:"none",fillRule:"evenodd"},r.createElement("g",{transform:"translate(1 1)",strokeWidth:"2"},r.createElement("circle",{strokeOpacity:".3",cx:"18",cy:"18",r:"18"}),r.createElement("path",{d:"M36 18c0-9.94-8.06-18-18-18"},r.createElement("animateTransform",{attributeName:"transform",type:"rotate",from:"0 18 18",to:"360 18 18",dur:"1s",repeatCount:"indefinite"})))))}function Ht(){return r.createElement("svg",{width:"20",height:"20",viewBox:"0 0 20 20"},r.createElement("g",{stroke:"currentColor",fill:"none",fillRule:"evenodd",strokeLinecap:"round",strokeLinejoin:"round"},r.createElement("path",{d:"M3.18 6.6a8.23 8.23 0 1112.93 9.94h0a8.23 8.23 0 01-11.63 0"}),r.createElement("path",{d:"M6.44 7.25H2.55V3.36M10.45 6v5.6M10.45 11.6L13 13"})))}function qt(){return r.createElement("svg",{width:"20",height:"20",viewBox:"0 0 20 20"},r.createElement("path",{d:"M10 10l5.09-5.09L10 10l5.09 5.09L10 10zm0 0L4.91 4.91 10 10l-5.09 5.09L10 10z",stroke:"currentColor",fill:"none",fillRule:"evenodd",strokeLinecap:"round",strokeLinejoin:"round"}))}function Vt(){return r.createElement("svg",{className:"DocSearch-Hit-Select-Icon",width:"20",height:"20",viewBox:"0 0 20 20"},r.createElement("g",{stroke:"currentColor",fill:"none",fillRule:"evenodd",strokeLinecap:"round",strokeLinejoin:"round"},r.createElement("path",{d:"M18 3v4c0 2-2 4-4 4H2"}),r.createElement("path",{d:"M8 17l-6-6 6-6"})))}var Wt=function(){return r.createElement("svg",{width:"20",height:"20",viewBox:"0 0 20 20"},r.createElement("path",{d:"M17 6v12c0 .52-.2 1-1 1H4c-.7 0-1-.33-1-1V2c0-.55.42-1 1-1h8l5 5zM14 8h-3.13c-.51 0-.87-.34-.87-.87V4",stroke:"currentColor",fill:"none",fillRule:"evenodd",strokeLinejoin:"round"}))};function Gt(e){switch(e.type){case"lvl1":return r.createElement(Wt,null);case"content":return r.createElement(Yt,null);default:return r.createElement(Kt,null)}}function Kt(){return r.createElement("svg",{width:"20",height:"20",viewBox:"0 0 20 20"},r.createElement("path",{d:"M13 13h4-4V8H7v5h6v4-4H7V8H3h4V3v5h6V3v5h4-4v5zm-6 0v4-4H3h4z",stroke:"currentColor",fill:"none",fillRule:"evenodd",strokeLinecap:"round",strokeLinejoin:"round"}))}function Yt(){return r.createElement("svg",{width:"20",height:"20",viewBox:"0 0 20 20"},r.createElement("path",{d:"M17 5H3h14zm0 5H3h14zm0 5H3h14z",stroke:"currentColor",fill:"none",fillRule:"evenodd",strokeLinejoin:"round"}))}function Qt(){return r.createElement("svg",{width:"20",height:"20",viewBox:"0 0 20 20"},r.createElement("path",{d:"M10 14.2L5 17l1-5.6-4-4 5.5-.7 2.5-5 2.5 5 5.6.8-4 4 .9 5.5z",stroke:"currentColor",fill:"none",fillRule:"evenodd",strokeLinejoin:"round"}))}function Zt(){return r.createElement("svg",{width:"40",height:"40",viewBox:"0 0 20 20",fill:"none",fillRule:"evenodd",stroke:"currentColor",strokeLinecap:"round",strokeLinejoin:"round"},r.createElement("path",{d:"M19 4.8a16 16 0 00-2-1.2m-3.3-1.2A16 16 0 001.1 4.7M16.7 8a12 12 0 00-2.8-1.4M10 6a12 12 0 00-6.7 2M12.3 14.7a4 4 0 00-4.5 0M14.5 11.4A8 8 0 0010 10M3 16L18 2M10 18h0"}))}function Xt(){return r.createElement("svg",{width:"40",height:"40",viewBox:"0 0 20 20",fill:"none",fillRule:"evenodd",stroke:"currentColor",strokeLinecap:"round",strokeLinejoin:"round"},r.createElement("path",{d:"M15.5 4.8c2 3 1.7 7-1 9.7h0l4.3 4.3-4.3-4.3a7.8 7.8 0 01-9.8 1m-2.2-2.2A7.8 7.8 0 0113.2 2.4M2 18L18 2"}))}function Jt(e){var t=e.translations,n=void 0===t?{}:t,o=n.titleText,a=void 0===o?"Unable to fetch results":o,i=n.helpText,c=void 0===i?"You might want to check your network connection.":i;return r.createElement("div",{className:"DocSearch-ErrorScreen"},r.createElement("div",{className:"DocSearch-Screen-Icon"},r.createElement(Zt,null)),r.createElement("p",{className:"DocSearch-Title"},a),r.createElement("p",{className:"DocSearch-Help"},c))}var en=["translations"];function tn(e){var t=e.translations,n=void 0===t?{}:t,o=b(e,en),a=n.noResultsText,i=void 0===a?"No results for":a,c=n.suggestedQueryText,s=void 0===c?"Try searching for":c,l=n.reportMissingResultsText,u=void 0===l?"Believe this query should return results?":l,d=n.reportMissingResultsLinkText,p=void 0===d?"Let us know.":d,f=o.state.context.searchSuggestions;return r.createElement("div",{className:"DocSearch-NoResults"},r.createElement("div",{className:"DocSearch-Screen-Icon"},r.createElement(Xt,null)),r.createElement("p",{className:"DocSearch-Title"},i,' "',r.createElement("strong",null,o.state.query),'"'),f&&f.length>0&&r.createElement("div",{className:"DocSearch-NoResults-Prefill-List"},r.createElement("p",{className:"DocSearch-Help"},s,":"),r.createElement("ul",null,f.slice(0,3).reduce((function(e,t){return[].concat(S(e),[r.createElement("li",{key:t},r.createElement("button",{className:"DocSearch-Prefill",key:t,type:"button",onClick:function(){o.setQuery(t.toLowerCase()+" "),o.refresh(),o.inputRef.current.focus()}},t))])}),[]))),o.getMissingResultsUrl&&r.createElement("p",{className:"DocSearch-Help"},"".concat(u," "),r.createElement("a",{href:o.getMissingResultsUrl({query:o.state.query}),target:"_blank",rel:"noopener noreferrer"},p)))}var nn=["hit","attribute","tagName"];function rn(e,t){return t.split(".").reduce((function(e,t){return null!=e&&e[t]?e[t]:null}),e)}function on(e){var t=e.hit,n=e.attribute,o=e.tagName,a=void 0===o?"span":o,i=b(e,nn);return(0,r.createElement)(a,h(h({},i),{},{dangerouslySetInnerHTML:{__html:rn(t,"_snippetResult.".concat(n,".value"))||rn(t,n)}}))}function an(e){return e.collection&&0!==e.collection.items.length?r.createElement("section",{className:"DocSearch-Hits"},r.createElement("div",{className:"DocSearch-Hit-source"},e.title),r.createElement("ul",e.getListProps(),e.collection.items.map((function(t,n){return r.createElement(cn,d({key:[e.title,t.objectID].join(":"),item:t,index:n},e))})))):null}function cn(e){var t=e.item,n=e.index,o=e.renderIcon,a=e.renderAction,i=e.getItemProps,c=e.onItemClick,s=e.collection,l=e.hitComponent,u=w(r.useState(!1),2),p=u[0],f=u[1],m=w(r.useState(!1),2),g=m[0],h=m[1],b=r.useRef(null),y=l;return r.createElement("li",d({className:["DocSearch-Hit",t.__docsearch_parent&&"DocSearch-Hit--Child",p&&"DocSearch-Hit--deleting",g&&"DocSearch-Hit--favoriting"].filter(Boolean).join(" "),onTransitionEnd:function(){b.current&&b.current()}},i({item:t,source:s.source,onClick:function(e){c(t,e)}})),r.createElement(y,{hit:t},r.createElement("div",{className:"DocSearch-Hit-Container"},o({item:t,index:n}),t.hierarchy[t.type]&&"lvl1"===t.type&&r.createElement("div",{className:"DocSearch-Hit-content-wrapper"},r.createElement(on,{className:"DocSearch-Hit-title",hit:t,attribute:"hierarchy.lvl1"}),t.content&&r.createElement(on,{className:"DocSearch-Hit-path",hit:t,attribute:"content"})),t.hierarchy[t.type]&&("lvl2"===t.type||"lvl3"===t.type||"lvl4"===t.type||"lvl5"===t.type||"lvl6"===t.type)&&r.createElement("div",{className:"DocSearch-Hit-content-wrapper"},r.createElement(on,{className:"DocSearch-Hit-title",hit:t,attribute:"hierarchy.".concat(t.type)}),r.createElement(on,{className:"DocSearch-Hit-path",hit:t,attribute:"hierarchy.lvl1"})),"content"===t.type&&r.createElement("div",{className:"DocSearch-Hit-content-wrapper"},r.createElement(on,{className:"DocSearch-Hit-title",hit:t,attribute:"content"}),r.createElement(on,{className:"DocSearch-Hit-path",hit:t,attribute:"hierarchy.lvl1"})),a({item:t,runDeleteTransition:function(e){f(!0),b.current=e},runFavoriteTransition:function(e){h(!0),b.current=e}}))))}function sn(e,t,n){return e.reduce((function(e,r){var o=t(r);return e.hasOwnProperty(o)||(e[o]=[]),e[o].length<(n||5)&&e[o].push(r),e}),{})}function ln(e){return e}function un(e){return 1===e.button||e.altKey||e.ctrlKey||e.metaKey||e.shiftKey}function dn(){}var pn=/(<mark>|<\/mark>)/g,fn=RegExp(pn.source);function mn(e){var t,n,r=e;if(!r.__docsearch_parent&&!e._highlightResult)return e.hierarchy.lvl0;var o=r.__docsearch_parent?null===(t=r.__docsearch_parent)||void 0===t||null===(t=t._highlightResult)||void 0===t||null===(t=t.hierarchy)||void 0===t?void 0:t.lvl0:null===(n=e._highlightResult)||void 0===n||null===(n=n.hierarchy)||void 0===n?void 0:n.lvl0;return o?o.value&&fn.test(o.value)?o.value.replace(pn,""):o.value:e.hierarchy.lvl0}function gn(e){return r.createElement("div",{className:"DocSearch-Dropdown-Container"},e.state.collections.map((function(t){if(0===t.items.length)return null;var n=mn(t.items[0]);return r.createElement(an,d({},e,{key:t.source.sourceId,title:n,collection:t,renderIcon:function(e){var n,o=e.item,a=e.index;return r.createElement(r.Fragment,null,o.__docsearch_parent&&r.createElement("svg",{className:"DocSearch-Hit-Tree",viewBox:"0 0 24 54"},r.createElement("g",{stroke:"currentColor",fill:"none",fillRule:"evenodd",strokeLinecap:"round",strokeLinejoin:"round"},o.__docsearch_parent!==(null===(n=t.items[a+1])||void 0===n?void 0:n.__docsearch_parent)?r.createElement("path",{d:"M8 6v21M20 27H8.3"}):r.createElement("path",{d:"M8 6v42M20 27H8.3"}))),r.createElement("div",{className:"DocSearch-Hit-icon"},r.createElement(Gt,{type:o.type})))},renderAction:function(){return r.createElement("div",{className:"DocSearch-Hit-action"},r.createElement(Vt,null))}}))})),e.resultsFooterComponent&&r.createElement("section",{className:"DocSearch-HitsFooter"},r.createElement(e.resultsFooterComponent,{state:e.state})))}var hn=["translations"];function bn(e){var t=e.translations,n=void 0===t?{}:t,o=b(e,hn),a=n.recentSearchesTitle,i=void 0===a?"Recent":a,c=n.noRecentSearchesText,s=void 0===c?"No recent searches":c,l=n.saveRecentSearchButtonTitle,u=void 0===l?"Save this search":l,p=n.removeRecentSearchButtonTitle,f=void 0===p?"Remove this search from history":p,m=n.favoriteSearchesTitle,g=void 0===m?"Favorite":m,h=n.removeFavoriteSearchButtonTitle,y=void 0===h?"Remove this search from favorites":h;return"idle"===o.state.status&&!1===o.hasCollections?o.disableUserPersonalization?null:r.createElement("div",{className:"DocSearch-StartScreen"},r.createElement("p",{className:"DocSearch-Help"},s)):!1===o.hasCollections?null:r.createElement("div",{className:"DocSearch-Dropdown-Container"},r.createElement(an,d({},o,{title:i,collection:o.state.collections[0],renderIcon:function(){return r.createElement("div",{className:"DocSearch-Hit-icon"},r.createElement(Ht,null))},renderAction:function(e){var t=e.item,n=e.runFavoriteTransition,a=e.runDeleteTransition;return r.createElement(r.Fragment,null,r.createElement("div",{className:"DocSearch-Hit-action"},r.createElement("button",{className:"DocSearch-Hit-action-button",title:u,type:"submit",onClick:function(e){e.preventDefault(),e.stopPropagation(),n((function(){o.favoriteSearches.add(t),o.recentSearches.remove(t),o.refresh()}))}},r.createElement(Qt,null))),r.createElement("div",{className:"DocSearch-Hit-action"},r.createElement("button",{className:"DocSearch-Hit-action-button",title:f,type:"submit",onClick:function(e){e.preventDefault(),e.stopPropagation(),a((function(){o.recentSearches.remove(t),o.refresh()}))}},r.createElement(qt,null))))}})),r.createElement(an,d({},o,{title:g,collection:o.state.collections[1],renderIcon:function(){return r.createElement("div",{className:"DocSearch-Hit-icon"},r.createElement(Qt,null))},renderAction:function(e){var t=e.item,n=e.runDeleteTransition;return r.createElement("div",{className:"DocSearch-Hit-action"},r.createElement("button",{className:"DocSearch-Hit-action-button",title:y,type:"submit",onClick:function(e){e.preventDefault(),e.stopPropagation(),n((function(){o.favoriteSearches.remove(t),o.refresh()}))}},r.createElement(qt,null)))}})))}var yn=["translations"],vn=r.memo((function(e){var t=e.translations,n=void 0===t?{}:t,o=b(e,yn);if("error"===o.state.status)return r.createElement(Jt,{translations:null==n?void 0:n.errorScreen});var a=o.state.collections.some((function(e){return e.items.length>0}));return o.state.query?!1===a?r.createElement(tn,d({},o,{translations:null==n?void 0:n.noResultsScreen})):r.createElement(gn,o):r.createElement(bn,d({},o,{hasCollections:a,translations:null==n?void 0:n.startScreen}))}),(function(e,t){return"loading"===t.state.status||"stalled"===t.state.status})),wn=["translations"];function Sn(e){var t=e.translations,n=void 0===t?{}:t,o=b(e,wn),a=n.resetButtonTitle,i=void 0===a?"Clear the query":a,c=n.resetButtonAriaLabel,s=void 0===c?"Clear the query":c,l=n.cancelButtonText,u=void 0===l?"Cancel":l,p=n.cancelButtonAriaLabel,f=void 0===p?"Cancel":p,m=n.searchInputLabel,g=void 0===m?"Search":m,h=o.getFormProps({inputElement:o.inputRef.current}).onReset;return r.useEffect((function(){o.autoFocus&&o.inputRef.current&&o.inputRef.current.focus()}),[o.autoFocus,o.inputRef]),r.useEffect((function(){o.isFromSelection&&o.inputRef.current&&o.inputRef.current.select()}),[o.isFromSelection,o.inputRef]),r.createElement(r.Fragment,null,r.createElement("form",{className:"DocSearch-Form",onSubmit:function(e){e.preventDefault()},onReset:h},r.createElement("label",d({className:"DocSearch-MagnifierLabel"},o.getLabelProps()),r.createElement(C,null),r.createElement("span",{className:"DocSearch-VisuallyHiddenForAccessibility"},g)),r.createElement("div",{className:"DocSearch-LoadingIndicator"},r.createElement(Ut,null)),r.createElement("input",d({className:"DocSearch-Input",ref:o.inputRef},o.getInputProps({inputElement:o.inputRef.current,autoFocus:o.autoFocus,maxLength:64}))),r.createElement("button",{type:"reset",title:i,className:"DocSearch-Reset","aria-label":s,hidden:!o.state.query},r.createElement(qt,null))),r.createElement("button",{className:"DocSearch-Cancel",type:"reset","aria-label":f,onClick:o.onClose},u))}var kn=["_highlightResult","_snippetResult"];function xn(e){var t=e.key,n=e.limit,r=void 0===n?5:n,o=function(e){return!1===function(){var e="__TEST_KEY__";try{return localStorage.setItem(e,""),localStorage.removeItem(e),!0}catch(e){return!1}}()?{setItem:function(){},getItem:function(){return[]}}:{setItem:function(t){return window.localStorage.setItem(e,JSON.stringify(t))},getItem:function(){var t=window.localStorage.getItem(e);return t?JSON.parse(t):[]}}}(t),a=o.getItem().slice(0,r);return{add:function(e){var t=e;t._highlightResult,t._snippetResult;var n=b(t,kn),i=a.findIndex((function(e){return e.objectID===n.objectID}));i>-1&&a.splice(i,1),a.unshift(n),a=a.slice(0,r),o.setItem(a)},remove:function(e){a=a.filter((function(t){return t.objectID!==e.objectID})),o.setItem(a)},getAll:function(){return a}}}function _n(e){var t,n="algolia-client-js-".concat(e.key);function r(){return void 0===t&&(t=e.localStorage||window.localStorage),t}function o(){return JSON.parse(r().getItem(n)||"{}")}function a(e){r().setItem(n,JSON.stringify(e))}return{get:function(t,n){var r=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{miss:function(){return Promise.resolve()}};return Promise.resolve().then((function(){var n,r,i;return n=e.timeToLive?1e3*e.timeToLive:null,r=o(),a(i=Object.fromEntries(Object.entries(r).filter((function(e){return void 0!==w(e,2)[1].timestamp})))),n&&a(Object.fromEntries(Object.entries(i).filter((function(e){var t=w(e,2)[1],r=(new Date).getTime();return!(t.timestamp+n<r)})))),o()[JSON.stringify(t)]})).then((function(e){return Promise.all([e?e.value:n(),void 0!==e])})).then((function(e){var t=w(e,2),n=t[0],o=t[1];return Promise.all([n,o||r.miss(n)])})).then((function(e){return w(e,1)[0]}))},set:function(e,t){return Promise.resolve().then((function(){var a=o();return a[JSON.stringify(e)]={timestamp:(new Date).getTime(),value:t},r().setItem(n,JSON.stringify(a)),t}))},delete:function(e){return Promise.resolve().then((function(){var t=o();delete t[JSON.stringify(e)],r().setItem(n,JSON.stringify(t))}))},clear:function(){return Promise.resolve().then((function(){r().removeItem(n)}))}}}function Cn(e){var t=S(e.caches),n=t.shift();return void 0===n?{get:function(e,t){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{miss:function(){return Promise.resolve()}};return t().then((function(e){return Promise.all([e,n.miss(e)])})).then((function(e){return w(e,1)[0]}))},set:function(e,t){return Promise.resolve(t)},delete:function(e){return Promise.resolve()},clear:function(){return Promise.resolve()}}:{get:function(e,r){var o=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{miss:function(){return Promise.resolve()}};return n.get(e,r,o).catch((function(){return Cn({caches:t}).get(e,r,o)}))},set:function(e,r){return n.set(e,r).catch((function(){return Cn({caches:t}).set(e,r)}))},delete:function(e){return n.delete(e).catch((function(){return Cn({caches:t}).delete(e)}))},clear:function(){return n.clear().catch((function(){return Cn({caches:t}).clear()}))}}}function En(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{serializable:!0},t={};return{get:function(n,r){var o=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{miss:function(){return Promise.resolve()}},a=JSON.stringify(n);if(a in t)return Promise.resolve(e.serializable?JSON.parse(t[a]):t[a]);var i=r();return i.then((function(e){return o.miss(e)})).then((function(){return i}))},set:function(n,r){return t[JSON.stringify(n)]=e.serializable?JSON.stringify(r):r,Promise.resolve(r)},delete:function(e){return delete t[JSON.stringify(e)],Promise.resolve()},clear:function(){return t={},Promise.resolve()}}}function Dn(e){var t=e.algoliaAgents,n=e.client,r=e.version,o=function(e){var t={value:"Algolia for JavaScript (".concat(e,")"),add:function(e){var n="; ".concat(e.segment).concat(void 0!==e.version?" (".concat(e.version,")"):"");return-1===t.value.indexOf(n)&&(t.value="".concat(t.value).concat(n)),t}};return t}(r).add({segment:n,version:r});return t.forEach((function(e){return o.add(e)})),o}var jn=12e4;function On(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"up",n=Date.now();return h(h({},e),{},{status:t,lastUpdate:n,isUp:function(){return"up"===t||Date.now()-n>jn},isTimedOut:function(){return"timed out"===t&&Date.now()-n<=jn}})}var An=function(){function e(t,n){var r;return s(this,e),u(r=c(this,e,[t]),"name","AlgoliaError"),n&&(r.name=n),r}return f(e,x(Error)),l(e)}(),Tn=function(){function e(t,n,r){var o;return s(this,e),u(o=c(this,e,[t,r]),"stackTrace",void 0),o.stackTrace=n,o}return f(e,An),l(e)}(),Pn=function(){function e(t){return s(this,e),c(this,e,["Unreachable hosts - your application id may be incorrect. If the error persists, please reach out to the Algolia Support team: https://alg.li/support.",t,"RetryError"])}return f(e,Tn),l(e)}(),In=function(){function e(t,n,r){var o,a=arguments.length>3&&void 0!==arguments[3]?arguments[3]:"ApiError";return s(this,e),u(o=c(this,e,[t,r,a]),"status",void 0),o.status=n,o}return f(e,Tn),l(e)}(),Nn=function(){function e(t,n){var r;return s(this,e),u(r=c(this,e,[t,"DeserializationError"]),"response",void 0),r.response=n,r}return f(e,An),l(e)}(),Rn=function(){function e(t,n,r,o){var a;return s(this,e),u(a=c(this,e,[t,n,o,"DetailedApiError"]),"error",void 0),a.error=r,a}return f(e,In),l(e)}();function Ln(e,t,n){var r,o=(r=n,Object.keys(r).filter((function(e){return void 0!==r[e]})).sort().map((function(e){return"".concat(e,"=").concat(encodeURIComponent("[object Array]"===Object.prototype.toString.call(r[e])?r[e].join(","):r[e]).replace(/\+/g,"%20"))})).join("&")),a="".concat(e.protocol,"://").concat(e.url).concat(e.port?":".concat(e.port):"","/").concat("/"===t.charAt(0)?t.substring(1):t);return o.length&&(a+="?".concat(o)),a}function Mn(e,t){if("GET"!==e.method&&(void 0!==e.data||void 0!==t.data)){var n=Array.isArray(e.data)?e.data:h(h({},e.data),t.data);return JSON.stringify(n)}}function Fn(e,t,n){var r=h(h(h({Accept:"application/json"},e),t),n),o={};return Object.keys(r).forEach((function(e){var t=r[e];o[e.toLowerCase()]=t})),o}function Bn(e){try{return JSON.parse(e.content)}catch(t){throw new Nn(t.message,e)}}function zn(e,t){var n=e.content,r=e.status;try{var o=JSON.parse(n);return"error"in o?new Rn(o.message,r,o.error,t):new In(o.message,r,t)}catch(e){}return new In(n,r,t)}function $n(e){return e.map((function(e){return Un(e)}))}function Un(e){var t=e.request.headers["x-algolia-api-key"]?{"x-algolia-api-key":"*****"}:{};return h(h({},e),{},{request:h(h({},e.request),{},{headers:h(h({},e.request.headers),t)})})}var Hn=["appId","apiKey","authMode","algoliaAgents"],qn=["params"],Vn="5.12.0";function Wn(e){return[{url:"".concat(e,"-dsn.algolia.net"),accept:"read",protocol:"https"},{url:"".concat(e,".algolia.net"),accept:"write",protocol:"https"}].concat(function(e){for(var t=e,n=e.length-1;n>0;n--){var r=Math.floor(Math.random()*(n+1)),o=e[n];t[n]=e[r],t[r]=o}return t}([{url:"".concat(e,"-1.algolianet.com"),accept:"readWrite",protocol:"https"},{url:"".concat(e,"-2.algolianet.com"),accept:"readWrite",protocol:"https"},{url:"".concat(e,"-3.algolianet.com"),accept:"readWrite",protocol:"https"}]))}var Gn="3.8.0";function Kn(e,t,n){return r.useMemo((function(){var r=function(e,t){if(!e||"string"!=typeof e)throw new Error("`appId` is missing.");if(!t||"string"!=typeof t)throw new Error("`apiKey` is missing.");return function(e){var t=e.appId,n=e.apiKey,r=e.authMode,o=e.algoliaAgents,a=b(e,Hn),c=function(e,t){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:"WithinHeaders",r={"x-algolia-api-key":t,"x-algolia-application-id":e};return{headers:function(){return"WithinHeaders"===n?r:{}},queryParameters:function(){return"WithinQueryParameters"===n?r:{}}}}(t,n,r),s=function(e){var t=e.hosts,n=e.hostsCache,r=e.baseHeaders,o=e.logger,a=e.baseQueryParameters,c=e.algoliaAgent,s=e.timeouts,l=e.requester,u=e.requestsCache,d=e.responsesCache;function p(e){return f.apply(this,arguments)}function f(){return(f=i(y().mark((function e(t){var r,o,a,i,c;return y().wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return e.next=2,Promise.all(t.map((function(e){return n.get(e,(function(){return Promise.resolve(On(e))}))})));case 2:return r=e.sent,o=r.filter((function(e){return e.isUp()})),a=r.filter((function(e){return e.isTimedOut()})),i=[].concat(S(o),S(a)),c=i.length>0?i:t,e.abrupt("return",{hosts:c,getTimeout:function(e,t){return(0===a.length&&0===e?1:a.length+3+e)*t}});case 8:case"end":return e.stop()}}),e)})))).apply(this,arguments)}function m(e,t){return g.apply(this,arguments)}function g(){return g=i(y().mark((function e(u,d){var f,m,g,b,v,w,k,x,_,C,E,D,j,O=arguments;return y().wrap((function(e){for(;;)switch(e.prev=e.next){case 0:if(f=!(O.length>2&&void 0!==O[2])||O[2],m=[],g=Mn(u,d),b=Fn(r,u.headers,d.headers),v="GET"===u.method?h(h({},u.data),d.data):{},w=h(h(h({},a),u.queryParameters),v),c.value&&(w["x-algolia-agent"]=c.value),d&&d.queryParameters)for(k=0,x=Object.keys(d.queryParameters);k<x.length;k++)_=x[k],d.queryParameters[_]&&"[object Object]"!==Object.prototype.toString.call(d.queryParameters[_])?w[_]=d.queryParameters[_].toString():w[_]=d.queryParameters[_];return C=0,E=function(){var e=i(y().mark((function e(t,r){var a,i,c,p,v,S;return y().wrap((function(e){for(;;)switch(e.prev=e.next){case 0:if(void 0!==(a=t.pop())){e.next=3;break}throw new Pn($n(m));case 3:return i=h(h({},s),d.timeouts),c={data:g,headers:b,method:u.method,url:Ln(a,u.path,w),connectTimeout:r(C,i.connect),responseTimeout:r(C,f?i.read:i.write)},p=function(e){var n={request:c,response:e,host:a,triesLeft:t.length};return m.push(n),n},e.next=8,l.send(c);case 8:if(k=(y=v=e.sent).isTimedOut,x=y.status,!(k||function(e){return!e.isTimedOut&&!~~e.status}({isTimedOut:k,status:x})||2!=~~(x/100)&&4!=~~(x/100))){e.next=16;break}return S=p(v),v.isTimedOut&&C++,o.info("Retryable failure",Un(S)),e.next=15,n.set(a,On(a,v.isTimedOut?"timed out":"down"));case 15:return e.abrupt("return",E(t,r));case 16:if(2!=~~(v.status/100)){e.next=18;break}return e.abrupt("return",Bn(v));case 18:throw p(v),zn(v,m);case 20:case"end":return e.stop()}var y,k,x}),e)})));return function(t,n){return e.apply(this,arguments)}}(),D=t.filter((function(e){return"readWrite"===e.accept||(f?"read"===e.accept:"write"===e.accept)})),e.next=13,p(D);case 13:return j=e.sent,e.abrupt("return",E(S(j.hosts).reverse(),j.getTimeout));case 15:case"end":return e.stop()}}),e)}))),g.apply(this,arguments)}return{hostsCache:n,requester:l,timeouts:s,logger:o,algoliaAgent:c,baseHeaders:r,baseQueryParameters:a,hosts:t,request:function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},n=e.useReadTransporter||"GET"===e.method;if(!n)return m(e,t,n);var o=function(){return m(e,t)};if(!0!==(t.cacheable||e.cacheable))return o();var i={request:e,requestOptions:t,transporter:{queryParameters:a,headers:r}};return d.get(i,(function(){return u.get(i,(function(){return u.set(i,o()).then((function(e){return Promise.all([u.delete(i),e])}),(function(e){return Promise.all([u.delete(i),Promise.reject(e)])})).then((function(e){var t=w(e,2);return t[0],t[1]}))}))}),{miss:function(e){return d.set(i,e)}})},requestsCache:u,responsesCache:d}}(h(h({hosts:Wn(t)},a),{},{algoliaAgent:Dn({algoliaAgents:o,client:"Lite",version:Vn}),baseHeaders:h(h({"content-type":"text/plain"},c.headers()),a.baseHeaders),baseQueryParameters:h(h({},c.queryParameters()),a.baseQueryParameters)}));return{transporter:s,appId:t,clearCache:function(){return Promise.all([s.requestsCache.clear(),s.responsesCache.clear()]).then((function(){}))},get _ua(){return s.algoliaAgent.value},addAlgoliaAgent:function(e,t){s.algoliaAgent.add({segment:e,version:t})},setClientApiKey:function(e){var t=e.apiKey;r&&"WithinHeaders"!==r?s.baseQueryParameters["x-algolia-api-key"]=t:s.baseHeaders["x-algolia-api-key"]=t},searchForHits:function(e,t){return this.search(e,t)},searchForFacets:function(e,t){return this.search(e,t)},customPost:function(e,t){var n=e.path,r=e.parameters,o=e.body;if(!n)throw new Error("Parameter `path` is required when calling `customPost`.");var a={method:"POST",path:"/{path}".replace("{path}",n),queryParameters:r||{},headers:{},data:o||{}};return s.request(a,t)},getRecommendations:function(e,t){if(e&&Array.isArray(e)&&(e={requests:e}),!e)throw new Error("Parameter `getRecommendationsParams` is required when calling `getRecommendations`.");if(!e.requests)throw new Error("Parameter `getRecommendationsParams.requests` is required when calling `getRecommendations`.");var n={method:"POST",path:"/1/indexes/*/recommendations",queryParameters:{},headers:{},data:e,useReadTransporter:!0,cacheable:!0};return s.request(n,t)},search:function(e,t){if(e&&Array.isArray(e)){var n={requests:e.map((function(e){var t=e.params,n=b(e,qn);return"facet"===n.type?h(h(h({},n),t),{},{type:"facet"}):h(h(h({},n),t),{},{facet:void 0,maxFacetHits:void 0,facetQuery:void 0})}))};e=n}if(!e)throw new Error("Parameter `searchMethodParams` is required when calling `search`.");if(!e.requests)throw new Error("Parameter `searchMethodParams.requests` is required when calling `search`.");var r={method:"POST",path:"/1/indexes/*/queries",queryParameters:{},headers:{},data:e,useReadTransporter:!0,cacheable:!0};return s.request(r,t)}}}(h({appId:e,apiKey:t,timeouts:{connect:1e3,read:2e3,write:3e4},logger:{debug:function(e,t){return Promise.resolve()},info:function(e,t){return Promise.resolve()},error:function(e,t){return Promise.resolve()}},requester:{send:function(e){return new Promise((function(t){var n=new XMLHttpRequest;n.open(e.method,e.url,!0),Object.keys(e.headers).forEach((function(t){return n.setRequestHeader(t,e.headers[t])}));var r,o=function(e,r){return setTimeout((function(){n.abort(),t({status:0,content:r,isTimedOut:!0})}),e)},a=o(e.connectTimeout,"Connection timeout");n.onreadystatechange=function(){n.readyState>n.OPENED&&void 0===r&&(clearTimeout(a),r=o(e.responseTimeout,"Socket timeout"))},n.onerror=function(){0===n.status&&(clearTimeout(a),clearTimeout(r),t({content:n.responseText||"Network request failed",status:n.status,isTimedOut:!1}))},n.onload=function(){clearTimeout(a),clearTimeout(r),t({content:n.responseText,status:n.status,isTimedOut:!1})},n.send(e.data)}))}},algoliaAgents:[{segment:"Browser"}],authMode:"WithinQueryParameters",responsesCache:En(),requestsCache:En({serializable:!1}),hostsCache:Cn({caches:[_n({key:"".concat(Vn,"-").concat(e)}),En()]})},void 0))}(e,t);return r.addAlgoliaAgent("docsearch",Gn),!1===/docsearch.js \(.*\)/.test(r.transporter.algoliaAgent.value)&&r.addAlgoliaAgent("docsearch-react",Gn),n(r)}),[e,t,n])}var Yn=["footer","searchBox"];function Qn(e){var t=e.appId,n=e.apiKey,o=e.indexName,a=e.placeholder,i=void 0===a?"Search docs":a,c=e.searchParameters,s=e.maxResultsPerGroup,l=e.onClose,u=void 0===l?dn:l,p=e.transformItems,f=void 0===p?ln:p,m=e.hitComponent,g=void 0===m?$t:m,y=e.resultsFooterComponent,v=void 0===y?function(){return null}:y,S=e.navigator,k=e.initialScrollY,x=void 0===k?0:k,_=e.transformSearchClient,C=void 0===_?ln:_,E=e.disableUserPersonalization,D=void 0!==E&&E,j=e.initialQuery,O=void 0===j?"":j,A=e.translations,T=void 0===A?{}:A,P=e.getMissingResultsUrl,I=e.insights,N=void 0!==I&&I,R=T.footer,L=T.searchBox,M=b(T,Yn),F=w(r.useState({query:"",collections:[],completion:null,context:{},isOpen:!1,activeItemId:null,status:"idle"}),2),B=F[0],z=F[1],$=r.useRef(null),U=r.useRef(null),H=r.useRef(null),q=r.useRef(null),V=r.useRef(null),W=r.useRef(10),G=r.useRef("undefined"!=typeof window?window.getSelection().toString().slice(0,64):"").current,K=r.useRef(O||G).current,Y=Kn(t,n,C),Q=r.useRef(xn({key:"__DOCSEARCH_FAVORITE_SEARCHES__".concat(o),limit:10})).current,Z=r.useRef(xn({key:"__DOCSEARCH_RECENT_SEARCHES__".concat(o),limit:0===Q.getAll().length?7:4})).current,X=r.useCallback((function(e){if(!D){var t="content"===e.type?e.__docsearch_parent:e;t&&-1===Q.getAll().findIndex((function(e){return e.objectID===t.objectID}))&&Z.add(t)}}),[Q,Z,D]),J=r.useCallback((function(e){if(B.context.algoliaInsightsPlugin&&e.__autocomplete_id){var t=e,n={eventName:"Item Selected",index:t.__autocomplete_indexName,items:[t],positions:[e.__autocomplete_id],queryID:t.__autocomplete_queryID};B.context.algoliaInsightsPlugin.insights.clickedObjectIDsAfterSearch(n)}}),[B.context.algoliaInsightsPlugin]),ee=r.useMemo((function(){return Mt({id:"docsearch",defaultActiveItemId:0,placeholder:i,openOnFocus:!0,initialState:{query:K,context:{searchSuggestions:[]}},insights:N,navigator:S,onStateChange:function(e){z(e.state)},getSources:function(e){var r=e.query,a=e.state,i=e.setContext,l=e.setStatus;if(!r)return D?[]:[{sourceId:"recentSearches",onSelect:function(e){var t=e.item,n=e.event;X(t),un(n)||u()},getItemUrl:function(e){return e.item.url},getItems:function(){return Z.getAll()}},{sourceId:"favoriteSearches",onSelect:function(e){var t=e.item,n=e.event;X(t),un(n)||u()},getItemUrl:function(e){return e.item.url},getItems:function(){return Q.getAll()}}];var d=Boolean(N);return Y.search({requests:[h({query:r,indexName:o,attributesToRetrieve:["hierarchy.lvl0","hierarchy.lvl1","hierarchy.lvl2","hierarchy.lvl3","hierarchy.lvl4","hierarchy.lvl5","hierarchy.lvl6","content","type","url"],attributesToSnippet:["hierarchy.lvl1:".concat(W.current),"hierarchy.lvl2:".concat(W.current),"hierarchy.lvl3:".concat(W.current),"hierarchy.lvl4:".concat(W.current),"hierarchy.lvl5:".concat(W.current),"hierarchy.lvl6:".concat(W.current),"content:".concat(W.current)],snippetEllipsisText:"\u2026",highlightPreTag:"<mark>",highlightPostTag:"</mark>",hitsPerPage:20,clickAnalytics:d},c)]}).catch((function(e){throw"RetryError"===e.name&&l("error"),e})).then((function(e){var r=e.results[0],c=r.hits,l=r.nbHits,p=sn(c,(function(e){return mn(e)}),s);a.context.searchSuggestions.length<Object.keys(p).length&&i({searchSuggestions:Object.keys(p)}),i({nbHits:l});var m={};return d&&(m={__autocomplete_indexName:o,__autocomplete_queryID:r.queryID,__autocomplete_algoliaCredentials:{appId:t,apiKey:n}}),Object.values(p).map((function(e,t){return{sourceId:"hits".concat(t),onSelect:function(e){var t=e.item,n=e.event;X(t),un(n)||u()},getItemUrl:function(e){return e.item.url},getItems:function(){return Object.values(sn(e,(function(e){return e.hierarchy.lvl1}),s)).map(f).map((function(e){return e.map((function(t){var n=null,r=e.find((function(e){return"lvl1"===e.type&&e.hierarchy.lvl1===t.hierarchy.lvl1}));return"lvl1"!==t.type&&r&&(n=r),h(h({},t),{},{__docsearch_parent:n},m)}))})).flat()}}}))}))}})}),[o,c,s,Y,u,Z,Q,X,K,i,S,f,D,N,t,n]),te=ee.getEnvironmentProps,ne=ee.getRootProps,re=ee.refresh;return function(e){var t=e.getEnvironmentProps,n=e.panelElement,o=e.formElement,a=e.inputElement;r.useEffect((function(){if(n&&o&&a){var e=t({panelElement:n,formElement:o,inputElement:a}),r=e.onTouchStart,i=e.onTouchMove;return window.addEventListener("touchstart",r),window.addEventListener("touchmove",i),function(){window.removeEventListener("touchstart",r),window.removeEventListener("touchmove",i)}}}),[t,n,o,a])}({getEnvironmentProps:te,panelElement:q.current,formElement:H.current,inputElement:V.current}),function(e){var t=e.container;r.useEffect((function(){if(t){var e=t.querySelectorAll("a[href]:not([disabled]), button:not([disabled]), input:not([disabled])"),n=e[0],r=e[e.length-1];return t.addEventListener("keydown",o),function(){t.removeEventListener("keydown",o)}}function o(e){"Tab"===e.key&&(e.shiftKey?document.activeElement===n&&(e.preventDefault(),r.focus()):document.activeElement===r&&(e.preventDefault(),n.focus()))}}),[t])}({container:$.current}),r.useEffect((function(){return document.body.classList.add("DocSearch--active"),function(){var e,t;document.body.classList.remove("DocSearch--active"),null===(e=(t=window).scrollTo)||void 0===e||e.call(t,0,x)}}),[]),r.useEffect((function(){window.matchMedia("(max-width: 768px)").matches&&(W.current=5)}),[]),r.useEffect((function(){q.current&&(q.current.scrollTop=0)}),[B.query]),r.useEffect((function(){K.length>0&&(re(),V.current&&V.current.focus())}),[K,re]),r.useEffect((function(){function e(){if(U.current){var e=.01*window.innerHeight;U.current.style.setProperty("--docsearch-vh","".concat(e,"px"))}}return e(),window.addEventListener("resize",e),function(){window.removeEventListener("resize",e)}}),[]),r.createElement("div",d({ref:$},ne({"aria-expanded":!0}),{className:["DocSearch","DocSearch-Container","stalled"===B.status&&"DocSearch-Container--Stalled","error"===B.status&&"DocSearch-Container--Errored"].filter(Boolean).join(" "),role:"button",tabIndex:0,onMouseDown:function(e){e.target===e.currentTarget&&u()}}),r.createElement("div",{className:"DocSearch-Modal",ref:U},r.createElement("header",{className:"DocSearch-SearchBar",ref:H},r.createElement(Sn,d({},ee,{state:B,autoFocus:0===K.length,inputRef:V,isFromSelection:Boolean(K)&&K===G,translations:L,onClose:u}))),r.createElement("div",{className:"DocSearch-Dropdown",ref:q},r.createElement(vn,d({},ee,{indexName:o,state:B,hitComponent:g,resultsFooterComponent:v,disableUserPersonalization:D,recentSearches:Z,favoriteSearches:Q,inputRef:V,translations:M,getMissingResultsUrl:P,onItemClick:function(e,t){J(e),X(e),un(t)||u()}}))),r.createElement("footer",{className:"DocSearch-Footer"},r.createElement(zt,{translations:R}))))}function Zn(e){var t=e.isOpen,n=e.onOpen,o=e.onClose,a=e.onInput,i=e.searchButtonRef;r.useEffect((function(){function e(e){var r;if("Escape"===e.code&&t||"k"===(null===(r=e.key)||void 0===r?void 0:r.toLowerCase())&&(e.metaKey||e.ctrlKey)||!function(e){var t=e.target,n=t.tagName;return t.isContentEditable||"INPUT"===n||"SELECT"===n||"TEXTAREA"===n}(e)&&"/"===e.key&&!t)return e.preventDefault(),void(t?o():document.body.classList.contains("DocSearch--active")||n());i&&i.current===document.activeElement&&a&&/[a-zA-Z0-9]/.test(String.fromCharCode(e.keyCode))&&a(e)}return window.addEventListener("keydown",e),function(){window.removeEventListener("keydown",e)}}),[t,n,o,a,i])}},8328:(e,t,n)=>{"use strict";n.d(t,{A:()=>p});n(6540);var r=n(3259),o=n.n(r),a=n(4054);const i={"003b6e74":[()=>n.e(7562).then(n.bind(n,9430)),"@site/docs/05-go-client/16-distributed-cron.md",9430],"01a85c17":[()=>Promise.all([n.e(1869),n.e(8209)]).then(n.bind(n,9158)),"@theme/BlogTagsListPage",9158],"02de9280":[()=>n.e(9533).then(n.t.bind(n,9221,19)),"@generated/docusaurus-plugin-content-blog/default/p/cadence-docs-blog-084.json",9221],"02fb669a":[()=>n.e(1839).then(n.bind(n,3839)),"@site/docs/03-concepts/01-workflows.md",3839],"04634098":[()=>n.e(9053).then(n.t.bind(n,7858,19)),"@generated/docusaurus-plugin-content-blog/default/p/cadence-docs-blog-tags-announcements-844.json",7858],"05d44d04":[()=>n.e(3774).then(n.bind(n,79)),"@site/docs/04-java-client/07-versioning.md",79],"0826fbec":[()=>n.e(8067).then(n.bind(n,3952)),"@site/docs/05-go-client/17-tracing.md",3952],"08e09fce":[()=>n.e(4993).then(n.t.bind(n,7623,19)),"@generated/docusaurus-plugin-content-blog/default/p/cadence-docs-blog-authors-vytautas-karpavicius-f60.json",7623],"0b211f8a":[()=>n.e(6758).then(n.bind(n,8140)),"@site/docs/09-about/index.md",8140],"0b21c5b6":[()=>n.e(62).then(n.t.bind(n,4751,19)),"@generated/docusaurus-plugin-content-blog/default/p/cadence-docs-blog-tags-releases-45d.json",4751],"0b5e41cc":[()=>n.e(672).then(n.t.bind(n,8426,19)),"@generated/docusaurus-plugin-content-blog/default/p/cadence-docs-blog-authors-sharanf-4e7.json",8426],"0b6b8c62":[()=>n.e(1314).then(n.t.bind(n,7802,19)),"@generated/docusaurus-plugin-content-docs/community/p/cadence-docs-community-a44.json",7802],"0bc129c0":[()=>n.e(5371).then(n.bind(n,4425)),"@site/blog/2023-06-28-components-of-cadence-application-setup.md",4425],"0ece390c":[()=>n.e(8125).then(n.bind(n,9561)),"@site/docs/04-java-client/01-client-overview.md",9561],"115ec24d":[()=>n.e(5332).then(n.bind(n,2960)),"@site/blog/2024-11-18-cadence-workflows-github-organization.md",2960],"144c3ace":[()=>n.e(8035).then(n.bind(n,2817)),"@site/blog/2022-02-28-community-spotlight-february-2022.md?truncated=true",2817],"1685be14":[()=>n.e(1919).then(n.bind(n,7747)),"@site/docs/04-java-client/02-workflow-interface.md",7747],"177ff540":[()=>n.e(647).then(n.bind(n,4329)),"@site/blog/2021-10-19-moving-to-grpc/2021-10-19-moving-to-grpc.md",4329],17896441:[()=>Promise.all([n.e(1869),n.e(8498),n.e(8401)]).then(n.bind(n,575)),"@theme/DocItem",575],"18e1ae2c":[()=>n.e(3029).then(n.bind(n,3198)),"@site/blog/2023-07-05-implement-cadence-worker-from-scratch.md",3198],"1a4e3797":[()=>Promise.all([n.e(1869),n.e(2138)]).then(n.bind(n,4604)),"@theme/SearchPage",4604],"1c90ed0c":[()=>n.e(4860).then(n.bind(n,6553)),"@site/blog/2022-05-31-community-spotlight-update-may-2022.md?truncated=true",6553],"1dec29fa":[()=>n.e(9612).then(n.bind(n,3209)),"@site/docs/08-workflow-troubleshooting/01-timeouts.md",3209],"1df93b7f":[()=>Promise.all([n.e(1869),n.e(4583)]).then(n.bind(n,5579)),"@site/src/pages/index.tsx",5579],"1f391b9e":[()=>Promise.all([n.e(1869),n.e(8498),n.e(6061)]).then(n.bind(n,7973)),"@theme/MDXPage",7973],"20139c40":[()=>n.e(9369).then(n.bind(n,8281)),"@site/community/3-contributing.mdx",8281],"23beb9a4":[()=>n.e(2093).then(n.t.bind(n,2074,19)),"@generated/docusaurus-plugin-content-blog/default/p/cadence-docs-blog-authors-kcorbett-netapp-bc7.json",2074],"278bd730":[()=>n.e(1198).then(n.bind(n,9328)),"@site/blog/2021-09-30-long-term-commitment-and-support-for-the-cadence-project-and-its-community.md",9328],"27f46eca":[()=>n.e(447).then(n.bind(n,9303)),"@site/docs/09-about/01-license.md",9303],28839895:[()=>n.e(9171).then(n.bind(n,649)),"@site/docs/01-get-started/03-golang-hello-world.md",649],"28f6f2b5":[()=>n.e(4830).then(n.bind(n,3947)),"@site/blog/2021-10-19-moving-to-grpc/2021-10-19-moving-to-grpc.md?truncated=true",3947],"2955167d":[()=>n.e(8202).then(n.bind(n,5372)),"@site/blog/2023-08-28-nondeterministic-errors-replayers-shadowers.md",5372],"2a3fd662":[()=>n.e(2813).then(n.bind(n,9556)),"@site/docs/03-concepts/06-task-lists.md",9556],"2b58a6fe":[()=>n.e(3190).then(n.bind(n,5490)),"@site/docs/05-go-client/01-workers.md",5490],"2b6d3152":[()=>n.e(4468).then(n.t.bind(n,4450,19)),"@generated/docusaurus-plugin-content-blog/default/p/cadence-docs-blog-tags-deep-dives-fd8.json",4450],"2bc7f48b":[()=>n.e(5861).then(n.bind(n,6082)),"@site/docs/05-go-client/06-retries.md",6082],"31f8b8ae":[()=>n.e(4569).then(n.bind(n,9500)),"@site/blog/2024-11-18-cadence-workflows-github-organization.md?truncated=true",9500],"33348b0e":[()=>n.e(4739).then(n.bind(n,2399)),"@site/blog/2024-3-11-community-spotlight-update-march-2024.md?truncated=true",2399],"33cf8314":[()=>n.e(6806).then(n.bind(n,8644)),"@site/blog/2023-01-31-community-spotlight-january-2023.md?truncated=true",8644],"33fc5bb8":[()=>Promise.all([n.e(1869),n.e(8498),n.e(3347),n.e(867)]).then(n.bind(n,778)),"@theme/Blog/Pages/BlogAuthorsPostsPage",778],"3408eb41":[()=>n.e(9866).then(n.bind(n,7521)),"@site/docs/01-get-started/02-java-hello-world.md",7521],"3525dd13":[()=>n.e(7240).then(n.bind(n,5477)),"@site/docs/03-concepts/03-events.md",5477],"36994c47":[()=>n.e(9858).then(n.t.bind(n,5516,19)),"@generated/docusaurus-plugin-content-blog/default/__plugin.json",5516],"36aefe7c":[()=>n.e(9379).then(n.bind(n,8047)),"@site/blog/2023-02-28-community-spotlight-february.md?truncated=true",8047],"393be207":[()=>n.e(4134).then(n.bind(n,591)),"@site/src/pages/markdown-page.md",591],"3ca3c927":[()=>n.e(4552).then(n.bind(n,3438)),"@site/blog/2022-01-31-community-spotlight-january-2022.md",3438],"3ce9624a":[()=>n.e(2450).then(n.bind(n,3284)),"@site/community/2-resources.mdx",3284],"3d5497b2":[()=>n.e(2529).then(n.bind(n,6742)),"@site/blog/2022-04-30-community-spotlight-update-april-2022.md",6742],"3e206144":[()=>n.e(1898).then(n.bind(n,5335)),"@site/community/0-support.mdx",5335],"3e30df86":[()=>n.e(2222).then(n.bind(n,725)),"@site/docs/05-go-client/02.5-starting-workflows.md",725],"3faec549":[()=>n.e(2559).then(n.bind(n,6885)),"@site/docs/07-operation-guide/05-migration.md",6885],"41417ef6":[()=>n.e(6323).then(n.bind(n,3795)),"@site/docs/02-use-cases/08-deployment.md",3795],"43e9f1b6":[()=>n.e(8817).then(n.bind(n,4512)),"@site/docs/07-operation-guide/04-troubleshooting.md",4512],"44abbaf5":[()=>n.e(7682).then(n.bind(n,6513)),"@site/docs/04-java-client/04-starting-workflow-executions.md",6513],"44d6dde1":[()=>n.e(4471).then(n.bind(n,7739)),"@site/blog/2024-07-11-yearly-roadmap-update/2024-07-11-yearly-roadmap-update.md?truncated=true",7739],"45f9d173":[()=>n.e(4790).then(n.t.bind(n,3607,19)),"@generated/docusaurus-plugin-content-blog/default/p/cadence-docs-blog-authors-shaddoll-d21.json",3607],"47f0ea92":[()=>n.e(4669).then(n.bind(n,6981)),"@site/docs/04-java-client/15-continue-as-new.md",6981],"4807c528":[()=>n.e(278).then(n.t.bind(n,5958,19)),"@generated/docusaurus-plugin-content-blog/default/p/cadence-docs-blog-authors-jakobht-2cc.json",5958],"4b94b3ad":[()=>n.e(1816).then(n.bind(n,2088)),"@site/blog/2022-06-30-community-spotlight-update-june-2022.md",2088],"4c35ffca":[()=>n.e(2872).then(n.bind(n,8539)),"@site/docs/04-java-client/14-exception-handling.md",8539],"4c8ff8e7":[()=>n.e(9092).then(n.t.bind(n,6191,19)),"@generated/docusaurus-plugin-content-blog/default/p/cadence-docs-blog-authors-taylanisikdemir-354.json",6191],"4c9d8eaa":[()=>n.e(3116).then(n.bind(n,9614)),"@site/community/1-team.mdx",9614],"4d0beaf2":[()=>n.e(1507).then(n.t.bind(n,4950,19)),"@generated/docusaurus-plugin-content-blog/default/p/cadence-docs-blog-archive-c1d.json",4950],"4d332630":[()=>n.e(7748).then(n.bind(n,434)),"@site/blog/2022-08-31-community-spotlight-august-2022.md?truncated=true",434],"4d8144ae":[()=>n.e(6076).then(n.t.bind(n,1065,19)),"@generated/docusaurus-plugin-content-blog/default/p/cadence-docs-blog-tags-testing-603.json",1065],"4f20e2dc":[()=>n.e(4973).then(n.t.bind(n,7145,19)),"@generated/docusaurus-plugin-content-blog/default/p/cadence-docs-blog-authors-chopincode-05e.json",7145],"528620f0":[()=>n.e(7600).then(n.bind(n,5506)),"@site/blog/2022-11-30-community-spotlight-november-2022.md?truncated=true",5506],"533eb95b":[()=>n.e(5541).then(n.t.bind(n,8878,19)),"@generated/docusaurus-plugin-content-blog/default/p/cadence-docs-blog-page-4-2f6.json",8878],"534a6068":[()=>n.e(862).then(n.bind(n,3340)),"@site/blog/2023-07-10-cadence-bad-practices-part-1.md?truncated=true",3340],"5450051a":[()=>n.e(9528).then(n.bind(n,8781)),"@site/docs/07-operation-guide/02-maintain.md",8781],"55db2bea":[()=>n.e(573).then(n.bind(n,7919)),"@site/docs/07-operation-guide/01-setup.md",7919],"5806acc5":[()=>n.e(9306).then(n.bind(n,4639)),"@site/blog/2024-10-01-announcing-cadence-helm-charts-v0.md?truncated=true",4639],"580cfca3":[()=>n.e(7770).then(n.bind(n,3800)),"@site/blog/2023-11-30-community-spotlight-update-november-2023.md",3800],"5b895f91":[()=>n.e(7180).then(n.bind(n,3112)),"@site/blog/2023-08-28-nondeterministic-errors-replayers-shadowers.md?truncated=true",3112],"5cd48241":[()=>n.e(3732).then(n.bind(n,5835)),"@site/docs/02-use-cases/07-provisioning.md",5835],"5cfaf3a2":[()=>n.e(4344).then(n.bind(n,5101)),"@site/blog/zonal-isolation-v1/zonal-isolation-v1.md",5101],"5d1ead22":[()=>n.e(4713).then(n.bind(n,6462)),"@site/docs/04-java-client/16-side-effect.md",6462],"5e95c892":[()=>n.e(9647).then(n.bind(n,7121)),"@theme/DocsRoot",7121],"5e9f5e1a":[()=>Promise.resolve().then(n.bind(n,4784)),"@generated/docusaurus.config",4784],"5f63c9de":[()=>n.e(8770).then(n.bind(n,9344)),"@site/blog/2023-07-10-cadence-bad-practices-part-1.md",9344],"6081a96a":[()=>n.e(8729).then(n.bind(n,2428)),"@site/blog/2022-09-30-community-spotlight-september-2022.md",2428],"61aeb84e":[()=>n.e(2641).then(n.bind(n,754)),"@site/docs/04-java-client/index.md",754],"621db11d":[()=>Promise.all([n.e(1869),n.e(3347),n.e(4212)]).then(n.bind(n,3250)),"@theme/Blog/Pages/BlogAuthorsListPage",3250],"643bf5c6":[()=>n.e(4950).then(n.bind(n,5770)),"@site/docs/05-go-client/02-create-workflows.md",5770],"647edc7e":[()=>n.e(7478).then(n.bind(n,3108)),"@site/blog/2023-07-31-community-spotlight-july-2023.md",3108],"6601f8a9":[()=>n.e(7998).then(n.bind(n,3276)),"@site/docs/04-java-client/13-child-workflows.md",3276],"667be76f":[()=>n.e(4120).then(n.bind(n,1515)),"@site/blog/2023-06-28-components-of-cadence-application-setup.md?truncated=true",1515],"67affde7":[()=>n.e(9609).then(n.bind(n,5519)),"@site/docs/04-java-client/12-retries.md",5519],"67d45d0f":[()=>n.e(207).then(n.bind(n,5212)),"@site/docs/08-workflow-troubleshooting/03-retries.md",5212],"6875c492":[()=>Promise.all([n.e(1869),n.e(8498),n.e(3347),n.e(4813)]).then(n.bind(n,3069)),"@theme/BlogTagsPostsPage",3069],"69a323c8":[()=>n.e(6156).then(n.bind(n,887)),"@site/docs/05-go-client/04-execute-activity.md",887],"6abab11b":[()=>n.e(2709).then(n.t.bind(n,3571,19)),"@generated/docusaurus-plugin-content-docs/default/p/cadence-docs-docs-c0a.json",3571],"6e9b4a66":[()=>n.e(3252).then(n.bind(n,5907)),"@site/docs/07-operation-guide/03-monitoring.md",5907],"7373c0c0":[()=>n.e(2779).then(n.bind(n,2123)),"@site/docs/03-concepts/04-queries.md",2123],"73759d73":[()=>n.e(3364).then(n.bind(n,2855)),"@site/docs/04-java-client/03-implementing-workflows.md",2855],"7613fcd7":[()=>n.e(2370).then(n.bind(n,1675)),"@site/blog/2023-06-08-survey-results/2023-06-08-survey-results.md?truncated=true",1675],"7684a5b2":[()=>n.e(4422).then(n.bind(n,4778)),"@site/docs/02-use-cases/05-partitioned-scan.md",4778],"76dc6352":[()=>n.e(1347).then(n.bind(n,120)),"@site/blog/2024-09-05-workflow-specific-rate-limits.md?truncated=true",120],"775920c1":[()=>n.e(7009).then(n.bind(n,1614)),"@site/blog/2022-12-23-community-spotlight-december-2022.md",1614],"77a860e9":[()=>n.e(5538).then(n.bind(n,6454)),"@site/docs/04-java-client/08-distributed-cron.md",6454],"79f715ea":[()=>n.e(3314).then(n.bind(n,4316)),"@site/docs/02-use-cases/12-big-ml.md",4316],"7a568d1f":[()=>n.e(9699).then(n.bind(n,3915)),"@site/docs/04-java-client/11-queries.md",3915],"7afb0752":[()=>n.e(8929).then(n.bind(n,861)),"@site/blog/2023-02-28-community-spotlight-february.md",861],"7d996443":[()=>n.e(3685).then(n.bind(n,6611)),"@site/docs/08-workflow-troubleshooting/02-activity-failures.md",6611],"7f8511d4":[()=>n.e(8363).then(n.bind(n,84)),"@site/docs/01-get-started/01-server-installation.md",84],"7fda255c":[()=>n.e(4978).then(n.bind(n,7786)),"@site/blog/2024-02-15-cadence-non-deterministic-common-qa.md",7786],"80e02aec":[()=>n.e(1963).then(n.bind(n,2447)),"@site/blog/zonal-isolation-v1/zonal-isolation-v1.md?truncated=true",2447],"814003d2":[()=>n.e(751).then(n.bind(n,5092)),"@site/docs/03-concepts/07-archival.md",5092],"814f3328":[()=>n.e(7472).then(n.t.bind(n,5513,19)),"~blog/default/blog-post-list-prop-default.json",5513],"848b9863":[()=>n.e(7207).then(n.bind(n,4738)),"@site/docs/04-java-client/09-workers.md",4738],"849b28af":[()=>n.e(9881).then(n.bind(n,7705)),"@site/blog/2024-09-05-workflow-specific-rate-limits.md",7705],"86c2314d":[()=>n.e(7262).then(n.bind(n,8251)),"@site/docs/05-go-client/index.md",8251],"87d83cd2":[()=>n.e(9928).then(n.bind(n,994)),"@site/blog/2022-12-23-community-spotlight-december-2022.md?truncated=true",994],"88d84d8e":[()=>n.e(1094).then(n.bind(n,9003)),"@site/blog/2022-03-31-community-spotlight-update-march-2022.md",9003],"8a72c69a":[()=>n.e(4196).then(n.bind(n,3475)),"@site/blog/2023-07-16-write-your-first-workflow-with-cadence/2023-07-16-write-your-first-workflow-with-cadence.md?truncated=true",3475],"8d2e039e":[()=>n.e(4505).then(n.bind(n,1316)),"@site/docs/08-workflow-troubleshooting/index.md",1316],"8edf5fa8":[()=>n.e(5910).then(n.bind(n,7629)),"@site/blog/2024-3-11-community-spotlight-update-march-2024.md",7629],"90ce9713":[()=>n.e(8372).then(n.t.bind(n,9193,19)),"@generated/docusaurus-plugin-content-blog/default/p/cadence-docs-blog-tags-community-spotlights-page-2-2e0.json",9193],"90f276f1":[()=>n.e(4960).then(n.bind(n,8926)),"@site/docs/05-go-client/09-continue-as-new.md",8926],"91c0087d":[()=>n.e(245).then(n.t.bind(n,3666,19)),"@generated/docusaurus-plugin-content-blog/default/p/cadence-docs-blog-authors-enderdemirkaya-00b.json",3666],"92ce93dc":[()=>n.e(6941).then(n.bind(n,3273)),"@site/blog/2023-06-08-survey-results/2023-06-08-survey-results.md",3273],"9366521c":[()=>n.e(5086).then(n.bind(n,5365)),"@site/blog/2023-03-31-community-spotlight-march-2023.md",5365],"959827cd":[()=>n.e(150).then(n.bind(n,6392)),"@site/blog/2022-09-30-community-spotlight-september-2022.md?truncated=true",6392],"95cc356a":[()=>n.e(4324).then(n.bind(n,7669)),"@site/docs/05-go-client/18-workflow-replay-shadowing.md",7669],"95d054c5":[()=>n.e(9586).then(n.bind(n,7969)),"@site/docs/04-java-client/18-workflow-replay-shadowing.md",7969],"965c09ae":[()=>n.e(2469).then(n.bind(n,9382)),"@site/blog/2023-08-31-community-spotlight-august-2023.md?truncated=true",9382],"9674d0ef":[()=>n.e(1010).then(n.bind(n,6705)),"@site/docs/03-concepts/08-cross-dc-replication.md",6705],"981d14b8":[()=>n.e(7970).then(n.bind(n,2724)),"@site/blog/2023-11-30-community-spotlight-update-november-2023.md?truncated=true",2724],"98f5ac88":[()=>n.e(2235).then(n.bind(n,6724)),"@site/blog/2023-06-30-community-spotlight-june-2023.md",6724],"98f77afb":[()=>n.e(1193).then(n.bind(n,1786)),"@site/blog/2022-04-30-community-spotlight-update-april-2022.md?truncated=true",1786],"99c90dae":[()=>n.e(9203).then(n.bind(n,2771)),"@site/docs/03-concepts/index.md",2771],"9e4087bc":[()=>n.e(2711).then(n.bind(n,9331)),"@theme/BlogArchivePage",9331],"9e9bbe09":[()=>n.e(3718).then(n.bind(n,9118)),"@site/blog/2024-02-15-cadence-non-deterministic-common-qa.md?truncated=true",9118],a17e1a1b:[()=>n.e(9090).then(n.t.bind(n,2622,19)),"@generated/docusaurus-plugin-content-blog/default/p/cadence-docs-blog-tags-06e.json",2622],a197b989:[()=>n.e(6975).then(n.bind(n,5905)),"@site/blog/2023-07-16-write-your-first-workflow-with-cadence/2023-07-16-write-your-first-workflow-with-cadence.md",5905],a3dd65a2:[()=>n.e(1485).then(n.bind(n,9983)),"@site/blog/2022-02-28-community-spotlight-february-2022.md",9983],a4f1f4dd:[()=>n.e(9961).then(n.bind(n,2496)),"@site/docs/05-go-client/19-workflow-non-deterministic-error.md",2496],a6aa9e1f:[()=>Promise.all([n.e(1869),n.e(8498),n.e(3347),n.e(7643)]).then(n.bind(n,5124)),"@theme/BlogListPage",5124],a7456010:[()=>n.e(1235).then(n.t.bind(n,8552,19)),"@generated/docusaurus-plugin-content-pages/default/__plugin.json",8552],a7552915:[()=>n.e(9520).then(n.bind(n,1735)),"@site/docs/04-java-client/06-implementing-activities.md",1735],a7bd4aaa:[()=>n.e(7098).then(n.bind(n,4532)),"@theme/DocVersionRoot",4532],a7de3fbd:[()=>n.e(783).then(n.bind(n,8515)),"@site/docs/02-use-cases/11-dsl.md",8515],a82a64d4:[()=>n.e(9433).then(n.t.bind(n,5758,19)),"@generated/docusaurus-plugin-content-blog/default/p/cadence-docs-blog-tags-introduction-to-cadence-81c.json",5758],a844cb54:[()=>n.e(7940).then(n.t.bind(n,4002,19)),"@generated/docusaurus-plugin-content-blog/default/p/cadence-docs-blog-authors-9d3.json",4002],a94703ab:[()=>Promise.all([n.e(1869),n.e(9048)]).then(n.bind(n,1377)),"@theme/DocRoot",1377],a94774ec:[()=>n.e(2887).then(n.bind(n,2318)),"@site/blog/2022-08-31-community-spotlight-august-2022.md",2318],a9771bf1:[()=>n.e(7157).then(n.t.bind(n,2156,19)),"@generated/docusaurus-plugin-content-blog/default/p/cadence-docs-blog-authors-meiliang-86-e43.json",2156],aac593d4:[()=>n.e(6269).then(n.bind(n,5492)),"@site/blog/2022-06-30-community-spotlight-update-june-2022.md?truncated=true",5492],aacb5a6b:[()=>n.e(5620).then(n.bind(n,8146)),"@site/docs/05-go-client/07-error-handling.md",8146],aba21aa0:[()=>n.e(5742).then(n.t.bind(n,7093,19)),"@generated/docusaurus-plugin-content-docs/default/__plugin.json",7093],acecf23e:[()=>n.e(1903).then(n.t.bind(n,1912,19)),"~blog/default/blogMetadata-default.json",1912],acfca6f1:[()=>n.e(5484).then(n.bind(n,4066)),"@site/blog/2022-01-31-community-spotlight-january-2022.md?truncated=true",4066],ad4570fb:[()=>n.e(3700).then(n.t.bind(n,4772,19)),"@generated/docusaurus-plugin-content-blog/default/p/cadence-docs-blog-page-2-f3a.json",4772],ad9e871f:[()=>n.e(3992).then(n.bind(n,8696)),"@site/docs/01-get-started/04-video-tutorials.md",8696],aeb329ea:[()=>n.e(2937).then(n.bind(n,3347)),"@site/docs/GLOSSARY.md",3347],b4266c8b:[()=>n.e(4962).then(n.bind(n,8060)),"@site/docs/03-concepts/02-activities.md",8060],b69803f5:[()=>n.e(5552).then(n.bind(n,4055)),"@site/blog/2022-05-31-community-spotlight-update-may-2022.md",4055],bc79ac75:[()=>n.e(1662).then(n.bind(n,1241)),"@site/docs/02-use-cases/01-periodic-execution.md",1241],bde620bf:[()=>n.e(3890).then(n.bind(n,4591)),"@site/docs/05-go-client/12-activity-async-completion.md",4591],c0e193ae:[()=>n.e(4582).then(n.t.bind(n,8374,19)),"@generated/docusaurus-plugin-content-blog/default/p/cadence-docs-blog-tags-roadmap-7e8.json",8374],c141421f:[()=>n.e(957).then(n.t.bind(n,936,19)),"@generated/docusaurus-theme-search-algolia/default/__plugin.json",936],c47f6b82:[()=>n.e(9855).then(n.bind(n,4281)),"@site/blog/2024-07-11-yearly-roadmap-update/2024-07-11-yearly-roadmap-update.md",4281],c4da92db:[()=>n.e(1700).then(n.bind(n,8863)),"@site/docs/02-use-cases/10-interactive.md",8863],c5abbc6d:[()=>n.e(1337).then(n.bind(n,9976)),"@site/docs/05-go-client/15-sessions.md",9976],c74af710:[()=>n.e(2010).then(n.t.bind(n,4095,19)),"@generated/docusaurus-plugin-content-blog/default/p/cadence-docs-blog-authors-sharanf-authors-2-9bf.json",4095],c7e5f436:[()=>n.e(5078).then(n.t.bind(n,177,19)),"@generated/docusaurus-plugin-content-blog/default/p/cadence-docs-blog-page-3-152.json",177],ccc49370:[()=>Promise.all([n.e(1869),n.e(8498),n.e(3347),n.e(3249)]).then(n.bind(n,3858)),"@theme/BlogPostPage",3858],cccd73f1:[()=>n.e(9513).then(n.bind(n,5441)),"@site/docs/01-get-started/index.md",5441],cd7e9a8f:[()=>n.e(7338).then(n.bind(n,3907)),"@site/docs/03-concepts/10-http-api.md",3907],cdada9ee:[()=>n.e(1249).then(n.bind(n,1176)),"@site/docs/03-concepts/05-topology.md",1176],cdf6e634:[()=>n.e(3334).then(n.bind(n,8752)),"@site/blog/2023-06-30-community-spotlight-june-2023.md?truncated=true",8752],cfb807c8:[()=>n.e(9308).then(n.bind(n,8935)),"@site/blog/2022-07-31-community-spotlight-update-july-2022.md?truncated=true",8935],cfd61dd5:[()=>n.e(3044).then(n.bind(n,7237)),"@site/docs/02-use-cases/index.md",7237],d0ac2d40:[()=>n.e(6401).then(n.bind(n,9878)),"@site/docs/04-java-client/05-activity-interface.md",9878],d27d92a2:[()=>n.e(3060).then(n.bind(n,3592)),"@site/blog/2022-07-31-community-spotlight-update-july-2022.md",3592],d280f29d:[()=>n.e(4881).then(n.bind(n,1892)),"@site/docs/05-go-client/08-signals.md",1892],d33895f8:[()=>n.e(7125).then(n.bind(n,4669)),"@site/blog/2024-10-01-announcing-cadence-helm-charts-v0.md",4669],d33bd0ff:[()=>n.e(1759).then(n.bind(n,605)),"@site/blog/2022-03-31-community-spotlight-update-march-2022.md?truncated=true",605],d530ea3c:[()=>n.e(4639).then(n.t.bind(n,976,19)),"@generated/docusaurus-plugin-content-blog/default/p/cadence-docs-blog-tags-community-spotlights-48c.json",976],d67a7980:[()=>n.e(5733).then(n.bind(n,608)),"@site/docs/05-go-client/14-workflow-versioning.md",608],d6960a6f:[()=>n.e(5557).then(n.bind(n,5234)),"@site/blog/2023-07-05-implement-cadence-worker-from-scratch.md?truncated=true",5234],d70bd24b:[()=>n.e(1118).then(n.bind(n,5680)),"@site/blog/2023-07-31-community-spotlight-july-2023.md?truncated=true",5680],d7b037f3:[()=>n.e(5385).then(n.bind(n,3547)),"@site/docs/02-use-cases/02-orchestration.md",3547],d87fba2a:[()=>n.e(104).then(n.bind(n,2171)),"@site/docs/02-use-cases/09-operational-management.md",2171],d8ddffe9:[()=>n.e(1973).then(n.t.bind(n,6771,19)),"@generated/docusaurus-plugin-content-blog/default/p/cadence-docs-blog-authors-ibarrajo-6db.json",6771],de3708c6:[()=>n.e(4619).then(n.bind(n,988)),"@site/blog/2021-10-13-announcing-cadence-oss-office-hours-and-community-sync-up.md",988],dec4f520:[()=>n.e(4898).then(n.bind(n,190)),"@site/blog/2022-10-31-community-spotlight-october-2022.md?truncated=true",190],df4cf6e6:[()=>n.e(2379).then(n.bind(n,2652)),"@site/blog/2021-09-30-long-term-commitment-and-support-for-the-cadence-project-and-its-community.md?truncated=true",2652],e0719818:[()=>n.e(5220).then(n.t.bind(n,8669,19)),"@generated/docusaurus-plugin-content-docs/community/__plugin.json",8669],e1ea741a:[()=>n.e(2192).then(n.bind(n,1612)),"@site/docs/02-use-cases/03-polling.md",1612],e8018edf:[()=>n.e(2422).then(n.t.bind(n,3822,19)),"@generated/docusaurus-plugin-content-blog/default/p/cadence-docs-blog-tags-cadence-operations-d73.json",3822],e8c8106b:[()=>n.e(22).then(n.bind(n,2863)),"@site/docs/05-go-client/11-queries.md",2863],e9c26ae5:[()=>n.e(8631).then(n.bind(n,5726)),"@site/blog/2022-11-30-community-spotlight-november-2022.md",5726],ea1e4697:[()=>n.e(9617).then(n.bind(n,8442)),"@site/blog/2022-10-31-community-spotlight-october-2022.md",8442],eb57c500:[()=>n.e(7246).then(n.bind(n,266)),"@site/docs/05-go-client/10-side-effect.md",266],ec02fbe0:[()=>n.e(5438).then(n.bind(n,3231)),"@site/docs/05-go-client/03-activities.md",3231],ef69cbb3:[()=>n.e(6267).then(n.bind(n,5864)),"@site/blog/2023-01-31-community-spotlight-january-2023.md",5864],f0efcb43:[()=>n.e(4144).then(n.bind(n,71)),"@site/docs/05-go-client/05-child-workflows.md",71],f1de825c:[()=>n.e(9407).then(n.bind(n,4834)),"@site/blog/2023-08-31-community-spotlight-august-2023.md",4834],f2a162ea:[()=>n.e(3087).then(n.bind(n,1592)),"@site/docs/04-java-client/10-signals.md",1592],f5140c76:[()=>n.e(6763).then(n.bind(n,5658)),"@site/docs/04-java-client/17-testing.md",5658],f7be646d:[()=>n.e(5429).then(n.bind(n,455)),"@site/blog/2023-03-31-community-spotlight-march-2023.md?truncated=true",455],f81e7c5e:[()=>n.e(5351).then(n.bind(n,9540)),"@site/docs/05-go-client/13-workflow-testing.md",9540],f8f32361:[()=>n.e(734).then(n.bind(n,5913)),"@site/docs/06-cli/index.md",5913],f997f9c8:[()=>n.e(5138).then(n.bind(n,9691)),"@site/docs/07-operation-guide/index.md",9691],fa0e6b45:[()=>n.e(1328).then(n.bind(n,8094)),"@site/docs/02-use-cases/06-batch-job.md",8094],fcdcf093:[()=>n.e(9051).then(n.bind(n,4271)),"@site/docs/02-use-cases/04-event-driven.md",4271],fda2e45a:[()=>n.e(1653).then(n.bind(n,8856)),"@site/blog/2021-10-13-announcing-cadence-oss-office-hours-and-community-sync-up.md?truncated=true",8856],fde82b69:[()=>n.e(6185).then(n.bind(n,5410)),"@site/docs/03-concepts/09-search-workflows.md",5410]};var c=n(4848);function s(e){let{error:t,retry:n,pastDelay:r}=e;return t?(0,c.jsxs)("div",{style:{textAlign:"center",color:"#fff",backgroundColor:"#fa383e",borderColor:"#fa383e",borderStyle:"solid",borderRadius:"0.25rem",borderWidth:"1px",boxSizing:"border-box",display:"block",padding:"1rem",flex:"0 0 50%",marginLeft:"25%",marginRight:"25%",marginTop:"5rem",maxWidth:"50%",width:"100%"},children:[(0,c.jsx)("p",{children:String(t)}),(0,c.jsx)("div",{children:(0,c.jsx)("button",{type:"button",onClick:n,children:"Retry"})})]}):r?(0,c.jsx)("div",{style:{display:"flex",justifyContent:"center",alignItems:"center",height:"100vh"},children:(0,c.jsx)("svg",{id:"loader",style:{width:128,height:110,position:"absolute",top:"calc(100vh - 64%)"},viewBox:"0 0 45 45",xmlns:"http://www.w3.org/2000/svg",stroke:"#61dafb",children:(0,c.jsxs)("g",{fill:"none",fillRule:"evenodd",transform:"translate(1 1)",strokeWidth:"2",children:[(0,c.jsxs)("circle",{cx:"22",cy:"22",r:"6",strokeOpacity:"0",children:[(0,c.jsx)("animate",{attributeName:"r",begin:"1.5s",dur:"3s",values:"6;22",calcMode:"linear",repeatCount:"indefinite"}),(0,c.jsx)("animate",{attributeName:"stroke-opacity",begin:"1.5s",dur:"3s",values:"1;0",calcMode:"linear",repeatCount:"indefinite"}),(0,c.jsx)("animate",{attributeName:"stroke-width",begin:"1.5s",dur:"3s",values:"2;0",calcMode:"linear",repeatCount:"indefinite"})]}),(0,c.jsxs)("circle",{cx:"22",cy:"22",r:"6",strokeOpacity:"0",children:[(0,c.jsx)("animate",{attributeName:"r",begin:"3s",dur:"3s",values:"6;22",calcMode:"linear",repeatCount:"indefinite"}),(0,c.jsx)("animate",{attributeName:"stroke-opacity",begin:"3s",dur:"3s",values:"1;0",calcMode:"linear",repeatCount:"indefinite"}),(0,c.jsx)("animate",{attributeName:"stroke-width",begin:"3s",dur:"3s",values:"2;0",calcMode:"linear",repeatCount:"indefinite"})]}),(0,c.jsx)("circle",{cx:"22",cy:"22",r:"8",children:(0,c.jsx)("animate",{attributeName:"r",begin:"0s",dur:"1.5s",values:"6;1;2;3;4;5;6",calcMode:"linear",repeatCount:"indefinite"})})]})})}):null}var l=n(6921),u=n(3102);function d(e,t){if("*"===e)return o()({loading:s,loader:()=>n.e(2237).then(n.bind(n,2237)),modules:["@theme/NotFound"],webpack:()=>[2237],render(e,t){const n=e.default;return(0,c.jsx)(u.W,{value:{plugin:{name:"native",id:"default"}},children:(0,c.jsx)(n,{...t})})}});const r=a[`${e}-${t}`],d={},p=[],f=[],m=(0,l.A)(r);return Object.entries(m).forEach((e=>{let[t,n]=e;const r=i[n];r&&(d[t]=r[0],p.push(r[1]),f.push(r[2]))})),o().Map({loading:s,loader:d,modules:p,webpack:()=>f,render(t,n){const o=JSON.parse(JSON.stringify(r));Object.entries(t).forEach((t=>{let[n,r]=t;const a=r.default;if(!a)throw new Error(`The page component at ${e} doesn't have a default export. This makes it impossible to render anything. Consider default-exporting a React component.`);"object"!=typeof a&&"function"!=typeof a||Object.keys(r).filter((e=>"default"!==e)).forEach((e=>{a[e]=r[e]}));let i=o;const c=n.split(".");c.slice(0,-1).forEach((e=>{i=i[e]})),i[c[c.length-1]]=a}));const a=o.__comp;delete o.__comp;const i=o.__context;delete o.__context;const s=o.__props;return delete o.__props,(0,c.jsx)(u.W,{value:i,children:(0,c.jsx)(a,{...o,...s,...n})})}})}const p=[{path:"/Cadence-Docs/blog",component:d("/Cadence-Docs/blog","0a6"),exact:!0},{path:"/Cadence-Docs/blog/2021/09/30/long-term-commitment-and-support-for-the-cadence-project-and-its-community",component:d("/Cadence-Docs/blog/2021/09/30/long-term-commitment-and-support-for-the-cadence-project-and-its-community","395"),exact:!0},{path:"/Cadence-Docs/blog/2021/10/13/announcing-cadence-oss-office-hours-and-community-sync-up",component:d("/Cadence-Docs/blog/2021/10/13/announcing-cadence-oss-office-hours-and-community-sync-up","a52"),exact:!0},{path:"/Cadence-Docs/blog/2021/10/19/2021-10-19-moving-to-grpc/moving-to-grpc",component:d("/Cadence-Docs/blog/2021/10/19/2021-10-19-moving-to-grpc/moving-to-grpc","864"),exact:!0},{path:"/Cadence-Docs/blog/2022/01/31/community-spotlight-january-2022",component:d("/Cadence-Docs/blog/2022/01/31/community-spotlight-january-2022","71e"),exact:!0},{path:"/Cadence-Docs/blog/2022/02/28/community-spotlight-february-2022",component:d("/Cadence-Docs/blog/2022/02/28/community-spotlight-february-2022","6c1"),exact:!0},{path:"/Cadence-Docs/blog/2022/03/31/community-spotlight-update-march-2022",component:d("/Cadence-Docs/blog/2022/03/31/community-spotlight-update-march-2022","d8b"),exact:!0},{path:"/Cadence-Docs/blog/2022/04/30/community-spotlight-update-april-2022",component:d("/Cadence-Docs/blog/2022/04/30/community-spotlight-update-april-2022","834"),exact:!0},{path:"/Cadence-Docs/blog/2022/05/31/community-spotlight-update-may-2022",component:d("/Cadence-Docs/blog/2022/05/31/community-spotlight-update-may-2022","cc7"),exact:!0},{path:"/Cadence-Docs/blog/2022/06/30/community-spotlight-update-june-2022",component:d("/Cadence-Docs/blog/2022/06/30/community-spotlight-update-june-2022","f2b"),exact:!0},{path:"/Cadence-Docs/blog/2022/07/31/community-spotlight-update-july-2022",component:d("/Cadence-Docs/blog/2022/07/31/community-spotlight-update-july-2022","bfb"),exact:!0},{path:"/Cadence-Docs/blog/2022/08/31/community-spotlight-august-2022",component:d("/Cadence-Docs/blog/2022/08/31/community-spotlight-august-2022","a91"),exact:!0},{path:"/Cadence-Docs/blog/2022/09/30/community-spotlight-september-2022",component:d("/Cadence-Docs/blog/2022/09/30/community-spotlight-september-2022","05f"),exact:!0},{path:"/Cadence-Docs/blog/2022/10/31/community-spotlight-october-2022",component:d("/Cadence-Docs/blog/2022/10/31/community-spotlight-october-2022","d1d"),exact:!0},{path:"/Cadence-Docs/blog/2022/11/30/community-spotlight-november-2022",component:d("/Cadence-Docs/blog/2022/11/30/community-spotlight-november-2022","af1"),exact:!0},{path:"/Cadence-Docs/blog/2022/12/23/community-spotlight-december-2022",component:d("/Cadence-Docs/blog/2022/12/23/community-spotlight-december-2022","c64"),exact:!0},{path:"/Cadence-Docs/blog/2023/01/31/community-spotlight-january-2023",component:d("/Cadence-Docs/blog/2023/01/31/community-spotlight-january-2023","f18"),exact:!0},{path:"/Cadence-Docs/blog/2023/02/28/community-spotlight-february",component:d("/Cadence-Docs/blog/2023/02/28/community-spotlight-february","cac"),exact:!0},{path:"/Cadence-Docs/blog/2023/03/31/community-spotlight-march-2023",component:d("/Cadence-Docs/blog/2023/03/31/community-spotlight-march-2023","dd0"),exact:!0},{path:"/Cadence-Docs/blog/2023/06/08/2023-06-08-survey-results/survey-results",component:d("/Cadence-Docs/blog/2023/06/08/2023-06-08-survey-results/survey-results","258"),exact:!0},{path:"/Cadence-Docs/blog/2023/06/28/components-of-cadence-application-setup",component:d("/Cadence-Docs/blog/2023/06/28/components-of-cadence-application-setup","2f8"),exact:!0},{path:"/Cadence-Docs/blog/2023/06/30/community-spotlight-june-2023",component:d("/Cadence-Docs/blog/2023/06/30/community-spotlight-june-2023","589"),exact:!0},{path:"/Cadence-Docs/blog/2023/07/05/implement-cadence-worker-from-scratch",component:d("/Cadence-Docs/blog/2023/07/05/implement-cadence-worker-from-scratch","96d"),exact:!0},{path:"/Cadence-Docs/blog/2023/07/10/cadence-bad-practices-part-1",component:d("/Cadence-Docs/blog/2023/07/10/cadence-bad-practices-part-1","147"),exact:!0},{path:"/Cadence-Docs/blog/2023/07/16/2023-07-16-write-your-first-workflow-with-cadence/write-your-first-workflow-with-cadence",component:d("/Cadence-Docs/blog/2023/07/16/2023-07-16-write-your-first-workflow-with-cadence/write-your-first-workflow-with-cadence","5c3"),exact:!0},{path:"/Cadence-Docs/blog/2023/07/31/community-spotlight-july-2023",component:d("/Cadence-Docs/blog/2023/07/31/community-spotlight-july-2023","efe"),exact:!0},{path:"/Cadence-Docs/blog/2023/08/28/nondeterministic-errors-replayers-shadowers",component:d("/Cadence-Docs/blog/2023/08/28/nondeterministic-errors-replayers-shadowers","2e2"),exact:!0},{path:"/Cadence-Docs/blog/2023/08/31/community-spotlight-august-2023",component:d("/Cadence-Docs/blog/2023/08/31/community-spotlight-august-2023","978"),exact:!0},{path:"/Cadence-Docs/blog/2023/11/30/community-spotlight-update-november-2023",component:d("/Cadence-Docs/blog/2023/11/30/community-spotlight-update-november-2023","a5d"),exact:!0},{path:"/Cadence-Docs/blog/2024/02/15/cadence-non-deterministic-common-qa",component:d("/Cadence-Docs/blog/2024/02/15/cadence-non-deterministic-common-qa","4cd"),exact:!0},{path:"/Cadence-Docs/blog/2024/07/11/2024-07-11-yearly-roadmap-update/yearly-roadmap-update",component:d("/Cadence-Docs/blog/2024/07/11/2024-07-11-yearly-roadmap-update/yearly-roadmap-update","1a3"),exact:!0},{path:"/Cadence-Docs/blog/2024/09/05/workflow-specific-rate-limits",component:d("/Cadence-Docs/blog/2024/09/05/workflow-specific-rate-limits","fa3"),exact:!0},{path:"/Cadence-Docs/blog/2024/10/01/announcing-cadence-helm-charts-v0",component:d("/Cadence-Docs/blog/2024/10/01/announcing-cadence-helm-charts-v0","b72"),exact:!0},{path:"/Cadence-Docs/blog/2024/11/18/cadence-workflows-github-organization",component:d("/Cadence-Docs/blog/2024/11/18/cadence-workflows-github-organization","d1b"),exact:!0},{path:"/Cadence-Docs/blog/2024/3/11/community-spotlight-update-march-2024",component:d("/Cadence-Docs/blog/2024/3/11/community-spotlight-update-march-2024","196"),exact:!0},{path:"/Cadence-Docs/blog/archive",component:d("/Cadence-Docs/blog/archive","b94"),exact:!0},{path:"/Cadence-Docs/blog/authors",component:d("/Cadence-Docs/blog/authors","999"),exact:!0},{path:"/Cadence-Docs/blog/authors/chopincode",component:d("/Cadence-Docs/blog/authors/chopincode","ab3"),exact:!0},{path:"/Cadence-Docs/blog/authors/enderdemirkaya",component:d("/Cadence-Docs/blog/authors/enderdemirkaya","a8f"),exact:!0},{path:"/Cadence-Docs/blog/authors/ibarrajo",component:d("/Cadence-Docs/blog/authors/ibarrajo","cb3"),exact:!0},{path:"/Cadence-Docs/blog/authors/jakobht",component:d("/Cadence-Docs/blog/authors/jakobht","b6a"),exact:!0},{path:"/Cadence-Docs/blog/authors/kcorbett-netapp",component:d("/Cadence-Docs/blog/authors/kcorbett-netapp","b0f"),exact:!0},{path:"/Cadence-Docs/blog/authors/meiliang-86",component:d("/Cadence-Docs/blog/authors/meiliang-86","1a3"),exact:!0},{path:"/Cadence-Docs/blog/authors/shaddoll",component:d("/Cadence-Docs/blog/authors/shaddoll","d51"),exact:!0},{path:"/Cadence-Docs/blog/authors/sharanf",component:d("/Cadence-Docs/blog/authors/sharanf","185"),exact:!0},{path:"/Cadence-Docs/blog/authors/sharanf/authors/2",component:d("/Cadence-Docs/blog/authors/sharanf/authors/2","558"),exact:!0},{path:"/Cadence-Docs/blog/authors/taylanisikdemir",component:d("/Cadence-Docs/blog/authors/taylanisikdemir","72b"),exact:!0},{path:"/Cadence-Docs/blog/authors/vytautas-karpavicius",component:d("/Cadence-Docs/blog/authors/vytautas-karpavicius","b19"),exact:!0},{path:"/Cadence-Docs/blog/page/2",component:d("/Cadence-Docs/blog/page/2","0c8"),exact:!0},{path:"/Cadence-Docs/blog/page/3",component:d("/Cadence-Docs/blog/page/3","d10"),exact:!0},{path:"/Cadence-Docs/blog/page/4",component:d("/Cadence-Docs/blog/page/4","98f"),exact:!0},{path:"/Cadence-Docs/blog/tags",component:d("/Cadence-Docs/blog/tags","529"),exact:!0},{path:"/Cadence-Docs/blog/tags/announcements",component:d("/Cadence-Docs/blog/tags/announcements","71a"),exact:!0},{path:"/Cadence-Docs/blog/tags/cadence-operations",component:d("/Cadence-Docs/blog/tags/cadence-operations","5be"),exact:!0},{path:"/Cadence-Docs/blog/tags/community-spotlights",component:d("/Cadence-Docs/blog/tags/community-spotlights","5d5"),exact:!0},{path:"/Cadence-Docs/blog/tags/community-spotlights/page/2",component:d("/Cadence-Docs/blog/tags/community-spotlights/page/2","aab"),exact:!0},{path:"/Cadence-Docs/blog/tags/deep-dives",component:d("/Cadence-Docs/blog/tags/deep-dives","560"),exact:!0},{path:"/Cadence-Docs/blog/tags/introduction-to-cadence",component:d("/Cadence-Docs/blog/tags/introduction-to-cadence","012"),exact:!0},{path:"/Cadence-Docs/blog/tags/releases",component:d("/Cadence-Docs/blog/tags/releases","f14"),exact:!0},{path:"/Cadence-Docs/blog/tags/roadmap",component:d("/Cadence-Docs/blog/tags/roadmap","ab2"),exact:!0},{path:"/Cadence-Docs/blog/tags/testing",component:d("/Cadence-Docs/blog/tags/testing","2a4"),exact:!0},{path:"/Cadence-Docs/blog/zonal-isolation-v1/zonal-isolation-v1",component:d("/Cadence-Docs/blog/zonal-isolation-v1/zonal-isolation-v1","4b5"),exact:!0},{path:"/Cadence-Docs/markdown-page",component:d("/Cadence-Docs/markdown-page","c55"),exact:!0},{path:"/Cadence-Docs/search",component:d("/Cadence-Docs/search","7d9"),exact:!0},{path:"/Cadence-Docs/community",component:d("/Cadence-Docs/community","e90"),routes:[{path:"/Cadence-Docs/community",component:d("/Cadence-Docs/community","630"),routes:[{path:"/Cadence-Docs/community",component:d("/Cadence-Docs/community","852"),routes:[{path:"/Cadence-Docs/community/contributing",component:d("/Cadence-Docs/community/contributing","908"),exact:!0},{path:"/Cadence-Docs/community/resources",component:d("/Cadence-Docs/community/resources","2a0"),exact:!0},{path:"/Cadence-Docs/community/support",component:d("/Cadence-Docs/community/support","8a6"),exact:!0,sidebar:"community"},{path:"/Cadence-Docs/community/team",component:d("/Cadence-Docs/community/team","430"),exact:!0,sidebar:"community"}]}]}]},{path:"/Cadence-Docs/docs",component:d("/Cadence-Docs/docs","cbe"),routes:[{path:"/Cadence-Docs/docs",component:d("/Cadence-Docs/docs","651"),routes:[{path:"/Cadence-Docs/docs",component:d("/Cadence-Docs/docs","ae0"),routes:[{path:"/Cadence-Docs/docs/about",component:d("/Cadence-Docs/docs/about","a67"),exact:!0,sidebar:"docsSidebar"},{path:"/Cadence-Docs/docs/about/license",component:d("/Cadence-Docs/docs/about/license","eb7"),exact:!0,sidebar:"docsSidebar"},{path:"/Cadence-Docs/docs/cli",component:d("/Cadence-Docs/docs/cli","e8a"),exact:!0,sidebar:"docsSidebar"},{path:"/Cadence-Docs/docs/concepts",component:d("/Cadence-Docs/docs/concepts","957"),exact:!0,sidebar:"docsSidebar"},{path:"/Cadence-Docs/docs/concepts/activities",component:d("/Cadence-Docs/docs/concepts/activities","931"),exact:!0,sidebar:"docsSidebar"},{path:"/Cadence-Docs/docs/concepts/archival",component:d("/Cadence-Docs/docs/concepts/archival","0c8"),exact:!0,sidebar:"docsSidebar"},{path:"/Cadence-Docs/docs/concepts/cross-dc-replication",component:d("/Cadence-Docs/docs/concepts/cross-dc-replication","ac4"),exact:!0,sidebar:"docsSidebar"},{path:"/Cadence-Docs/docs/concepts/events",component:d("/Cadence-Docs/docs/concepts/events","853"),exact:!0,sidebar:"docsSidebar"},{path:"/Cadence-Docs/docs/concepts/http-api",component:d("/Cadence-Docs/docs/concepts/http-api","0df"),exact:!0,sidebar:"docsSidebar"},{path:"/Cadence-Docs/docs/concepts/queries",component:d("/Cadence-Docs/docs/concepts/queries","7a9"),exact:!0,sidebar:"docsSidebar"},{path:"/Cadence-Docs/docs/concepts/search-workflows",component:d("/Cadence-Docs/docs/concepts/search-workflows","1da"),exact:!0,sidebar:"docsSidebar"},{path:"/Cadence-Docs/docs/concepts/task-lists",component:d("/Cadence-Docs/docs/concepts/task-lists","e29"),exact:!0,sidebar:"docsSidebar"},{path:"/Cadence-Docs/docs/concepts/topology",component:d("/Cadence-Docs/docs/concepts/topology","fc5"),exact:!0,sidebar:"docsSidebar"},{path:"/Cadence-Docs/docs/concepts/workflows",component:d("/Cadence-Docs/docs/concepts/workflows","c85"),exact:!0},{path:"/Cadence-Docs/docs/get-started",component:d("/Cadence-Docs/docs/get-started","8a0"),exact:!0,sidebar:"docsSidebar"},{path:"/Cadence-Docs/docs/get-started/golang-hello-world",component:d("/Cadence-Docs/docs/get-started/golang-hello-world","629"),exact:!0,sidebar:"docsSidebar"},{path:"/Cadence-Docs/docs/get-started/java-hello-world",component:d("/Cadence-Docs/docs/get-started/java-hello-world","d67"),exact:!0,sidebar:"docsSidebar"},{path:"/Cadence-Docs/docs/get-started/server-installation",component:d("/Cadence-Docs/docs/get-started/server-installation","b6e"),exact:!0,sidebar:"docsSidebar"},{path:"/Cadence-Docs/docs/get-started/video-tutorials",component:d("/Cadence-Docs/docs/get-started/video-tutorials","880"),exact:!0,sidebar:"docsSidebar"},{path:"/Cadence-Docs/docs/glossary",component:d("/Cadence-Docs/docs/glossary","bdf"),exact:!0},{path:"/Cadence-Docs/docs/go-client",component:d("/Cadence-Docs/docs/go-client","b1e"),exact:!0,sidebar:"docsSidebar"},{path:"/Cadence-Docs/docs/go-client/02.5-starting-workflows",component:d("/Cadence-Docs/docs/go-client/02.5-starting-workflows","3bb"),exact:!0,sidebar:"docsSidebar"},{path:"/Cadence-Docs/docs/go-client/activities",component:d("/Cadence-Docs/docs/go-client/activities","914"),exact:!0,sidebar:"docsSidebar"},{path:"/Cadence-Docs/docs/go-client/activity-async-completion",component:d("/Cadence-Docs/docs/go-client/activity-async-completion","e7e"),exact:!0,sidebar:"docsSidebar"},{path:"/Cadence-Docs/docs/go-client/child-workflows",component:d("/Cadence-Docs/docs/go-client/child-workflows","53e"),exact:!0,sidebar:"docsSidebar"},{path:"/Cadence-Docs/docs/go-client/continue-as-new",component:d("/Cadence-Docs/docs/go-client/continue-as-new","e73"),exact:!0,sidebar:"docsSidebar"},{path:"/Cadence-Docs/docs/go-client/create-workflows",component:d("/Cadence-Docs/docs/go-client/create-workflows","650"),exact:!0,sidebar:"docsSidebar"},{path:"/Cadence-Docs/docs/go-client/distributed-cron",component:d("/Cadence-Docs/docs/go-client/distributed-cron","40b"),exact:!0,sidebar:"docsSidebar"},{path:"/Cadence-Docs/docs/go-client/error-handling",component:d("/Cadence-Docs/docs/go-client/error-handling","f2d"),exact:!0,sidebar:"docsSidebar"},{path:"/Cadence-Docs/docs/go-client/execute-activity",component:d("/Cadence-Docs/docs/go-client/execute-activity","897"),exact:!0,sidebar:"docsSidebar"},{path:"/Cadence-Docs/docs/go-client/queries",component:d("/Cadence-Docs/docs/go-client/queries","e99"),exact:!0,sidebar:"docsSidebar"},{path:"/Cadence-Docs/docs/go-client/retries",component:d("/Cadence-Docs/docs/go-client/retries","9e7"),exact:!0,sidebar:"docsSidebar"},{path:"/Cadence-Docs/docs/go-client/sessions",component:d("/Cadence-Docs/docs/go-client/sessions","676"),exact:!0,sidebar:"docsSidebar"},{path:"/Cadence-Docs/docs/go-client/side-effect",component:d("/Cadence-Docs/docs/go-client/side-effect","dd2"),exact:!0,sidebar:"docsSidebar"},{path:"/Cadence-Docs/docs/go-client/signals",component:d("/Cadence-Docs/docs/go-client/signals","8cf"),exact:!0,sidebar:"docsSidebar"},{path:"/Cadence-Docs/docs/go-client/tracing",component:d("/Cadence-Docs/docs/go-client/tracing","dc3"),exact:!0,sidebar:"docsSidebar"},{path:"/Cadence-Docs/docs/go-client/workers",component:d("/Cadence-Docs/docs/go-client/workers","847"),exact:!0,sidebar:"docsSidebar"},{path:"/Cadence-Docs/docs/go-client/workflow-non-deterministic-error",component:d("/Cadence-Docs/docs/go-client/workflow-non-deterministic-error","e67"),exact:!0},{path:"/Cadence-Docs/docs/go-client/workflow-replay-shadowing",component:d("/Cadence-Docs/docs/go-client/workflow-replay-shadowing","0e8"),exact:!0,sidebar:"docsSidebar"},{path:"/Cadence-Docs/docs/go-client/workflow-testing",component:d("/Cadence-Docs/docs/go-client/workflow-testing","a23"),exact:!0,sidebar:"docsSidebar"},{path:"/Cadence-Docs/docs/go-client/workflow-versioning",component:d("/Cadence-Docs/docs/go-client/workflow-versioning","c93"),exact:!0,sidebar:"docsSidebar"},{path:"/Cadence-Docs/docs/java-client",component:d("/Cadence-Docs/docs/java-client","0bb"),exact:!0,sidebar:"docsSidebar"},{path:"/Cadence-Docs/docs/java-client/activity-interface",component:d("/Cadence-Docs/docs/java-client/activity-interface","387"),exact:!0,sidebar:"docsSidebar"},{path:"/Cadence-Docs/docs/java-client/child-workflows",component:d("/Cadence-Docs/docs/java-client/child-workflows","a2c"),exact:!0,sidebar:"docsSidebar"},{path:"/Cadence-Docs/docs/java-client/client-overview",component:d("/Cadence-Docs/docs/java-client/client-overview","cb9"),exact:!0,sidebar:"docsSidebar"},{path:"/Cadence-Docs/docs/java-client/continue-as-new",component:d("/Cadence-Docs/docs/java-client/continue-as-new","a2e"),exact:!0,sidebar:"docsSidebar"},{path:"/Cadence-Docs/docs/java-client/distributed-cron",component:d("/Cadence-Docs/docs/java-client/distributed-cron","e20"),exact:!0,sidebar:"docsSidebar"},{path:"/Cadence-Docs/docs/java-client/exception-handling",component:d("/Cadence-Docs/docs/java-client/exception-handling","c21"),exact:!0,sidebar:"docsSidebar"},{path:"/Cadence-Docs/docs/java-client/implementing-activities",component:d("/Cadence-Docs/docs/java-client/implementing-activities","77e"),exact:!0},{path:"/Cadence-Docs/docs/java-client/implementing-workflows",component:d("/Cadence-Docs/docs/java-client/implementing-workflows","b50"),exact:!0,sidebar:"docsSidebar"},{path:"/Cadence-Docs/docs/java-client/queries",component:d("/Cadence-Docs/docs/java-client/queries","9e2"),exact:!0,sidebar:"docsSidebar"},{path:"/Cadence-Docs/docs/java-client/retries",component:d("/Cadence-Docs/docs/java-client/retries","ead"),exact:!0,sidebar:"docsSidebar"},{path:"/Cadence-Docs/docs/java-client/side-effect",component:d("/Cadence-Docs/docs/java-client/side-effect","89d"),exact:!0,sidebar:"docsSidebar"},{path:"/Cadence-Docs/docs/java-client/signals",component:d("/Cadence-Docs/docs/java-client/signals","855"),exact:!0,sidebar:"docsSidebar"},{path:"/Cadence-Docs/docs/java-client/starting-workflow-executions",component:d("/Cadence-Docs/docs/java-client/starting-workflow-executions","3e8"),exact:!0,sidebar:"docsSidebar"},{path:"/Cadence-Docs/docs/java-client/testing",component:d("/Cadence-Docs/docs/java-client/testing","a55"),exact:!0,sidebar:"docsSidebar"},{path:"/Cadence-Docs/docs/java-client/versioning",component:d("/Cadence-Docs/docs/java-client/versioning","2a1"),exact:!0,sidebar:"docsSidebar"},{path:"/Cadence-Docs/docs/java-client/workers",component:d("/Cadence-Docs/docs/java-client/workers","890"),exact:!0,sidebar:"docsSidebar"},{path:"/Cadence-Docs/docs/java-client/workflow-interface",component:d("/Cadence-Docs/docs/java-client/workflow-interface","25c"),exact:!0,sidebar:"docsSidebar"},{path:"/Cadence-Docs/docs/java-client/workflow-replay-shadowing",component:d("/Cadence-Docs/docs/java-client/workflow-replay-shadowing","991"),exact:!0,sidebar:"docsSidebar"},{path:"/Cadence-Docs/docs/operation-guide",component:d("/Cadence-Docs/docs/operation-guide","1be"),exact:!0,sidebar:"docsSidebar"},{path:"/Cadence-Docs/docs/operation-guide/maintain",component:d("/Cadence-Docs/docs/operation-guide/maintain","7a3"),exact:!0,sidebar:"docsSidebar"},{path:"/Cadence-Docs/docs/operation-guide/migration",component:d("/Cadence-Docs/docs/operation-guide/migration","a51"),exact:!0,sidebar:"docsSidebar"},{path:"/Cadence-Docs/docs/operation-guide/monitoring",component:d("/Cadence-Docs/docs/operation-guide/monitoring","ede"),exact:!0,sidebar:"docsSidebar"},{path:"/Cadence-Docs/docs/operation-guide/setup",component:d("/Cadence-Docs/docs/operation-guide/setup","b7f"),exact:!0,sidebar:"docsSidebar"},{path:"/Cadence-Docs/docs/operation-guide/troubleshooting",component:d("/Cadence-Docs/docs/operation-guide/troubleshooting","116"),exact:!0,sidebar:"docsSidebar"},{path:"/Cadence-Docs/docs/use-cases",component:d("/Cadence-Docs/docs/use-cases","109"),exact:!0,sidebar:"docsSidebar"},{path:"/Cadence-Docs/docs/use-cases/batch-job",component:d("/Cadence-Docs/docs/use-cases/batch-job","476"),exact:!0,sidebar:"docsSidebar"},{path:"/Cadence-Docs/docs/use-cases/big-ml",component:d("/Cadence-Docs/docs/use-cases/big-ml","d56"),exact:!0,sidebar:"docsSidebar"},{path:"/Cadence-Docs/docs/use-cases/deployment",component:d("/Cadence-Docs/docs/use-cases/deployment","c39"),exact:!0,sidebar:"docsSidebar"},{path:"/Cadence-Docs/docs/use-cases/dsl",component:d("/Cadence-Docs/docs/use-cases/dsl","c1b"),exact:!0,sidebar:"docsSidebar"},{path:"/Cadence-Docs/docs/use-cases/event-driven",component:d("/Cadence-Docs/docs/use-cases/event-driven","99c"),exact:!0,sidebar:"docsSidebar"},{path:"/Cadence-Docs/docs/use-cases/interactive",component:d("/Cadence-Docs/docs/use-cases/interactive","a3f"),exact:!0,sidebar:"docsSidebar"},{path:"/Cadence-Docs/docs/use-cases/operational-management",component:d("/Cadence-Docs/docs/use-cases/operational-management","7f7"),exact:!0,sidebar:"docsSidebar"},{path:"/Cadence-Docs/docs/use-cases/orchestration",component:d("/Cadence-Docs/docs/use-cases/orchestration","64a"),exact:!0,sidebar:"docsSidebar"},{path:"/Cadence-Docs/docs/use-cases/partitioned-scan",component:d("/Cadence-Docs/docs/use-cases/partitioned-scan","f35"),exact:!0,sidebar:"docsSidebar"},{path:"/Cadence-Docs/docs/use-cases/periodic-execution",component:d("/Cadence-Docs/docs/use-cases/periodic-execution","a11"),exact:!0,sidebar:"docsSidebar"},{path:"/Cadence-Docs/docs/use-cases/polling",component:d("/Cadence-Docs/docs/use-cases/polling","a3c"),exact:!0,sidebar:"docsSidebar"},{path:"/Cadence-Docs/docs/use-cases/provisioning",component:d("/Cadence-Docs/docs/use-cases/provisioning","42e"),exact:!0,sidebar:"docsSidebar"},{path:"/Cadence-Docs/docs/workflow-troubleshooting",component:d("/Cadence-Docs/docs/workflow-troubleshooting","646"),exact:!0,sidebar:"docsSidebar"},{path:"/Cadence-Docs/docs/workflow-troubleshooting/activity-failures",component:d("/Cadence-Docs/docs/workflow-troubleshooting/activity-failures","d42"),exact:!0,sidebar:"docsSidebar"},{path:"/Cadence-Docs/docs/workflow-troubleshooting/retries",component:d("/Cadence-Docs/docs/workflow-troubleshooting/retries","c08"),exact:!0,sidebar:"docsSidebar"},{path:"/Cadence-Docs/docs/workflow-troubleshooting/timeouts",component:d("/Cadence-Docs/docs/workflow-troubleshooting/timeouts","371"),exact:!0,sidebar:"docsSidebar"}]}]}]},{path:"/Cadence-Docs/",component:d("/Cadence-Docs/","9d2"),exact:!0},{path:"*",component:d("*")}]},6125:(e,t,n)=>{"use strict";n.d(t,{o:()=>a,x:()=>i});var r=n(6540),o=n(4848);const a=r.createContext(!1);function i(e){let{children:t}=e;const[n,i]=(0,r.useState)(!1);return(0,r.useEffect)((()=>{i(!0)}),[]),(0,o.jsx)(a.Provider,{value:n,children:t})}},8536:(e,t,n)=>{"use strict";var r=n(6540),o=n(5338),a=n(545),i=n(4625),c=n(4784),s=n(8193);const l=[n(1911),n(119),n(6491),n(6294),n(1043)];var u=n(8328),d=n(6347),p=n(2831),f=n(4848);function m(e){let{children:t}=e;return(0,f.jsx)(f.Fragment,{children:t})}var g=n(5260),h=n(4586),b=n(6025),y=n(6342),v=n(5500),w=n(2131),S=n(4090),k=n(2967),x=n(440),_=n(1463);function C(){const{i18n:{currentLocale:e,defaultLocale:t,localeConfigs:n}}=(0,h.A)(),r=(0,w.o)(),o=n[e].htmlLang,a=e=>e.replace("-","_");return(0,f.jsxs)(g.A,{children:[Object.entries(n).map((e=>{let[t,{htmlLang:n}]=e;return(0,f.jsx)("link",{rel:"alternate",href:r.createUrl({locale:t,fullyQualified:!0}),hrefLang:n},t)})),(0,f.jsx)("link",{rel:"alternate",href:r.createUrl({locale:t,fullyQualified:!0}),hrefLang:"x-default"}),(0,f.jsx)("meta",{property:"og:locale",content:a(o)}),Object.values(n).filter((e=>o!==e.htmlLang)).map((e=>(0,f.jsx)("meta",{property:"og:locale:alternate",content:a(e.htmlLang)},`meta-og-${e.htmlLang}`)))]})}function E(e){let{permalink:t}=e;const{siteConfig:{url:n}}=(0,h.A)(),r=function(){const{siteConfig:{url:e,baseUrl:t,trailingSlash:n}}=(0,h.A)(),{pathname:r}=(0,d.zy)();return e+(0,x.Ks)((0,b.Ay)(r),{trailingSlash:n,baseUrl:t})}(),o=t?`${n}${t}`:r;return(0,f.jsxs)(g.A,{children:[(0,f.jsx)("meta",{property:"og:url",content:o}),(0,f.jsx)("link",{rel:"canonical",href:o})]})}function D(){const{i18n:{currentLocale:e}}=(0,h.A)(),{metadata:t,image:n}=(0,y.p)();return(0,f.jsxs)(f.Fragment,{children:[(0,f.jsxs)(g.A,{children:[(0,f.jsx)("meta",{name:"twitter:card",content:"summary_large_image"}),(0,f.jsx)("body",{className:S.w})]}),n&&(0,f.jsx)(v.be,{image:n}),(0,f.jsx)(E,{}),(0,f.jsx)(C,{}),(0,f.jsx)(_.A,{tag:k.C,locale:e}),(0,f.jsx)(g.A,{children:t.map(((e,t)=>(0,f.jsx)("meta",{...e},t)))})]})}const j=new Map;var O=n(6125),A=n(6988),T=n(205);function P(e){for(var t=arguments.length,n=new Array(t>1?t-1:0),r=1;r<t;r++)n[r-1]=arguments[r];const o=l.map((t=>{const r=t.default?.[e]??t[e];return r?.(...n)}));return()=>o.forEach((e=>e?.()))}const I=function(e){let{children:t,location:n,previousLocation:r}=e;return(0,T.A)((()=>{r!==n&&(!function(e){let{location:t,previousLocation:n}=e;if(!n)return;const r=t.pathname===n.pathname,o=t.hash===n.hash,a=t.search===n.search;if(r&&o&&!a)return;const{hash:i}=t;if(i){const e=decodeURIComponent(i.substring(1)),t=document.getElementById(e);t?.scrollIntoView()}else window.scrollTo(0,0)}({location:n,previousLocation:r}),P("onRouteDidUpdate",{previousLocation:r,location:n}))}),[r,n]),t};function N(e){const t=Array.from(new Set([e,decodeURI(e)])).map((e=>(0,p.u)(u.A,e))).flat();return Promise.all(t.map((e=>e.route.component.preload?.())))}class R extends r.Component{previousLocation;routeUpdateCleanupCb;constructor(e){super(e),this.previousLocation=null,this.routeUpdateCleanupCb=s.A.canUseDOM?P("onRouteUpdate",{previousLocation:null,location:this.props.location}):()=>{},this.state={nextRouteHasLoaded:!0}}shouldComponentUpdate(e,t){if(e.location===this.props.location)return t.nextRouteHasLoaded;const n=e.location;return this.previousLocation=this.props.location,this.setState({nextRouteHasLoaded:!1}),this.routeUpdateCleanupCb=P("onRouteUpdate",{previousLocation:this.previousLocation,location:n}),N(n.pathname).then((()=>{this.routeUpdateCleanupCb(),this.setState({nextRouteHasLoaded:!0})})).catch((e=>{console.warn(e),window.location.reload()})),!1}render(){const{children:e,location:t}=this.props;return(0,f.jsx)(I,{previousLocation:this.previousLocation,location:t,children:(0,f.jsx)(d.qh,{location:t,render:()=>e})})}}const L=R,M="__docusaurus-base-url-issue-banner-suggestion-container";function F(e){return`\ndocument.addEventListener('DOMContentLoaded', function maybeInsertBanner() {\n var shouldInsert = typeof window['docusaurus'] === 'undefined';\n shouldInsert && insertBanner();\n});\n\nfunction insertBanner() {\n var bannerContainer = document.createElement('div');\n bannerContainer.id = '__docusaurus-base-url-issue-banner-container';\n var bannerHtml = ${JSON.stringify(function(e){return`\n<div id="__docusaurus-base-url-issue-banner" style="border: thick solid red; background-color: rgb(255, 230, 179); margin: 20px; padding: 20px; font-size: 20px;">\n <p style="font-weight: bold; font-size: 30px;">Your Docusaurus site did not load properly.</p>\n <p>A very common reason is a wrong site <a href="https://docusaurus.io/docs/docusaurus.config.js/#baseUrl" style="font-weight: bold;">baseUrl configuration</a>.</p>\n <p>Current configured baseUrl = <span style="font-weight: bold; color: red;">${e}</span> ${"/"===e?" (default value)":""}</p>\n <p>We suggest trying baseUrl = <span id="${M}" style="font-weight: bold; color: green;"></span></p>\n</div>\n`}(e)).replace(/</g,"\\<")};\n bannerContainer.innerHTML = bannerHtml;\n document.body.prepend(bannerContainer);\n var suggestionContainer = document.getElementById('${M}');\n var actualHomePagePath = window.location.pathname;\n var suggestedBaseUrl = actualHomePagePath.substr(-1) === '/'\n ? actualHomePagePath\n : actualHomePagePath + '/';\n suggestionContainer.innerHTML = suggestedBaseUrl;\n}\n`}function B(){const{siteConfig:{baseUrl:e}}=(0,h.A)();return(0,f.jsx)(f.Fragment,{children:!s.A.canUseDOM&&(0,f.jsx)(g.A,{children:(0,f.jsx)("script",{children:F(e)})})})}function z(){const{siteConfig:{baseUrl:e,baseUrlIssueBanner:t}}=(0,h.A)(),{pathname:n}=(0,d.zy)();return t&&n===e?(0,f.jsx)(B,{}):null}function $(){const{siteConfig:{favicon:e,title:t,noIndex:n},i18n:{currentLocale:r,localeConfigs:o}}=(0,h.A)(),a=(0,b.Ay)(e),{htmlLang:i,direction:c}=o[r];return(0,f.jsxs)(g.A,{children:[(0,f.jsx)("html",{lang:i,dir:c}),(0,f.jsx)("title",{children:t}),(0,f.jsx)("meta",{property:"og:title",content:t}),(0,f.jsx)("meta",{name:"viewport",content:"width=device-width, initial-scale=1.0"}),n&&(0,f.jsx)("meta",{name:"robots",content:"noindex, nofollow"}),e&&(0,f.jsx)("link",{rel:"icon",href:a})]})}var U=n(7489),H=n(2303);function q(){const e=(0,H.A)();return(0,f.jsx)(g.A,{children:(0,f.jsx)("html",{"data-has-hydrated":e})})}const V=(0,p.v)(u.A);function W(){const e=function(e){if(j.has(e.pathname))return{...e,pathname:j.get(e.pathname)};if((0,p.u)(u.A,e.pathname).some((e=>{let{route:t}=e;return!0===t.exact})))return j.set(e.pathname,e.pathname),e;const t=e.pathname.trim().replace(/(?:\/index)?\.html$/,"")||"/";return j.set(e.pathname,t),{...e,pathname:t}}((0,d.zy)());return(0,f.jsx)(L,{location:e,children:V})}function G(){return(0,f.jsx)(U.A,{children:(0,f.jsx)(A.l,{children:(0,f.jsxs)(O.x,{children:[(0,f.jsxs)(m,{children:[(0,f.jsx)($,{}),(0,f.jsx)(D,{}),(0,f.jsx)(z,{}),(0,f.jsx)(W,{})]}),(0,f.jsx)(q,{})]})})})}var K=n(4054);const Y=function(e){try{return document.createElement("link").relList.supports(e)}catch{return!1}}("prefetch")?function(e){return new Promise(((t,n)=>{if("undefined"==typeof document)return void n();const r=document.createElement("link");r.setAttribute("rel","prefetch"),r.setAttribute("href",e),r.onload=()=>t(),r.onerror=()=>n();const o=document.getElementsByTagName("head")[0]??document.getElementsByName("script")[0]?.parentNode;o?.appendChild(r)}))}:function(e){return new Promise(((t,n)=>{const r=new XMLHttpRequest;r.open("GET",e,!0),r.withCredentials=!0,r.onload=()=>{200===r.status?t():n()},r.send(null)}))};var Q=n(6921);const Z=new Set,X=new Set,J=()=>navigator.connection?.effectiveType.includes("2g")||navigator.connection?.saveData,ee={prefetch:e=>{if(!(e=>!J()&&!X.has(e)&&!Z.has(e))(e))return!1;Z.add(e);const t=(0,p.u)(u.A,e).flatMap((e=>{return t=e.route.path,Object.entries(K).filter((e=>{let[n]=e;return n.replace(/-[^-]+$/,"")===t})).flatMap((e=>{let[,t]=e;return Object.values((0,Q.A)(t))}));var t}));return Promise.all(t.map((e=>{const t=n.gca(e);return t&&!t.includes("undefined")?Y(t).catch((()=>{})):Promise.resolve()})))},preload:e=>!!(e=>!J()&&!X.has(e))(e)&&(X.add(e),N(e))},te=Object.freeze(ee);function ne(e){let{children:t}=e;return"hash"===c.default.future.experimental_router?(0,f.jsx)(i.I9,{children:t}):(0,f.jsx)(i.Kd,{children:t})}const re=Boolean(!0);if(s.A.canUseDOM){window.docusaurus=te;const e=document.getElementById("__docusaurus"),t=(0,f.jsx)(a.vd,{children:(0,f.jsx)(ne,{children:(0,f.jsx)(G,{})})}),n=(e,t)=>{console.error("Docusaurus React Root onRecoverableError:",e,t)},i=()=>{if(window.docusaurusRoot)window.docusaurusRoot.render(t);else if(re)window.docusaurusRoot=o.hydrateRoot(e,t,{onRecoverableError:n});else{const r=o.createRoot(e,{onRecoverableError:n});r.render(t),window.docusaurusRoot=r}};N(window.location.pathname).then((()=>{(0,r.startTransition)(i)}))}},6988:(e,t,n)=>{"use strict";n.d(t,{o:()=>d,l:()=>p});var r=n(6540),o=n(4784);const a=JSON.parse('{"docusaurus-plugin-content-docs":{"default":{"path":"/Cadence-Docs/docs","versions":[{"name":"current","label":"Next","isLast":true,"path":"/Cadence-Docs/docs","mainDocId":"get-started/index","docs":[{"id":"about/index","path":"/Cadence-Docs/docs/about/","sidebar":"docsSidebar"},{"id":"about/license","path":"/Cadence-Docs/docs/about/license","sidebar":"docsSidebar"},{"id":"cli/index","path":"/Cadence-Docs/docs/cli/","sidebar":"docsSidebar"},{"id":"concepts/activities","path":"/Cadence-Docs/docs/concepts/activities","sidebar":"docsSidebar"},{"id":"concepts/archival","path":"/Cadence-Docs/docs/concepts/archival","sidebar":"docsSidebar"},{"id":"concepts/cross-dc-replication","path":"/Cadence-Docs/docs/concepts/cross-dc-replication","sidebar":"docsSidebar"},{"id":"concepts/events","path":"/Cadence-Docs/docs/concepts/events","sidebar":"docsSidebar"},{"id":"concepts/http-api","path":"/Cadence-Docs/docs/concepts/http-api","sidebar":"docsSidebar"},{"id":"concepts/index","path":"/Cadence-Docs/docs/concepts/","sidebar":"docsSidebar"},{"id":"concepts/queries","path":"/Cadence-Docs/docs/concepts/queries","sidebar":"docsSidebar"},{"id":"concepts/search-workflows","path":"/Cadence-Docs/docs/concepts/search-workflows","sidebar":"docsSidebar"},{"id":"concepts/task-lists","path":"/Cadence-Docs/docs/concepts/task-lists","sidebar":"docsSidebar"},{"id":"concepts/topology","path":"/Cadence-Docs/docs/concepts/topology","sidebar":"docsSidebar"},{"id":"concepts/workflows","path":"/Cadence-Docs/docs/concepts/workflows"},{"id":"get-started/golang-hello-world","path":"/Cadence-Docs/docs/get-started/golang-hello-world","sidebar":"docsSidebar"},{"id":"get-started/index","path":"/Cadence-Docs/docs/get-started/","sidebar":"docsSidebar"},{"id":"get-started/java-hello-world","path":"/Cadence-Docs/docs/get-started/java-hello-world","sidebar":"docsSidebar"},{"id":"get-started/server-installation","path":"/Cadence-Docs/docs/get-started/server-installation","sidebar":"docsSidebar"},{"id":"get-started/video-tutorials","path":"/Cadence-Docs/docs/get-started/video-tutorials","sidebar":"docsSidebar"},{"id":"glossary","path":"/Cadence-Docs/docs/glossary"},{"id":"go-client/02.5-starting-workflows","path":"/Cadence-Docs/docs/go-client/02.5-starting-workflows","sidebar":"docsSidebar"},{"id":"go-client/activities","path":"/Cadence-Docs/docs/go-client/activities","sidebar":"docsSidebar"},{"id":"go-client/activity-async-completion","path":"/Cadence-Docs/docs/go-client/activity-async-completion","sidebar":"docsSidebar"},{"id":"go-client/child-workflows","path":"/Cadence-Docs/docs/go-client/child-workflows","sidebar":"docsSidebar"},{"id":"go-client/continue-as-new","path":"/Cadence-Docs/docs/go-client/continue-as-new","sidebar":"docsSidebar"},{"id":"go-client/create-workflows","path":"/Cadence-Docs/docs/go-client/create-workflows","sidebar":"docsSidebar"},{"id":"go-client/distributed-cron","path":"/Cadence-Docs/docs/go-client/distributed-cron","sidebar":"docsSidebar"},{"id":"go-client/error-handling","path":"/Cadence-Docs/docs/go-client/error-handling","sidebar":"docsSidebar"},{"id":"go-client/execute-activity","path":"/Cadence-Docs/docs/go-client/execute-activity","sidebar":"docsSidebar"},{"id":"go-client/index","path":"/Cadence-Docs/docs/go-client/","sidebar":"docsSidebar"},{"id":"go-client/queries","path":"/Cadence-Docs/docs/go-client/queries","sidebar":"docsSidebar"},{"id":"go-client/retries","path":"/Cadence-Docs/docs/go-client/retries","sidebar":"docsSidebar"},{"id":"go-client/sessions","path":"/Cadence-Docs/docs/go-client/sessions","sidebar":"docsSidebar"},{"id":"go-client/side-effect","path":"/Cadence-Docs/docs/go-client/side-effect","sidebar":"docsSidebar"},{"id":"go-client/signals","path":"/Cadence-Docs/docs/go-client/signals","sidebar":"docsSidebar"},{"id":"go-client/tracing","path":"/Cadence-Docs/docs/go-client/tracing","sidebar":"docsSidebar"},{"id":"go-client/workers","path":"/Cadence-Docs/docs/go-client/workers","sidebar":"docsSidebar"},{"id":"go-client/workflow-non-deterministic-error","path":"/Cadence-Docs/docs/go-client/workflow-non-deterministic-error"},{"id":"go-client/workflow-replay-shadowing","path":"/Cadence-Docs/docs/go-client/workflow-replay-shadowing","sidebar":"docsSidebar"},{"id":"go-client/workflow-testing","path":"/Cadence-Docs/docs/go-client/workflow-testing","sidebar":"docsSidebar"},{"id":"go-client/workflow-versioning","path":"/Cadence-Docs/docs/go-client/workflow-versioning","sidebar":"docsSidebar"},{"id":"java-client/activity-interface","path":"/Cadence-Docs/docs/java-client/activity-interface","sidebar":"docsSidebar"},{"id":"java-client/child-workflows","path":"/Cadence-Docs/docs/java-client/child-workflows","sidebar":"docsSidebar"},{"id":"java-client/client-overview","path":"/Cadence-Docs/docs/java-client/client-overview","sidebar":"docsSidebar"},{"id":"java-client/continue-as-new","path":"/Cadence-Docs/docs/java-client/continue-as-new","sidebar":"docsSidebar"},{"id":"java-client/distributed-cron","path":"/Cadence-Docs/docs/java-client/distributed-cron","sidebar":"docsSidebar"},{"id":"java-client/exception-handling","path":"/Cadence-Docs/docs/java-client/exception-handling","sidebar":"docsSidebar"},{"id":"java-client/implementing-activities","path":"/Cadence-Docs/docs/java-client/implementing-activities"},{"id":"java-client/implementing-workflows","path":"/Cadence-Docs/docs/java-client/implementing-workflows","sidebar":"docsSidebar"},{"id":"java-client/index","path":"/Cadence-Docs/docs/java-client/","sidebar":"docsSidebar"},{"id":"java-client/queries","path":"/Cadence-Docs/docs/java-client/queries","sidebar":"docsSidebar"},{"id":"java-client/retries","path":"/Cadence-Docs/docs/java-client/retries","sidebar":"docsSidebar"},{"id":"java-client/side-effect","path":"/Cadence-Docs/docs/java-client/side-effect","sidebar":"docsSidebar"},{"id":"java-client/signals","path":"/Cadence-Docs/docs/java-client/signals","sidebar":"docsSidebar"},{"id":"java-client/starting-workflow-executions","path":"/Cadence-Docs/docs/java-client/starting-workflow-executions","sidebar":"docsSidebar"},{"id":"java-client/testing","path":"/Cadence-Docs/docs/java-client/testing","sidebar":"docsSidebar"},{"id":"java-client/versioning","path":"/Cadence-Docs/docs/java-client/versioning","sidebar":"docsSidebar"},{"id":"java-client/workers","path":"/Cadence-Docs/docs/java-client/workers","sidebar":"docsSidebar"},{"id":"java-client/workflow-interface","path":"/Cadence-Docs/docs/java-client/workflow-interface","sidebar":"docsSidebar"},{"id":"java-client/workflow-replay-shadowing","path":"/Cadence-Docs/docs/java-client/workflow-replay-shadowing","sidebar":"docsSidebar"},{"id":"operation-guide/index","path":"/Cadence-Docs/docs/operation-guide/","sidebar":"docsSidebar"},{"id":"operation-guide/maintain","path":"/Cadence-Docs/docs/operation-guide/maintain","sidebar":"docsSidebar"},{"id":"operation-guide/migration","path":"/Cadence-Docs/docs/operation-guide/migration","sidebar":"docsSidebar"},{"id":"operation-guide/monitoring","path":"/Cadence-Docs/docs/operation-guide/monitoring","sidebar":"docsSidebar"},{"id":"operation-guide/setup","path":"/Cadence-Docs/docs/operation-guide/setup","sidebar":"docsSidebar"},{"id":"operation-guide/troubleshooting","path":"/Cadence-Docs/docs/operation-guide/troubleshooting","sidebar":"docsSidebar"},{"id":"use-cases/batch-job","path":"/Cadence-Docs/docs/use-cases/batch-job","sidebar":"docsSidebar"},{"id":"use-cases/big-ml","path":"/Cadence-Docs/docs/use-cases/big-ml","sidebar":"docsSidebar"},{"id":"use-cases/deployment","path":"/Cadence-Docs/docs/use-cases/deployment","sidebar":"docsSidebar"},{"id":"use-cases/dsl","path":"/Cadence-Docs/docs/use-cases/dsl","sidebar":"docsSidebar"},{"id":"use-cases/event-driven","path":"/Cadence-Docs/docs/use-cases/event-driven","sidebar":"docsSidebar"},{"id":"use-cases/index","path":"/Cadence-Docs/docs/use-cases/","sidebar":"docsSidebar"},{"id":"use-cases/interactive","path":"/Cadence-Docs/docs/use-cases/interactive","sidebar":"docsSidebar"},{"id":"use-cases/operational-management","path":"/Cadence-Docs/docs/use-cases/operational-management","sidebar":"docsSidebar"},{"id":"use-cases/orchestration","path":"/Cadence-Docs/docs/use-cases/orchestration","sidebar":"docsSidebar"},{"id":"use-cases/partitioned-scan","path":"/Cadence-Docs/docs/use-cases/partitioned-scan","sidebar":"docsSidebar"},{"id":"use-cases/periodic-execution","path":"/Cadence-Docs/docs/use-cases/periodic-execution","sidebar":"docsSidebar"},{"id":"use-cases/polling","path":"/Cadence-Docs/docs/use-cases/polling","sidebar":"docsSidebar"},{"id":"use-cases/provisioning","path":"/Cadence-Docs/docs/use-cases/provisioning","sidebar":"docsSidebar"},{"id":"workflow-troubleshooting/activity-failures","path":"/Cadence-Docs/docs/workflow-troubleshooting/activity-failures","sidebar":"docsSidebar"},{"id":"workflow-troubleshooting/index","path":"/Cadence-Docs/docs/workflow-troubleshooting/","sidebar":"docsSidebar"},{"id":"workflow-troubleshooting/retries","path":"/Cadence-Docs/docs/workflow-troubleshooting/retries","sidebar":"docsSidebar"},{"id":"workflow-troubleshooting/timeouts","path":"/Cadence-Docs/docs/workflow-troubleshooting/timeouts","sidebar":"docsSidebar"}],"draftIds":[],"sidebars":{"docsSidebar":{"link":{"path":"/Cadence-Docs/docs/get-started/","label":"get-started/index"}}}}],"breadcrumbs":true},"community":{"path":"/Cadence-Docs/community","versions":[{"name":"current","label":"Next","isLast":true,"path":"/Cadence-Docs/community","mainDocId":"support","docs":[{"id":"contributing","path":"/Cadence-Docs/community/contributing"},{"id":"resources","path":"/Cadence-Docs/community/resources"},{"id":"support","path":"/Cadence-Docs/community/support","sidebar":"community"},{"id":"team","path":"/Cadence-Docs/community/team","sidebar":"community"}],"draftIds":[],"sidebars":{"community":{"link":{"path":"/Cadence-Docs/community/support","label":"support"}}}}],"breadcrumbs":true}},"docusaurus-plugin-google-gtag":{"default":{"trackingID":["G-W63QD8QE6E"],"anonymizeIP":true,"id":"default"}},"docusaurus-plugin-google-tag-manager":{"default":{"containerId":"G-W63QD8QE6E","id":"default"}}}'),i=JSON.parse('{"defaultLocale":"en","locales":["en"],"path":"i18n","currentLocale":"en","localeConfigs":{"en":{"label":"English","direction":"ltr","htmlLang":"en","calendar":"gregory","path":"en"}}}');var c=n(2654);const s=JSON.parse('{"docusaurusVersion":"3.6.3","siteVersion":"1.0.0","pluginVersions":{"docusaurus-plugin-content-docs":{"type":"package","name":"@docusaurus/plugin-content-docs","version":"3.6.3"},"docusaurus-plugin-content-blog":{"type":"package","name":"@docusaurus/plugin-content-blog","version":"3.6.3"},"docusaurus-plugin-content-pages":{"type":"package","name":"@docusaurus/plugin-content-pages","version":"3.6.3"},"docusaurus-plugin-google-gtag":{"type":"package","name":"@docusaurus/plugin-google-gtag","version":"3.6.3"},"docusaurus-plugin-google-tag-manager":{"type":"package","name":"@docusaurus/plugin-google-tag-manager","version":"3.6.3"},"docusaurus-plugin-sitemap":{"type":"package","name":"@docusaurus/plugin-sitemap","version":"3.6.3"},"docusaurus-theme-classic":{"type":"package","name":"@docusaurus/theme-classic","version":"3.6.3"},"docusaurus-theme-search-algolia":{"type":"package","name":"@docusaurus/theme-search-algolia","version":"3.6.3"},"changelog-plugin":{"type":"project"},"docusaurus-plugin-client-redirects":{"type":"package","name":"@docusaurus/plugin-client-redirects","version":"3.6.3"}}}');var l=n(4848);const u={siteConfig:o.default,siteMetadata:s,globalData:a,i18n:i,codeTranslations:c},d=r.createContext(u);function p(e){let{children:t}=e;return(0,l.jsx)(d.Provider,{value:u,children:t})}},7489:(e,t,n)=>{"use strict";n.d(t,{A:()=>g});var r=n(6540),o=n(8193),a=n(5260),i=n(440),c=n(1957),s=n(3102),l=n(4848);function u(e){let{error:t,tryAgain:n}=e;return(0,l.jsxs)("div",{style:{display:"flex",flexDirection:"column",justifyContent:"center",alignItems:"flex-start",minHeight:"100vh",width:"100%",maxWidth:"80ch",fontSize:"20px",margin:"0 auto",padding:"1rem"},children:[(0,l.jsx)("h1",{style:{fontSize:"3rem"},children:"This page crashed"}),(0,l.jsx)("button",{type:"button",onClick:n,style:{margin:"1rem 0",fontSize:"2rem",cursor:"pointer",borderRadius:20,padding:"1rem"},children:"Try again"}),(0,l.jsx)(d,{error:t})]})}function d(e){let{error:t}=e;const n=(0,i.rA)(t).map((e=>e.message)).join("\n\nCause:\n");return(0,l.jsx)("p",{style:{whiteSpace:"pre-wrap"},children:n})}function p(e){let{children:t}=e;return(0,l.jsx)(s.W,{value:{plugin:{name:"docusaurus-core-error-boundary",id:"default"}},children:t})}function f(e){let{error:t,tryAgain:n}=e;return(0,l.jsx)(p,{children:(0,l.jsxs)(g,{fallback:()=>(0,l.jsx)(u,{error:t,tryAgain:n}),children:[(0,l.jsx)(a.A,{children:(0,l.jsx)("title",{children:"Page Error"})}),(0,l.jsx)(c.A,{children:(0,l.jsx)(u,{error:t,tryAgain:n})})]})})}const m=e=>(0,l.jsx)(f,{...e});class g extends r.Component{constructor(e){super(e),this.state={error:null}}componentDidCatch(e){o.A.canUseDOM&&this.setState({error:e})}render(){const{children:e}=this.props,{error:t}=this.state;if(t){const e={error:t,tryAgain:()=>this.setState({error:null})};return(this.props.fallback??m)(e)}return e??null}}},8193:(e,t,n)=>{"use strict";n.d(t,{A:()=>o});const r="undefined"!=typeof window&&"document"in window&&"createElement"in window.document,o={canUseDOM:r,canUseEventListeners:r&&("addEventListener"in window||"attachEvent"in window),canUseIntersectionObserver:r&&"IntersectionObserver"in window,canUseViewport:r&&"screen"in window}},5260:(e,t,n)=>{"use strict";n.d(t,{A:()=>a});n(6540);var r=n(545),o=n(4848);function a(e){return(0,o.jsx)(r.mg,{...e})}},8774:(e,t,n)=>{"use strict";n.d(t,{A:()=>f});var r=n(6540),o=n(4625),a=n(440),i=n(4586),c=n(6654),s=n(8193),l=n(3427),u=n(6025),d=n(4848);function p(e,t){let{isNavLink:n,to:p,href:f,activeClassName:m,isActive:g,"data-noBrokenLinkCheck":h,autoAddBaseUrl:b=!0,...y}=e;const{siteConfig:v}=(0,i.A)(),{trailingSlash:w,baseUrl:S}=v,k=v.future.experimental_router,{withBaseUrl:x}=(0,u.hH)(),_=(0,l.A)(),C=(0,r.useRef)(null);(0,r.useImperativeHandle)(t,(()=>C.current));const E=p||f;const D=(0,c.A)(E),j=E?.replace("pathname://","");let O=void 0!==j?(A=j,b&&(e=>e.startsWith("/"))(A)?x(A):A):void 0;var A;"hash"===k&&O?.startsWith("./")&&(O=O?.slice(1)),O&&D&&(O=(0,a.Ks)(O,{trailingSlash:w,baseUrl:S}));const T=(0,r.useRef)(!1),P=n?o.k2:o.N_,I=s.A.canUseIntersectionObserver,N=(0,r.useRef)(),R=()=>{T.current||null==O||(window.docusaurus.preload(O),T.current=!0)};(0,r.useEffect)((()=>(!I&&D&&s.A.canUseDOM&&null!=O&&window.docusaurus.prefetch(O),()=>{I&&N.current&&N.current.disconnect()})),[N,O,I,D]);const L=O?.startsWith("#")??!1,M=!y.target||"_self"===y.target,F=!O||!D||!M||L&&"hash"!==k;h||!L&&F||_.collectLink(O),y.id&&_.collectAnchor(y.id);const B={};return F?(0,d.jsx)("a",{ref:C,href:O,...E&&!D&&{target:"_blank",rel:"noopener noreferrer"},...y,...B}):(0,d.jsx)(P,{...y,onMouseEnter:R,onTouchStart:R,innerRef:e=>{C.current=e,I&&e&&D&&(N.current=new window.IntersectionObserver((t=>{t.forEach((t=>{e===t.target&&(t.isIntersecting||t.intersectionRatio>0)&&(N.current.unobserve(e),N.current.disconnect(),null!=O&&window.docusaurus.prefetch(O))}))})),N.current.observe(e))},to:O,...n&&{isActive:g,activeClassName:m},...B})}const f=r.forwardRef(p)},1312:(e,t,n)=>{"use strict";n.d(t,{A:()=>l,T:()=>s});var r=n(6540),o=n(4848);function a(e,t){const n=e.split(/(\{\w+\})/).map(((e,n)=>{if(n%2==1){const n=t?.[e.slice(1,-1)];if(void 0!==n)return n}return e}));return n.some((e=>(0,r.isValidElement)(e)))?n.map(((e,t)=>(0,r.isValidElement)(e)?r.cloneElement(e,{key:t}):e)).filter((e=>""!==e)):n.join("")}var i=n(2654);function c(e){let{id:t,message:n}=e;if(void 0===t&&void 0===n)throw new Error("Docusaurus translation declarations must have at least a translation id or a default translation message");return i[t??n]??n??t}function s(e,t){let{message:n,id:r}=e;return a(c({message:n,id:r}),t)}function l(e){let{children:t,id:n,values:r}=e;if(t&&"string"!=typeof t)throw console.warn("Illegal <Translate> children",t),new Error("The Docusaurus <Translate> component only accept simple string values");const i=c({message:t,id:n});return(0,o.jsx)(o.Fragment,{children:a(i,r)})}},7065:(e,t,n)=>{"use strict";n.d(t,{W:()=>r});const r="default"},6654:(e,t,n)=>{"use strict";function r(e){return/^(?:\w*:|\/\/)/.test(e)}function o(e){return void 0!==e&&!r(e)}n.d(t,{A:()=>o,z:()=>r})},6025:(e,t,n)=>{"use strict";n.d(t,{Ay:()=>c,hH:()=>i});var r=n(6540),o=n(4586),a=n(6654);function i(){const{siteConfig:e}=(0,o.A)(),{baseUrl:t,url:n}=e,i=e.future.experimental_router,c=(0,r.useCallback)(((e,r)=>function(e){let{siteUrl:t,baseUrl:n,url:r,options:{forcePrependBaseUrl:o=!1,absolute:i=!1}={},router:c}=e;if(!r||r.startsWith("#")||(0,a.z)(r))return r;if("hash"===c)return r.startsWith("/")?`.${r}`:`./${r}`;if(o)return n+r.replace(/^\//,"");if(r===n.replace(/\/$/,""))return n;const s=r.startsWith(n)?r:n+r.replace(/^\//,"");return i?t+s:s}({siteUrl:n,baseUrl:t,url:e,options:r,router:i})),[n,t,i]);return{withBaseUrl:c}}function c(e,t){void 0===t&&(t={});const{withBaseUrl:n}=i();return n(e,t)}},3427:(e,t,n)=>{"use strict";n.d(t,{A:()=>i});var r=n(6540);n(4848);const o=r.createContext({collectAnchor:()=>{},collectLink:()=>{}}),a=()=>(0,r.useContext)(o);function i(){return a()}},4586:(e,t,n)=>{"use strict";n.d(t,{A:()=>a});var r=n(6540),o=n(6988);function a(){return(0,r.useContext)(o.o)}},2303:(e,t,n)=>{"use strict";n.d(t,{A:()=>a});var r=n(6540),o=n(6125);function a(){return(0,r.useContext)(o.o)}},205:(e,t,n)=>{"use strict";n.d(t,{A:()=>o});var r=n(6540);const o=n(8193).A.canUseDOM?r.useLayoutEffect:r.useEffect},6803:(e,t,n)=>{"use strict";n.d(t,{A:()=>a});var r=n(6540),o=n(3102);function a(){const e=r.useContext(o.o);if(!e)throw new Error("Unexpected: no Docusaurus route context found");return e}},6921:(e,t,n)=>{"use strict";n.d(t,{A:()=>o});const r=e=>"object"==typeof e&&!!e&&Object.keys(e).length>0;function o(e){const t={};return function e(n,o){Object.entries(n).forEach((n=>{let[a,i]=n;const c=o?`${o}.${a}`:a;r(i)?e(i,c):t[c]=i}))}(e),t}},3102:(e,t,n)=>{"use strict";n.d(t,{W:()=>i,o:()=>a});var r=n(6540),o=n(4848);const a=r.createContext(null);function i(e){let{children:t,value:n}=e;const i=r.useContext(a),c=(0,r.useMemo)((()=>function(e){let{parent:t,value:n}=e;if(!t){if(!n)throw new Error("Unexpected: no Docusaurus route context found");if(!("plugin"in n))throw new Error("Unexpected: Docusaurus topmost route context has no `plugin` attribute");return n}const r={...t.data,...n?.data};return{plugin:t.plugin,data:r}}({parent:i,value:n})),[i,n]);return(0,o.jsx)(a.Provider,{value:c,children:t})}},3886:(e,t,n)=>{"use strict";n.d(t,{VQ:()=>h,XK:()=>v,g1:()=>y});var r=n(6540),o=n(4070),a=n(7065),i=n(6342),c=n(679),s=n(9532),l=n(4848);const u=e=>`docs-preferred-version-${e}`,d={save:(e,t,n)=>{(0,c.Wf)(u(e),{persistence:t}).set(n)},read:(e,t)=>(0,c.Wf)(u(e),{persistence:t}).get(),clear:(e,t)=>{(0,c.Wf)(u(e),{persistence:t}).del()}},p=e=>Object.fromEntries(e.map((e=>[e,{preferredVersionName:null}])));const f=r.createContext(null);function m(){const e=(0,o.Gy)(),t=(0,i.p)().docs.versionPersistence,n=(0,r.useMemo)((()=>Object.keys(e)),[e]),[a,c]=(0,r.useState)((()=>p(n)));(0,r.useEffect)((()=>{c(function(e){let{pluginIds:t,versionPersistence:n,allDocsData:r}=e;function o(e){const t=d.read(e,n);return r[e].versions.some((e=>e.name===t))?{preferredVersionName:t}:(d.clear(e,n),{preferredVersionName:null})}return Object.fromEntries(t.map((e=>[e,o(e)])))}({allDocsData:e,versionPersistence:t,pluginIds:n}))}),[e,t,n]);return[a,(0,r.useMemo)((()=>({savePreferredVersion:function(e,n){d.save(e,t,n),c((t=>({...t,[e]:{preferredVersionName:n}})))}})),[t])]}function g(e){let{children:t}=e;const n=m();return(0,l.jsx)(f.Provider,{value:n,children:t})}function h(e){let{children:t}=e;return(0,l.jsx)(g,{children:t})}function b(){const e=(0,r.useContext)(f);if(!e)throw new s.dV("DocsPreferredVersionContextProvider");return e}function y(e){void 0===e&&(e=a.W);const t=(0,o.ht)(e),[n,i]=b(),{preferredVersionName:c}=n[e];return{preferredVersion:t.versions.find((e=>e.name===c))??null,savePreferredVersionName:(0,r.useCallback)((t=>{i.savePreferredVersion(e,t)}),[i,e])}}function v(){const e=(0,o.Gy)(),[t]=b();function n(n){const r=e[n],{preferredVersionName:o}=t[n];return r.versions.find((e=>e.name===o))??null}const r=Object.keys(e);return Object.fromEntries(r.map((e=>[e,n(e)])))}},2565:(e,t,n)=>{"use strict";n.d(t,{k:()=>a,v:()=>i});var r=n(4070),o=n(3886);function a(e,t){return`docs-${e}-${t}`}function i(){const e=(0,r.Gy)(),t=(0,r.gk)(),n=(0,o.XK)();return[...Object.keys(e).map((function(r){const o=t?.activePlugin.pluginId===r?t.activeVersion:void 0,i=n[r],c=e[r].versions.find((e=>e.isLast));return a(r,(o??i??c).name)}))]}},609:(e,t,n)=>{"use strict";n.d(t,{V:()=>s,t:()=>l});var r=n(6540),o=n(9532),a=n(4848);const i=Symbol("EmptyContext"),c=r.createContext(i);function s(e){let{children:t,name:n,items:o}=e;const i=(0,r.useMemo)((()=>n&&o?{name:n,items:o}:null),[n,o]);return(0,a.jsx)(c.Provider,{value:i,children:t})}function l(){const e=(0,r.useContext)(c);if(e===i)throw new o.dV("DocsSidebarProvider");return e}},6972:(e,t,n)=>{"use strict";n.d(t,{B5:()=>x,Nr:()=>p,OF:()=>v,QB:()=>k,Vd:()=>w,Y:()=>b,fW:()=>S,w8:()=>g});var r=n(6540),o=n(6347),a=n(2831),i=n(4070),c=n(9169),s=n(1682),l=n(3886),u=n(3025),d=n(609);function p(e){return"link"!==e.type||e.unlisted?"category"===e.type?function(e){if(e.href&&!e.linkUnlisted)return e.href;for(const t of e.items){const e=p(t);if(e)return e}}(e):void 0:e.href}const f=(e,t)=>void 0!==e&&(0,c.ys)(e,t),m=(e,t)=>e.some((e=>g(e,t)));function g(e,t){return"link"===e.type?f(e.href,t):"category"===e.type&&(f(e.href,t)||m(e.items,t))}function h(e,t){switch(e.type){case"category":return g(e,t)||e.items.some((e=>h(e,t)));case"link":return!e.unlisted||g(e,t);default:return!0}}function b(e,t){return(0,r.useMemo)((()=>e.filter((e=>h(e,t)))),[e,t])}function y(e){let{sidebarItems:t,pathname:n,onlyCategories:r=!1}=e;const o=[];return function e(t){for(const a of t)if("category"===a.type&&((0,c.ys)(a.href,n)||e(a.items))||"link"===a.type&&(0,c.ys)(a.href,n)){return r&&"category"!==a.type||o.unshift(a),!0}return!1}(t),o}function v(){const e=(0,d.t)(),{pathname:t}=(0,o.zy)(),n=(0,i.vT)()?.pluginData.breadcrumbs;return!1!==n&&e?y({sidebarItems:e.items,pathname:t}):null}function w(e){const{activeVersion:t}=(0,i.zK)(e),{preferredVersion:n}=(0,l.g1)(e),o=(0,i.r7)(e);return(0,r.useMemo)((()=>(0,s.sb)([t,n,o].filter(Boolean))),[t,n,o])}function S(e,t){const n=w(t);return(0,r.useMemo)((()=>{const t=n.flatMap((e=>e.sidebars?Object.entries(e.sidebars):[])),r=t.find((t=>t[0]===e));if(!r)throw new Error(`Can't find any sidebar with id "${e}" in version${n.length>1?"s":""} ${n.map((e=>e.name)).join(", ")}".\nAvailable sidebar ids are:\n- ${t.map((e=>e[0])).join("\n- ")}`);return r[1]}),[e,n])}function k(e,t){const n=w(t);return(0,r.useMemo)((()=>{const t=n.flatMap((e=>e.docs)),r=t.find((t=>t.id===e));if(!r){if(n.flatMap((e=>e.draftIds)).includes(e))return null;throw new Error(`Couldn't find any doc with id "${e}" in version${n.length>1?"s":""} "${n.map((e=>e.name)).join(", ")}".\nAvailable doc ids are:\n- ${(0,s.sb)(t.map((e=>e.id))).join("\n- ")}`)}return r}),[e,n])}function x(e){let{route:t}=e;const n=(0,o.zy)(),r=(0,u.r)(),i=t.routes,c=i.find((e=>(0,o.B6)(n.pathname,e)));if(!c)return null;const s=c.sidebar,l=s?r.docsSidebars[s]:void 0;return{docElement:(0,a.v)(i),sidebarName:s,sidebarItems:l}}},3025:(e,t,n)=>{"use strict";n.d(t,{n:()=>c,r:()=>s});var r=n(6540),o=n(9532),a=n(4848);const i=r.createContext(null);function c(e){let{children:t,version:n}=e;return(0,a.jsx)(i.Provider,{value:n,children:t})}function s(){const e=(0,r.useContext)(i);if(null===e)throw new o.dV("DocsVersionProvider");return e}},4070:(e,t,n)=>{"use strict";n.d(t,{zK:()=>b,vT:()=>f,gk:()=>m,Gy:()=>d,HW:()=>y,ht:()=>p,r7:()=>h,jh:()=>g});var r=n(6347),o=n(4586),a=n(7065);function i(e,t){void 0===t&&(t={});const n=function(){const{globalData:e}=(0,o.A)();return e}()[e];if(!n&&t.failfast)throw new Error(`Docusaurus plugin global data not found for "${e}" plugin.`);return n}const c=e=>e.versions.find((e=>e.isLast));function s(e,t){return[...e.versions].sort(((e,t)=>e.path===t.path?0:e.path.includes(t.path)?-1:t.path.includes(e.path)?1:0)).find((e=>!!(0,r.B6)(t,{path:e.path,exact:!1,strict:!1})))}function l(e,t){const n=s(e,t),o=n?.docs.find((e=>!!(0,r.B6)(t,{path:e.path,exact:!0,strict:!1})));return{activeVersion:n,activeDoc:o,alternateDocVersions:o?function(t){const n={};return e.versions.forEach((e=>{e.docs.forEach((r=>{r.id===t&&(n[e.name]=r)}))})),n}(o.id):{}}}const u={},d=()=>i("docusaurus-plugin-content-docs")??u,p=e=>{try{return function(e,t,n){void 0===t&&(t=a.W),void 0===n&&(n={});const r=i(e),o=r?.[t];if(!o&&n.failfast)throw new Error(`Docusaurus plugin global data not found for "${e}" plugin with id "${t}".`);return o}("docusaurus-plugin-content-docs",e,{failfast:!0})}catch(t){throw new Error("You are using a feature of the Docusaurus docs plugin, but this plugin does not seem to be enabled"+("Default"===e?"":` (pluginId=${e}`),{cause:t})}};function f(e){void 0===e&&(e={});const t=d(),{pathname:n}=(0,r.zy)();return function(e,t,n){void 0===n&&(n={});const o=Object.entries(e).sort(((e,t)=>t[1].path.localeCompare(e[1].path))).find((e=>{let[,n]=e;return!!(0,r.B6)(t,{path:n.path,exact:!1,strict:!1})})),a=o?{pluginId:o[0],pluginData:o[1]}:void 0;if(!a&&n.failfast)throw new Error(`Can't find active docs plugin for "${t}" pathname, while it was expected to be found. Maybe you tried to use a docs feature that can only be used on a docs-related page? Existing docs plugin paths are: ${Object.values(e).map((e=>e.path)).join(", ")}`);return a}(t,n,e)}function m(e){void 0===e&&(e={});const t=f(e),{pathname:n}=(0,r.zy)();if(!t)return;return{activePlugin:t,activeVersion:s(t.pluginData,n)}}function g(e){return p(e).versions}function h(e){const t=p(e);return c(t)}function b(e){const t=p(e),{pathname:n}=(0,r.zy)();return l(t,n)}function y(e){const t=p(e),{pathname:n}=(0,r.zy)();return function(e,t){const n=c(e);return{latestDocSuggestion:l(e,t).alternateDocVersions[n.name],latestVersionSuggestion:n}}(t,n)}},1911:(e,t,n)=>{"use strict";n.r(t),n.d(t,{default:()=>r});const r={onRouteDidUpdate(e){let{location:t,previousLocation:n}=e;!n||t.pathname===n.pathname&&t.search===n.search&&t.hash===n.hash||setTimeout((()=>{window.gtag("set","page_path",t.pathname+t.search+t.hash),window.gtag("event","page_view")}))}}},6294:(e,t,n)=>{"use strict";n.r(t),n.d(t,{default:()=>a});var r=n(5947),o=n.n(r);o().configure({showSpinner:!1});const a={onRouteUpdate(e){let{location:t,previousLocation:n}=e;if(n&&t.pathname!==n.pathname){const e=window.setTimeout((()=>{o().start()}),200);return()=>window.clearTimeout(e)}},onRouteDidUpdate(){o().done()}}},6491:(e,t,n)=>{"use strict";var r=n(1765),o=n(4784);!function(e){const{themeConfig:{prism:t}}=o.default,{additionalLanguages:r}=t,a=globalThis.Prism;globalThis.Prism=e,r.forEach((e=>{"php"===e&&n(9700),n(803)(`./prism-${e}`)})),n(7712),delete globalThis.Prism,void 0!==a&&(globalThis.Prism=e)}(r.My)},1107:(e,t,n)=>{"use strict";n.d(t,{A:()=>u});n(6540);var r=n(4164),o=n(1312),a=n(6342),i=n(8774),c=n(3427);const s={anchorWithStickyNavbar:"anchorWithStickyNavbar_LWe7",anchorWithHideOnScrollNavbar:"anchorWithHideOnScrollNavbar_WYt5"};var l=n(4848);function u(e){let{as:t,id:n,...u}=e;const d=(0,c.A)(),{navbar:{hideOnScroll:p}}=(0,a.p)();if("h1"===t||!n)return(0,l.jsx)(t,{...u,id:void 0});d.collectAnchor(n);const f=(0,o.T)({id:"theme.common.headingLinkTitle",message:"Direct link to {heading}",description:"Title for link to heading"},{heading:"string"==typeof u.children?u.children:n});return(0,l.jsxs)(t,{...u,className:(0,r.A)("anchor",p?s.anchorWithHideOnScrollNavbar:s.anchorWithStickyNavbar,u.className),id:n,children:[u.children,(0,l.jsx)(i.A,{className:"hash-link",to:`#${n}`,"aria-label":f,title:f,children:"\u200b"})]})}},3186:(e,t,n)=>{"use strict";n.d(t,{A:()=>a});n(6540);const r={iconExternalLink:"iconExternalLink_nPIU"};var o=n(4848);function a(e){let{width:t=13.5,height:n=13.5}=e;return(0,o.jsx)("svg",{width:t,height:n,"aria-hidden":"true",viewBox:"0 0 24 24",className:r.iconExternalLink,children:(0,o.jsx)("path",{fill:"currentColor",d:"M21 13v10h-21v-19h12v2h-10v15h17v-8h2zm3-12h-10.988l4.035 4-6.977 7.07 2.828 2.828 6.977-7.07 4.125 4.172v-11z"})})}},1957:(e,t,n)=>{"use strict";n.d(t,{A:()=>Et});var r=n(6540),o=n(4164),a=n(7489),i=n(5500),c=n(6347),s=n(1312),l=n(5062),u=n(4848);const d="__docusaurus_skipToContent_fallback";function p(e){e.setAttribute("tabindex","-1"),e.focus(),e.removeAttribute("tabindex")}function f(){const e=(0,r.useRef)(null),{action:t}=(0,c.W6)(),n=(0,r.useCallback)((e=>{e.preventDefault();const t=document.querySelector("main:first-of-type")??document.getElementById(d);t&&p(t)}),[]);return(0,l.$)((n=>{let{location:r}=n;e.current&&!r.hash&&"PUSH"===t&&p(e.current)})),{containerRef:e,onClick:n}}const m=(0,s.T)({id:"theme.common.skipToMainContent",description:"The skip to content label used for accessibility, allowing to rapidly navigate to main content with keyboard tab/enter navigation",message:"Skip to main content"});function g(e){const t=e.children??m,{containerRef:n,onClick:r}=f();return(0,u.jsx)("div",{ref:n,role:"region","aria-label":m,children:(0,u.jsx)("a",{...e,href:`#${d}`,onClick:r,children:t})})}var h=n(7559),b=n(4090);const y={skipToContent:"skipToContent_fXgn"};function v(){return(0,u.jsx)(g,{className:y.skipToContent})}var w=n(6342),S=n(5041);function k(e){let{width:t=21,height:n=21,color:r="currentColor",strokeWidth:o=1.2,className:a,...i}=e;return(0,u.jsx)("svg",{viewBox:"0 0 15 15",width:t,height:n,...i,children:(0,u.jsx)("g",{stroke:r,strokeWidth:o,children:(0,u.jsx)("path",{d:"M.75.75l13.5 13.5M14.25.75L.75 14.25"})})})}const x={closeButton:"closeButton_CVFx"};function _(e){return(0,u.jsx)("button",{type:"button","aria-label":(0,s.T)({id:"theme.AnnouncementBar.closeButtonAriaLabel",message:"Close",description:"The ARIA label for close button of announcement bar"}),...e,className:(0,o.A)("clean-btn close",x.closeButton,e.className),children:(0,u.jsx)(k,{width:14,height:14,strokeWidth:3.1})})}const C={content:"content_knG7"};function E(e){const{announcementBar:t}=(0,w.p)(),{content:n}=t;return(0,u.jsx)("div",{...e,className:(0,o.A)(C.content,e.className),dangerouslySetInnerHTML:{__html:n}})}const D={announcementBar:"announcementBar_mb4j",announcementBarPlaceholder:"announcementBarPlaceholder_vyr4",announcementBarClose:"announcementBarClose_gvF7",announcementBarContent:"announcementBarContent_xLdY"};function j(){const{announcementBar:e}=(0,w.p)(),{isActive:t,close:n}=(0,S.M)();if(!t)return null;const{backgroundColor:r,textColor:o,isCloseable:a}=e;return(0,u.jsxs)("div",{className:D.announcementBar,style:{backgroundColor:r,color:o},role:"banner",children:[a&&(0,u.jsx)("div",{className:D.announcementBarPlaceholder}),(0,u.jsx)(E,{className:D.announcementBarContent}),a&&(0,u.jsx)(_,{onClick:n,className:D.announcementBarClose})]})}var O=n(2069),A=n(3104);var T=n(9532),P=n(5600);const I=r.createContext(null);function N(e){let{children:t}=e;const n=function(){const e=(0,O.M)(),t=(0,P.YL)(),[n,o]=(0,r.useState)(!1),a=null!==t.component,i=(0,T.ZC)(a);return(0,r.useEffect)((()=>{a&&!i&&o(!0)}),[a,i]),(0,r.useEffect)((()=>{a?e.shown||o(!0):o(!1)}),[e.shown,a]),(0,r.useMemo)((()=>[n,o]),[n])}();return(0,u.jsx)(I.Provider,{value:n,children:t})}function R(e){if(e.component){const t=e.component;return(0,u.jsx)(t,{...e.props})}}function L(){const e=(0,r.useContext)(I);if(!e)throw new T.dV("NavbarSecondaryMenuDisplayProvider");const[t,n]=e,o=(0,r.useCallback)((()=>n(!1)),[n]),a=(0,P.YL)();return(0,r.useMemo)((()=>({shown:t,hide:o,content:R(a)})),[o,a,t])}function M(e){let{header:t,primaryMenu:n,secondaryMenu:r}=e;const{shown:a}=L();return(0,u.jsxs)("div",{className:"navbar-sidebar",children:[t,(0,u.jsxs)("div",{className:(0,o.A)("navbar-sidebar__items",{"navbar-sidebar__items--show-secondary":a}),children:[(0,u.jsx)("div",{className:"navbar-sidebar__item menu",children:n}),(0,u.jsx)("div",{className:"navbar-sidebar__item menu",children:r})]})]})}var F=n(5293),B=n(2303);function z(e){return(0,u.jsx)("svg",{viewBox:"0 0 24 24",width:24,height:24,...e,children:(0,u.jsx)("path",{fill:"currentColor",d:"M12,9c1.65,0,3,1.35,3,3s-1.35,3-3,3s-3-1.35-3-3S10.35,9,12,9 M12,7c-2.76,0-5,2.24-5,5s2.24,5,5,5s5-2.24,5-5 S14.76,7,12,7L12,7z M2,13l2,0c0.55,0,1-0.45,1-1s-0.45-1-1-1l-2,0c-0.55,0-1,0.45-1,1S1.45,13,2,13z M20,13l2,0c0.55,0,1-0.45,1-1 s-0.45-1-1-1l-2,0c-0.55,0-1,0.45-1,1S19.45,13,20,13z M11,2v2c0,0.55,0.45,1,1,1s1-0.45,1-1V2c0-0.55-0.45-1-1-1S11,1.45,11,2z M11,20v2c0,0.55,0.45,1,1,1s1-0.45,1-1v-2c0-0.55-0.45-1-1-1C11.45,19,11,19.45,11,20z M5.99,4.58c-0.39-0.39-1.03-0.39-1.41,0 c-0.39,0.39-0.39,1.03,0,1.41l1.06,1.06c0.39,0.39,1.03,0.39,1.41,0s0.39-1.03,0-1.41L5.99,4.58z M18.36,16.95 c-0.39-0.39-1.03-0.39-1.41,0c-0.39,0.39-0.39,1.03,0,1.41l1.06,1.06c0.39,0.39,1.03,0.39,1.41,0c0.39-0.39,0.39-1.03,0-1.41 L18.36,16.95z M19.42,5.99c0.39-0.39,0.39-1.03,0-1.41c-0.39-0.39-1.03-0.39-1.41,0l-1.06,1.06c-0.39,0.39-0.39,1.03,0,1.41 s1.03,0.39,1.41,0L19.42,5.99z M7.05,18.36c0.39-0.39,0.39-1.03,0-1.41c-0.39-0.39-1.03-0.39-1.41,0l-1.06,1.06 c-0.39,0.39-0.39,1.03,0,1.41s1.03,0.39,1.41,0L7.05,18.36z"})})}function $(e){return(0,u.jsx)("svg",{viewBox:"0 0 24 24",width:24,height:24,...e,children:(0,u.jsx)("path",{fill:"currentColor",d:"M9.37,5.51C9.19,6.15,9.1,6.82,9.1,7.5c0,4.08,3.32,7.4,7.4,7.4c0.68,0,1.35-0.09,1.99-0.27C17.45,17.19,14.93,19,12,19 c-3.86,0-7-3.14-7-7C5,9.07,6.81,6.55,9.37,5.51z M12,3c-4.97,0-9,4.03-9,9s4.03,9,9,9s9-4.03,9-9c0-0.46-0.04-0.92-0.1-1.36 c-0.98,1.37-2.58,2.26-4.4,2.26c-2.98,0-5.4-2.42-5.4-5.4c0-1.81,0.89-3.42,2.26-4.4C12.92,3.04,12.46,3,12,3L12,3z"})})}const U={toggle:"toggle_vylO",toggleButton:"toggleButton_gllP",darkToggleIcon:"darkToggleIcon_wfgR",lightToggleIcon:"lightToggleIcon_pyhR",toggleButtonDisabled:"toggleButtonDisabled_aARS"};function H(e){let{className:t,buttonClassName:n,value:r,onChange:a}=e;const i=(0,B.A)(),c=(0,s.T)({message:"Switch between dark and light mode (currently {mode})",id:"theme.colorToggle.ariaLabel",description:"The ARIA label for the navbar color mode toggle"},{mode:"dark"===r?(0,s.T)({message:"dark mode",id:"theme.colorToggle.ariaLabel.mode.dark",description:"The name for the dark color mode"}):(0,s.T)({message:"light mode",id:"theme.colorToggle.ariaLabel.mode.light",description:"The name for the light color mode"})});return(0,u.jsx)("div",{className:(0,o.A)(U.toggle,t),children:(0,u.jsxs)("button",{className:(0,o.A)("clean-btn",U.toggleButton,!i&&U.toggleButtonDisabled,n),type:"button",onClick:()=>a("dark"===r?"light":"dark"),disabled:!i,title:c,"aria-label":c,"aria-live":"polite","aria-pressed":"dark"===r?"true":"false",children:[(0,u.jsx)(z,{className:(0,o.A)(U.toggleIcon,U.lightToggleIcon)}),(0,u.jsx)($,{className:(0,o.A)(U.toggleIcon,U.darkToggleIcon)})]})})}const q=r.memo(H),V={darkNavbarColorModeToggle:"darkNavbarColorModeToggle_X3D1"};function W(e){let{className:t}=e;const n=(0,w.p)().navbar.style,r=(0,w.p)().colorMode.disableSwitch,{colorMode:o,setColorMode:a}=(0,F.G)();return r?null:(0,u.jsx)(q,{className:t,buttonClassName:"dark"===n?V.darkNavbarColorModeToggle:void 0,value:o,onChange:a})}var G=n(3465);function K(){return(0,u.jsx)(G.A,{className:"navbar__brand",imageClassName:"navbar__logo",titleClassName:"navbar__title text--truncate"})}function Y(){const e=(0,O.M)();return(0,u.jsx)("button",{type:"button","aria-label":(0,s.T)({id:"theme.docs.sidebar.closeSidebarButtonAriaLabel",message:"Close navigation bar",description:"The ARIA label for close button of mobile sidebar"}),className:"clean-btn navbar-sidebar__close",onClick:()=>e.toggle(),children:(0,u.jsx)(k,{color:"var(--ifm-color-emphasis-600)"})})}function Q(){return(0,u.jsxs)("div",{className:"navbar-sidebar__brand",children:[(0,u.jsx)(K,{}),(0,u.jsx)(W,{className:"margin-right--md"}),(0,u.jsx)(Y,{})]})}var Z=n(8774),X=n(6025),J=n(6654),ee=n(1252),te=n(3186);function ne(e){let{activeBasePath:t,activeBaseRegex:n,to:r,href:o,label:a,html:i,isDropdownLink:c,prependBaseUrlToHref:s,...l}=e;const d=(0,X.Ay)(r),p=(0,X.Ay)(t),f=(0,X.Ay)(o,{forcePrependBaseUrl:!0}),m=a&&o&&!(0,J.A)(o),g=i?{dangerouslySetInnerHTML:{__html:i}}:{children:(0,u.jsxs)(u.Fragment,{children:[a,m&&(0,u.jsx)(te.A,{...c&&{width:12,height:12}})]})};return o?(0,u.jsx)(Z.A,{href:s?f:o,...l,...g}):(0,u.jsx)(Z.A,{to:d,isNavLink:!0,...(t||n)&&{isActive:(e,t)=>n?(0,ee.G)(n,t.pathname):t.pathname.startsWith(p)},...l,...g})}function re(e){let{className:t,isDropdownItem:n=!1,...r}=e;const a=(0,u.jsx)(ne,{className:(0,o.A)(n?"dropdown__link":"navbar__item navbar__link",t),isDropdownLink:n,...r});return n?(0,u.jsx)("li",{children:a}):a}function oe(e){let{className:t,isDropdownItem:n,...r}=e;return(0,u.jsx)("li",{className:"menu__list-item",children:(0,u.jsx)(ne,{className:(0,o.A)("menu__link",t),...r})})}function ae(e){let{mobile:t=!1,position:n,...r}=e;const o=t?oe:re;return(0,u.jsx)(o,{...r,activeClassName:r.activeClassName??(t?"menu__link--active":"navbar__link--active")})}var ie=n(1422),ce=n(9169),se=n(4586);const le="dropdownNavbarItemMobile_S0Fm";function ue(e,t){return e.some((e=>function(e,t){return!!(0,ce.ys)(e.to,t)||!!(0,ee.G)(e.activeBaseRegex,t)||!(!e.activeBasePath||!t.startsWith(e.activeBasePath))}(e,t)))}function de(e){let{items:t,position:n,className:a,onClick:i,...c}=e;const s=(0,r.useRef)(null),[l,d]=(0,r.useState)(!1);return(0,r.useEffect)((()=>{const e=e=>{s.current&&!s.current.contains(e.target)&&d(!1)};return document.addEventListener("mousedown",e),document.addEventListener("touchstart",e),document.addEventListener("focusin",e),()=>{document.removeEventListener("mousedown",e),document.removeEventListener("touchstart",e),document.removeEventListener("focusin",e)}}),[s]),(0,u.jsxs)("div",{ref:s,className:(0,o.A)("navbar__item","dropdown","dropdown--hoverable",{"dropdown--right":"right"===n,"dropdown--show":l}),children:[(0,u.jsx)(ne,{"aria-haspopup":"true","aria-expanded":l,role:"button",href:c.to?void 0:"#",className:(0,o.A)("navbar__link",a),...c,onClick:c.to?void 0:e=>e.preventDefault(),onKeyDown:e=>{"Enter"===e.key&&(e.preventDefault(),d(!l))},children:c.children??c.label}),(0,u.jsx)("ul",{className:"dropdown__menu",children:t.map(((e,t)=>(0,r.createElement)(Fe,{isDropdownItem:!0,activeClassName:"dropdown__link--active",...e,key:t})))})]})}function pe(e){let{items:t,className:n,position:a,onClick:i,...s}=e;const l=function(){const{siteConfig:{baseUrl:e}}=(0,se.A)(),{pathname:t}=(0,c.zy)();return t.replace(e,"/")}(),d=ue(t,l),{collapsed:p,toggleCollapsed:f,setCollapsed:m}=(0,ie.u)({initialState:()=>!d});return(0,r.useEffect)((()=>{d&&m(!d)}),[l,d,m]),(0,u.jsxs)("li",{className:(0,o.A)("menu__list-item",{"menu__list-item--collapsed":p}),children:[(0,u.jsx)(ne,{role:"button",className:(0,o.A)(le,"menu__link menu__link--sublist menu__link--sublist-caret",n),...s,onClick:e=>{e.preventDefault(),f()},children:s.children??s.label}),(0,u.jsx)(ie.N,{lazy:!0,as:"ul",className:"menu__list",collapsed:p,children:t.map(((e,t)=>(0,r.createElement)(Fe,{mobile:!0,isDropdownItem:!0,onClick:i,activeClassName:"menu__link--active",...e,key:t})))})]})}function fe(e){let{mobile:t=!1,...n}=e;const r=t?pe:de;return(0,u.jsx)(r,{...n})}var me=n(2131);function ge(e){let{width:t=20,height:n=20,...r}=e;return(0,u.jsx)("svg",{viewBox:"0 0 24 24",width:t,height:n,"aria-hidden":!0,...r,children:(0,u.jsx)("path",{fill:"currentColor",d:"M12.87 15.07l-2.54-2.51.03-.03c1.74-1.94 2.98-4.17 3.71-6.53H17V4h-7V2H8v2H1v1.99h11.17C11.5 7.92 10.44 9.75 9 11.35 8.07 10.32 7.3 9.19 6.69 8h-2c.73 1.63 1.73 3.17 2.98 4.56l-5.09 5.02L4 19l5-5 3.11 3.11.76-2.04zM18.5 10h-2L12 22h2l1.12-3h4.75L21 22h2l-4.5-12zm-2.62 7l1.62-4.33L19.12 17h-3.24z"})})}const he="iconLanguage_nlXk";var be=n(961),ye=n(3219),ve=n(5260),we=n(4255),Se=n(1062),ke=n(2967),xe=n(2565);function _e(){return[`language:${(0,se.A)().i18n.currentLocale}`,function(){const e=(0,xe.v)();return[ke.C,...e]}().map((e=>`docusaurus_tag:${e}`))]}const Ce={button:{buttonText:(0,s.T)({id:"theme.SearchBar.label",message:"Search",description:"The ARIA label and placeholder for search button"}),buttonAriaLabel:(0,s.T)({id:"theme.SearchBar.label",message:"Search",description:"The ARIA label and placeholder for search button"})},modal:{searchBox:{resetButtonTitle:(0,s.T)({id:"theme.SearchModal.searchBox.resetButtonTitle",message:"Clear the query",description:"The label and ARIA label for search box reset button"}),resetButtonAriaLabel:(0,s.T)({id:"theme.SearchModal.searchBox.resetButtonTitle",message:"Clear the query",description:"The label and ARIA label for search box reset button"}),cancelButtonText:(0,s.T)({id:"theme.SearchModal.searchBox.cancelButtonText",message:"Cancel",description:"The label and ARIA label for search box cancel button"}),cancelButtonAriaLabel:(0,s.T)({id:"theme.SearchModal.searchBox.cancelButtonText",message:"Cancel",description:"The label and ARIA label for search box cancel button"})},startScreen:{recentSearchesTitle:(0,s.T)({id:"theme.SearchModal.startScreen.recentSearchesTitle",message:"Recent",description:"The title for recent searches"}),noRecentSearchesText:(0,s.T)({id:"theme.SearchModal.startScreen.noRecentSearchesText",message:"No recent searches",description:"The text when no recent searches"}),saveRecentSearchButtonTitle:(0,s.T)({id:"theme.SearchModal.startScreen.saveRecentSearchButtonTitle",message:"Save this search",description:"The label for save recent search button"}),removeRecentSearchButtonTitle:(0,s.T)({id:"theme.SearchModal.startScreen.removeRecentSearchButtonTitle",message:"Remove this search from history",description:"The label for remove recent search button"}),favoriteSearchesTitle:(0,s.T)({id:"theme.SearchModal.startScreen.favoriteSearchesTitle",message:"Favorite",description:"The title for favorite searches"}),removeFavoriteSearchButtonTitle:(0,s.T)({id:"theme.SearchModal.startScreen.removeFavoriteSearchButtonTitle",message:"Remove this search from favorites",description:"The label for remove favorite search button"})},errorScreen:{titleText:(0,s.T)({id:"theme.SearchModal.errorScreen.titleText",message:"Unable to fetch results",description:"The title for error screen of search modal"}),helpText:(0,s.T)({id:"theme.SearchModal.errorScreen.helpText",message:"You might want to check your network connection.",description:"The help text for error screen of search modal"})},footer:{selectText:(0,s.T)({id:"theme.SearchModal.footer.selectText",message:"to select",description:"The explanatory text of the action for the enter key"}),selectKeyAriaLabel:(0,s.T)({id:"theme.SearchModal.footer.selectKeyAriaLabel",message:"Enter key",description:"The ARIA label for the Enter key button that makes the selection"}),navigateText:(0,s.T)({id:"theme.SearchModal.footer.navigateText",message:"to navigate",description:"The explanatory text of the action for the Arrow up and Arrow down key"}),navigateUpKeyAriaLabel:(0,s.T)({id:"theme.SearchModal.footer.navigateUpKeyAriaLabel",message:"Arrow up",description:"The ARIA label for the Arrow up key button that makes the navigation"}),navigateDownKeyAriaLabel:(0,s.T)({id:"theme.SearchModal.footer.navigateDownKeyAriaLabel",message:"Arrow down",description:"The ARIA label for the Arrow down key button that makes the navigation"}),closeText:(0,s.T)({id:"theme.SearchModal.footer.closeText",message:"to close",description:"The explanatory text of the action for Escape key"}),closeKeyAriaLabel:(0,s.T)({id:"theme.SearchModal.footer.closeKeyAriaLabel",message:"Escape key",description:"The ARIA label for the Escape key button that close the modal"}),searchByText:(0,s.T)({id:"theme.SearchModal.footer.searchByText",message:"Search by",description:"The text explain that the search is making by Algolia"})},noResultsScreen:{noResultsText:(0,s.T)({id:"theme.SearchModal.noResultsScreen.noResultsText",message:"No results for",description:"The text explains that there are no results for the following search"}),suggestedQueryText:(0,s.T)({id:"theme.SearchModal.noResultsScreen.suggestedQueryText",message:"Try searching for",description:"The text for the suggested query when no results are found for the following search"}),reportMissingResultsText:(0,s.T)({id:"theme.SearchModal.noResultsScreen.reportMissingResultsText",message:"Believe this query should return results?",description:"The text for the question where the user thinks there are missing results"}),reportMissingResultsLinkText:(0,s.T)({id:"theme.SearchModal.noResultsScreen.reportMissingResultsLinkText",message:"Let us know.",description:"The text for the link to report missing results"})}},placeholder:(0,s.T)({id:"theme.SearchModal.placeholder",message:"Search docs",description:"The placeholder of the input of the DocSearch pop-up modal"})};let Ee=null;function De(e){let{hit:t,children:n}=e;return(0,u.jsx)(Z.A,{to:t.url,children:n})}function je(e){let{state:t,onClose:n}=e;const r=(0,we.w)();return(0,u.jsx)(Z.A,{to:r(t.query),onClick:n,children:(0,u.jsx)(s.A,{id:"theme.SearchBar.seeAll",values:{count:t.context.nbHits},children:"See all {count} results"})})}function Oe(e){let{contextualSearch:t,externalUrlRegex:o,...a}=e;const{siteMetadata:i}=(0,se.A)(),s=(0,Se.C)(),l=_e(),d=a.searchParameters?.facetFilters??[],p=t?function(e,t){const n=e=>"string"==typeof e?[e]:e;return[...n(e),...n(t)]}(l,d):d,f={...a.searchParameters,facetFilters:p},m=(0,c.W6)(),g=(0,r.useRef)(null),h=(0,r.useRef)(null),[b,y]=(0,r.useState)(!1),[v,w]=(0,r.useState)(void 0),S=(0,r.useCallback)((()=>Ee?Promise.resolve():Promise.all([n.e(8158).then(n.bind(n,8158)),Promise.all([n.e(1869),n.e(8913)]).then(n.bind(n,8913)),Promise.all([n.e(1869),n.e(416)]).then(n.bind(n,416))]).then((e=>{let[{DocSearchModal:t}]=e;Ee=t}))),[]),k=(0,r.useCallback)((()=>{if(!g.current){const e=document.createElement("div");g.current=e,document.body.insertBefore(e,document.body.firstChild)}}),[]),x=(0,r.useCallback)((()=>{k(),S().then((()=>y(!0)))}),[S,k]),_=(0,r.useCallback)((()=>{y(!1),h.current?.focus()}),[]),C=(0,r.useCallback)((e=>{"f"===e.key&&(e.metaKey||e.ctrlKey)||(e.preventDefault(),w(e.key),x())}),[x]),E=(0,r.useRef)({navigate(e){let{itemUrl:t}=e;(0,ee.G)(o,t)?window.location.href=t:m.push(t)}}).current,D=(0,r.useRef)((e=>a.transformItems?a.transformItems(e):e.map((e=>({...e,url:s(e.url)}))))).current,j=(0,r.useMemo)((()=>e=>(0,u.jsx)(je,{...e,onClose:_})),[_]),O=(0,r.useCallback)((e=>(e.addAlgoliaAgent("docusaurus",i.docusaurusVersion),e)),[i.docusaurusVersion]);return(0,ye.E8)({isOpen:b,onOpen:x,onClose:_,onInput:C,searchButtonRef:h}),(0,u.jsxs)(u.Fragment,{children:[(0,u.jsx)(ve.A,{children:(0,u.jsx)("link",{rel:"preconnect",href:`https://${a.appId}-dsn.algolia.net`,crossOrigin:"anonymous"})}),(0,u.jsx)(ye.Bc,{onTouchStart:S,onFocus:S,onMouseOver:S,onClick:x,ref:h,translations:Ce.button}),b&&Ee&&g.current&&(0,be.createPortal)((0,u.jsx)(Ee,{onClose:_,initialScrollY:window.scrollY,initialQuery:v,navigator:E,transformItems:D,hitComponent:De,transformSearchClient:O,...a.searchPagePath&&{resultsFooterComponent:j},...a,searchParameters:f,placeholder:Ce.placeholder,translations:Ce.modal}),g.current)]})}function Ae(){const{siteConfig:e}=(0,se.A)();return(0,u.jsx)(Oe,{...e.themeConfig.algolia})}const Te={navbarSearchContainer:"navbarSearchContainer_Bca1"};function Pe(e){let{children:t,className:n}=e;return(0,u.jsx)("div",{className:(0,o.A)(n,Te.navbarSearchContainer),children:t})}var Ie=n(4070),Ne=n(6972);var Re=n(3886);function Le(e,t){return t.alternateDocVersions[e.name]??function(e){return e.docs.find((t=>t.id===e.mainDocId))}(e)}const Me={default:ae,localeDropdown:function(e){let{mobile:t,dropdownItemsBefore:n,dropdownItemsAfter:r,queryString:o="",...a}=e;const{i18n:{currentLocale:i,locales:l,localeConfigs:d}}=(0,se.A)(),p=(0,me.o)(),{search:f,hash:m}=(0,c.zy)(),g=[...n,...l.map((e=>{const n=`${`pathname://${p.createUrl({locale:e,fullyQualified:!1})}`}${f}${m}${o}`;return{label:d[e].label,lang:d[e].htmlLang,to:n,target:"_self",autoAddBaseUrl:!1,className:e===i?t?"menu__link--active":"dropdown__link--active":""}})),...r],h=t?(0,s.T)({message:"Languages",id:"theme.navbar.mobileLanguageDropdown.label",description:"The label for the mobile language switcher dropdown"}):d[i].label;return(0,u.jsx)(fe,{...a,mobile:t,label:(0,u.jsxs)(u.Fragment,{children:[(0,u.jsx)(ge,{className:he}),h]}),items:g})},search:function(e){let{mobile:t,className:n}=e;return t?null:(0,u.jsx)(Pe,{className:n,children:(0,u.jsx)(Ae,{})})},dropdown:fe,html:function(e){let{value:t,className:n,mobile:r=!1,isDropdownItem:a=!1}=e;const i=a?"li":"div";return(0,u.jsx)(i,{className:(0,o.A)({navbar__item:!r&&!a,"menu__list-item":r},n),dangerouslySetInnerHTML:{__html:t}})},doc:function(e){let{docId:t,label:n,docsPluginId:r,...o}=e;const{activeDoc:a}=(0,Ie.zK)(r),i=(0,Ne.QB)(t,r),c=a?.path===i?.path;return null===i||i.unlisted&&!c?null:(0,u.jsx)(ae,{exact:!0,...o,isActive:()=>c||!!a?.sidebar&&a.sidebar===i.sidebar,label:n??i.id,to:i.path})},docSidebar:function(e){let{sidebarId:t,label:n,docsPluginId:r,...o}=e;const{activeDoc:a}=(0,Ie.zK)(r),i=(0,Ne.fW)(t,r).link;if(!i)throw new Error(`DocSidebarNavbarItem: Sidebar with ID "${t}" doesn't have anything to be linked to.`);return(0,u.jsx)(ae,{exact:!0,...o,isActive:()=>a?.sidebar===t,label:n??i.label,to:i.path})},docsVersion:function(e){let{label:t,to:n,docsPluginId:r,...o}=e;const a=(0,Ne.Vd)(r)[0],i=t??a.label,c=n??(e=>e.docs.find((t=>t.id===e.mainDocId)))(a).path;return(0,u.jsx)(ae,{...o,label:i,to:c})},docsVersionDropdown:function(e){let{mobile:t,docsPluginId:n,dropdownActiveClassDisabled:r,dropdownItemsBefore:o,dropdownItemsAfter:a,...i}=e;const{search:l,hash:d}=(0,c.zy)(),p=(0,Ie.zK)(n),f=(0,Ie.jh)(n),{savePreferredVersionName:m}=(0,Re.g1)(n),g=[...o,...f.map((function(e){const t=Le(e,p);return{label:e.label,to:`${t.path}${l}${d}`,isActive:()=>e===p.activeVersion,onClick:()=>m(e.name)}})),...a],h=(0,Ne.Vd)(n)[0],b=t&&g.length>1?(0,s.T)({id:"theme.navbar.mobileVersionsDropdown.label",message:"Versions",description:"The label for the navbar versions dropdown on mobile view"}):h.label,y=t&&g.length>1?void 0:Le(h,p).path;return g.length<=1?(0,u.jsx)(ae,{...i,mobile:t,label:b,to:y,isActive:r?()=>!1:void 0}):(0,u.jsx)(fe,{...i,mobile:t,label:b,to:y,items:g,isActive:r?()=>!1:void 0})}};function Fe(e){let{type:t,...n}=e;const r=function(e,t){return e&&"default"!==e?e:"items"in t?"dropdown":"default"}(t,n),o=Me[r];if(!o)throw new Error(`No NavbarItem component found for type "${t}".`);return(0,u.jsx)(o,{...n})}function Be(){const e=(0,O.M)(),t=(0,w.p)().navbar.items;return(0,u.jsx)("ul",{className:"menu__list",children:t.map(((t,n)=>(0,r.createElement)(Fe,{mobile:!0,...t,onClick:()=>e.toggle(),key:n})))})}function ze(e){return(0,u.jsx)("button",{...e,type:"button",className:"clean-btn navbar-sidebar__back",children:(0,u.jsx)(s.A,{id:"theme.navbar.mobileSidebarSecondaryMenu.backButtonLabel",description:"The label of the back button to return to main menu, inside the mobile navbar sidebar secondary menu (notably used to display the docs sidebar)",children:"\u2190 Back to main menu"})})}function $e(){const e=0===(0,w.p)().navbar.items.length,t=L();return(0,u.jsxs)(u.Fragment,{children:[!e&&(0,u.jsx)(ze,{onClick:()=>t.hide()}),t.content]})}function Ue(){const e=(0,O.M)();var t;return void 0===(t=e.shown)&&(t=!0),(0,r.useEffect)((()=>(document.body.style.overflow=t?"hidden":"visible",()=>{document.body.style.overflow="visible"})),[t]),e.shouldRender?(0,u.jsx)(M,{header:(0,u.jsx)(Q,{}),primaryMenu:(0,u.jsx)(Be,{}),secondaryMenu:(0,u.jsx)($e,{})}):null}const He={navbarHideable:"navbarHideable_m1mJ",navbarHidden:"navbarHidden_jGov"};function qe(e){return(0,u.jsx)("div",{role:"presentation",...e,className:(0,o.A)("navbar-sidebar__backdrop",e.className)})}function Ve(e){let{children:t}=e;const{navbar:{hideOnScroll:n,style:a}}=(0,w.p)(),i=(0,O.M)(),{navbarRef:c,isNavbarVisible:d}=function(e){const[t,n]=(0,r.useState)(e),o=(0,r.useRef)(!1),a=(0,r.useRef)(0),i=(0,r.useCallback)((e=>{null!==e&&(a.current=e.getBoundingClientRect().height)}),[]);return(0,A.Mq)(((t,r)=>{let{scrollY:i}=t;if(!e)return;if(i<a.current)return void n(!0);if(o.current)return void(o.current=!1);const c=r?.scrollY,s=document.documentElement.scrollHeight-a.current,l=window.innerHeight;c&&i>=c?n(!1):i+l<s&&n(!0)})),(0,l.$)((t=>{if(!e)return;const r=t.location.hash;if(r?document.getElementById(r.substring(1)):void 0)return o.current=!0,void n(!1);n(!0)})),{navbarRef:i,isNavbarVisible:t}}(n);return(0,u.jsxs)("nav",{ref:c,"aria-label":(0,s.T)({id:"theme.NavBar.navAriaLabel",message:"Main",description:"The ARIA label for the main navigation"}),className:(0,o.A)("navbar","navbar--fixed-top",n&&[He.navbarHideable,!d&&He.navbarHidden],{"navbar--dark":"dark"===a,"navbar--primary":"primary"===a,"navbar-sidebar--show":i.shown}),children:[t,(0,u.jsx)(qe,{onClick:i.toggle}),(0,u.jsx)(Ue,{})]})}var We=n(440);const Ge={errorBoundaryError:"errorBoundaryError_a6uf",errorBoundaryFallback:"errorBoundaryFallback_VBag"};function Ke(e){return(0,u.jsx)("button",{type:"button",...e,children:(0,u.jsx)(s.A,{id:"theme.ErrorPageContent.tryAgain",description:"The label of the button to try again rendering when the React error boundary captures an error",children:"Try again"})})}function Ye(e){let{error:t}=e;const n=(0,We.rA)(t).map((e=>e.message)).join("\n\nCause:\n");return(0,u.jsx)("p",{className:Ge.errorBoundaryError,children:n})}class Qe extends r.Component{componentDidCatch(e,t){throw this.props.onError(e,t)}render(){return this.props.children}}const Ze="right";function Xe(e){let{width:t=30,height:n=30,className:r,...o}=e;return(0,u.jsx)("svg",{className:r,width:t,height:n,viewBox:"0 0 30 30","aria-hidden":"true",...o,children:(0,u.jsx)("path",{stroke:"currentColor",strokeLinecap:"round",strokeMiterlimit:"10",strokeWidth:"2",d:"M4 7h22M4 15h22M4 23h22"})})}function Je(){const{toggle:e,shown:t}=(0,O.M)();return(0,u.jsx)("button",{onClick:e,"aria-label":(0,s.T)({id:"theme.docs.sidebar.toggleSidebarButtonAriaLabel",message:"Toggle navigation bar",description:"The ARIA label for hamburger menu button of mobile navigation"}),"aria-expanded":t,className:"navbar__toggle clean-btn",type:"button",children:(0,u.jsx)(Xe,{})})}const et={colorModeToggle:"colorModeToggle_DEke"};function tt(e){let{items:t}=e;return(0,u.jsx)(u.Fragment,{children:t.map(((e,t)=>(0,u.jsx)(Qe,{onError:t=>new Error(`A theme navbar item failed to render.\nPlease double-check the following navbar item (themeConfig.navbar.items) of your Docusaurus config:\n${JSON.stringify(e,null,2)}`,{cause:t}),children:(0,u.jsx)(Fe,{...e})},t)))})}function nt(e){let{left:t,right:n}=e;return(0,u.jsxs)("div",{className:"navbar__inner",children:[(0,u.jsx)("div",{className:"navbar__items",children:t}),(0,u.jsx)("div",{className:"navbar__items navbar__items--right",children:n})]})}function rt(){const e=(0,O.M)(),t=(0,w.p)().navbar.items,[n,r]=function(e){function t(e){return"left"===(e.position??Ze)}return[e.filter(t),e.filter((e=>!t(e)))]}(t),o=t.find((e=>"search"===e.type));return(0,u.jsx)(nt,{left:(0,u.jsxs)(u.Fragment,{children:[!e.disabled&&(0,u.jsx)(Je,{}),(0,u.jsx)(K,{}),(0,u.jsx)(tt,{items:n})]}),right:(0,u.jsxs)(u.Fragment,{children:[(0,u.jsx)(tt,{items:r}),(0,u.jsx)(W,{className:et.colorModeToggle}),!o&&(0,u.jsx)(Pe,{children:(0,u.jsx)(Ae,{})})]})})}function ot(){return(0,u.jsx)(Ve,{children:(0,u.jsx)(rt,{})})}function at(e){let{item:t}=e;const{to:n,href:r,label:o,prependBaseUrlToHref:a,...i}=t,c=(0,X.Ay)(n),s=(0,X.Ay)(r,{forcePrependBaseUrl:!0});return(0,u.jsxs)(Z.A,{className:"footer__link-item",...r?{href:a?s:r}:{to:c},...i,children:[o,r&&!(0,J.A)(r)&&(0,u.jsx)(te.A,{})]})}function it(e){let{item:t}=e;return t.html?(0,u.jsx)("li",{className:"footer__item",dangerouslySetInnerHTML:{__html:t.html}}):(0,u.jsx)("li",{className:"footer__item",children:(0,u.jsx)(at,{item:t})},t.href??t.to)}function ct(e){let{column:t}=e;return(0,u.jsxs)("div",{className:"col footer__col",children:[(0,u.jsx)("div",{className:"footer__title",children:t.title}),(0,u.jsx)("ul",{className:"footer__items clean-list",children:t.items.map(((e,t)=>(0,u.jsx)(it,{item:e},t)))})]})}function st(e){let{columns:t}=e;return(0,u.jsx)("div",{className:"row footer__links",children:t.map(((e,t)=>(0,u.jsx)(ct,{column:e},t)))})}function lt(){return(0,u.jsx)("span",{className:"footer__link-separator",children:"\xb7"})}function ut(e){let{item:t}=e;return t.html?(0,u.jsx)("span",{className:"footer__link-item",dangerouslySetInnerHTML:{__html:t.html}}):(0,u.jsx)(at,{item:t})}function dt(e){let{links:t}=e;return(0,u.jsx)("div",{className:"footer__links text--center",children:(0,u.jsx)("div",{className:"footer__links",children:t.map(((e,n)=>(0,u.jsxs)(r.Fragment,{children:[(0,u.jsx)(ut,{item:e}),t.length!==n+1&&(0,u.jsx)(lt,{})]},n)))})})}function pt(e){let{links:t}=e;return function(e){return"title"in e[0]}(t)?(0,u.jsx)(st,{columns:t}):(0,u.jsx)(dt,{links:t})}var ft=n(1122);const mt="footerLogoLink_BH7S";function gt(e){let{logo:t}=e;const{withBaseUrl:n}=(0,X.hH)(),r={light:n(t.src),dark:n(t.srcDark??t.src)};return(0,u.jsx)(ft.A,{className:(0,o.A)("footer__logo",t.className),alt:t.alt,sources:r,width:t.width,height:t.height,style:t.style})}function ht(e){let{logo:t}=e;return t.href?(0,u.jsx)(Z.A,{href:t.href,className:mt,target:t.target,children:(0,u.jsx)(gt,{logo:t})}):(0,u.jsx)(gt,{logo:t})}function bt(e){let{copyright:t}=e;return(0,u.jsx)("div",{className:"footer__copyright",dangerouslySetInnerHTML:{__html:t}})}function yt(e){let{style:t,links:n,logo:r,copyright:a}=e;return(0,u.jsx)("footer",{className:(0,o.A)("footer",{"footer--dark":"dark"===t}),children:(0,u.jsxs)("div",{className:"container container-fluid",children:[n,(r||a)&&(0,u.jsxs)("div",{className:"footer__bottom text--center",children:[r&&(0,u.jsx)("div",{className:"margin-bottom--sm",children:r}),a]})]})})}function vt(){const{footer:e}=(0,w.p)();if(!e)return null;const{copyright:t,links:n,logo:r,style:o}=e;return(0,u.jsx)(yt,{style:o,links:n&&n.length>0&&(0,u.jsx)(pt,{links:n}),logo:r&&(0,u.jsx)(ht,{logo:r}),copyright:t&&(0,u.jsx)(bt,{copyright:t})})}const wt=r.memo(vt),St=(0,T.fM)([F.a,S.o,A.Tv,Re.VQ,i.Jx,function(e){let{children:t}=e;return(0,u.jsx)(P.y_,{children:(0,u.jsx)(O.e,{children:(0,u.jsx)(N,{children:t})})})}]);function kt(e){let{children:t}=e;return(0,u.jsx)(St,{children:t})}var xt=n(1107);function _t(e){let{error:t,tryAgain:n}=e;return(0,u.jsx)("main",{className:"container margin-vert--xl",children:(0,u.jsx)("div",{className:"row",children:(0,u.jsxs)("div",{className:"col col--6 col--offset-3",children:[(0,u.jsx)(xt.A,{as:"h1",className:"hero__title",children:(0,u.jsx)(s.A,{id:"theme.ErrorPageContent.title",description:"The title of the fallback page when the page crashed",children:"This page crashed."})}),(0,u.jsx)("div",{className:"margin-vert--lg",children:(0,u.jsx)(Ke,{onClick:n,className:"button button--primary shadow--lw"})}),(0,u.jsx)("hr",{}),(0,u.jsx)("div",{className:"margin-vert--md",children:(0,u.jsx)(Ye,{error:t})})]})})})}const Ct={mainWrapper:"mainWrapper_z2l0"};function Et(e){const{children:t,noFooter:n,wrapperClassName:r,title:c,description:s}=e;return(0,b.J)(),(0,u.jsxs)(kt,{children:[(0,u.jsx)(i.be,{title:c,description:s}),(0,u.jsx)(v,{}),(0,u.jsx)(j,{}),(0,u.jsx)(ot,{}),(0,u.jsx)("div",{id:d,className:(0,o.A)(h.G.wrapper.main,Ct.mainWrapper,r),children:(0,u.jsx)(a.A,{fallback:e=>(0,u.jsx)(_t,{...e}),children:t})}),!n&&(0,u.jsx)(wt,{})]})}},3465:(e,t,n)=>{"use strict";n.d(t,{A:()=>u});n(6540);var r=n(8774),o=n(6025),a=n(4586),i=n(6342),c=n(1122),s=n(4848);function l(e){let{logo:t,alt:n,imageClassName:r}=e;const a={light:(0,o.Ay)(t.src),dark:(0,o.Ay)(t.srcDark||t.src)},i=(0,s.jsx)(c.A,{className:t.className,sources:a,height:t.height,width:t.width,alt:n,style:t.style});return r?(0,s.jsx)("div",{className:r,children:i}):i}function u(e){const{siteConfig:{title:t}}=(0,a.A)(),{navbar:{title:n,logo:c}}=(0,i.p)(),{imageClassName:u,titleClassName:d,...p}=e,f=(0,o.Ay)(c?.href||"/"),m=n?"":t,g=c?.alt??m;return(0,s.jsxs)(r.A,{to:f,...p,...c?.target&&{target:c.target},children:[c&&(0,s.jsx)(l,{logo:c,alt:g,imageClassName:u}),null!=n&&(0,s.jsx)("b",{className:d,children:n})]})}},1463:(e,t,n)=>{"use strict";n.d(t,{A:()=>a});n(6540);var r=n(5260),o=n(4848);function a(e){let{locale:t,version:n,tag:a}=e;const i=t;return(0,o.jsxs)(r.A,{children:[t&&(0,o.jsx)("meta",{name:"docusaurus_locale",content:t}),n&&(0,o.jsx)("meta",{name:"docusaurus_version",content:n}),a&&(0,o.jsx)("meta",{name:"docusaurus_tag",content:a}),i&&(0,o.jsx)("meta",{name:"docsearch:language",content:i}),n&&(0,o.jsx)("meta",{name:"docsearch:version",content:n}),a&&(0,o.jsx)("meta",{name:"docsearch:docusaurus_tag",content:a})]})}},1122:(e,t,n)=>{"use strict";n.d(t,{A:()=>u});var r=n(6540),o=n(4164),a=n(2303),i=n(5293);const c={themedComponent:"themedComponent_mlkZ","themedComponent--light":"themedComponent--light_NVdE","themedComponent--dark":"themedComponent--dark_xIcU"};var s=n(4848);function l(e){let{className:t,children:n}=e;const l=(0,a.A)(),{colorMode:u}=(0,i.G)();return(0,s.jsx)(s.Fragment,{children:(l?"dark"===u?["dark"]:["light"]:["light","dark"]).map((e=>{const a=n({theme:e,className:(0,o.A)(t,c.themedComponent,c[`themedComponent--${e}`])});return(0,s.jsx)(r.Fragment,{children:a},e)}))})}function u(e){const{sources:t,className:n,alt:r,...o}=e;return(0,s.jsx)(l,{className:n,children:e=>{let{theme:n,className:a}=e;return(0,s.jsx)("img",{src:t[n],alt:r,className:a,...o})}})}},1422:(e,t,n)=>{"use strict";n.d(t,{N:()=>b,u:()=>l});var r=n(6540),o=n(8193),a=n(205),i=n(3109),c=n(4848);const s="ease-in-out";function l(e){let{initialState:t}=e;const[n,o]=(0,r.useState)(t??!1),a=(0,r.useCallback)((()=>{o((e=>!e))}),[]);return{collapsed:n,setCollapsed:o,toggleCollapsed:a}}const u={display:"none",overflow:"hidden",height:"0px"},d={display:"block",overflow:"visible",height:"auto"};function p(e,t){const n=t?u:d;e.style.display=n.display,e.style.overflow=n.overflow,e.style.height=n.height}function f(e){let{collapsibleRef:t,collapsed:n,animation:o}=e;const a=(0,r.useRef)(!1);(0,r.useEffect)((()=>{const e=t.current;function r(){const t=e.scrollHeight,n=o?.duration??function(e){if((0,i.O)())return 1;const t=e/36;return Math.round(10*(4+15*t**.25+t/5))}(t);return{transition:`height ${n}ms ${o?.easing??s}`,height:`${t}px`}}function c(){const t=r();e.style.transition=t.transition,e.style.height=t.height}if(!a.current)return p(e,n),void(a.current=!0);return e.style.willChange="height",function(){const t=requestAnimationFrame((()=>{n?(c(),requestAnimationFrame((()=>{e.style.height=u.height,e.style.overflow=u.overflow}))):(e.style.display="block",requestAnimationFrame((()=>{c()})))}));return()=>cancelAnimationFrame(t)}()}),[t,n,o])}function m(e){if(!o.A.canUseDOM)return e?u:d}function g(e){let{as:t="div",collapsed:n,children:o,animation:a,onCollapseTransitionEnd:i,className:s,disableSSRStyle:l}=e;const u=(0,r.useRef)(null);return f({collapsibleRef:u,collapsed:n,animation:a}),(0,c.jsx)(t,{ref:u,style:l?void 0:m(n),onTransitionEnd:e=>{"height"===e.propertyName&&(p(u.current,n),i?.(n))},className:s,children:o})}function h(e){let{collapsed:t,...n}=e;const[o,i]=(0,r.useState)(!t),[s,l]=(0,r.useState)(t);return(0,a.A)((()=>{t||i(!0)}),[t]),(0,a.A)((()=>{o&&l(t)}),[o,t]),o?(0,c.jsx)(g,{...n,collapsed:s}):null}function b(e){let{lazy:t,...n}=e;const r=t?h:g;return(0,c.jsx)(r,{...n})}},5041:(e,t,n)=>{"use strict";n.d(t,{M:()=>g,o:()=>m});var r=n(6540),o=n(2303),a=n(679),i=n(9532),c=n(6342),s=n(4848);const l=(0,a.Wf)("docusaurus.announcement.dismiss"),u=(0,a.Wf)("docusaurus.announcement.id"),d=()=>"true"===l.get(),p=e=>l.set(String(e)),f=r.createContext(null);function m(e){let{children:t}=e;const n=function(){const{announcementBar:e}=(0,c.p)(),t=(0,o.A)(),[n,a]=(0,r.useState)((()=>!!t&&d()));(0,r.useEffect)((()=>{a(d())}),[]);const i=(0,r.useCallback)((()=>{p(!0),a(!0)}),[]);return(0,r.useEffect)((()=>{if(!e)return;const{id:t}=e;let n=u.get();"annoucement-bar"===n&&(n="announcement-bar");const r=t!==n;u.set(t),r&&p(!1),!r&&d()||a(!1)}),[e]),(0,r.useMemo)((()=>({isActive:!!e&&!n,close:i})),[e,n,i])}();return(0,s.jsx)(f.Provider,{value:n,children:t})}function g(){const e=(0,r.useContext)(f);if(!e)throw new i.dV("AnnouncementBarProvider");return e}},5293:(e,t,n)=>{"use strict";n.d(t,{G:()=>b,a:()=>h});var r=n(6540),o=n(8193),a=n(9532),i=n(679),c=n(6342),s=n(4848);const l=r.createContext(void 0),u="theme",d=(0,i.Wf)(u),p={light:"light",dark:"dark"},f=e=>e===p.dark?p.dark:p.light,m=e=>o.A.canUseDOM?f(document.documentElement.getAttribute("data-theme")):f(e),g=e=>{d.set(f(e))};function h(e){let{children:t}=e;const n=function(){const{colorMode:{defaultMode:e,disableSwitch:t,respectPrefersColorScheme:n}}=(0,c.p)(),[o,a]=(0,r.useState)(m(e));(0,r.useEffect)((()=>{t&&d.del()}),[t]);const i=(0,r.useCallback)((function(t,r){void 0===r&&(r={});const{persist:o=!0}=r;t?(a(t),o&&g(t)):(a(n?window.matchMedia("(prefers-color-scheme: dark)").matches?p.dark:p.light:e),d.del())}),[n,e]);(0,r.useEffect)((()=>{document.documentElement.setAttribute("data-theme",f(o))}),[o]),(0,r.useEffect)((()=>{if(t)return;const e=e=>{if(e.key!==u)return;const t=d.get();null!==t&&i(f(t))};return window.addEventListener("storage",e),()=>window.removeEventListener("storage",e)}),[t,i]);const s=(0,r.useRef)(!1);return(0,r.useEffect)((()=>{if(t&&!n)return;const e=window.matchMedia("(prefers-color-scheme: dark)"),r=()=>{window.matchMedia("print").matches||s.current?s.current=window.matchMedia("print").matches:i(null)};return e.addListener(r),()=>e.removeListener(r)}),[i,t,n]),(0,r.useMemo)((()=>({colorMode:o,setColorMode:i,get isDarkTheme(){return o===p.dark},setLightTheme(){i(p.light)},setDarkTheme(){i(p.dark)}})),[o,i])}();return(0,s.jsx)(l.Provider,{value:n,children:t})}function b(){const e=(0,r.useContext)(l);if(null==e)throw new a.dV("ColorModeProvider","Please see https://docusaurus.io/docs/api/themes/configuration#use-color-mode.");return e}},2069:(e,t,n)=>{"use strict";n.d(t,{M:()=>f,e:()=>p});var r=n(6540),o=n(5600),a=n(4581),i=n(7485),c=n(6342),s=n(9532),l=n(4848);const u=r.createContext(void 0);function d(){const e=function(){const e=(0,o.YL)(),{items:t}=(0,c.p)().navbar;return 0===t.length&&!e.component}(),t=(0,a.l)(),n=!e&&"mobile"===t,[s,l]=(0,r.useState)(!1);(0,i.$Z)((()=>{if(s)return l(!1),!1}));const u=(0,r.useCallback)((()=>{l((e=>!e))}),[]);return(0,r.useEffect)((()=>{"desktop"===t&&l(!1)}),[t]),(0,r.useMemo)((()=>({disabled:e,shouldRender:n,toggle:u,shown:s})),[e,n,u,s])}function p(e){let{children:t}=e;const n=d();return(0,l.jsx)(u.Provider,{value:n,children:t})}function f(){const e=r.useContext(u);if(void 0===e)throw new s.dV("NavbarMobileSidebarProvider");return e}},5600:(e,t,n)=>{"use strict";n.d(t,{GX:()=>l,YL:()=>s,y_:()=>c});var r=n(6540),o=n(9532),a=n(4848);const i=r.createContext(null);function c(e){let{children:t}=e;const n=(0,r.useState)({component:null,props:null});return(0,a.jsx)(i.Provider,{value:n,children:t})}function s(){const e=(0,r.useContext)(i);if(!e)throw new o.dV("NavbarSecondaryMenuContentProvider");return e[0]}function l(e){let{component:t,props:n}=e;const a=(0,r.useContext)(i);if(!a)throw new o.dV("NavbarSecondaryMenuContentProvider");const[,c]=a,s=(0,o.Be)(n);return(0,r.useEffect)((()=>{c({component:t,props:s})}),[c,t,s]),(0,r.useEffect)((()=>()=>c({component:null,props:null})),[c]),null}},4090:(e,t,n)=>{"use strict";n.d(t,{w:()=>o,J:()=>a});var r=n(6540);const o="navigation-with-keyboard";function a(){(0,r.useEffect)((()=>{function e(e){"keydown"===e.type&&"Tab"===e.key&&document.body.classList.add(o),"mousedown"===e.type&&document.body.classList.remove(o)}return document.addEventListener("keydown",e),document.addEventListener("mousedown",e),()=>{document.body.classList.remove(o),document.removeEventListener("keydown",e),document.removeEventListener("mousedown",e)}}),[])}},4255:(e,t,n)=>{"use strict";n.d(t,{b:()=>c,w:()=>s});var r=n(6540),o=n(4586),a=n(7485);const i="q";function c(){return(0,a.l)(i)}function s(){const{siteConfig:{baseUrl:e,themeConfig:t}}=(0,o.A)(),{algolia:{searchPagePath:n}}=t;return(0,r.useCallback)((t=>`${e}${n}?${i}=${encodeURIComponent(t)}`),[e,n])}},4581:(e,t,n)=>{"use strict";n.d(t,{l:()=>c});var r=n(6540),o=n(8193);const a={desktop:"desktop",mobile:"mobile",ssr:"ssr"},i=996;function c(e){let{desktopBreakpoint:t=i}=void 0===e?{}:e;const[n,c]=(0,r.useState)((()=>"ssr"));return(0,r.useEffect)((()=>{function e(){c(function(e){if(!o.A.canUseDOM)throw new Error("getWindowSize() should only be called after React hydration");return window.innerWidth>e?a.desktop:a.mobile}(t))}return e(),window.addEventListener("resize",e),()=>{window.removeEventListener("resize",e)}}),[t]),n}},7559:(e,t,n)=>{"use strict";n.d(t,{G:()=>r});const r={page:{blogListPage:"blog-list-page",blogPostPage:"blog-post-page",blogTagsListPage:"blog-tags-list-page",blogTagPostListPage:"blog-tags-post-list-page",blogAuthorsListPage:"blog-authors-list-page",blogAuthorsPostsPage:"blog-authors-posts-page",docsDocPage:"docs-doc-page",docsTagsListPage:"docs-tags-list-page",docsTagDocListPage:"docs-tags-doc-list-page",mdxPage:"mdx-page"},wrapper:{main:"main-wrapper",blogPages:"blog-wrapper",docsPages:"docs-wrapper",mdxPages:"mdx-wrapper"},common:{editThisPage:"theme-edit-this-page",lastUpdated:"theme-last-updated",backToTopButton:"theme-back-to-top-button",codeBlock:"theme-code-block",admonition:"theme-admonition",unlistedBanner:"theme-unlisted-banner",draftBanner:"theme-draft-banner",admonitionType:e=>`theme-admonition-${e}`},layout:{},docs:{docVersionBanner:"theme-doc-version-banner",docVersionBadge:"theme-doc-version-badge",docBreadcrumbs:"theme-doc-breadcrumbs",docMarkdown:"theme-doc-markdown",docTocMobile:"theme-doc-toc-mobile",docTocDesktop:"theme-doc-toc-desktop",docFooter:"theme-doc-footer",docFooterTagsRow:"theme-doc-footer-tags-row",docFooterEditMetaRow:"theme-doc-footer-edit-meta-row",docSidebarContainer:"theme-doc-sidebar-container",docSidebarMenu:"theme-doc-sidebar-menu",docSidebarItemCategory:"theme-doc-sidebar-item-category",docSidebarItemLink:"theme-doc-sidebar-item-link",docSidebarItemCategoryLevel:e=>`theme-doc-sidebar-item-category-level-${e}`,docSidebarItemLinkLevel:e=>`theme-doc-sidebar-item-link-level-${e}`},blog:{blogFooterTagsRow:"theme-blog-footer-tags-row",blogFooterEditMetaRow:"theme-blog-footer-edit-meta-row"},pages:{pageFooterEditMetaRow:"theme-pages-footer-edit-meta-row"}}},3109:(e,t,n)=>{"use strict";function r(){return window.matchMedia("(prefers-reduced-motion: reduce)").matches}n.d(t,{O:()=>r})},481:(e,t,n)=>{"use strict";n.d(t,{s:()=>o});var r=n(4586);function o(e){const{siteConfig:t}=(0,r.A)(),{title:n,titleDelimiter:o}=t;return e?.trim().length?`${e.trim()} ${o} ${n}`:n}},7485:(e,t,n)=>{"use strict";n.d(t,{$Z:()=>i,l:()=>s});var r=n(6540),o=n(6347),a=n(9532);function i(e){!function(e){const t=(0,o.W6)(),n=(0,a._q)(e);(0,r.useEffect)((()=>t.block(((e,t)=>n(e,t)))),[t,n])}(((t,n)=>{if("POP"===n)return e(t,n)}))}function c(e){const t=(0,o.W6)();return(0,r.useSyncExternalStore)(t.listen,(()=>e(t)),(()=>e(t)))}function s(e){const t=function(e){return c((t=>null===e?null:new URLSearchParams(t.location.search).get(e)))}(e)??"",n=function(e){const t=(0,o.W6)();return(0,r.useCallback)(((n,r)=>{const o=new URLSearchParams(t.location.search);n?o.set(e,n):o.delete(e),(r?.push?t.push:t.replace)({search:o.toString()})}),[e,t])}(e);return[t,n]}},1682:(e,t,n)=>{"use strict";function r(e){return Array.from(new Set(e))}function o(e,t){const n={};let r=0;for(const o of e){const e=t(o,r);n[e]??=[],n[e].push(o),r+=1}return n}n.d(t,{$z:()=>o,sb:()=>r})},5500:(e,t,n)=>{"use strict";n.d(t,{Jx:()=>f,be:()=>u,e3:()=>p});var r=n(6540),o=n(4164),a=n(5260),i=n(6803),c=n(6025),s=n(481),l=n(4848);function u(e){let{title:t,description:n,keywords:r,image:o,children:i}=e;const u=(0,s.s)(t),{withBaseUrl:d}=(0,c.hH)(),p=o?d(o,{absolute:!0}):void 0;return(0,l.jsxs)(a.A,{children:[t&&(0,l.jsx)("title",{children:u}),t&&(0,l.jsx)("meta",{property:"og:title",content:u}),n&&(0,l.jsx)("meta",{name:"description",content:n}),n&&(0,l.jsx)("meta",{property:"og:description",content:n}),r&&(0,l.jsx)("meta",{name:"keywords",content:Array.isArray(r)?r.join(","):r}),p&&(0,l.jsx)("meta",{property:"og:image",content:p}),p&&(0,l.jsx)("meta",{name:"twitter:image",content:p}),i]})}const d=r.createContext(void 0);function p(e){let{className:t,children:n}=e;const i=r.useContext(d),c=(0,o.A)(i,t);return(0,l.jsxs)(d.Provider,{value:c,children:[(0,l.jsx)(a.A,{children:(0,l.jsx)("html",{className:c})}),n]})}function f(e){let{children:t}=e;const n=(0,i.A)(),r=`plugin-${n.plugin.name.replace(/docusaurus-(?:plugin|theme)-(?:content-)?/gi,"")}`;const a=`plugin-id-${n.plugin.id}`;return(0,l.jsx)(p,{className:(0,o.A)(r,a),children:t})}},9532:(e,t,n)=>{"use strict";n.d(t,{Be:()=>l,ZC:()=>c,_q:()=>i,dV:()=>s,fM:()=>u});var r=n(6540),o=n(205),a=n(4848);function i(e){const t=(0,r.useRef)(e);return(0,o.A)((()=>{t.current=e}),[e]),(0,r.useCallback)((function(){return t.current(...arguments)}),[])}function c(e){const t=(0,r.useRef)();return(0,o.A)((()=>{t.current=e})),t.current}class s extends Error{constructor(e,t){super(),this.name="ReactContextError",this.message=`Hook ${this.stack?.split("\n")[1]?.match(/at (?:\w+\.)?(?<name>\w+)/)?.groups.name??""} is called outside the <${e}>. ${t??""}`}}function l(e){const t=Object.entries(e);return t.sort(((e,t)=>e[0].localeCompare(t[0]))),(0,r.useMemo)((()=>e),t.flat())}function u(e){return t=>{let{children:n}=t;return(0,a.jsx)(a.Fragment,{children:e.reduceRight(((e,t)=>(0,a.jsx)(t,{children:e})),n)})}}},1252:(e,t,n)=>{"use strict";function r(e,t){return void 0!==e&&void 0!==t&&new RegExp(e,"gi").test(t)}n.d(t,{G:()=>r})},9169:(e,t,n)=>{"use strict";n.d(t,{Dt:()=>c,ys:()=>i});var r=n(6540),o=n(8328),a=n(4586);function i(e,t){const n=e=>(!e||e.endsWith("/")?e:`${e}/`)?.toLowerCase();return n(e)===n(t)}function c(){const{baseUrl:e}=(0,a.A)().siteConfig;return(0,r.useMemo)((()=>function(e){let{baseUrl:t,routes:n}=e;function r(e){return e.path===t&&!0===e.exact}function o(e){return e.path===t&&!e.exact}return function e(t){if(0===t.length)return;return t.find(r)||e(t.filter(o).flatMap((e=>e.routes??[])))}(n)}({routes:o.A,baseUrl:e})),[e])}},3104:(e,t,n)=>{"use strict";n.d(t,{Mq:()=>p,Tv:()=>l,gk:()=>f});var r=n(6540),o=n(8193),a=n(2303),i=(n(205),n(9532)),c=n(4848);const s=r.createContext(void 0);function l(e){let{children:t}=e;const n=function(){const e=(0,r.useRef)(!0);return(0,r.useMemo)((()=>({scrollEventsEnabledRef:e,enableScrollEvents:()=>{e.current=!0},disableScrollEvents:()=>{e.current=!1}})),[])}();return(0,c.jsx)(s.Provider,{value:n,children:t})}function u(){const e=(0,r.useContext)(s);if(null==e)throw new i.dV("ScrollControllerProvider");return e}const d=()=>o.A.canUseDOM?{scrollX:window.pageXOffset,scrollY:window.pageYOffset}:null;function p(e,t){void 0===t&&(t=[]);const{scrollEventsEnabledRef:n}=u(),o=(0,r.useRef)(d()),a=(0,i._q)(e);(0,r.useEffect)((()=>{const e=()=>{if(!n.current)return;const e=d();a(e,o.current),o.current=e},t={passive:!0};return e(),window.addEventListener("scroll",e,t),()=>window.removeEventListener("scroll",e,t)}),[a,n,...t])}function f(){const e=(0,r.useRef)(null),t=(0,a.A)()&&"smooth"===getComputedStyle(document.documentElement).scrollBehavior;return{startScroll:n=>{e.current=t?function(e){return window.scrollTo({top:e,behavior:"smooth"}),()=>{}}(n):function(e){let t=null;const n=document.documentElement.scrollTop>e;return function r(){const o=document.documentElement.scrollTop;(n&&o>e||!n&&o<e)&&(t=requestAnimationFrame(r),window.scrollTo(0,Math.floor(.85*(o-e))+e))}(),()=>t&&cancelAnimationFrame(t)}(n)},cancelScroll:()=>e.current?.()}}},2967:(e,t,n)=>{"use strict";n.d(t,{C:()=>r});const r="default"},679:(e,t,n)=>{"use strict";n.d(t,{Wf:()=>l});n(6540);const r=JSON.parse('{"N":"localStorage","M":""}'),o=r.N;function a(e){let{key:t,oldValue:n,newValue:r,storage:o}=e;if(n===r)return;const a=document.createEvent("StorageEvent");a.initStorageEvent("storage",!1,!1,t,n,r,window.location.href,o),window.dispatchEvent(a)}function i(e){if(void 0===e&&(e=o),"undefined"==typeof window)throw new Error("Browser storage is not available on Node.js/Docusaurus SSR process.");if("none"===e)return null;try{return window[e]}catch(n){return t=n,c||(console.warn("Docusaurus browser storage is not available.\nPossible reasons: running Docusaurus in an iframe, in an incognito browser session, or using too strict browser privacy settings.",t),c=!0),null}var t}let c=!1;const s={get:()=>null,set:()=>{},del:()=>{},listen:()=>()=>{}};function l(e,t){const n=`${e}${r.M}`;if("undefined"==typeof window)return function(e){function t(){throw new Error(`Illegal storage API usage for storage key "${e}".\nDocusaurus storage APIs are not supposed to be called on the server-rendering process.\nPlease only call storage APIs in effects and event handlers.`)}return{get:t,set:t,del:t,listen:t}}(n);const o=i(t?.persistence);return null===o?s:{get:()=>{try{return o.getItem(n)}catch(e){return console.error(`Docusaurus storage error, can't get key=${n}`,e),null}},set:e=>{try{const t=o.getItem(n);o.setItem(n,e),a({key:n,oldValue:t,newValue:e,storage:o})}catch(t){console.error(`Docusaurus storage error, can't set ${n}=${e}`,t)}},del:()=>{try{const e=o.getItem(n);o.removeItem(n),a({key:n,oldValue:e,newValue:null,storage:o})}catch(e){console.error(`Docusaurus storage error, can't delete key=${n}`,e)}},listen:e=>{try{const t=t=>{t.storageArea===o&&t.key===n&&e(t)};return window.addEventListener("storage",t),()=>window.removeEventListener("storage",t)}catch(t){return console.error(`Docusaurus storage error, can't listen for changes of key=${n}`,t),()=>{}}}}}},2131:(e,t,n)=>{"use strict";n.d(t,{o:()=>i});var r=n(4586),o=n(6347),a=n(440);function i(){const{siteConfig:{baseUrl:e,url:t,trailingSlash:n},i18n:{defaultLocale:i,currentLocale:c}}=(0,r.A)(),{pathname:s}=(0,o.zy)(),l=(0,a.Ks)(s,{trailingSlash:n,baseUrl:e}),u=c===i?e:e.replace(`/${c}/`,"/"),d=l.replace(e,"");return{createUrl:function(e){let{locale:n,fullyQualified:r}=e;return`${r?t:""}${function(e){return e===i?`${u}`:`${u}${e}/`}(n)}${d}`}}}},5062:(e,t,n)=>{"use strict";n.d(t,{$:()=>i});var r=n(6540),o=n(6347),a=n(9532);function i(e){const t=(0,o.zy)(),n=(0,a.ZC)(t),i=(0,a._q)(e);(0,r.useEffect)((()=>{n&&t!==n&&i({location:t,previousLocation:n})}),[i,t,n])}},6342:(e,t,n)=>{"use strict";n.d(t,{p:()=>o});var r=n(4586);function o(){return(0,r.A)().siteConfig.themeConfig}},8126:(e,t,n)=>{"use strict";n.d(t,{c:()=>o});var r=n(4586);function o(){const{siteConfig:{themeConfig:e}}=(0,r.A)();return e}},1062:(e,t,n)=>{"use strict";n.d(t,{C:()=>c});var r=n(6540),o=n(1252),a=n(6025),i=n(8126);function c(){const{withBaseUrl:e}=(0,a.hH)(),{algolia:{externalUrlRegex:t,replaceSearchResultPathname:n}}=(0,i.c)();return(0,r.useCallback)((r=>{const a=new URL(r);if((0,o.G)(t,a.href))return r;const i=`${a.pathname+a.hash}`;return e(function(e,t){return t?e.replaceAll(new RegExp(t.from,"g"),t.to):e}(i,n))}),[e,t,n])}},2983:(e,t,n)=>{"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.addTrailingSlash=o,t.default=function(e,t){const{trailingSlash:n,baseUrl:r}=t;if(e.startsWith("#"))return e;if(void 0===n)return e;const[i]=e.split(/[#?]/),c="/"===i||i===r?i:(s=i,l=n,l?o(s):a(s));var s,l;return e.replace(i,c)},t.addLeadingSlash=function(e){return(0,r.addPrefix)(e,"/")},t.removeTrailingSlash=a;const r=n(2566);function o(e){return e.endsWith("/")?e:`${e}/`}function a(e){return(0,r.removeSuffix)(e,"/")}},253:(e,t)=>{"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.getErrorCausalChain=function e(t){if(t.cause)return[t,...e(t.cause)];return[t]}},440:(e,t,n)=>{"use strict";t.rA=t.Ks=t.LU=void 0;const r=n(1635);t.LU="__blog-post-container";var o=n(2983);Object.defineProperty(t,"Ks",{enumerable:!0,get:function(){return r.__importDefault(o).default}});var a=n(2566);var i=n(253);Object.defineProperty(t,"rA",{enumerable:!0,get:function(){return i.getErrorCausalChain}})},2566:(e,t)=>{"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.addPrefix=function(e,t){return e.startsWith(t)?e:`${t}${e}`},t.removeSuffix=function(e,t){if(""===t)return e;return e.endsWith(t)?e.slice(0,-t.length):e},t.addSuffix=function(e,t){return e.endsWith(t)?e:`${e}${t}`},t.removePrefix=function(e,t){return e.startsWith(t)?e.slice(t.length):e}},7712:()=>{Prism.languages.dql={comment:[{pattern:/(^|[^\\])\/\*[\s\S]*?(?:\*\/|$)/,lookbehind:!0,greedy:!0},{pattern:/(^|[^\\:])\/\/.*/,lookbehind:!0,greedy:!0}],string:{pattern:/(["'])(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,greedy:!0},"class-name":{pattern:/(\b(?:env|service|operation_name|resource_name|status|ingestion_reason|trace_id)\s+|\bcatch\s+\()[\w.\\]+/i,lookbehind:!0,inside:{punctuation:/[.\\]/}},entity:/\b(?:env|service|operation_name|resource_name|status|ingestion_reason|trace_id)\b/,keyword:/\b(?:by|in|and|not|count|count\sby|stddev|p\d\d)\b/i,boolean:/\b(?:false|true)\b/i,function:/(\b\w+(?=\())|(\w+(?=:))/,number:/\b0x[\da-f]+\b|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?!\d*percentile)(?:e[+-]?\d+)?/i,operator:/[<>]=?|[!=]=?=?|--?|\+\+?|&&?|\|\|?|[?*/~^%]|->|=>/i,punctuation:/[{}[\];(),.:]/,builtin:{pattern:/\b(\d{2}percentile)\b|\b(avg|max|min|sum|set|median|count|is_greater|is_less|is_between|quantile)\b/i},variable:/\$+(?:\w+\b|(?=\{))/},Prism.languages.insertBefore("dql","operator",{"literal-property":{pattern:/((?:^|[,{])[ \t]*)(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*:)/m,lookbehind:!0,alias:"property"}})},1513:(e,t,n)=>{"use strict";n.d(t,{zR:()=>w,TM:()=>E,yJ:()=>f,sC:()=>j,AO:()=>p});var r=n(8168);function o(e){return"/"===e.charAt(0)}function a(e,t){for(var n=t,r=n+1,o=e.length;r<o;n+=1,r+=1)e[n]=e[r];e.pop()}const i=function(e,t){void 0===t&&(t="");var n,r=e&&e.split("/")||[],i=t&&t.split("/")||[],c=e&&o(e),s=t&&o(t),l=c||s;if(e&&o(e)?i=r:r.length&&(i.pop(),i=i.concat(r)),!i.length)return"/";if(i.length){var u=i[i.length-1];n="."===u||".."===u||""===u}else n=!1;for(var d=0,p=i.length;p>=0;p--){var f=i[p];"."===f?a(i,p):".."===f?(a(i,p),d++):d&&(a(i,p),d--)}if(!l)for(;d--;d)i.unshift("..");!l||""===i[0]||i[0]&&o(i[0])||i.unshift("");var m=i.join("/");return n&&"/"!==m.substr(-1)&&(m+="/"),m};var c=n(1561);function s(e){return"/"===e.charAt(0)?e:"/"+e}function l(e){return"/"===e.charAt(0)?e.substr(1):e}function u(e,t){return function(e,t){return 0===e.toLowerCase().indexOf(t.toLowerCase())&&-1!=="/?#".indexOf(e.charAt(t.length))}(e,t)?e.substr(t.length):e}function d(e){return"/"===e.charAt(e.length-1)?e.slice(0,-1):e}function p(e){var t=e.pathname,n=e.search,r=e.hash,o=t||"/";return n&&"?"!==n&&(o+="?"===n.charAt(0)?n:"?"+n),r&&"#"!==r&&(o+="#"===r.charAt(0)?r:"#"+r),o}function f(e,t,n,o){var a;"string"==typeof e?(a=function(e){var t=e||"/",n="",r="",o=t.indexOf("#");-1!==o&&(r=t.substr(o),t=t.substr(0,o));var a=t.indexOf("?");return-1!==a&&(n=t.substr(a),t=t.substr(0,a)),{pathname:t,search:"?"===n?"":n,hash:"#"===r?"":r}}(e),a.state=t):(void 0===(a=(0,r.A)({},e)).pathname&&(a.pathname=""),a.search?"?"!==a.search.charAt(0)&&(a.search="?"+a.search):a.search="",a.hash?"#"!==a.hash.charAt(0)&&(a.hash="#"+a.hash):a.hash="",void 0!==t&&void 0===a.state&&(a.state=t));try{a.pathname=decodeURI(a.pathname)}catch(c){throw c instanceof URIError?new URIError('Pathname "'+a.pathname+'" could not be decoded. This is likely caused by an invalid percent-encoding.'):c}return n&&(a.key=n),o?a.pathname?"/"!==a.pathname.charAt(0)&&(a.pathname=i(a.pathname,o.pathname)):a.pathname=o.pathname:a.pathname||(a.pathname="/"),a}function m(){var e=null;var t=[];return{setPrompt:function(t){return e=t,function(){e===t&&(e=null)}},confirmTransitionTo:function(t,n,r,o){if(null!=e){var a="function"==typeof e?e(t,n):e;"string"==typeof a?"function"==typeof r?r(a,o):o(!0):o(!1!==a)}else o(!0)},appendListener:function(e){var n=!0;function r(){n&&e.apply(void 0,arguments)}return t.push(r),function(){n=!1,t=t.filter((function(e){return e!==r}))}},notifyListeners:function(){for(var e=arguments.length,n=new Array(e),r=0;r<e;r++)n[r]=arguments[r];t.forEach((function(e){return e.apply(void 0,n)}))}}}var g=!("undefined"==typeof window||!window.document||!window.document.createElement);function h(e,t){t(window.confirm(e))}var b="popstate",y="hashchange";function v(){try{return window.history.state||{}}catch(e){return{}}}function w(e){void 0===e&&(e={}),g||(0,c.A)(!1);var t,n=window.history,o=(-1===(t=window.navigator.userAgent).indexOf("Android 2.")&&-1===t.indexOf("Android 4.0")||-1===t.indexOf("Mobile Safari")||-1!==t.indexOf("Chrome")||-1!==t.indexOf("Windows Phone"))&&window.history&&"pushState"in window.history,a=!(-1===window.navigator.userAgent.indexOf("Trident")),i=e,l=i.forceRefresh,w=void 0!==l&&l,S=i.getUserConfirmation,k=void 0===S?h:S,x=i.keyLength,_=void 0===x?6:x,C=e.basename?d(s(e.basename)):"";function E(e){var t=e||{},n=t.key,r=t.state,o=window.location,a=o.pathname+o.search+o.hash;return C&&(a=u(a,C)),f(a,r,n)}function D(){return Math.random().toString(36).substr(2,_)}var j=m();function O(e){(0,r.A)($,e),$.length=n.length,j.notifyListeners($.location,$.action)}function A(e){(function(e){return void 0===e.state&&-1===navigator.userAgent.indexOf("CriOS")})(e)||I(E(e.state))}function T(){I(E(v()))}var P=!1;function I(e){if(P)P=!1,O();else{j.confirmTransitionTo(e,"POP",k,(function(t){t?O({action:"POP",location:e}):function(e){var t=$.location,n=R.indexOf(t.key);-1===n&&(n=0);var r=R.indexOf(e.key);-1===r&&(r=0);var o=n-r;o&&(P=!0,M(o))}(e)}))}}var N=E(v()),R=[N.key];function L(e){return C+p(e)}function M(e){n.go(e)}var F=0;function B(e){1===(F+=e)&&1===e?(window.addEventListener(b,A),a&&window.addEventListener(y,T)):0===F&&(window.removeEventListener(b,A),a&&window.removeEventListener(y,T))}var z=!1;var $={length:n.length,action:"POP",location:N,createHref:L,push:function(e,t){var r="PUSH",a=f(e,t,D(),$.location);j.confirmTransitionTo(a,r,k,(function(e){if(e){var t=L(a),i=a.key,c=a.state;if(o)if(n.pushState({key:i,state:c},null,t),w)window.location.href=t;else{var s=R.indexOf($.location.key),l=R.slice(0,s+1);l.push(a.key),R=l,O({action:r,location:a})}else window.location.href=t}}))},replace:function(e,t){var r="REPLACE",a=f(e,t,D(),$.location);j.confirmTransitionTo(a,r,k,(function(e){if(e){var t=L(a),i=a.key,c=a.state;if(o)if(n.replaceState({key:i,state:c},null,t),w)window.location.replace(t);else{var s=R.indexOf($.location.key);-1!==s&&(R[s]=a.key),O({action:r,location:a})}else window.location.replace(t)}}))},go:M,goBack:function(){M(-1)},goForward:function(){M(1)},block:function(e){void 0===e&&(e=!1);var t=j.setPrompt(e);return z||(B(1),z=!0),function(){return z&&(z=!1,B(-1)),t()}},listen:function(e){var t=j.appendListener(e);return B(1),function(){B(-1),t()}}};return $}var S="hashchange",k={hashbang:{encodePath:function(e){return"!"===e.charAt(0)?e:"!/"+l(e)},decodePath:function(e){return"!"===e.charAt(0)?e.substr(1):e}},noslash:{encodePath:l,decodePath:s},slash:{encodePath:s,decodePath:s}};function x(e){var t=e.indexOf("#");return-1===t?e:e.slice(0,t)}function _(){var e=window.location.href,t=e.indexOf("#");return-1===t?"":e.substring(t+1)}function C(e){window.location.replace(x(window.location.href)+"#"+e)}function E(e){void 0===e&&(e={}),g||(0,c.A)(!1);var t=window.history,n=(window.navigator.userAgent.indexOf("Firefox"),e),o=n.getUserConfirmation,a=void 0===o?h:o,i=n.hashType,l=void 0===i?"slash":i,b=e.basename?d(s(e.basename)):"",y=k[l],v=y.encodePath,w=y.decodePath;function E(){var e=w(_());return b&&(e=u(e,b)),f(e)}var D=m();function j(e){(0,r.A)(z,e),z.length=t.length,D.notifyListeners(z.location,z.action)}var O=!1,A=null;function T(){var e,t,n=_(),r=v(n);if(n!==r)C(r);else{var o=E(),i=z.location;if(!O&&(t=o,(e=i).pathname===t.pathname&&e.search===t.search&&e.hash===t.hash))return;if(A===p(o))return;A=null,function(e){if(O)O=!1,j();else{var t="POP";D.confirmTransitionTo(e,t,a,(function(n){n?j({action:t,location:e}):function(e){var t=z.location,n=R.lastIndexOf(p(t));-1===n&&(n=0);var r=R.lastIndexOf(p(e));-1===r&&(r=0);var o=n-r;o&&(O=!0,L(o))}(e)}))}}(o)}}var P=_(),I=v(P);P!==I&&C(I);var N=E(),R=[p(N)];function L(e){t.go(e)}var M=0;function F(e){1===(M+=e)&&1===e?window.addEventListener(S,T):0===M&&window.removeEventListener(S,T)}var B=!1;var z={length:t.length,action:"POP",location:N,createHref:function(e){var t=document.querySelector("base"),n="";return t&&t.getAttribute("href")&&(n=x(window.location.href)),n+"#"+v(b+p(e))},push:function(e,t){var n="PUSH",r=f(e,void 0,void 0,z.location);D.confirmTransitionTo(r,n,a,(function(e){if(e){var t=p(r),o=v(b+t);if(_()!==o){A=t,function(e){window.location.hash=e}(o);var a=R.lastIndexOf(p(z.location)),i=R.slice(0,a+1);i.push(t),R=i,j({action:n,location:r})}else j()}}))},replace:function(e,t){var n="REPLACE",r=f(e,void 0,void 0,z.location);D.confirmTransitionTo(r,n,a,(function(e){if(e){var t=p(r),o=v(b+t);_()!==o&&(A=t,C(o));var a=R.indexOf(p(z.location));-1!==a&&(R[a]=t),j({action:n,location:r})}}))},go:L,goBack:function(){L(-1)},goForward:function(){L(1)},block:function(e){void 0===e&&(e=!1);var t=D.setPrompt(e);return B||(F(1),B=!0),function(){return B&&(B=!1,F(-1)),t()}},listen:function(e){var t=D.appendListener(e);return F(1),function(){F(-1),t()}}};return z}function D(e,t,n){return Math.min(Math.max(e,t),n)}function j(e){void 0===e&&(e={});var t=e,n=t.getUserConfirmation,o=t.initialEntries,a=void 0===o?["/"]:o,i=t.initialIndex,c=void 0===i?0:i,s=t.keyLength,l=void 0===s?6:s,u=m();function d(e){(0,r.A)(w,e),w.length=w.entries.length,u.notifyListeners(w.location,w.action)}function g(){return Math.random().toString(36).substr(2,l)}var h=D(c,0,a.length-1),b=a.map((function(e){return f(e,void 0,"string"==typeof e?g():e.key||g())})),y=p;function v(e){var t=D(w.index+e,0,w.entries.length-1),r=w.entries[t];u.confirmTransitionTo(r,"POP",n,(function(e){e?d({action:"POP",location:r,index:t}):d()}))}var w={length:b.length,action:"POP",location:b[h],index:h,entries:b,createHref:y,push:function(e,t){var r="PUSH",o=f(e,t,g(),w.location);u.confirmTransitionTo(o,r,n,(function(e){if(e){var t=w.index+1,n=w.entries.slice(0);n.length>t?n.splice(t,n.length-t,o):n.push(o),d({action:r,location:o,index:t,entries:n})}}))},replace:function(e,t){var r="REPLACE",o=f(e,t,g(),w.location);u.confirmTransitionTo(o,r,n,(function(e){e&&(w.entries[w.index]=o,d({action:r,location:o}))}))},go:v,goBack:function(){v(-1)},goForward:function(){v(1)},canGo:function(e){var t=w.index+e;return t>=0&&t<w.entries.length},block:function(e){return void 0===e&&(e=!1),u.setPrompt(e)},listen:function(e){return u.appendListener(e)}};return w}},4146:(e,t,n)=>{"use strict";var r=n(4363),o={childContextTypes:!0,contextType:!0,contextTypes:!0,defaultProps:!0,displayName:!0,getDefaultProps:!0,getDerivedStateFromError:!0,getDerivedStateFromProps:!0,mixins:!0,propTypes:!0,type:!0},a={name:!0,length:!0,prototype:!0,caller:!0,callee:!0,arguments:!0,arity:!0},i={$$typeof:!0,compare:!0,defaultProps:!0,displayName:!0,propTypes:!0,type:!0},c={};function s(e){return r.isMemo(e)?i:c[e.$$typeof]||o}c[r.ForwardRef]={$$typeof:!0,render:!0,defaultProps:!0,displayName:!0,propTypes:!0},c[r.Memo]=i;var l=Object.defineProperty,u=Object.getOwnPropertyNames,d=Object.getOwnPropertySymbols,p=Object.getOwnPropertyDescriptor,f=Object.getPrototypeOf,m=Object.prototype;e.exports=function e(t,n,r){if("string"!=typeof n){if(m){var o=f(n);o&&o!==m&&e(t,o,r)}var i=u(n);d&&(i=i.concat(d(n)));for(var c=s(t),g=s(n),h=0;h<i.length;++h){var b=i[h];if(!(a[b]||r&&r[b]||g&&g[b]||c&&c[b])){var y=p(n,b);try{l(t,b,y)}catch(v){}}}}return t}},311:e=>{"use strict";e.exports=function(e,t,n,r,o,a,i,c){if(!e){var s;if(void 0===t)s=new Error("Minified exception occurred; use the non-minified dev environment for the full error message and additional helpful warnings.");else{var l=[n,r,o,a,i,c],u=0;(s=new Error(t.replace(/%s/g,(function(){return l[u++]})))).name="Invariant Violation"}throw s.framesToPop=1,s}}},4634:e=>{e.exports=Array.isArray||function(e){return"[object Array]"==Object.prototype.toString.call(e)}},119:(e,t,n)=>{"use strict";n.r(t)},1043:(e,t,n)=>{"use strict";n.r(t)},5947:function(e,t,n){var r,o;r=function(){var e,t,n={version:"0.2.0"},r=n.settings={minimum:.08,easing:"ease",positionUsing:"",speed:200,trickle:!0,trickleRate:.02,trickleSpeed:800,showSpinner:!0,barSelector:'[role="bar"]',spinnerSelector:'[role="spinner"]',parent:"body",template:'<div class="bar" role="bar"><div class="peg"></div></div><div class="spinner" role="spinner"><div class="spinner-icon"></div></div>'};function o(e,t,n){return e<t?t:e>n?n:e}function a(e){return 100*(-1+e)}function i(e,t,n){var o;return(o="translate3d"===r.positionUsing?{transform:"translate3d("+a(e)+"%,0,0)"}:"translate"===r.positionUsing?{transform:"translate("+a(e)+"%,0)"}:{"margin-left":a(e)+"%"}).transition="all "+t+"ms "+n,o}n.configure=function(e){var t,n;for(t in e)void 0!==(n=e[t])&&e.hasOwnProperty(t)&&(r[t]=n);return this},n.status=null,n.set=function(e){var t=n.isStarted();e=o(e,r.minimum,1),n.status=1===e?null:e;var a=n.render(!t),l=a.querySelector(r.barSelector),u=r.speed,d=r.easing;return a.offsetWidth,c((function(t){""===r.positionUsing&&(r.positionUsing=n.getPositioningCSS()),s(l,i(e,u,d)),1===e?(s(a,{transition:"none",opacity:1}),a.offsetWidth,setTimeout((function(){s(a,{transition:"all "+u+"ms linear",opacity:0}),setTimeout((function(){n.remove(),t()}),u)}),u)):setTimeout(t,u)})),this},n.isStarted=function(){return"number"==typeof n.status},n.start=function(){n.status||n.set(0);var e=function(){setTimeout((function(){n.status&&(n.trickle(),e())}),r.trickleSpeed)};return r.trickle&&e(),this},n.done=function(e){return e||n.status?n.inc(.3+.5*Math.random()).set(1):this},n.inc=function(e){var t=n.status;return t?("number"!=typeof e&&(e=(1-t)*o(Math.random()*t,.1,.95)),t=o(t+e,0,.994),n.set(t)):n.start()},n.trickle=function(){return n.inc(Math.random()*r.trickleRate)},e=0,t=0,n.promise=function(r){return r&&"resolved"!==r.state()?(0===t&&n.start(),e++,t++,r.always((function(){0==--t?(e=0,n.done()):n.set((e-t)/e)})),this):this},n.render=function(e){if(n.isRendered())return document.getElementById("nprogress");u(document.documentElement,"nprogress-busy");var t=document.createElement("div");t.id="nprogress",t.innerHTML=r.template;var o,i=t.querySelector(r.barSelector),c=e?"-100":a(n.status||0),l=document.querySelector(r.parent);return s(i,{transition:"all 0 linear",transform:"translate3d("+c+"%,0,0)"}),r.showSpinner||(o=t.querySelector(r.spinnerSelector))&&f(o),l!=document.body&&u(l,"nprogress-custom-parent"),l.appendChild(t),t},n.remove=function(){d(document.documentElement,"nprogress-busy"),d(document.querySelector(r.parent),"nprogress-custom-parent");var e=document.getElementById("nprogress");e&&f(e)},n.isRendered=function(){return!!document.getElementById("nprogress")},n.getPositioningCSS=function(){var e=document.body.style,t="WebkitTransform"in e?"Webkit":"MozTransform"in e?"Moz":"msTransform"in e?"ms":"OTransform"in e?"O":"";return t+"Perspective"in e?"translate3d":t+"Transform"in e?"translate":"margin"};var c=function(){var e=[];function t(){var n=e.shift();n&&n(t)}return function(n){e.push(n),1==e.length&&t()}}(),s=function(){var e=["Webkit","O","Moz","ms"],t={};function n(e){return e.replace(/^-ms-/,"ms-").replace(/-([\da-z])/gi,(function(e,t){return t.toUpperCase()}))}function r(t){var n=document.body.style;if(t in n)return t;for(var r,o=e.length,a=t.charAt(0).toUpperCase()+t.slice(1);o--;)if((r=e[o]+a)in n)return r;return t}function o(e){return e=n(e),t[e]||(t[e]=r(e))}function a(e,t,n){t=o(t),e.style[t]=n}return function(e,t){var n,r,o=arguments;if(2==o.length)for(n in t)void 0!==(r=t[n])&&t.hasOwnProperty(n)&&a(e,n,r);else a(e,o[1],o[2])}}();function l(e,t){return("string"==typeof e?e:p(e)).indexOf(" "+t+" ")>=0}function u(e,t){var n=p(e),r=n+t;l(n,t)||(e.className=r.substring(1))}function d(e,t){var n,r=p(e);l(e,t)&&(n=r.replace(" "+t+" "," "),e.className=n.substring(1,n.length-1))}function p(e){return(" "+(e.className||"")+" ").replace(/\s+/gi," ")}function f(e){e&&e.parentNode&&e.parentNode.removeChild(e)}return n},void 0===(o="function"==typeof r?r.call(t,n,t,e):r)||(e.exports=o)},5302:(e,t,n)=>{var r=n(4634);e.exports=m,e.exports.parse=a,e.exports.compile=function(e,t){return s(a(e,t),t)},e.exports.tokensToFunction=s,e.exports.tokensToRegExp=f;var o=new RegExp(["(\\\\.)","([\\/.])?(?:(?:\\:(\\w+)(?:\\(((?:\\\\.|[^\\\\()])+)\\))?|\\(((?:\\\\.|[^\\\\()])+)\\))([+*?])?|(\\*))"].join("|"),"g");function a(e,t){for(var n,r=[],a=0,c=0,s="",l=t&&t.delimiter||"/";null!=(n=o.exec(e));){var d=n[0],p=n[1],f=n.index;if(s+=e.slice(c,f),c=f+d.length,p)s+=p[1];else{var m=e[c],g=n[2],h=n[3],b=n[4],y=n[5],v=n[6],w=n[7];s&&(r.push(s),s="");var S=null!=g&&null!=m&&m!==g,k="+"===v||"*"===v,x="?"===v||"*"===v,_=g||l,C=b||y,E=g||("string"==typeof r[r.length-1]?r[r.length-1]:"");r.push({name:h||a++,prefix:g||"",delimiter:_,optional:x,repeat:k,partial:S,asterisk:!!w,pattern:C?u(C):w?".*":i(_,E)})}}return c<e.length&&(s+=e.substr(c)),s&&r.push(s),r}function i(e,t){return!t||t.indexOf(e)>-1?"[^"+l(e)+"]+?":l(t)+"|(?:(?!"+l(t)+")[^"+l(e)+"])+?"}function c(e){return encodeURI(e).replace(/[\/?#]/g,(function(e){return"%"+e.charCodeAt(0).toString(16).toUpperCase()}))}function s(e,t){for(var n=new Array(e.length),o=0;o<e.length;o++)"object"==typeof e[o]&&(n[o]=new RegExp("^(?:"+e[o].pattern+")$",p(t)));return function(t,o){for(var a="",i=t||{},s=(o||{}).pretty?c:encodeURIComponent,l=0;l<e.length;l++){var u=e[l];if("string"!=typeof u){var d,p=i[u.name];if(null==p){if(u.optional){u.partial&&(a+=u.prefix);continue}throw new TypeError('Expected "'+u.name+'" to be defined')}if(r(p)){if(!u.repeat)throw new TypeError('Expected "'+u.name+'" to not repeat, but received `'+JSON.stringify(p)+"`");if(0===p.length){if(u.optional)continue;throw new TypeError('Expected "'+u.name+'" to not be empty')}for(var f=0;f<p.length;f++){if(d=s(p[f]),!n[l].test(d))throw new TypeError('Expected all "'+u.name+'" to match "'+u.pattern+'", but received `'+JSON.stringify(d)+"`");a+=(0===f?u.prefix:u.delimiter)+d}}else{if(d=u.asterisk?encodeURI(p).replace(/[?#]/g,(function(e){return"%"+e.charCodeAt(0).toString(16).toUpperCase()})):s(p),!n[l].test(d))throw new TypeError('Expected "'+u.name+'" to match "'+u.pattern+'", but received "'+d+'"');a+=u.prefix+d}}else a+=u}return a}}function l(e){return e.replace(/([.+*?=^!:${}()[\]|\/\\])/g,"\\$1")}function u(e){return e.replace(/([=!:$\/()])/g,"\\$1")}function d(e,t){return e.keys=t,e}function p(e){return e&&e.sensitive?"":"i"}function f(e,t,n){r(t)||(n=t||n,t=[]);for(var o=(n=n||{}).strict,a=!1!==n.end,i="",c=0;c<e.length;c++){var s=e[c];if("string"==typeof s)i+=l(s);else{var u=l(s.prefix),f="(?:"+s.pattern+")";t.push(s),s.repeat&&(f+="(?:"+u+f+")*"),i+=f=s.optional?s.partial?u+"("+f+")?":"(?:"+u+"("+f+"))?":u+"("+f+")"}}var m=l(n.delimiter||"/"),g=i.slice(-m.length)===m;return o||(i=(g?i.slice(0,-m.length):i)+"(?:"+m+"(?=$))?"),i+=a?"$":o&&g?"":"(?="+m+"|$)",d(new RegExp("^"+i,p(n)),t)}function m(e,t,n){return r(t)||(n=t||n,t=[]),n=n||{},e instanceof RegExp?function(e,t){var n=e.source.match(/\((?!\?)/g);if(n)for(var r=0;r<n.length;r++)t.push({name:r,prefix:null,delimiter:null,optional:!1,repeat:!1,partial:!1,asterisk:!1,pattern:null});return d(e,t)}(e,t):r(e)?function(e,t,n){for(var r=[],o=0;o<e.length;o++)r.push(m(e[o],t,n).source);return d(new RegExp("(?:"+r.join("|")+")",p(n)),t)}(e,t,n):function(e,t,n){return f(a(e,n),t,n)}(e,t,n)}},7022:()=>{!function(e){var t="\\b(?:BASH|BASHOPTS|BASH_ALIASES|BASH_ARGC|BASH_ARGV|BASH_CMDS|BASH_COMPLETION_COMPAT_DIR|BASH_LINENO|BASH_REMATCH|BASH_SOURCE|BASH_VERSINFO|BASH_VERSION|COLORTERM|COLUMNS|COMP_WORDBREAKS|DBUS_SESSION_BUS_ADDRESS|DEFAULTS_PATH|DESKTOP_SESSION|DIRSTACK|DISPLAY|EUID|GDMSESSION|GDM_LANG|GNOME_KEYRING_CONTROL|GNOME_KEYRING_PID|GPG_AGENT_INFO|GROUPS|HISTCONTROL|HISTFILE|HISTFILESIZE|HISTSIZE|HOME|HOSTNAME|HOSTTYPE|IFS|INSTANCE|JOB|LANG|LANGUAGE|LC_ADDRESS|LC_ALL|LC_IDENTIFICATION|LC_MEASUREMENT|LC_MONETARY|LC_NAME|LC_NUMERIC|LC_PAPER|LC_TELEPHONE|LC_TIME|LESSCLOSE|LESSOPEN|LINES|LOGNAME|LS_COLORS|MACHTYPE|MAILCHECK|MANDATORY_PATH|NO_AT_BRIDGE|OLDPWD|OPTERR|OPTIND|ORBIT_SOCKETDIR|OSTYPE|PAPERSIZE|PATH|PIPESTATUS|PPID|PS1|PS2|PS3|PS4|PWD|RANDOM|REPLY|SECONDS|SELINUX_INIT|SESSION|SESSIONTYPE|SESSION_MANAGER|SHELL|SHELLOPTS|SHLVL|SSH_AUTH_SOCK|TERM|UID|UPSTART_EVENTS|UPSTART_INSTANCE|UPSTART_JOB|UPSTART_SESSION|USER|WINDOWID|XAUTHORITY|XDG_CONFIG_DIRS|XDG_CURRENT_DESKTOP|XDG_DATA_DIRS|XDG_GREETER_DATA_DIR|XDG_MENU_PREFIX|XDG_RUNTIME_DIR|XDG_SEAT|XDG_SEAT_PATH|XDG_SESSION_DESKTOP|XDG_SESSION_ID|XDG_SESSION_PATH|XDG_SESSION_TYPE|XDG_VTNR|XMODIFIERS)\\b",n={pattern:/(^(["']?)\w+\2)[ \t]+\S.*/,lookbehind:!0,alias:"punctuation",inside:null},r={bash:n,environment:{pattern:RegExp("\\$"+t),alias:"constant"},variable:[{pattern:/\$?\(\([\s\S]+?\)\)/,greedy:!0,inside:{variable:[{pattern:/(^\$\(\([\s\S]+)\)\)/,lookbehind:!0},/^\$\(\(/],number:/\b0x[\dA-Fa-f]+\b|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:[Ee]-?\d+)?/,operator:/--|\+\+|\*\*=?|<<=?|>>=?|&&|\|\||[=!+\-*/%<>^&|]=?|[?~:]/,punctuation:/\(\(?|\)\)?|,|;/}},{pattern:/\$\((?:\([^)]+\)|[^()])+\)|`[^`]+`/,greedy:!0,inside:{variable:/^\$\(|^`|\)$|`$/}},{pattern:/\$\{[^}]+\}/,greedy:!0,inside:{operator:/:[-=?+]?|[!\/]|##?|%%?|\^\^?|,,?/,punctuation:/[\[\]]/,environment:{pattern:RegExp("(\\{)"+t),lookbehind:!0,alias:"constant"}}},/\$(?:\w+|[#?*!@$])/],entity:/\\(?:[abceEfnrtv\\"]|O?[0-7]{1,3}|U[0-9a-fA-F]{8}|u[0-9a-fA-F]{4}|x[0-9a-fA-F]{1,2})/};e.languages.bash={shebang:{pattern:/^#!\s*\/.*/,alias:"important"},comment:{pattern:/(^|[^"{\\$])#.*/,lookbehind:!0},"function-name":[{pattern:/(\bfunction\s+)[\w-]+(?=(?:\s*\(?:\s*\))?\s*\{)/,lookbehind:!0,alias:"function"},{pattern:/\b[\w-]+(?=\s*\(\s*\)\s*\{)/,alias:"function"}],"for-or-select":{pattern:/(\b(?:for|select)\s+)\w+(?=\s+in\s)/,alias:"variable",lookbehind:!0},"assign-left":{pattern:/(^|[\s;|&]|[<>]\()\w+(?:\.\w+)*(?=\+?=)/,inside:{environment:{pattern:RegExp("(^|[\\s;|&]|[<>]\\()"+t),lookbehind:!0,alias:"constant"}},alias:"variable",lookbehind:!0},parameter:{pattern:/(^|\s)-{1,2}(?:\w+:[+-]?)?\w+(?:\.\w+)*(?=[=\s]|$)/,alias:"variable",lookbehind:!0},string:[{pattern:/((?:^|[^<])<<-?\s*)(\w+)\s[\s\S]*?(?:\r?\n|\r)\2/,lookbehind:!0,greedy:!0,inside:r},{pattern:/((?:^|[^<])<<-?\s*)(["'])(\w+)\2\s[\s\S]*?(?:\r?\n|\r)\3/,lookbehind:!0,greedy:!0,inside:{bash:n}},{pattern:/(^|[^\\](?:\\\\)*)"(?:\\[\s\S]|\$\([^)]+\)|\$(?!\()|`[^`]+`|[^"\\`$])*"/,lookbehind:!0,greedy:!0,inside:r},{pattern:/(^|[^$\\])'[^']*'/,lookbehind:!0,greedy:!0},{pattern:/\$'(?:[^'\\]|\\[\s\S])*'/,greedy:!0,inside:{entity:r.entity}}],environment:{pattern:RegExp("\\$?"+t),alias:"constant"},variable:r.variable,function:{pattern:/(^|[\s;|&]|[<>]\()(?:add|apropos|apt|apt-cache|apt-get|aptitude|aspell|automysqlbackup|awk|basename|bash|bc|bconsole|bg|bzip2|cal|cargo|cat|cfdisk|chgrp|chkconfig|chmod|chown|chroot|cksum|clear|cmp|column|comm|composer|cp|cron|crontab|csplit|curl|cut|date|dc|dd|ddrescue|debootstrap|df|diff|diff3|dig|dir|dircolors|dirname|dirs|dmesg|docker|docker-compose|du|egrep|eject|env|ethtool|expand|expect|expr|fdformat|fdisk|fg|fgrep|file|find|fmt|fold|format|free|fsck|ftp|fuser|gawk|git|gparted|grep|groupadd|groupdel|groupmod|groups|grub-mkconfig|gzip|halt|head|hg|history|host|hostname|htop|iconv|id|ifconfig|ifdown|ifup|import|install|ip|java|jobs|join|kill|killall|less|link|ln|locate|logname|logrotate|look|lpc|lpr|lprint|lprintd|lprintq|lprm|ls|lsof|lynx|make|man|mc|mdadm|mkconfig|mkdir|mke2fs|mkfifo|mkfs|mkisofs|mknod|mkswap|mmv|more|most|mount|mtools|mtr|mutt|mv|nano|nc|netstat|nice|nl|node|nohup|notify-send|npm|nslookup|op|open|parted|passwd|paste|pathchk|ping|pkill|pnpm|podman|podman-compose|popd|pr|printcap|printenv|ps|pushd|pv|quota|quotacheck|quotactl|ram|rar|rcp|reboot|remsync|rename|renice|rev|rm|rmdir|rpm|rsync|scp|screen|sdiff|sed|sendmail|seq|service|sftp|sh|shellcheck|shuf|shutdown|sleep|slocate|sort|split|ssh|stat|strace|su|sudo|sum|suspend|swapon|sync|sysctl|tac|tail|tar|tee|time|timeout|top|touch|tr|traceroute|tsort|tty|umount|uname|unexpand|uniq|units|unrar|unshar|unzip|update-grub|uptime|useradd|userdel|usermod|users|uudecode|uuencode|v|vcpkg|vdir|vi|vim|virsh|vmstat|wait|watch|wc|wget|whereis|which|who|whoami|write|xargs|xdg-open|yarn|yes|zenity|zip|zsh|zypper)(?=$|[)\s;|&])/,lookbehind:!0},keyword:{pattern:/(^|[\s;|&]|[<>]\()(?:case|do|done|elif|else|esac|fi|for|function|if|in|select|then|until|while)(?=$|[)\s;|&])/,lookbehind:!0},builtin:{pattern:/(^|[\s;|&]|[<>]\()(?:\.|:|alias|bind|break|builtin|caller|cd|command|continue|declare|echo|enable|eval|exec|exit|export|getopts|hash|help|let|local|logout|mapfile|printf|pwd|read|readarray|readonly|return|set|shift|shopt|source|test|times|trap|type|typeset|ulimit|umask|unalias|unset)(?=$|[)\s;|&])/,lookbehind:!0,alias:"class-name"},boolean:{pattern:/(^|[\s;|&]|[<>]\()(?:false|true)(?=$|[)\s;|&])/,lookbehind:!0},"file-descriptor":{pattern:/\B&\d\b/,alias:"important"},operator:{pattern:/\d?<>|>\||\+=|=[=~]?|!=?|<<[<-]?|[&\d]?>>|\d[<>]&?|[<>][&=]?|&[>&]?|\|[&|]?/,inside:{"file-descriptor":{pattern:/^\d/,alias:"important"}}},punctuation:/\$?\(\(?|\)\)?|\.\.|[{}[\];\\]/,number:{pattern:/(^|\s)(?:[1-9]\d*|0)(?:[.,]\d+)?\b/,lookbehind:!0}},n.inside=e.languages.bash;for(var o=["comment","function-name","for-or-select","assign-left","parameter","string","environment","function","keyword","builtin","boolean","file-descriptor","operator","punctuation","number"],a=r.variable[1].inside,i=0;i<o.length;i++)a[o[i]]=e.languages.bash[o[i]];e.languages.sh=e.languages.bash,e.languages.shell=e.languages.bash}(Prism)},6378:()=>{Prism.languages.go=Prism.languages.extend("clike",{string:{pattern:/(^|[^\\])"(?:\\.|[^"\\\r\n])*"|`[^`]*`/,lookbehind:!0,greedy:!0},keyword:/\b(?:break|case|chan|const|continue|default|defer|else|fallthrough|for|func|go(?:to)?|if|import|interface|map|package|range|return|select|struct|switch|type|var)\b/,boolean:/\b(?:_|false|iota|nil|true)\b/,number:[/\b0(?:b[01_]+|o[0-7_]+)i?\b/i,/\b0x(?:[a-f\d_]+(?:\.[a-f\d_]*)?|\.[a-f\d_]+)(?:p[+-]?\d+(?:_\d+)*)?i?(?!\w)/i,/(?:\b\d[\d_]*(?:\.[\d_]*)?|\B\.\d[\d_]*)(?:e[+-]?[\d_]+)?i?(?!\w)/i],operator:/[*\/%^!=]=?|\+[=+]?|-[=-]?|\|[=|]?|&(?:=|&|\^=?)?|>(?:>=?|=)?|<(?:<=?|=|-)?|:=|\.\.\./,builtin:/\b(?:append|bool|byte|cap|close|complex|complex(?:64|128)|copy|delete|error|float(?:32|64)|u?int(?:8|16|32|64)?|imag|len|make|new|panic|print(?:ln)?|real|recover|rune|string|uintptr)\b/}),Prism.languages.insertBefore("go","string",{char:{pattern:/'(?:\\.|[^'\\\r\n]){0,10}'/,greedy:!0}}),delete Prism.languages.go["class-name"]},3523:()=>{!function(e){var t={pattern:/((?:^|[^\\$])(?:\\{2})*)\$(?:\w+|\{[^{}]*\})/,lookbehind:!0,inside:{"interpolation-punctuation":{pattern:/^\$\{?|\}$/,alias:"punctuation"},expression:{pattern:/[\s\S]+/,inside:null}}};e.languages.gradle=e.languages.extend("clike",{string:{pattern:/'''(?:[^\\]|\\[\s\S])*?'''|'(?:\\.|[^\\'\r\n])*'/,greedy:!0},keyword:/\b(?:apply|def|dependencies|else|if|implementation|import|plugin|plugins|project|repositories|repository|sourceSets|tasks|val)\b/,number:/\b(?:0b[01_]+|0x[\da-f_]+(?:\.[\da-f_p\-]+)?|[\d_]+(?:\.[\d_]+)?(?:e[+-]?\d+)?)[glidf]?\b/i,operator:{pattern:/(^|[^.])(?:~|==?~?|\?[.:]?|\*(?:[.=]|\*=?)?|\.[@&]|\.\.<|\.\.(?!\.)|-[-=>]?|\+[+=]?|!=?|<(?:<=?|=>?)?|>(?:>>?=?|=)?|&[&=]?|\|[|=]?|\/=?|\^=?|%=?)/,lookbehind:!0},punctuation:/\.+|[{}[\];(),:$]/}),e.languages.insertBefore("gradle","string",{shebang:{pattern:/#!.+/,alias:"comment",greedy:!0},"interpolation-string":{pattern:/"""(?:[^\\]|\\[\s\S])*?"""|(["/])(?:\\.|(?!\1)[^\\\r\n])*\1|\$\/(?:[^/$]|\$(?:[/$]|(?![/$]))|\/(?!\$))*\/\$/,greedy:!0,inside:{interpolation:t,string:/[\s\S]+/}}}),e.languages.insertBefore("gradle","punctuation",{"spock-block":/\b(?:and|cleanup|expect|given|setup|then|when|where):/}),e.languages.insertBefore("gradle","function",{annotation:{pattern:/(^|[^.])@\w+/,lookbehind:!0,alias:"punctuation"}}),t.inside.expression.inside=e.languages.gradle}(Prism)},6976:()=>{!function(e){var t=/\b(?:abstract|assert|boolean|break|byte|case|catch|char|class|const|continue|default|do|double|else|enum|exports|extends|final|finally|float|for|goto|if|implements|import|instanceof|int|interface|long|module|native|new|non-sealed|null|open|opens|package|permits|private|protected|provides|public|record(?!\s*[(){}[\]<>=%~.:,;?+\-*/&|^])|requires|return|sealed|short|static|strictfp|super|switch|synchronized|this|throw|throws|to|transient|transitive|try|uses|var|void|volatile|while|with|yield)\b/,n=/(?:[a-z]\w*\s*\.\s*)*(?:[A-Z]\w*\s*\.\s*)*/.source,r={pattern:RegExp(/(^|[^\w.])/.source+n+/[A-Z](?:[\d_A-Z]*[a-z]\w*)?\b/.source),lookbehind:!0,inside:{namespace:{pattern:/^[a-z]\w*(?:\s*\.\s*[a-z]\w*)*(?:\s*\.)?/,inside:{punctuation:/\./}},punctuation:/\./}};e.languages.java=e.languages.extend("clike",{string:{pattern:/(^|[^\\])"(?:\\.|[^"\\\r\n])*"/,lookbehind:!0,greedy:!0},"class-name":[r,{pattern:RegExp(/(^|[^\w.])/.source+n+/[A-Z]\w*(?=\s+\w+\s*[;,=()]|\s*(?:\[[\s,]*\]\s*)?::\s*new\b)/.source),lookbehind:!0,inside:r.inside},{pattern:RegExp(/(\b(?:class|enum|extends|implements|instanceof|interface|new|record|throws)\s+)/.source+n+/[A-Z]\w*\b/.source),lookbehind:!0,inside:r.inside}],keyword:t,function:[e.languages.clike.function,{pattern:/(::\s*)[a-z_]\w*/,lookbehind:!0}],number:/\b0b[01][01_]*L?\b|\b0x(?:\.[\da-f_p+-]+|[\da-f_]+(?:\.[\da-f_p+-]+)?)\b|(?:\b\d[\d_]*(?:\.[\d_]*)?|\B\.\d[\d_]*)(?:e[+-]?\d[\d_]*)?[dfl]?/i,operator:{pattern:/(^|[^.])(?:<<=?|>>>?=?|->|--|\+\+|&&|\|\||::|[?:~]|[-+*/%&|^!=<>]=?)/m,lookbehind:!0},constant:/\b[A-Z][A-Z_\d]+\b/}),e.languages.insertBefore("java","string",{"triple-quoted-string":{pattern:/"""[ \t]*[\r\n](?:(?:"|"")?(?:\\.|[^"\\]))*"""/,greedy:!0,alias:"string"},char:{pattern:/'(?:\\.|[^'\\\r\n]){1,6}'/,greedy:!0}}),e.languages.insertBefore("java","class-name",{annotation:{pattern:/(^|[^.])@\w+(?:\s*\.\s*\w+)*/,lookbehind:!0,alias:"punctuation"},generics:{pattern:/<(?:[\w\s,.?]|&(?!&)|<(?:[\w\s,.?]|&(?!&)|<(?:[\w\s,.?]|&(?!&)|<(?:[\w\s,.?]|&(?!&))*>)*>)*>)*>/,inside:{"class-name":r,keyword:t,punctuation:/[<>(),.:]/,operator:/[?&|]/}},import:[{pattern:RegExp(/(\bimport\s+)/.source+n+/(?:[A-Z]\w*|\*)(?=\s*;)/.source),lookbehind:!0,inside:{namespace:r.inside.namespace,punctuation:/\./,operator:/\*/,"class-name":/\w+/}},{pattern:RegExp(/(\bimport\s+static\s+)/.source+n+/(?:\w+|\*)(?=\s*;)/.source),lookbehind:!0,alias:"static",inside:{namespace:r.inside.namespace,static:/\b\w+$/,punctuation:/\./,operator:/\*/,"class-name":/\w+/}}],namespace:{pattern:RegExp(/(\b(?:exports|import(?:\s+static)?|module|open|opens|package|provides|requires|to|transitive|uses|with)\s+)(?!<keyword>)[a-z]\w*(?:\.[a-z]\w*)*\.?/.source.replace(/<keyword>/g,(function(){return t.source}))),lookbehind:!0,inside:{punctuation:/\./}}})}(Prism)},2514:()=>{Prism.languages.json={property:{pattern:/(^|[^\\])"(?:\\.|[^\\"\r\n])*"(?=\s*:)/,lookbehind:!0,greedy:!0},string:{pattern:/(^|[^\\])"(?:\\.|[^\\"\r\n])*"(?!\s*:)/,lookbehind:!0,greedy:!0},comment:{pattern:/\/\/.*|\/\*[\s\S]*?(?:\*\/|$)/,greedy:!0},number:/-?\b\d+(?:\.\d+)?(?:e[+-]?\d+)?\b/i,punctuation:/[{}[\],]/,operator:/:/,boolean:/\b(?:false|true)\b/,null:{pattern:/\bnull\b/,alias:"keyword"}},Prism.languages.webmanifest=Prism.languages.json},8160:()=>{Prism.languages.log={string:{pattern:/"(?:[^"\\\r\n]|\\.)*"|'(?![st] | \w)(?:[^'\\\r\n]|\\.)*'/,greedy:!0},exception:{pattern:/(^|[^\w.])[a-z][\w.]*(?:Error|Exception):.*(?:(?:\r\n?|\n)[ \t]*(?:at[ \t].+|\.{3}.*|Caused by:.*))+(?:(?:\r\n?|\n)[ \t]*\.\.\. .*)?/,lookbehind:!0,greedy:!0,alias:["javastacktrace","language-javastacktrace"],inside:Prism.languages.javastacktrace||{keyword:/\bat\b/,function:/[a-z_][\w$]*(?=\()/,punctuation:/[.:()]/}},level:[{pattern:/\b(?:ALERT|CRIT|CRITICAL|EMERG|EMERGENCY|ERR|ERROR|FAILURE|FATAL|SEVERE)\b/,alias:["error","important"]},{pattern:/\b(?:WARN|WARNING|WRN)\b/,alias:["warning","important"]},{pattern:/\b(?:DISPLAY|INF|INFO|NOTICE|STATUS)\b/,alias:["info","keyword"]},{pattern:/\b(?:DBG|DEBUG|FINE)\b/,alias:["debug","keyword"]},{pattern:/\b(?:FINER|FINEST|TRACE|TRC|VERBOSE|VRB)\b/,alias:["trace","comment"]}],property:{pattern:/((?:^|[\]|])[ \t]*)[a-z_](?:[\w-]|\b\/\b)*(?:[. ]\(?\w(?:[\w-]|\b\/\b)*\)?)*:(?=\s)/im,lookbehind:!0},separator:{pattern:/(^|[^-+])-{3,}|={3,}|\*{3,}|- - /m,lookbehind:!0,alias:"comment"},url:/\b(?:file|ftp|https?):\/\/[^\s|,;'"]*[^\s|,;'">.]/,email:{pattern:/(^|\s)[-\w+.]+@[a-z][a-z0-9-]*(?:\.[a-z][a-z0-9-]*)+(?=\s)/,lookbehind:!0,alias:"url"},"ip-address":{pattern:/\b(?:\d{1,3}(?:\.\d{1,3}){3})\b/,alias:"constant"},"mac-address":{pattern:/\b[a-f0-9]{2}(?::[a-f0-9]{2}){5}\b/i,alias:"constant"},domain:{pattern:/(^|\s)[a-z][a-z0-9-]*(?:\.[a-z][a-z0-9-]*)*\.[a-z][a-z0-9-]+(?=\s)/,lookbehind:!0,alias:"constant"},uuid:{pattern:/\b[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\b/i,alias:"constant"},hash:{pattern:/\b(?:[a-f0-9]{32}){1,2}\b/i,alias:"constant"},"file-path":{pattern:/\b[a-z]:[\\/][^\s|,;:(){}\[\]"']+|(^|[\s:\[\](>|])\.{0,2}\/\w[^\s|,;:(){}\[\]"']*/i,lookbehind:!0,greedy:!0,alias:"string"},date:{pattern:RegExp(/\b\d{4}[-/]\d{2}[-/]\d{2}(?:T(?=\d{1,2}:)|(?=\s\d{1,2}:))/.source+"|"+/\b\d{1,4}[-/ ](?:\d{1,2}|Apr|Aug|Dec|Feb|Jan|Jul|Jun|Mar|May|Nov|Oct|Sep)[-/ ]\d{2,4}T?\b/.source+"|"+/\b(?:(?:Fri|Mon|Sat|Sun|Thu|Tue|Wed)(?:\s{1,2}(?:Apr|Aug|Dec|Feb|Jan|Jul|Jun|Mar|May|Nov|Oct|Sep))?|Apr|Aug|Dec|Feb|Jan|Jul|Jun|Mar|May|Nov|Oct|Sep)\s{1,2}\d{1,2}\b/.source,"i"),alias:"number"},time:{pattern:/\b\d{1,2}:\d{1,2}:\d{1,2}(?:[.,:]\d+)?(?:\s?[+-]\d{2}:?\d{2}|Z)?\b/,alias:"number"},boolean:/\b(?:false|null|true)\b/i,number:{pattern:/(^|[^.\w])(?:0x[a-f0-9]+|0o[0-7]+|0b[01]+|v?\d[\da-f]*(?:\.\d+)*(?:e[+-]?\d+)?[a-z]{0,3}\b)\b(?!\.\w)/i,lookbehind:!0},operator:/[;:?<=>~/@!$%&+\-|^(){}*#]/,punctuation:/[\[\].,]/}},9700:()=>{!function(e){function t(e,t){return"___"+e.toUpperCase()+t+"___"}Object.defineProperties(e.languages["markup-templating"]={},{buildPlaceholders:{value:function(n,r,o,a){if(n.language===r){var i=n.tokenStack=[];n.code=n.code.replace(o,(function(e){if("function"==typeof a&&!a(e))return e;for(var o,c=i.length;-1!==n.code.indexOf(o=t(r,c));)++c;return i[c]=e,o})),n.grammar=e.languages.markup}}},tokenizePlaceholders:{value:function(n,r){if(n.language===r&&n.tokenStack){n.grammar=e.languages[r];var o=0,a=Object.keys(n.tokenStack);!function i(c){for(var s=0;s<c.length&&!(o>=a.length);s++){var l=c[s];if("string"==typeof l||l.content&&"string"==typeof l.content){var u=a[o],d=n.tokenStack[u],p="string"==typeof l?l:l.content,f=t(r,u),m=p.indexOf(f);if(m>-1){++o;var g=p.substring(0,m),h=new e.Token(r,e.tokenize(d,n.grammar),"language-"+r,d),b=p.substring(m+f.length),y=[];g&&y.push.apply(y,i([g])),y.push(h),b&&y.push.apply(y,i([b])),"string"==typeof l?c.splice.apply(c,[s,1].concat(y)):l.content=y}}else l.content&&i(l.content)}return c}(n.tokens)}}}})}(Prism)},4312:()=>{Prism.languages.markup={comment:{pattern:/<!--(?:(?!<!--)[\s\S])*?-->/,greedy:!0},prolog:{pattern:/<\?[\s\S]+?\?>/,greedy:!0},doctype:{pattern:/<!DOCTYPE(?:[^>"'[\]]|"[^"]*"|'[^']*')+(?:\[(?:[^<"'\]]|"[^"]*"|'[^']*'|<(?!!--)|<!--(?:[^-]|-(?!->))*-->)*\]\s*)?>/i,greedy:!0,inside:{"internal-subset":{pattern:/(^[^\[]*\[)[\s\S]+(?=\]>$)/,lookbehind:!0,greedy:!0,inside:null},string:{pattern:/"[^"]*"|'[^']*'/,greedy:!0},punctuation:/^<!|>$|[[\]]/,"doctype-tag":/^DOCTYPE/i,name:/[^\s<>'"]+/}},cdata:{pattern:/<!\[CDATA\[[\s\S]*?\]\]>/i,greedy:!0},tag:{pattern:/<\/?(?!\d)[^\s>\/=$<%]+(?:\s(?:\s*[^\s>\/=]+(?:\s*=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+(?=[\s>]))|(?=[\s/>])))+)?\s*\/?>/,greedy:!0,inside:{tag:{pattern:/^<\/?[^\s>\/]+/,inside:{punctuation:/^<\/?/,namespace:/^[^\s>\/:]+:/}},"special-attr":[],"attr-value":{pattern:/=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+)/,inside:{punctuation:[{pattern:/^=/,alias:"attr-equals"},{pattern:/^(\s*)["']|["']$/,lookbehind:!0}]}},punctuation:/\/?>/,"attr-name":{pattern:/[^\s>\/]+/,inside:{namespace:/^[^\s>\/:]+:/}}}},entity:[{pattern:/&[\da-z]{1,8};/i,alias:"named-entity"},/&#x?[\da-f]{1,8};/i]},Prism.languages.markup.tag.inside["attr-value"].inside.entity=Prism.languages.markup.entity,Prism.languages.markup.doctype.inside["internal-subset"].inside=Prism.languages.markup,Prism.hooks.add("wrap",(function(e){"entity"===e.type&&(e.attributes.title=e.content.replace(/&/,"&"))})),Object.defineProperty(Prism.languages.markup.tag,"addInlined",{value:function(e,t){var n={};n["language-"+t]={pattern:/(^<!\[CDATA\[)[\s\S]+?(?=\]\]>$)/i,lookbehind:!0,inside:Prism.languages[t]},n.cdata=/^<!\[CDATA\[|\]\]>$/i;var r={"included-cdata":{pattern:/<!\[CDATA\[[\s\S]*?\]\]>/i,inside:n}};r["language-"+t]={pattern:/[\s\S]+/,inside:Prism.languages[t]};var o={};o[e]={pattern:RegExp(/(<__[^>]*>)(?:<!\[CDATA\[(?:[^\]]|\](?!\]>))*\]\]>|(?!<!\[CDATA\[)[\s\S])*?(?=<\/__>)/.source.replace(/__/g,(function(){return e})),"i"),lookbehind:!0,greedy:!0,inside:r},Prism.languages.insertBefore("markup","cdata",o)}}),Object.defineProperty(Prism.languages.markup.tag,"addAttribute",{value:function(e,t){Prism.languages.markup.tag.inside["special-attr"].push({pattern:RegExp(/(^|["'\s])/.source+"(?:"+e+")"+/\s*=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+(?=[\s>]))/.source,"i"),lookbehind:!0,inside:{"attr-name":/^[^\s=]+/,"attr-value":{pattern:/=[\s\S]+/,inside:{value:{pattern:/(^=\s*(["']|(?!["'])))\S[\s\S]*(?=\2$)/,lookbehind:!0,alias:[t,"language-"+t],inside:Prism.languages[t]},punctuation:[{pattern:/^=/,alias:"attr-equals"},/"|'/]}}}})}}),Prism.languages.html=Prism.languages.markup,Prism.languages.mathml=Prism.languages.markup,Prism.languages.svg=Prism.languages.markup,Prism.languages.xml=Prism.languages.extend("markup",{}),Prism.languages.ssml=Prism.languages.xml,Prism.languages.atom=Prism.languages.xml,Prism.languages.rss=Prism.languages.xml},61:()=>{!function(e){var t=[/"(?:\\[\s\S]|\$\([^)]+\)|\$(?!\()|`[^`]+`|[^"\\`$])*"/.source,/'[^']*'/.source,/\$'(?:[^'\\]|\\[\s\S])*'/.source,/<<-?\s*(["']?)(\w+)\1\s[\s\S]*?[\r\n]\2/.source].join("|");e.languages["shell-session"]={command:{pattern:RegExp(/^/.source+"(?:"+/[^\s@:$#%*!/\\]+@[^\r\n@:$#%*!/\\]+(?::[^\0-\x1F$#%*?"<>:;|]+)?/.source+"|"+/[/~.][^\0-\x1F$#%*?"<>@:;|]*/.source+")?"+/[$#%](?=\s)/.source+/(?:[^\\\r\n \t'"<$]|[ \t](?:(?!#)|#.*$)|\\(?:[^\r]|\r\n?)|\$(?!')|<(?!<)|<<str>>)+/.source.replace(/<<str>>/g,(function(){return t})),"m"),greedy:!0,inside:{info:{pattern:/^[^#$%]+/,alias:"punctuation",inside:{user:/^[^\s@:$#%*!/\\]+@[^\r\n@:$#%*!/\\]+/,punctuation:/:/,path:/[\s\S]+/}},bash:{pattern:/(^[$#%]\s*)\S[\s\S]*/,lookbehind:!0,alias:"language-bash",inside:e.languages.bash},"shell-symbol":{pattern:/^[$#%]/,alias:"important"}}},output:/.(?:.*(?:[\r\n]|.$))*/},e.languages["sh-session"]=e.languages.shellsession=e.languages["shell-session"]}(Prism)},83:()=>{!function(e){var t=/[*&][^\s[\]{},]+/,n=/!(?:<[\w\-%#;/?:@&=+$,.!~*'()[\]]+>|(?:[a-zA-Z\d-]*!)?[\w\-%#;/?:@&=+$.~*'()]+)?/,r="(?:"+n.source+"(?:[ \t]+"+t.source+")?|"+t.source+"(?:[ \t]+"+n.source+")?)",o=/(?:[^\s\x00-\x08\x0e-\x1f!"#%&'*,\-:>?@[\]`{|}\x7f-\x84\x86-\x9f\ud800-\udfff\ufffe\uffff]|[?:-]<PLAIN>)(?:[ \t]*(?:(?![#:])<PLAIN>|:<PLAIN>))*/.source.replace(/<PLAIN>/g,(function(){return/[^\s\x00-\x08\x0e-\x1f,[\]{}\x7f-\x84\x86-\x9f\ud800-\udfff\ufffe\uffff]/.source})),a=/"(?:[^"\\\r\n]|\\.)*"|'(?:[^'\\\r\n]|\\.)*'/.source;function i(e,t){t=(t||"").replace(/m/g,"")+"m";var n=/([:\-,[{]\s*(?:\s<<prop>>[ \t]+)?)(?:<<value>>)(?=[ \t]*(?:$|,|\]|\}|(?:[\r\n]\s*)?#))/.source.replace(/<<prop>>/g,(function(){return r})).replace(/<<value>>/g,(function(){return e}));return RegExp(n,t)}e.languages.yaml={scalar:{pattern:RegExp(/([\-:]\s*(?:\s<<prop>>[ \t]+)?[|>])[ \t]*(?:((?:\r?\n|\r)[ \t]+)\S[^\r\n]*(?:\2[^\r\n]+)*)/.source.replace(/<<prop>>/g,(function(){return r}))),lookbehind:!0,alias:"string"},comment:/#.*/,key:{pattern:RegExp(/((?:^|[:\-,[{\r\n?])[ \t]*(?:<<prop>>[ \t]+)?)<<key>>(?=\s*:\s)/.source.replace(/<<prop>>/g,(function(){return r})).replace(/<<key>>/g,(function(){return"(?:"+o+"|"+a+")"}))),lookbehind:!0,greedy:!0,alias:"atrule"},directive:{pattern:/(^[ \t]*)%.+/m,lookbehind:!0,alias:"important"},datetime:{pattern:i(/\d{4}-\d\d?-\d\d?(?:[tT]|[ \t]+)\d\d?:\d{2}:\d{2}(?:\.\d*)?(?:[ \t]*(?:Z|[-+]\d\d?(?::\d{2})?))?|\d{4}-\d{2}-\d{2}|\d\d?:\d{2}(?::\d{2}(?:\.\d*)?)?/.source),lookbehind:!0,alias:"number"},boolean:{pattern:i(/false|true/.source,"i"),lookbehind:!0,alias:"important"},null:{pattern:i(/null|~/.source,"i"),lookbehind:!0,alias:"important"},string:{pattern:i(a),lookbehind:!0,greedy:!0},number:{pattern:i(/[+-]?(?:0x[\da-f]+|0o[0-7]+|(?:\d+(?:\.\d*)?|\.\d+)(?:e[+-]?\d+)?|\.inf|\.nan)/.source,"i"),lookbehind:!0},tag:n,important:t,punctuation:/---|[:[\]{}\-,|>?]|\.\.\./},e.languages.yml=e.languages.yaml}(Prism)},803:(e,t,n)=>{var r={"./prism-bash":7022,"./prism-go":6378,"./prism-gradle":3523,"./prism-java":6976,"./prism-json":2514,"./prism-log":8160,"./prism-markup":4312,"./prism-shell-session":61,"./prism-yaml":83};function o(e){var t=a(e);return n(t)}function a(e){if(!n.o(r,e)){var t=new Error("Cannot find module '"+e+"'");throw t.code="MODULE_NOT_FOUND",t}return r[e]}o.keys=function(){return Object.keys(r)},o.resolve=a,e.exports=o,o.id=803},2694:(e,t,n)=>{"use strict";var r=n(6925);function o(){}function a(){}a.resetWarningCache=o,e.exports=function(){function e(e,t,n,o,a,i){if(i!==r){var c=new Error("Calling PropTypes validators directly is not supported by the `prop-types` package. Use PropTypes.checkPropTypes() to call them. Read more at http://fb.me/use-check-prop-types");throw c.name="Invariant Violation",c}}function t(){return e}e.isRequired=e;var n={array:e,bigint:e,bool:e,func:e,number:e,object:e,string:e,symbol:e,any:e,arrayOf:t,element:e,elementType:e,instanceOf:t,node:e,objectOf:t,oneOf:t,oneOfType:t,shape:t,exact:t,checkPropTypes:a,resetWarningCache:o};return n.PropTypes=n,n}},5556:(e,t,n)=>{e.exports=n(2694)()},6925:e=>{"use strict";e.exports="SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED"},2551:(e,t,n)=>{"use strict";var r=n(6540),o=n(9982);function a(e){for(var t="https://reactjs.org/docs/error-decoder.html?invariant="+e,n=1;n<arguments.length;n++)t+="&args[]="+encodeURIComponent(arguments[n]);return"Minified React error #"+e+"; visit "+t+" for the full message or use the non-minified dev environment for full errors and additional helpful warnings."}var i=new Set,c={};function s(e,t){l(e,t),l(e+"Capture",t)}function l(e,t){for(c[e]=t,e=0;e<t.length;e++)i.add(t[e])}var u=!("undefined"==typeof window||void 0===window.document||void 0===window.document.createElement),d=Object.prototype.hasOwnProperty,p=/^[:A-Z_a-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD][:A-Z_a-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD\-.0-9\u00B7\u0300-\u036F\u203F-\u2040]*$/,f={},m={};function g(e,t,n,r,o,a,i){this.acceptsBooleans=2===t||3===t||4===t,this.attributeName=r,this.attributeNamespace=o,this.mustUseProperty=n,this.propertyName=e,this.type=t,this.sanitizeURL=a,this.removeEmptyString=i}var h={};"children dangerouslySetInnerHTML defaultValue defaultChecked innerHTML suppressContentEditableWarning suppressHydrationWarning style".split(" ").forEach((function(e){h[e]=new g(e,0,!1,e,null,!1,!1)})),[["acceptCharset","accept-charset"],["className","class"],["htmlFor","for"],["httpEquiv","http-equiv"]].forEach((function(e){var t=e[0];h[t]=new g(t,1,!1,e[1],null,!1,!1)})),["contentEditable","draggable","spellCheck","value"].forEach((function(e){h[e]=new g(e,2,!1,e.toLowerCase(),null,!1,!1)})),["autoReverse","externalResourcesRequired","focusable","preserveAlpha"].forEach((function(e){h[e]=new g(e,2,!1,e,null,!1,!1)})),"allowFullScreen async autoFocus autoPlay controls default defer disabled disablePictureInPicture disableRemotePlayback formNoValidate hidden loop noModule noValidate open playsInline readOnly required reversed scoped seamless itemScope".split(" ").forEach((function(e){h[e]=new g(e,3,!1,e.toLowerCase(),null,!1,!1)})),["checked","multiple","muted","selected"].forEach((function(e){h[e]=new g(e,3,!0,e,null,!1,!1)})),["capture","download"].forEach((function(e){h[e]=new g(e,4,!1,e,null,!1,!1)})),["cols","rows","size","span"].forEach((function(e){h[e]=new g(e,6,!1,e,null,!1,!1)})),["rowSpan","start"].forEach((function(e){h[e]=new g(e,5,!1,e.toLowerCase(),null,!1,!1)}));var b=/[\-:]([a-z])/g;function y(e){return e[1].toUpperCase()}function v(e,t,n,r){var o=h.hasOwnProperty(t)?h[t]:null;(null!==o?0!==o.type:r||!(2<t.length)||"o"!==t[0]&&"O"!==t[0]||"n"!==t[1]&&"N"!==t[1])&&(function(e,t,n,r){if(null==t||function(e,t,n,r){if(null!==n&&0===n.type)return!1;switch(typeof t){case"function":case"symbol":return!0;case"boolean":return!r&&(null!==n?!n.acceptsBooleans:"data-"!==(e=e.toLowerCase().slice(0,5))&&"aria-"!==e);default:return!1}}(e,t,n,r))return!0;if(r)return!1;if(null!==n)switch(n.type){case 3:return!t;case 4:return!1===t;case 5:return isNaN(t);case 6:return isNaN(t)||1>t}return!1}(t,n,o,r)&&(n=null),r||null===o?function(e){return!!d.call(m,e)||!d.call(f,e)&&(p.test(e)?m[e]=!0:(f[e]=!0,!1))}(t)&&(null===n?e.removeAttribute(t):e.setAttribute(t,""+n)):o.mustUseProperty?e[o.propertyName]=null===n?3!==o.type&&"":n:(t=o.attributeName,r=o.attributeNamespace,null===n?e.removeAttribute(t):(n=3===(o=o.type)||4===o&&!0===n?"":""+n,r?e.setAttributeNS(r,t,n):e.setAttribute(t,n))))}"accent-height alignment-baseline arabic-form baseline-shift cap-height clip-path clip-rule color-interpolation color-interpolation-filters color-profile color-rendering dominant-baseline enable-background fill-opacity fill-rule flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-name glyph-orientation-horizontal glyph-orientation-vertical horiz-adv-x horiz-origin-x image-rendering letter-spacing lighting-color marker-end marker-mid marker-start overline-position overline-thickness paint-order panose-1 pointer-events rendering-intent shape-rendering stop-color stop-opacity strikethrough-position strikethrough-thickness stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width text-anchor text-decoration text-rendering underline-position underline-thickness unicode-bidi unicode-range units-per-em v-alphabetic v-hanging v-ideographic v-mathematical vector-effect vert-adv-y vert-origin-x vert-origin-y word-spacing writing-mode xmlns:xlink x-height".split(" ").forEach((function(e){var t=e.replace(b,y);h[t]=new g(t,1,!1,e,null,!1,!1)})),"xlink:actuate xlink:arcrole xlink:role xlink:show xlink:title xlink:type".split(" ").forEach((function(e){var t=e.replace(b,y);h[t]=new g(t,1,!1,e,"http://www.w3.org/1999/xlink",!1,!1)})),["xml:base","xml:lang","xml:space"].forEach((function(e){var t=e.replace(b,y);h[t]=new g(t,1,!1,e,"http://www.w3.org/XML/1998/namespace",!1,!1)})),["tabIndex","crossOrigin"].forEach((function(e){h[e]=new g(e,1,!1,e.toLowerCase(),null,!1,!1)})),h.xlinkHref=new g("xlinkHref",1,!1,"xlink:href","http://www.w3.org/1999/xlink",!0,!1),["src","href","action","formAction"].forEach((function(e){h[e]=new g(e,1,!1,e.toLowerCase(),null,!0,!0)}));var w=r.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED,S=Symbol.for("react.element"),k=Symbol.for("react.portal"),x=Symbol.for("react.fragment"),_=Symbol.for("react.strict_mode"),C=Symbol.for("react.profiler"),E=Symbol.for("react.provider"),D=Symbol.for("react.context"),j=Symbol.for("react.forward_ref"),O=Symbol.for("react.suspense"),A=Symbol.for("react.suspense_list"),T=Symbol.for("react.memo"),P=Symbol.for("react.lazy");Symbol.for("react.scope"),Symbol.for("react.debug_trace_mode");var I=Symbol.for("react.offscreen");Symbol.for("react.legacy_hidden"),Symbol.for("react.cache"),Symbol.for("react.tracing_marker");var N=Symbol.iterator;function R(e){return null===e||"object"!=typeof e?null:"function"==typeof(e=N&&e[N]||e["@@iterator"])?e:null}var L,M=Object.assign;function F(e){if(void 0===L)try{throw Error()}catch(n){var t=n.stack.trim().match(/\n( *(at )?)/);L=t&&t[1]||""}return"\n"+L+e}var B=!1;function z(e,t){if(!e||B)return"";B=!0;var n=Error.prepareStackTrace;Error.prepareStackTrace=void 0;try{if(t)if(t=function(){throw Error()},Object.defineProperty(t.prototype,"props",{set:function(){throw Error()}}),"object"==typeof Reflect&&Reflect.construct){try{Reflect.construct(t,[])}catch(l){var r=l}Reflect.construct(e,[],t)}else{try{t.call()}catch(l){r=l}e.call(t.prototype)}else{try{throw Error()}catch(l){r=l}e()}}catch(l){if(l&&r&&"string"==typeof l.stack){for(var o=l.stack.split("\n"),a=r.stack.split("\n"),i=o.length-1,c=a.length-1;1<=i&&0<=c&&o[i]!==a[c];)c--;for(;1<=i&&0<=c;i--,c--)if(o[i]!==a[c]){if(1!==i||1!==c)do{if(i--,0>--c||o[i]!==a[c]){var s="\n"+o[i].replace(" at new "," at ");return e.displayName&&s.includes("<anonymous>")&&(s=s.replace("<anonymous>",e.displayName)),s}}while(1<=i&&0<=c);break}}}finally{B=!1,Error.prepareStackTrace=n}return(e=e?e.displayName||e.name:"")?F(e):""}function $(e){switch(e.tag){case 5:return F(e.type);case 16:return F("Lazy");case 13:return F("Suspense");case 19:return F("SuspenseList");case 0:case 2:case 15:return e=z(e.type,!1);case 11:return e=z(e.type.render,!1);case 1:return e=z(e.type,!0);default:return""}}function U(e){if(null==e)return null;if("function"==typeof e)return e.displayName||e.name||null;if("string"==typeof e)return e;switch(e){case x:return"Fragment";case k:return"Portal";case C:return"Profiler";case _:return"StrictMode";case O:return"Suspense";case A:return"SuspenseList"}if("object"==typeof e)switch(e.$$typeof){case D:return(e.displayName||"Context")+".Consumer";case E:return(e._context.displayName||"Context")+".Provider";case j:var t=e.render;return(e=e.displayName)||(e=""!==(e=t.displayName||t.name||"")?"ForwardRef("+e+")":"ForwardRef"),e;case T:return null!==(t=e.displayName||null)?t:U(e.type)||"Memo";case P:t=e._payload,e=e._init;try{return U(e(t))}catch(n){}}return null}function H(e){var t=e.type;switch(e.tag){case 24:return"Cache";case 9:return(t.displayName||"Context")+".Consumer";case 10:return(t._context.displayName||"Context")+".Provider";case 18:return"DehydratedFragment";case 11:return e=(e=t.render).displayName||e.name||"",t.displayName||(""!==e?"ForwardRef("+e+")":"ForwardRef");case 7:return"Fragment";case 5:return t;case 4:return"Portal";case 3:return"Root";case 6:return"Text";case 16:return U(t);case 8:return t===_?"StrictMode":"Mode";case 22:return"Offscreen";case 12:return"Profiler";case 21:return"Scope";case 13:return"Suspense";case 19:return"SuspenseList";case 25:return"TracingMarker";case 1:case 0:case 17:case 2:case 14:case 15:if("function"==typeof t)return t.displayName||t.name||null;if("string"==typeof t)return t}return null}function q(e){switch(typeof e){case"boolean":case"number":case"string":case"undefined":case"object":return e;default:return""}}function V(e){var t=e.type;return(e=e.nodeName)&&"input"===e.toLowerCase()&&("checkbox"===t||"radio"===t)}function W(e){e._valueTracker||(e._valueTracker=function(e){var t=V(e)?"checked":"value",n=Object.getOwnPropertyDescriptor(e.constructor.prototype,t),r=""+e[t];if(!e.hasOwnProperty(t)&&void 0!==n&&"function"==typeof n.get&&"function"==typeof n.set){var o=n.get,a=n.set;return Object.defineProperty(e,t,{configurable:!0,get:function(){return o.call(this)},set:function(e){r=""+e,a.call(this,e)}}),Object.defineProperty(e,t,{enumerable:n.enumerable}),{getValue:function(){return r},setValue:function(e){r=""+e},stopTracking:function(){e._valueTracker=null,delete e[t]}}}}(e))}function G(e){if(!e)return!1;var t=e._valueTracker;if(!t)return!0;var n=t.getValue(),r="";return e&&(r=V(e)?e.checked?"true":"false":e.value),(e=r)!==n&&(t.setValue(e),!0)}function K(e){if(void 0===(e=e||("undefined"!=typeof document?document:void 0)))return null;try{return e.activeElement||e.body}catch(t){return e.body}}function Y(e,t){var n=t.checked;return M({},t,{defaultChecked:void 0,defaultValue:void 0,value:void 0,checked:null!=n?n:e._wrapperState.initialChecked})}function Q(e,t){var n=null==t.defaultValue?"":t.defaultValue,r=null!=t.checked?t.checked:t.defaultChecked;n=q(null!=t.value?t.value:n),e._wrapperState={initialChecked:r,initialValue:n,controlled:"checkbox"===t.type||"radio"===t.type?null!=t.checked:null!=t.value}}function Z(e,t){null!=(t=t.checked)&&v(e,"checked",t,!1)}function X(e,t){Z(e,t);var n=q(t.value),r=t.type;if(null!=n)"number"===r?(0===n&&""===e.value||e.value!=n)&&(e.value=""+n):e.value!==""+n&&(e.value=""+n);else if("submit"===r||"reset"===r)return void e.removeAttribute("value");t.hasOwnProperty("value")?ee(e,t.type,n):t.hasOwnProperty("defaultValue")&&ee(e,t.type,q(t.defaultValue)),null==t.checked&&null!=t.defaultChecked&&(e.defaultChecked=!!t.defaultChecked)}function J(e,t,n){if(t.hasOwnProperty("value")||t.hasOwnProperty("defaultValue")){var r=t.type;if(!("submit"!==r&&"reset"!==r||void 0!==t.value&&null!==t.value))return;t=""+e._wrapperState.initialValue,n||t===e.value||(e.value=t),e.defaultValue=t}""!==(n=e.name)&&(e.name=""),e.defaultChecked=!!e._wrapperState.initialChecked,""!==n&&(e.name=n)}function ee(e,t,n){"number"===t&&K(e.ownerDocument)===e||(null==n?e.defaultValue=""+e._wrapperState.initialValue:e.defaultValue!==""+n&&(e.defaultValue=""+n))}var te=Array.isArray;function ne(e,t,n,r){if(e=e.options,t){t={};for(var o=0;o<n.length;o++)t["$"+n[o]]=!0;for(n=0;n<e.length;n++)o=t.hasOwnProperty("$"+e[n].value),e[n].selected!==o&&(e[n].selected=o),o&&r&&(e[n].defaultSelected=!0)}else{for(n=""+q(n),t=null,o=0;o<e.length;o++){if(e[o].value===n)return e[o].selected=!0,void(r&&(e[o].defaultSelected=!0));null!==t||e[o].disabled||(t=e[o])}null!==t&&(t.selected=!0)}}function re(e,t){if(null!=t.dangerouslySetInnerHTML)throw Error(a(91));return M({},t,{value:void 0,defaultValue:void 0,children:""+e._wrapperState.initialValue})}function oe(e,t){var n=t.value;if(null==n){if(n=t.children,t=t.defaultValue,null!=n){if(null!=t)throw Error(a(92));if(te(n)){if(1<n.length)throw Error(a(93));n=n[0]}t=n}null==t&&(t=""),n=t}e._wrapperState={initialValue:q(n)}}function ae(e,t){var n=q(t.value),r=q(t.defaultValue);null!=n&&((n=""+n)!==e.value&&(e.value=n),null==t.defaultValue&&e.defaultValue!==n&&(e.defaultValue=n)),null!=r&&(e.defaultValue=""+r)}function ie(e){var t=e.textContent;t===e._wrapperState.initialValue&&""!==t&&null!==t&&(e.value=t)}function ce(e){switch(e){case"svg":return"http://www.w3.org/2000/svg";case"math":return"http://www.w3.org/1998/Math/MathML";default:return"http://www.w3.org/1999/xhtml"}}function se(e,t){return null==e||"http://www.w3.org/1999/xhtml"===e?ce(t):"http://www.w3.org/2000/svg"===e&&"foreignObject"===t?"http://www.w3.org/1999/xhtml":e}var le,ue,de=(ue=function(e,t){if("http://www.w3.org/2000/svg"!==e.namespaceURI||"innerHTML"in e)e.innerHTML=t;else{for((le=le||document.createElement("div")).innerHTML="<svg>"+t.valueOf().toString()+"</svg>",t=le.firstChild;e.firstChild;)e.removeChild(e.firstChild);for(;t.firstChild;)e.appendChild(t.firstChild)}},"undefined"!=typeof MSApp&&MSApp.execUnsafeLocalFunction?function(e,t,n,r){MSApp.execUnsafeLocalFunction((function(){return ue(e,t)}))}:ue);function pe(e,t){if(t){var n=e.firstChild;if(n&&n===e.lastChild&&3===n.nodeType)return void(n.nodeValue=t)}e.textContent=t}var fe={animationIterationCount:!0,aspectRatio:!0,borderImageOutset:!0,borderImageSlice:!0,borderImageWidth:!0,boxFlex:!0,boxFlexGroup:!0,boxOrdinalGroup:!0,columnCount:!0,columns:!0,flex:!0,flexGrow:!0,flexPositive:!0,flexShrink:!0,flexNegative:!0,flexOrder:!0,gridArea:!0,gridRow:!0,gridRowEnd:!0,gridRowSpan:!0,gridRowStart:!0,gridColumn:!0,gridColumnEnd:!0,gridColumnSpan:!0,gridColumnStart:!0,fontWeight:!0,lineClamp:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,tabSize:!0,widows:!0,zIndex:!0,zoom:!0,fillOpacity:!0,floodOpacity:!0,stopOpacity:!0,strokeDasharray:!0,strokeDashoffset:!0,strokeMiterlimit:!0,strokeOpacity:!0,strokeWidth:!0},me=["Webkit","ms","Moz","O"];function ge(e,t,n){return null==t||"boolean"==typeof t||""===t?"":n||"number"!=typeof t||0===t||fe.hasOwnProperty(e)&&fe[e]?(""+t).trim():t+"px"}function he(e,t){for(var n in e=e.style,t)if(t.hasOwnProperty(n)){var r=0===n.indexOf("--"),o=ge(n,t[n],r);"float"===n&&(n="cssFloat"),r?e.setProperty(n,o):e[n]=o}}Object.keys(fe).forEach((function(e){me.forEach((function(t){t=t+e.charAt(0).toUpperCase()+e.substring(1),fe[t]=fe[e]}))}));var be=M({menuitem:!0},{area:!0,base:!0,br:!0,col:!0,embed:!0,hr:!0,img:!0,input:!0,keygen:!0,link:!0,meta:!0,param:!0,source:!0,track:!0,wbr:!0});function ye(e,t){if(t){if(be[e]&&(null!=t.children||null!=t.dangerouslySetInnerHTML))throw Error(a(137,e));if(null!=t.dangerouslySetInnerHTML){if(null!=t.children)throw Error(a(60));if("object"!=typeof t.dangerouslySetInnerHTML||!("__html"in t.dangerouslySetInnerHTML))throw Error(a(61))}if(null!=t.style&&"object"!=typeof t.style)throw Error(a(62))}}function ve(e,t){if(-1===e.indexOf("-"))return"string"==typeof t.is;switch(e){case"annotation-xml":case"color-profile":case"font-face":case"font-face-src":case"font-face-uri":case"font-face-format":case"font-face-name":case"missing-glyph":return!1;default:return!0}}var we=null;function Se(e){return(e=e.target||e.srcElement||window).correspondingUseElement&&(e=e.correspondingUseElement),3===e.nodeType?e.parentNode:e}var ke=null,xe=null,_e=null;function Ce(e){if(e=wo(e)){if("function"!=typeof ke)throw Error(a(280));var t=e.stateNode;t&&(t=ko(t),ke(e.stateNode,e.type,t))}}function Ee(e){xe?_e?_e.push(e):_e=[e]:xe=e}function De(){if(xe){var e=xe,t=_e;if(_e=xe=null,Ce(e),t)for(e=0;e<t.length;e++)Ce(t[e])}}function je(e,t){return e(t)}function Oe(){}var Ae=!1;function Te(e,t,n){if(Ae)return e(t,n);Ae=!0;try{return je(e,t,n)}finally{Ae=!1,(null!==xe||null!==_e)&&(Oe(),De())}}function Pe(e,t){var n=e.stateNode;if(null===n)return null;var r=ko(n);if(null===r)return null;n=r[t];e:switch(t){case"onClick":case"onClickCapture":case"onDoubleClick":case"onDoubleClickCapture":case"onMouseDown":case"onMouseDownCapture":case"onMouseMove":case"onMouseMoveCapture":case"onMouseUp":case"onMouseUpCapture":case"onMouseEnter":(r=!r.disabled)||(r=!("button"===(e=e.type)||"input"===e||"select"===e||"textarea"===e)),e=!r;break e;default:e=!1}if(e)return null;if(n&&"function"!=typeof n)throw Error(a(231,t,typeof n));return n}var Ie=!1;if(u)try{var Ne={};Object.defineProperty(Ne,"passive",{get:function(){Ie=!0}}),window.addEventListener("test",Ne,Ne),window.removeEventListener("test",Ne,Ne)}catch(ue){Ie=!1}function Re(e,t,n,r,o,a,i,c,s){var l=Array.prototype.slice.call(arguments,3);try{t.apply(n,l)}catch(u){this.onError(u)}}var Le=!1,Me=null,Fe=!1,Be=null,ze={onError:function(e){Le=!0,Me=e}};function $e(e,t,n,r,o,a,i,c,s){Le=!1,Me=null,Re.apply(ze,arguments)}function Ue(e){var t=e,n=e;if(e.alternate)for(;t.return;)t=t.return;else{e=t;do{!!(4098&(t=e).flags)&&(n=t.return),e=t.return}while(e)}return 3===t.tag?n:null}function He(e){if(13===e.tag){var t=e.memoizedState;if(null===t&&(null!==(e=e.alternate)&&(t=e.memoizedState)),null!==t)return t.dehydrated}return null}function qe(e){if(Ue(e)!==e)throw Error(a(188))}function Ve(e){return null!==(e=function(e){var t=e.alternate;if(!t){if(null===(t=Ue(e)))throw Error(a(188));return t!==e?null:e}for(var n=e,r=t;;){var o=n.return;if(null===o)break;var i=o.alternate;if(null===i){if(null!==(r=o.return)){n=r;continue}break}if(o.child===i.child){for(i=o.child;i;){if(i===n)return qe(o),e;if(i===r)return qe(o),t;i=i.sibling}throw Error(a(188))}if(n.return!==r.return)n=o,r=i;else{for(var c=!1,s=o.child;s;){if(s===n){c=!0,n=o,r=i;break}if(s===r){c=!0,r=o,n=i;break}s=s.sibling}if(!c){for(s=i.child;s;){if(s===n){c=!0,n=i,r=o;break}if(s===r){c=!0,r=i,n=o;break}s=s.sibling}if(!c)throw Error(a(189))}}if(n.alternate!==r)throw Error(a(190))}if(3!==n.tag)throw Error(a(188));return n.stateNode.current===n?e:t}(e))?We(e):null}function We(e){if(5===e.tag||6===e.tag)return e;for(e=e.child;null!==e;){var t=We(e);if(null!==t)return t;e=e.sibling}return null}var Ge=o.unstable_scheduleCallback,Ke=o.unstable_cancelCallback,Ye=o.unstable_shouldYield,Qe=o.unstable_requestPaint,Ze=o.unstable_now,Xe=o.unstable_getCurrentPriorityLevel,Je=o.unstable_ImmediatePriority,et=o.unstable_UserBlockingPriority,tt=o.unstable_NormalPriority,nt=o.unstable_LowPriority,rt=o.unstable_IdlePriority,ot=null,at=null;var it=Math.clz32?Math.clz32:function(e){return e>>>=0,0===e?32:31-(ct(e)/st|0)|0},ct=Math.log,st=Math.LN2;var lt=64,ut=4194304;function dt(e){switch(e&-e){case 1:return 1;case 2:return 2;case 4:return 4;case 8:return 8;case 16:return 16;case 32:return 32;case 64:case 128:case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:case 262144:case 524288:case 1048576:case 2097152:return 4194240&e;case 4194304:case 8388608:case 16777216:case 33554432:case 67108864:return 130023424&e;case 134217728:return 134217728;case 268435456:return 268435456;case 536870912:return 536870912;case 1073741824:return 1073741824;default:return e}}function pt(e,t){var n=e.pendingLanes;if(0===n)return 0;var r=0,o=e.suspendedLanes,a=e.pingedLanes,i=268435455&n;if(0!==i){var c=i&~o;0!==c?r=dt(c):0!==(a&=i)&&(r=dt(a))}else 0!==(i=n&~o)?r=dt(i):0!==a&&(r=dt(a));if(0===r)return 0;if(0!==t&&t!==r&&!(t&o)&&((o=r&-r)>=(a=t&-t)||16===o&&4194240&a))return t;if(4&r&&(r|=16&n),0!==(t=e.entangledLanes))for(e=e.entanglements,t&=r;0<t;)o=1<<(n=31-it(t)),r|=e[n],t&=~o;return r}function ft(e,t){switch(e){case 1:case 2:case 4:return t+250;case 8:case 16:case 32:case 64:case 128:case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:case 262144:case 524288:case 1048576:case 2097152:return t+5e3;default:return-1}}function mt(e){return 0!==(e=-1073741825&e.pendingLanes)?e:1073741824&e?1073741824:0}function gt(){var e=lt;return!(4194240&(lt<<=1))&&(lt=64),e}function ht(e){for(var t=[],n=0;31>n;n++)t.push(e);return t}function bt(e,t,n){e.pendingLanes|=t,536870912!==t&&(e.suspendedLanes=0,e.pingedLanes=0),(e=e.eventTimes)[t=31-it(t)]=n}function yt(e,t){var n=e.entangledLanes|=t;for(e=e.entanglements;n;){var r=31-it(n),o=1<<r;o&t|e[r]&t&&(e[r]|=t),n&=~o}}var vt=0;function wt(e){return 1<(e&=-e)?4<e?268435455&e?16:536870912:4:1}var St,kt,xt,_t,Ct,Et=!1,Dt=[],jt=null,Ot=null,At=null,Tt=new Map,Pt=new Map,It=[],Nt="mousedown mouseup touchcancel touchend touchstart auxclick dblclick pointercancel pointerdown pointerup dragend dragstart drop compositionend compositionstart keydown keypress keyup input textInput copy cut paste click change contextmenu reset submit".split(" ");function Rt(e,t){switch(e){case"focusin":case"focusout":jt=null;break;case"dragenter":case"dragleave":Ot=null;break;case"mouseover":case"mouseout":At=null;break;case"pointerover":case"pointerout":Tt.delete(t.pointerId);break;case"gotpointercapture":case"lostpointercapture":Pt.delete(t.pointerId)}}function Lt(e,t,n,r,o,a){return null===e||e.nativeEvent!==a?(e={blockedOn:t,domEventName:n,eventSystemFlags:r,nativeEvent:a,targetContainers:[o]},null!==t&&(null!==(t=wo(t))&&kt(t)),e):(e.eventSystemFlags|=r,t=e.targetContainers,null!==o&&-1===t.indexOf(o)&&t.push(o),e)}function Mt(e){var t=vo(e.target);if(null!==t){var n=Ue(t);if(null!==n)if(13===(t=n.tag)){if(null!==(t=He(n)))return e.blockedOn=t,void Ct(e.priority,(function(){xt(n)}))}else if(3===t&&n.stateNode.current.memoizedState.isDehydrated)return void(e.blockedOn=3===n.tag?n.stateNode.containerInfo:null)}e.blockedOn=null}function Ft(e){if(null!==e.blockedOn)return!1;for(var t=e.targetContainers;0<t.length;){var n=Yt(e.domEventName,e.eventSystemFlags,t[0],e.nativeEvent);if(null!==n)return null!==(t=wo(n))&&kt(t),e.blockedOn=n,!1;var r=new(n=e.nativeEvent).constructor(n.type,n);we=r,n.target.dispatchEvent(r),we=null,t.shift()}return!0}function Bt(e,t,n){Ft(e)&&n.delete(t)}function zt(){Et=!1,null!==jt&&Ft(jt)&&(jt=null),null!==Ot&&Ft(Ot)&&(Ot=null),null!==At&&Ft(At)&&(At=null),Tt.forEach(Bt),Pt.forEach(Bt)}function $t(e,t){e.blockedOn===t&&(e.blockedOn=null,Et||(Et=!0,o.unstable_scheduleCallback(o.unstable_NormalPriority,zt)))}function Ut(e){function t(t){return $t(t,e)}if(0<Dt.length){$t(Dt[0],e);for(var n=1;n<Dt.length;n++){var r=Dt[n];r.blockedOn===e&&(r.blockedOn=null)}}for(null!==jt&&$t(jt,e),null!==Ot&&$t(Ot,e),null!==At&&$t(At,e),Tt.forEach(t),Pt.forEach(t),n=0;n<It.length;n++)(r=It[n]).blockedOn===e&&(r.blockedOn=null);for(;0<It.length&&null===(n=It[0]).blockedOn;)Mt(n),null===n.blockedOn&&It.shift()}var Ht=w.ReactCurrentBatchConfig,qt=!0;function Vt(e,t,n,r){var o=vt,a=Ht.transition;Ht.transition=null;try{vt=1,Gt(e,t,n,r)}finally{vt=o,Ht.transition=a}}function Wt(e,t,n,r){var o=vt,a=Ht.transition;Ht.transition=null;try{vt=4,Gt(e,t,n,r)}finally{vt=o,Ht.transition=a}}function Gt(e,t,n,r){if(qt){var o=Yt(e,t,n,r);if(null===o)qr(e,t,r,Kt,n),Rt(e,r);else if(function(e,t,n,r,o){switch(t){case"focusin":return jt=Lt(jt,e,t,n,r,o),!0;case"dragenter":return Ot=Lt(Ot,e,t,n,r,o),!0;case"mouseover":return At=Lt(At,e,t,n,r,o),!0;case"pointerover":var a=o.pointerId;return Tt.set(a,Lt(Tt.get(a)||null,e,t,n,r,o)),!0;case"gotpointercapture":return a=o.pointerId,Pt.set(a,Lt(Pt.get(a)||null,e,t,n,r,o)),!0}return!1}(o,e,t,n,r))r.stopPropagation();else if(Rt(e,r),4&t&&-1<Nt.indexOf(e)){for(;null!==o;){var a=wo(o);if(null!==a&&St(a),null===(a=Yt(e,t,n,r))&&qr(e,t,r,Kt,n),a===o)break;o=a}null!==o&&r.stopPropagation()}else qr(e,t,r,null,n)}}var Kt=null;function Yt(e,t,n,r){if(Kt=null,null!==(e=vo(e=Se(r))))if(null===(t=Ue(e)))e=null;else if(13===(n=t.tag)){if(null!==(e=He(t)))return e;e=null}else if(3===n){if(t.stateNode.current.memoizedState.isDehydrated)return 3===t.tag?t.stateNode.containerInfo:null;e=null}else t!==e&&(e=null);return Kt=e,null}function Qt(e){switch(e){case"cancel":case"click":case"close":case"contextmenu":case"copy":case"cut":case"auxclick":case"dblclick":case"dragend":case"dragstart":case"drop":case"focusin":case"focusout":case"input":case"invalid":case"keydown":case"keypress":case"keyup":case"mousedown":case"mouseup":case"paste":case"pause":case"play":case"pointercancel":case"pointerdown":case"pointerup":case"ratechange":case"reset":case"resize":case"seeked":case"submit":case"touchcancel":case"touchend":case"touchstart":case"volumechange":case"change":case"selectionchange":case"textInput":case"compositionstart":case"compositionend":case"compositionupdate":case"beforeblur":case"afterblur":case"beforeinput":case"blur":case"fullscreenchange":case"focus":case"hashchange":case"popstate":case"select":case"selectstart":return 1;case"drag":case"dragenter":case"dragexit":case"dragleave":case"dragover":case"mousemove":case"mouseout":case"mouseover":case"pointermove":case"pointerout":case"pointerover":case"scroll":case"toggle":case"touchmove":case"wheel":case"mouseenter":case"mouseleave":case"pointerenter":case"pointerleave":return 4;case"message":switch(Xe()){case Je:return 1;case et:return 4;case tt:case nt:return 16;case rt:return 536870912;default:return 16}default:return 16}}var Zt=null,Xt=null,Jt=null;function en(){if(Jt)return Jt;var e,t,n=Xt,r=n.length,o="value"in Zt?Zt.value:Zt.textContent,a=o.length;for(e=0;e<r&&n[e]===o[e];e++);var i=r-e;for(t=1;t<=i&&n[r-t]===o[a-t];t++);return Jt=o.slice(e,1<t?1-t:void 0)}function tn(e){var t=e.keyCode;return"charCode"in e?0===(e=e.charCode)&&13===t&&(e=13):e=t,10===e&&(e=13),32<=e||13===e?e:0}function nn(){return!0}function rn(){return!1}function on(e){function t(t,n,r,o,a){for(var i in this._reactName=t,this._targetInst=r,this.type=n,this.nativeEvent=o,this.target=a,this.currentTarget=null,e)e.hasOwnProperty(i)&&(t=e[i],this[i]=t?t(o):o[i]);return this.isDefaultPrevented=(null!=o.defaultPrevented?o.defaultPrevented:!1===o.returnValue)?nn:rn,this.isPropagationStopped=rn,this}return M(t.prototype,{preventDefault:function(){this.defaultPrevented=!0;var e=this.nativeEvent;e&&(e.preventDefault?e.preventDefault():"unknown"!=typeof e.returnValue&&(e.returnValue=!1),this.isDefaultPrevented=nn)},stopPropagation:function(){var e=this.nativeEvent;e&&(e.stopPropagation?e.stopPropagation():"unknown"!=typeof e.cancelBubble&&(e.cancelBubble=!0),this.isPropagationStopped=nn)},persist:function(){},isPersistent:nn}),t}var an,cn,sn,ln={eventPhase:0,bubbles:0,cancelable:0,timeStamp:function(e){return e.timeStamp||Date.now()},defaultPrevented:0,isTrusted:0},un=on(ln),dn=M({},ln,{view:0,detail:0}),pn=on(dn),fn=M({},dn,{screenX:0,screenY:0,clientX:0,clientY:0,pageX:0,pageY:0,ctrlKey:0,shiftKey:0,altKey:0,metaKey:0,getModifierState:Cn,button:0,buttons:0,relatedTarget:function(e){return void 0===e.relatedTarget?e.fromElement===e.srcElement?e.toElement:e.fromElement:e.relatedTarget},movementX:function(e){return"movementX"in e?e.movementX:(e!==sn&&(sn&&"mousemove"===e.type?(an=e.screenX-sn.screenX,cn=e.screenY-sn.screenY):cn=an=0,sn=e),an)},movementY:function(e){return"movementY"in e?e.movementY:cn}}),mn=on(fn),gn=on(M({},fn,{dataTransfer:0})),hn=on(M({},dn,{relatedTarget:0})),bn=on(M({},ln,{animationName:0,elapsedTime:0,pseudoElement:0})),yn=M({},ln,{clipboardData:function(e){return"clipboardData"in e?e.clipboardData:window.clipboardData}}),vn=on(yn),wn=on(M({},ln,{data:0})),Sn={Esc:"Escape",Spacebar:" ",Left:"ArrowLeft",Up:"ArrowUp",Right:"ArrowRight",Down:"ArrowDown",Del:"Delete",Win:"OS",Menu:"ContextMenu",Apps:"ContextMenu",Scroll:"ScrollLock",MozPrintableKey:"Unidentified"},kn={8:"Backspace",9:"Tab",12:"Clear",13:"Enter",16:"Shift",17:"Control",18:"Alt",19:"Pause",20:"CapsLock",27:"Escape",32:" ",33:"PageUp",34:"PageDown",35:"End",36:"Home",37:"ArrowLeft",38:"ArrowUp",39:"ArrowRight",40:"ArrowDown",45:"Insert",46:"Delete",112:"F1",113:"F2",114:"F3",115:"F4",116:"F5",117:"F6",118:"F7",119:"F8",120:"F9",121:"F10",122:"F11",123:"F12",144:"NumLock",145:"ScrollLock",224:"Meta"},xn={Alt:"altKey",Control:"ctrlKey",Meta:"metaKey",Shift:"shiftKey"};function _n(e){var t=this.nativeEvent;return t.getModifierState?t.getModifierState(e):!!(e=xn[e])&&!!t[e]}function Cn(){return _n}var En=M({},dn,{key:function(e){if(e.key){var t=Sn[e.key]||e.key;if("Unidentified"!==t)return t}return"keypress"===e.type?13===(e=tn(e))?"Enter":String.fromCharCode(e):"keydown"===e.type||"keyup"===e.type?kn[e.keyCode]||"Unidentified":""},code:0,location:0,ctrlKey:0,shiftKey:0,altKey:0,metaKey:0,repeat:0,locale:0,getModifierState:Cn,charCode:function(e){return"keypress"===e.type?tn(e):0},keyCode:function(e){return"keydown"===e.type||"keyup"===e.type?e.keyCode:0},which:function(e){return"keypress"===e.type?tn(e):"keydown"===e.type||"keyup"===e.type?e.keyCode:0}}),Dn=on(En),jn=on(M({},fn,{pointerId:0,width:0,height:0,pressure:0,tangentialPressure:0,tiltX:0,tiltY:0,twist:0,pointerType:0,isPrimary:0})),On=on(M({},dn,{touches:0,targetTouches:0,changedTouches:0,altKey:0,metaKey:0,ctrlKey:0,shiftKey:0,getModifierState:Cn})),An=on(M({},ln,{propertyName:0,elapsedTime:0,pseudoElement:0})),Tn=M({},fn,{deltaX:function(e){return"deltaX"in e?e.deltaX:"wheelDeltaX"in e?-e.wheelDeltaX:0},deltaY:function(e){return"deltaY"in e?e.deltaY:"wheelDeltaY"in e?-e.wheelDeltaY:"wheelDelta"in e?-e.wheelDelta:0},deltaZ:0,deltaMode:0}),Pn=on(Tn),In=[9,13,27,32],Nn=u&&"CompositionEvent"in window,Rn=null;u&&"documentMode"in document&&(Rn=document.documentMode);var Ln=u&&"TextEvent"in window&&!Rn,Mn=u&&(!Nn||Rn&&8<Rn&&11>=Rn),Fn=String.fromCharCode(32),Bn=!1;function zn(e,t){switch(e){case"keyup":return-1!==In.indexOf(t.keyCode);case"keydown":return 229!==t.keyCode;case"keypress":case"mousedown":case"focusout":return!0;default:return!1}}function $n(e){return"object"==typeof(e=e.detail)&&"data"in e?e.data:null}var Un=!1;var Hn={color:!0,date:!0,datetime:!0,"datetime-local":!0,email:!0,month:!0,number:!0,password:!0,range:!0,search:!0,tel:!0,text:!0,time:!0,url:!0,week:!0};function qn(e){var t=e&&e.nodeName&&e.nodeName.toLowerCase();return"input"===t?!!Hn[e.type]:"textarea"===t}function Vn(e,t,n,r){Ee(r),0<(t=Wr(t,"onChange")).length&&(n=new un("onChange","change",null,n,r),e.push({event:n,listeners:t}))}var Wn=null,Gn=null;function Kn(e){Fr(e,0)}function Yn(e){if(G(So(e)))return e}function Qn(e,t){if("change"===e)return t}var Zn=!1;if(u){var Xn;if(u){var Jn="oninput"in document;if(!Jn){var er=document.createElement("div");er.setAttribute("oninput","return;"),Jn="function"==typeof er.oninput}Xn=Jn}else Xn=!1;Zn=Xn&&(!document.documentMode||9<document.documentMode)}function tr(){Wn&&(Wn.detachEvent("onpropertychange",nr),Gn=Wn=null)}function nr(e){if("value"===e.propertyName&&Yn(Gn)){var t=[];Vn(t,Gn,e,Se(e)),Te(Kn,t)}}function rr(e,t,n){"focusin"===e?(tr(),Gn=n,(Wn=t).attachEvent("onpropertychange",nr)):"focusout"===e&&tr()}function or(e){if("selectionchange"===e||"keyup"===e||"keydown"===e)return Yn(Gn)}function ar(e,t){if("click"===e)return Yn(t)}function ir(e,t){if("input"===e||"change"===e)return Yn(t)}var cr="function"==typeof Object.is?Object.is:function(e,t){return e===t&&(0!==e||1/e==1/t)||e!=e&&t!=t};function sr(e,t){if(cr(e,t))return!0;if("object"!=typeof e||null===e||"object"!=typeof t||null===t)return!1;var n=Object.keys(e),r=Object.keys(t);if(n.length!==r.length)return!1;for(r=0;r<n.length;r++){var o=n[r];if(!d.call(t,o)||!cr(e[o],t[o]))return!1}return!0}function lr(e){for(;e&&e.firstChild;)e=e.firstChild;return e}function ur(e,t){var n,r=lr(e);for(e=0;r;){if(3===r.nodeType){if(n=e+r.textContent.length,e<=t&&n>=t)return{node:r,offset:t-e};e=n}e:{for(;r;){if(r.nextSibling){r=r.nextSibling;break e}r=r.parentNode}r=void 0}r=lr(r)}}function dr(e,t){return!(!e||!t)&&(e===t||(!e||3!==e.nodeType)&&(t&&3===t.nodeType?dr(e,t.parentNode):"contains"in e?e.contains(t):!!e.compareDocumentPosition&&!!(16&e.compareDocumentPosition(t))))}function pr(){for(var e=window,t=K();t instanceof e.HTMLIFrameElement;){try{var n="string"==typeof t.contentWindow.location.href}catch(r){n=!1}if(!n)break;t=K((e=t.contentWindow).document)}return t}function fr(e){var t=e&&e.nodeName&&e.nodeName.toLowerCase();return t&&("input"===t&&("text"===e.type||"search"===e.type||"tel"===e.type||"url"===e.type||"password"===e.type)||"textarea"===t||"true"===e.contentEditable)}function mr(e){var t=pr(),n=e.focusedElem,r=e.selectionRange;if(t!==n&&n&&n.ownerDocument&&dr(n.ownerDocument.documentElement,n)){if(null!==r&&fr(n))if(t=r.start,void 0===(e=r.end)&&(e=t),"selectionStart"in n)n.selectionStart=t,n.selectionEnd=Math.min(e,n.value.length);else if((e=(t=n.ownerDocument||document)&&t.defaultView||window).getSelection){e=e.getSelection();var o=n.textContent.length,a=Math.min(r.start,o);r=void 0===r.end?a:Math.min(r.end,o),!e.extend&&a>r&&(o=r,r=a,a=o),o=ur(n,a);var i=ur(n,r);o&&i&&(1!==e.rangeCount||e.anchorNode!==o.node||e.anchorOffset!==o.offset||e.focusNode!==i.node||e.focusOffset!==i.offset)&&((t=t.createRange()).setStart(o.node,o.offset),e.removeAllRanges(),a>r?(e.addRange(t),e.extend(i.node,i.offset)):(t.setEnd(i.node,i.offset),e.addRange(t)))}for(t=[],e=n;e=e.parentNode;)1===e.nodeType&&t.push({element:e,left:e.scrollLeft,top:e.scrollTop});for("function"==typeof n.focus&&n.focus(),n=0;n<t.length;n++)(e=t[n]).element.scrollLeft=e.left,e.element.scrollTop=e.top}}var gr=u&&"documentMode"in document&&11>=document.documentMode,hr=null,br=null,yr=null,vr=!1;function wr(e,t,n){var r=n.window===n?n.document:9===n.nodeType?n:n.ownerDocument;vr||null==hr||hr!==K(r)||("selectionStart"in(r=hr)&&fr(r)?r={start:r.selectionStart,end:r.selectionEnd}:r={anchorNode:(r=(r.ownerDocument&&r.ownerDocument.defaultView||window).getSelection()).anchorNode,anchorOffset:r.anchorOffset,focusNode:r.focusNode,focusOffset:r.focusOffset},yr&&sr(yr,r)||(yr=r,0<(r=Wr(br,"onSelect")).length&&(t=new un("onSelect","select",null,t,n),e.push({event:t,listeners:r}),t.target=hr)))}function Sr(e,t){var n={};return n[e.toLowerCase()]=t.toLowerCase(),n["Webkit"+e]="webkit"+t,n["Moz"+e]="moz"+t,n}var kr={animationend:Sr("Animation","AnimationEnd"),animationiteration:Sr("Animation","AnimationIteration"),animationstart:Sr("Animation","AnimationStart"),transitionend:Sr("Transition","TransitionEnd")},xr={},_r={};function Cr(e){if(xr[e])return xr[e];if(!kr[e])return e;var t,n=kr[e];for(t in n)if(n.hasOwnProperty(t)&&t in _r)return xr[e]=n[t];return e}u&&(_r=document.createElement("div").style,"AnimationEvent"in window||(delete kr.animationend.animation,delete kr.animationiteration.animation,delete kr.animationstart.animation),"TransitionEvent"in window||delete kr.transitionend.transition);var Er=Cr("animationend"),Dr=Cr("animationiteration"),jr=Cr("animationstart"),Or=Cr("transitionend"),Ar=new Map,Tr="abort auxClick cancel canPlay canPlayThrough click close contextMenu copy cut drag dragEnd dragEnter dragExit dragLeave dragOver dragStart drop durationChange emptied encrypted ended error gotPointerCapture input invalid keyDown keyPress keyUp load loadedData loadedMetadata loadStart lostPointerCapture mouseDown mouseMove mouseOut mouseOver mouseUp paste pause play playing pointerCancel pointerDown pointerMove pointerOut pointerOver pointerUp progress rateChange reset resize seeked seeking stalled submit suspend timeUpdate touchCancel touchEnd touchStart volumeChange scroll toggle touchMove waiting wheel".split(" ");function Pr(e,t){Ar.set(e,t),s(t,[e])}for(var Ir=0;Ir<Tr.length;Ir++){var Nr=Tr[Ir];Pr(Nr.toLowerCase(),"on"+(Nr[0].toUpperCase()+Nr.slice(1)))}Pr(Er,"onAnimationEnd"),Pr(Dr,"onAnimationIteration"),Pr(jr,"onAnimationStart"),Pr("dblclick","onDoubleClick"),Pr("focusin","onFocus"),Pr("focusout","onBlur"),Pr(Or,"onTransitionEnd"),l("onMouseEnter",["mouseout","mouseover"]),l("onMouseLeave",["mouseout","mouseover"]),l("onPointerEnter",["pointerout","pointerover"]),l("onPointerLeave",["pointerout","pointerover"]),s("onChange","change click focusin focusout input keydown keyup selectionchange".split(" ")),s("onSelect","focusout contextmenu dragend focusin keydown keyup mousedown mouseup selectionchange".split(" ")),s("onBeforeInput",["compositionend","keypress","textInput","paste"]),s("onCompositionEnd","compositionend focusout keydown keypress keyup mousedown".split(" ")),s("onCompositionStart","compositionstart focusout keydown keypress keyup mousedown".split(" ")),s("onCompositionUpdate","compositionupdate focusout keydown keypress keyup mousedown".split(" "));var Rr="abort canplay canplaythrough durationchange emptied encrypted ended error loadeddata loadedmetadata loadstart pause play playing progress ratechange resize seeked seeking stalled suspend timeupdate volumechange waiting".split(" "),Lr=new Set("cancel close invalid load scroll toggle".split(" ").concat(Rr));function Mr(e,t,n){var r=e.type||"unknown-event";e.currentTarget=n,function(e,t,n,r,o,i,c,s,l){if($e.apply(this,arguments),Le){if(!Le)throw Error(a(198));var u=Me;Le=!1,Me=null,Fe||(Fe=!0,Be=u)}}(r,t,void 0,e),e.currentTarget=null}function Fr(e,t){t=!!(4&t);for(var n=0;n<e.length;n++){var r=e[n],o=r.event;r=r.listeners;e:{var a=void 0;if(t)for(var i=r.length-1;0<=i;i--){var c=r[i],s=c.instance,l=c.currentTarget;if(c=c.listener,s!==a&&o.isPropagationStopped())break e;Mr(o,c,l),a=s}else for(i=0;i<r.length;i++){if(s=(c=r[i]).instance,l=c.currentTarget,c=c.listener,s!==a&&o.isPropagationStopped())break e;Mr(o,c,l),a=s}}}if(Fe)throw e=Be,Fe=!1,Be=null,e}function Br(e,t){var n=t[ho];void 0===n&&(n=t[ho]=new Set);var r=e+"__bubble";n.has(r)||(Hr(t,e,2,!1),n.add(r))}function zr(e,t,n){var r=0;t&&(r|=4),Hr(n,e,r,t)}var $r="_reactListening"+Math.random().toString(36).slice(2);function Ur(e){if(!e[$r]){e[$r]=!0,i.forEach((function(t){"selectionchange"!==t&&(Lr.has(t)||zr(t,!1,e),zr(t,!0,e))}));var t=9===e.nodeType?e:e.ownerDocument;null===t||t[$r]||(t[$r]=!0,zr("selectionchange",!1,t))}}function Hr(e,t,n,r){switch(Qt(t)){case 1:var o=Vt;break;case 4:o=Wt;break;default:o=Gt}n=o.bind(null,t,n,e),o=void 0,!Ie||"touchstart"!==t&&"touchmove"!==t&&"wheel"!==t||(o=!0),r?void 0!==o?e.addEventListener(t,n,{capture:!0,passive:o}):e.addEventListener(t,n,!0):void 0!==o?e.addEventListener(t,n,{passive:o}):e.addEventListener(t,n,!1)}function qr(e,t,n,r,o){var a=r;if(!(1&t||2&t||null===r))e:for(;;){if(null===r)return;var i=r.tag;if(3===i||4===i){var c=r.stateNode.containerInfo;if(c===o||8===c.nodeType&&c.parentNode===o)break;if(4===i)for(i=r.return;null!==i;){var s=i.tag;if((3===s||4===s)&&((s=i.stateNode.containerInfo)===o||8===s.nodeType&&s.parentNode===o))return;i=i.return}for(;null!==c;){if(null===(i=vo(c)))return;if(5===(s=i.tag)||6===s){r=a=i;continue e}c=c.parentNode}}r=r.return}Te((function(){var r=a,o=Se(n),i=[];e:{var c=Ar.get(e);if(void 0!==c){var s=un,l=e;switch(e){case"keypress":if(0===tn(n))break e;case"keydown":case"keyup":s=Dn;break;case"focusin":l="focus",s=hn;break;case"focusout":l="blur",s=hn;break;case"beforeblur":case"afterblur":s=hn;break;case"click":if(2===n.button)break e;case"auxclick":case"dblclick":case"mousedown":case"mousemove":case"mouseup":case"mouseout":case"mouseover":case"contextmenu":s=mn;break;case"drag":case"dragend":case"dragenter":case"dragexit":case"dragleave":case"dragover":case"dragstart":case"drop":s=gn;break;case"touchcancel":case"touchend":case"touchmove":case"touchstart":s=On;break;case Er:case Dr:case jr:s=bn;break;case Or:s=An;break;case"scroll":s=pn;break;case"wheel":s=Pn;break;case"copy":case"cut":case"paste":s=vn;break;case"gotpointercapture":case"lostpointercapture":case"pointercancel":case"pointerdown":case"pointermove":case"pointerout":case"pointerover":case"pointerup":s=jn}var u=!!(4&t),d=!u&&"scroll"===e,p=u?null!==c?c+"Capture":null:c;u=[];for(var f,m=r;null!==m;){var g=(f=m).stateNode;if(5===f.tag&&null!==g&&(f=g,null!==p&&(null!=(g=Pe(m,p))&&u.push(Vr(m,g,f)))),d)break;m=m.return}0<u.length&&(c=new s(c,l,null,n,o),i.push({event:c,listeners:u}))}}if(!(7&t)){if(s="mouseout"===e||"pointerout"===e,(!(c="mouseover"===e||"pointerover"===e)||n===we||!(l=n.relatedTarget||n.fromElement)||!vo(l)&&!l[go])&&(s||c)&&(c=o.window===o?o:(c=o.ownerDocument)?c.defaultView||c.parentWindow:window,s?(s=r,null!==(l=(l=n.relatedTarget||n.toElement)?vo(l):null)&&(l!==(d=Ue(l))||5!==l.tag&&6!==l.tag)&&(l=null)):(s=null,l=r),s!==l)){if(u=mn,g="onMouseLeave",p="onMouseEnter",m="mouse","pointerout"!==e&&"pointerover"!==e||(u=jn,g="onPointerLeave",p="onPointerEnter",m="pointer"),d=null==s?c:So(s),f=null==l?c:So(l),(c=new u(g,m+"leave",s,n,o)).target=d,c.relatedTarget=f,g=null,vo(o)===r&&((u=new u(p,m+"enter",l,n,o)).target=f,u.relatedTarget=d,g=u),d=g,s&&l)e:{for(p=l,m=0,f=u=s;f;f=Gr(f))m++;for(f=0,g=p;g;g=Gr(g))f++;for(;0<m-f;)u=Gr(u),m--;for(;0<f-m;)p=Gr(p),f--;for(;m--;){if(u===p||null!==p&&u===p.alternate)break e;u=Gr(u),p=Gr(p)}u=null}else u=null;null!==s&&Kr(i,c,s,u,!1),null!==l&&null!==d&&Kr(i,d,l,u,!0)}if("select"===(s=(c=r?So(r):window).nodeName&&c.nodeName.toLowerCase())||"input"===s&&"file"===c.type)var h=Qn;else if(qn(c))if(Zn)h=ir;else{h=or;var b=rr}else(s=c.nodeName)&&"input"===s.toLowerCase()&&("checkbox"===c.type||"radio"===c.type)&&(h=ar);switch(h&&(h=h(e,r))?Vn(i,h,n,o):(b&&b(e,c,r),"focusout"===e&&(b=c._wrapperState)&&b.controlled&&"number"===c.type&&ee(c,"number",c.value)),b=r?So(r):window,e){case"focusin":(qn(b)||"true"===b.contentEditable)&&(hr=b,br=r,yr=null);break;case"focusout":yr=br=hr=null;break;case"mousedown":vr=!0;break;case"contextmenu":case"mouseup":case"dragend":vr=!1,wr(i,n,o);break;case"selectionchange":if(gr)break;case"keydown":case"keyup":wr(i,n,o)}var y;if(Nn)e:{switch(e){case"compositionstart":var v="onCompositionStart";break e;case"compositionend":v="onCompositionEnd";break e;case"compositionupdate":v="onCompositionUpdate";break e}v=void 0}else Un?zn(e,n)&&(v="onCompositionEnd"):"keydown"===e&&229===n.keyCode&&(v="onCompositionStart");v&&(Mn&&"ko"!==n.locale&&(Un||"onCompositionStart"!==v?"onCompositionEnd"===v&&Un&&(y=en()):(Xt="value"in(Zt=o)?Zt.value:Zt.textContent,Un=!0)),0<(b=Wr(r,v)).length&&(v=new wn(v,e,null,n,o),i.push({event:v,listeners:b}),y?v.data=y:null!==(y=$n(n))&&(v.data=y))),(y=Ln?function(e,t){switch(e){case"compositionend":return $n(t);case"keypress":return 32!==t.which?null:(Bn=!0,Fn);case"textInput":return(e=t.data)===Fn&&Bn?null:e;default:return null}}(e,n):function(e,t){if(Un)return"compositionend"===e||!Nn&&zn(e,t)?(e=en(),Jt=Xt=Zt=null,Un=!1,e):null;switch(e){case"paste":default:return null;case"keypress":if(!(t.ctrlKey||t.altKey||t.metaKey)||t.ctrlKey&&t.altKey){if(t.char&&1<t.char.length)return t.char;if(t.which)return String.fromCharCode(t.which)}return null;case"compositionend":return Mn&&"ko"!==t.locale?null:t.data}}(e,n))&&(0<(r=Wr(r,"onBeforeInput")).length&&(o=new wn("onBeforeInput","beforeinput",null,n,o),i.push({event:o,listeners:r}),o.data=y))}Fr(i,t)}))}function Vr(e,t,n){return{instance:e,listener:t,currentTarget:n}}function Wr(e,t){for(var n=t+"Capture",r=[];null!==e;){var o=e,a=o.stateNode;5===o.tag&&null!==a&&(o=a,null!=(a=Pe(e,n))&&r.unshift(Vr(e,a,o)),null!=(a=Pe(e,t))&&r.push(Vr(e,a,o))),e=e.return}return r}function Gr(e){if(null===e)return null;do{e=e.return}while(e&&5!==e.tag);return e||null}function Kr(e,t,n,r,o){for(var a=t._reactName,i=[];null!==n&&n!==r;){var c=n,s=c.alternate,l=c.stateNode;if(null!==s&&s===r)break;5===c.tag&&null!==l&&(c=l,o?null!=(s=Pe(n,a))&&i.unshift(Vr(n,s,c)):o||null!=(s=Pe(n,a))&&i.push(Vr(n,s,c))),n=n.return}0!==i.length&&e.push({event:t,listeners:i})}var Yr=/\r\n?/g,Qr=/\u0000|\uFFFD/g;function Zr(e){return("string"==typeof e?e:""+e).replace(Yr,"\n").replace(Qr,"")}function Xr(e,t,n){if(t=Zr(t),Zr(e)!==t&&n)throw Error(a(425))}function Jr(){}var eo=null,to=null;function no(e,t){return"textarea"===e||"noscript"===e||"string"==typeof t.children||"number"==typeof t.children||"object"==typeof t.dangerouslySetInnerHTML&&null!==t.dangerouslySetInnerHTML&&null!=t.dangerouslySetInnerHTML.__html}var ro="function"==typeof setTimeout?setTimeout:void 0,oo="function"==typeof clearTimeout?clearTimeout:void 0,ao="function"==typeof Promise?Promise:void 0,io="function"==typeof queueMicrotask?queueMicrotask:void 0!==ao?function(e){return ao.resolve(null).then(e).catch(co)}:ro;function co(e){setTimeout((function(){throw e}))}function so(e,t){var n=t,r=0;do{var o=n.nextSibling;if(e.removeChild(n),o&&8===o.nodeType)if("/$"===(n=o.data)){if(0===r)return e.removeChild(o),void Ut(t);r--}else"$"!==n&&"$?"!==n&&"$!"!==n||r++;n=o}while(n);Ut(t)}function lo(e){for(;null!=e;e=e.nextSibling){var t=e.nodeType;if(1===t||3===t)break;if(8===t){if("$"===(t=e.data)||"$!"===t||"$?"===t)break;if("/$"===t)return null}}return e}function uo(e){e=e.previousSibling;for(var t=0;e;){if(8===e.nodeType){var n=e.data;if("$"===n||"$!"===n||"$?"===n){if(0===t)return e;t--}else"/$"===n&&t++}e=e.previousSibling}return null}var po=Math.random().toString(36).slice(2),fo="__reactFiber$"+po,mo="__reactProps$"+po,go="__reactContainer$"+po,ho="__reactEvents$"+po,bo="__reactListeners$"+po,yo="__reactHandles$"+po;function vo(e){var t=e[fo];if(t)return t;for(var n=e.parentNode;n;){if(t=n[go]||n[fo]){if(n=t.alternate,null!==t.child||null!==n&&null!==n.child)for(e=uo(e);null!==e;){if(n=e[fo])return n;e=uo(e)}return t}n=(e=n).parentNode}return null}function wo(e){return!(e=e[fo]||e[go])||5!==e.tag&&6!==e.tag&&13!==e.tag&&3!==e.tag?null:e}function So(e){if(5===e.tag||6===e.tag)return e.stateNode;throw Error(a(33))}function ko(e){return e[mo]||null}var xo=[],_o=-1;function Co(e){return{current:e}}function Eo(e){0>_o||(e.current=xo[_o],xo[_o]=null,_o--)}function Do(e,t){_o++,xo[_o]=e.current,e.current=t}var jo={},Oo=Co(jo),Ao=Co(!1),To=jo;function Po(e,t){var n=e.type.contextTypes;if(!n)return jo;var r=e.stateNode;if(r&&r.__reactInternalMemoizedUnmaskedChildContext===t)return r.__reactInternalMemoizedMaskedChildContext;var o,a={};for(o in n)a[o]=t[o];return r&&((e=e.stateNode).__reactInternalMemoizedUnmaskedChildContext=t,e.__reactInternalMemoizedMaskedChildContext=a),a}function Io(e){return null!=(e=e.childContextTypes)}function No(){Eo(Ao),Eo(Oo)}function Ro(e,t,n){if(Oo.current!==jo)throw Error(a(168));Do(Oo,t),Do(Ao,n)}function Lo(e,t,n){var r=e.stateNode;if(t=t.childContextTypes,"function"!=typeof r.getChildContext)return n;for(var o in r=r.getChildContext())if(!(o in t))throw Error(a(108,H(e)||"Unknown",o));return M({},n,r)}function Mo(e){return e=(e=e.stateNode)&&e.__reactInternalMemoizedMergedChildContext||jo,To=Oo.current,Do(Oo,e),Do(Ao,Ao.current),!0}function Fo(e,t,n){var r=e.stateNode;if(!r)throw Error(a(169));n?(e=Lo(e,t,To),r.__reactInternalMemoizedMergedChildContext=e,Eo(Ao),Eo(Oo),Do(Oo,e)):Eo(Ao),Do(Ao,n)}var Bo=null,zo=!1,$o=!1;function Uo(e){null===Bo?Bo=[e]:Bo.push(e)}function Ho(){if(!$o&&null!==Bo){$o=!0;var e=0,t=vt;try{var n=Bo;for(vt=1;e<n.length;e++){var r=n[e];do{r=r(!0)}while(null!==r)}Bo=null,zo=!1}catch(o){throw null!==Bo&&(Bo=Bo.slice(e+1)),Ge(Je,Ho),o}finally{vt=t,$o=!1}}return null}var qo=[],Vo=0,Wo=null,Go=0,Ko=[],Yo=0,Qo=null,Zo=1,Xo="";function Jo(e,t){qo[Vo++]=Go,qo[Vo++]=Wo,Wo=e,Go=t}function ea(e,t,n){Ko[Yo++]=Zo,Ko[Yo++]=Xo,Ko[Yo++]=Qo,Qo=e;var r=Zo;e=Xo;var o=32-it(r)-1;r&=~(1<<o),n+=1;var a=32-it(t)+o;if(30<a){var i=o-o%5;a=(r&(1<<i)-1).toString(32),r>>=i,o-=i,Zo=1<<32-it(t)+o|n<<o|r,Xo=a+e}else Zo=1<<a|n<<o|r,Xo=e}function ta(e){null!==e.return&&(Jo(e,1),ea(e,1,0))}function na(e){for(;e===Wo;)Wo=qo[--Vo],qo[Vo]=null,Go=qo[--Vo],qo[Vo]=null;for(;e===Qo;)Qo=Ko[--Yo],Ko[Yo]=null,Xo=Ko[--Yo],Ko[Yo]=null,Zo=Ko[--Yo],Ko[Yo]=null}var ra=null,oa=null,aa=!1,ia=null;function ca(e,t){var n=Tl(5,null,null,0);n.elementType="DELETED",n.stateNode=t,n.return=e,null===(t=e.deletions)?(e.deletions=[n],e.flags|=16):t.push(n)}function sa(e,t){switch(e.tag){case 5:var n=e.type;return null!==(t=1!==t.nodeType||n.toLowerCase()!==t.nodeName.toLowerCase()?null:t)&&(e.stateNode=t,ra=e,oa=lo(t.firstChild),!0);case 6:return null!==(t=""===e.pendingProps||3!==t.nodeType?null:t)&&(e.stateNode=t,ra=e,oa=null,!0);case 13:return null!==(t=8!==t.nodeType?null:t)&&(n=null!==Qo?{id:Zo,overflow:Xo}:null,e.memoizedState={dehydrated:t,treeContext:n,retryLane:1073741824},(n=Tl(18,null,null,0)).stateNode=t,n.return=e,e.child=n,ra=e,oa=null,!0);default:return!1}}function la(e){return!(!(1&e.mode)||128&e.flags)}function ua(e){if(aa){var t=oa;if(t){var n=t;if(!sa(e,t)){if(la(e))throw Error(a(418));t=lo(n.nextSibling);var r=ra;t&&sa(e,t)?ca(r,n):(e.flags=-4097&e.flags|2,aa=!1,ra=e)}}else{if(la(e))throw Error(a(418));e.flags=-4097&e.flags|2,aa=!1,ra=e}}}function da(e){for(e=e.return;null!==e&&5!==e.tag&&3!==e.tag&&13!==e.tag;)e=e.return;ra=e}function pa(e){if(e!==ra)return!1;if(!aa)return da(e),aa=!0,!1;var t;if((t=3!==e.tag)&&!(t=5!==e.tag)&&(t="head"!==(t=e.type)&&"body"!==t&&!no(e.type,e.memoizedProps)),t&&(t=oa)){if(la(e))throw fa(),Error(a(418));for(;t;)ca(e,t),t=lo(t.nextSibling)}if(da(e),13===e.tag){if(!(e=null!==(e=e.memoizedState)?e.dehydrated:null))throw Error(a(317));e:{for(e=e.nextSibling,t=0;e;){if(8===e.nodeType){var n=e.data;if("/$"===n){if(0===t){oa=lo(e.nextSibling);break e}t--}else"$"!==n&&"$!"!==n&&"$?"!==n||t++}e=e.nextSibling}oa=null}}else oa=ra?lo(e.stateNode.nextSibling):null;return!0}function fa(){for(var e=oa;e;)e=lo(e.nextSibling)}function ma(){oa=ra=null,aa=!1}function ga(e){null===ia?ia=[e]:ia.push(e)}var ha=w.ReactCurrentBatchConfig;function ba(e,t,n){if(null!==(e=n.ref)&&"function"!=typeof e&&"object"!=typeof e){if(n._owner){if(n=n._owner){if(1!==n.tag)throw Error(a(309));var r=n.stateNode}if(!r)throw Error(a(147,e));var o=r,i=""+e;return null!==t&&null!==t.ref&&"function"==typeof t.ref&&t.ref._stringRef===i?t.ref:(t=function(e){var t=o.refs;null===e?delete t[i]:t[i]=e},t._stringRef=i,t)}if("string"!=typeof e)throw Error(a(284));if(!n._owner)throw Error(a(290,e))}return e}function ya(e,t){throw e=Object.prototype.toString.call(t),Error(a(31,"[object Object]"===e?"object with keys {"+Object.keys(t).join(", ")+"}":e))}function va(e){return(0,e._init)(e._payload)}function wa(e){function t(t,n){if(e){var r=t.deletions;null===r?(t.deletions=[n],t.flags|=16):r.push(n)}}function n(n,r){if(!e)return null;for(;null!==r;)t(n,r),r=r.sibling;return null}function r(e,t){for(e=new Map;null!==t;)null!==t.key?e.set(t.key,t):e.set(t.index,t),t=t.sibling;return e}function o(e,t){return(e=Il(e,t)).index=0,e.sibling=null,e}function i(t,n,r){return t.index=r,e?null!==(r=t.alternate)?(r=r.index)<n?(t.flags|=2,n):r:(t.flags|=2,n):(t.flags|=1048576,n)}function c(t){return e&&null===t.alternate&&(t.flags|=2),t}function s(e,t,n,r){return null===t||6!==t.tag?((t=Ml(n,e.mode,r)).return=e,t):((t=o(t,n)).return=e,t)}function l(e,t,n,r){var a=n.type;return a===x?d(e,t,n.props.children,r,n.key):null!==t&&(t.elementType===a||"object"==typeof a&&null!==a&&a.$$typeof===P&&va(a)===t.type)?((r=o(t,n.props)).ref=ba(e,t,n),r.return=e,r):((r=Nl(n.type,n.key,n.props,null,e.mode,r)).ref=ba(e,t,n),r.return=e,r)}function u(e,t,n,r){return null===t||4!==t.tag||t.stateNode.containerInfo!==n.containerInfo||t.stateNode.implementation!==n.implementation?((t=Fl(n,e.mode,r)).return=e,t):((t=o(t,n.children||[])).return=e,t)}function d(e,t,n,r,a){return null===t||7!==t.tag?((t=Rl(n,e.mode,r,a)).return=e,t):((t=o(t,n)).return=e,t)}function p(e,t,n){if("string"==typeof t&&""!==t||"number"==typeof t)return(t=Ml(""+t,e.mode,n)).return=e,t;if("object"==typeof t&&null!==t){switch(t.$$typeof){case S:return(n=Nl(t.type,t.key,t.props,null,e.mode,n)).ref=ba(e,null,t),n.return=e,n;case k:return(t=Fl(t,e.mode,n)).return=e,t;case P:return p(e,(0,t._init)(t._payload),n)}if(te(t)||R(t))return(t=Rl(t,e.mode,n,null)).return=e,t;ya(e,t)}return null}function f(e,t,n,r){var o=null!==t?t.key:null;if("string"==typeof n&&""!==n||"number"==typeof n)return null!==o?null:s(e,t,""+n,r);if("object"==typeof n&&null!==n){switch(n.$$typeof){case S:return n.key===o?l(e,t,n,r):null;case k:return n.key===o?u(e,t,n,r):null;case P:return f(e,t,(o=n._init)(n._payload),r)}if(te(n)||R(n))return null!==o?null:d(e,t,n,r,null);ya(e,n)}return null}function m(e,t,n,r,o){if("string"==typeof r&&""!==r||"number"==typeof r)return s(t,e=e.get(n)||null,""+r,o);if("object"==typeof r&&null!==r){switch(r.$$typeof){case S:return l(t,e=e.get(null===r.key?n:r.key)||null,r,o);case k:return u(t,e=e.get(null===r.key?n:r.key)||null,r,o);case P:return m(e,t,n,(0,r._init)(r._payload),o)}if(te(r)||R(r))return d(t,e=e.get(n)||null,r,o,null);ya(t,r)}return null}function g(o,a,c,s){for(var l=null,u=null,d=a,g=a=0,h=null;null!==d&&g<c.length;g++){d.index>g?(h=d,d=null):h=d.sibling;var b=f(o,d,c[g],s);if(null===b){null===d&&(d=h);break}e&&d&&null===b.alternate&&t(o,d),a=i(b,a,g),null===u?l=b:u.sibling=b,u=b,d=h}if(g===c.length)return n(o,d),aa&&Jo(o,g),l;if(null===d){for(;g<c.length;g++)null!==(d=p(o,c[g],s))&&(a=i(d,a,g),null===u?l=d:u.sibling=d,u=d);return aa&&Jo(o,g),l}for(d=r(o,d);g<c.length;g++)null!==(h=m(d,o,g,c[g],s))&&(e&&null!==h.alternate&&d.delete(null===h.key?g:h.key),a=i(h,a,g),null===u?l=h:u.sibling=h,u=h);return e&&d.forEach((function(e){return t(o,e)})),aa&&Jo(o,g),l}function h(o,c,s,l){var u=R(s);if("function"!=typeof u)throw Error(a(150));if(null==(s=u.call(s)))throw Error(a(151));for(var d=u=null,g=c,h=c=0,b=null,y=s.next();null!==g&&!y.done;h++,y=s.next()){g.index>h?(b=g,g=null):b=g.sibling;var v=f(o,g,y.value,l);if(null===v){null===g&&(g=b);break}e&&g&&null===v.alternate&&t(o,g),c=i(v,c,h),null===d?u=v:d.sibling=v,d=v,g=b}if(y.done)return n(o,g),aa&&Jo(o,h),u;if(null===g){for(;!y.done;h++,y=s.next())null!==(y=p(o,y.value,l))&&(c=i(y,c,h),null===d?u=y:d.sibling=y,d=y);return aa&&Jo(o,h),u}for(g=r(o,g);!y.done;h++,y=s.next())null!==(y=m(g,o,h,y.value,l))&&(e&&null!==y.alternate&&g.delete(null===y.key?h:y.key),c=i(y,c,h),null===d?u=y:d.sibling=y,d=y);return e&&g.forEach((function(e){return t(o,e)})),aa&&Jo(o,h),u}return function e(r,a,i,s){if("object"==typeof i&&null!==i&&i.type===x&&null===i.key&&(i=i.props.children),"object"==typeof i&&null!==i){switch(i.$$typeof){case S:e:{for(var l=i.key,u=a;null!==u;){if(u.key===l){if((l=i.type)===x){if(7===u.tag){n(r,u.sibling),(a=o(u,i.props.children)).return=r,r=a;break e}}else if(u.elementType===l||"object"==typeof l&&null!==l&&l.$$typeof===P&&va(l)===u.type){n(r,u.sibling),(a=o(u,i.props)).ref=ba(r,u,i),a.return=r,r=a;break e}n(r,u);break}t(r,u),u=u.sibling}i.type===x?((a=Rl(i.props.children,r.mode,s,i.key)).return=r,r=a):((s=Nl(i.type,i.key,i.props,null,r.mode,s)).ref=ba(r,a,i),s.return=r,r=s)}return c(r);case k:e:{for(u=i.key;null!==a;){if(a.key===u){if(4===a.tag&&a.stateNode.containerInfo===i.containerInfo&&a.stateNode.implementation===i.implementation){n(r,a.sibling),(a=o(a,i.children||[])).return=r,r=a;break e}n(r,a);break}t(r,a),a=a.sibling}(a=Fl(i,r.mode,s)).return=r,r=a}return c(r);case P:return e(r,a,(u=i._init)(i._payload),s)}if(te(i))return g(r,a,i,s);if(R(i))return h(r,a,i,s);ya(r,i)}return"string"==typeof i&&""!==i||"number"==typeof i?(i=""+i,null!==a&&6===a.tag?(n(r,a.sibling),(a=o(a,i)).return=r,r=a):(n(r,a),(a=Ml(i,r.mode,s)).return=r,r=a),c(r)):n(r,a)}}var Sa=wa(!0),ka=wa(!1),xa=Co(null),_a=null,Ca=null,Ea=null;function Da(){Ea=Ca=_a=null}function ja(e){var t=xa.current;Eo(xa),e._currentValue=t}function Oa(e,t,n){for(;null!==e;){var r=e.alternate;if((e.childLanes&t)!==t?(e.childLanes|=t,null!==r&&(r.childLanes|=t)):null!==r&&(r.childLanes&t)!==t&&(r.childLanes|=t),e===n)break;e=e.return}}function Aa(e,t){_a=e,Ea=Ca=null,null!==(e=e.dependencies)&&null!==e.firstContext&&(!!(e.lanes&t)&&(vc=!0),e.firstContext=null)}function Ta(e){var t=e._currentValue;if(Ea!==e)if(e={context:e,memoizedValue:t,next:null},null===Ca){if(null===_a)throw Error(a(308));Ca=e,_a.dependencies={lanes:0,firstContext:e}}else Ca=Ca.next=e;return t}var Pa=null;function Ia(e){null===Pa?Pa=[e]:Pa.push(e)}function Na(e,t,n,r){var o=t.interleaved;return null===o?(n.next=n,Ia(t)):(n.next=o.next,o.next=n),t.interleaved=n,Ra(e,r)}function Ra(e,t){e.lanes|=t;var n=e.alternate;for(null!==n&&(n.lanes|=t),n=e,e=e.return;null!==e;)e.childLanes|=t,null!==(n=e.alternate)&&(n.childLanes|=t),n=e,e=e.return;return 3===n.tag?n.stateNode:null}var La=!1;function Ma(e){e.updateQueue={baseState:e.memoizedState,firstBaseUpdate:null,lastBaseUpdate:null,shared:{pending:null,interleaved:null,lanes:0},effects:null}}function Fa(e,t){e=e.updateQueue,t.updateQueue===e&&(t.updateQueue={baseState:e.baseState,firstBaseUpdate:e.firstBaseUpdate,lastBaseUpdate:e.lastBaseUpdate,shared:e.shared,effects:e.effects})}function Ba(e,t){return{eventTime:e,lane:t,tag:0,payload:null,callback:null,next:null}}function za(e,t,n){var r=e.updateQueue;if(null===r)return null;if(r=r.shared,2&js){var o=r.pending;return null===o?t.next=t:(t.next=o.next,o.next=t),r.pending=t,Ra(e,n)}return null===(o=r.interleaved)?(t.next=t,Ia(r)):(t.next=o.next,o.next=t),r.interleaved=t,Ra(e,n)}function $a(e,t,n){if(null!==(t=t.updateQueue)&&(t=t.shared,4194240&n)){var r=t.lanes;n|=r&=e.pendingLanes,t.lanes=n,yt(e,n)}}function Ua(e,t){var n=e.updateQueue,r=e.alternate;if(null!==r&&n===(r=r.updateQueue)){var o=null,a=null;if(null!==(n=n.firstBaseUpdate)){do{var i={eventTime:n.eventTime,lane:n.lane,tag:n.tag,payload:n.payload,callback:n.callback,next:null};null===a?o=a=i:a=a.next=i,n=n.next}while(null!==n);null===a?o=a=t:a=a.next=t}else o=a=t;return n={baseState:r.baseState,firstBaseUpdate:o,lastBaseUpdate:a,shared:r.shared,effects:r.effects},void(e.updateQueue=n)}null===(e=n.lastBaseUpdate)?n.firstBaseUpdate=t:e.next=t,n.lastBaseUpdate=t}function Ha(e,t,n,r){var o=e.updateQueue;La=!1;var a=o.firstBaseUpdate,i=o.lastBaseUpdate,c=o.shared.pending;if(null!==c){o.shared.pending=null;var s=c,l=s.next;s.next=null,null===i?a=l:i.next=l,i=s;var u=e.alternate;null!==u&&((c=(u=u.updateQueue).lastBaseUpdate)!==i&&(null===c?u.firstBaseUpdate=l:c.next=l,u.lastBaseUpdate=s))}if(null!==a){var d=o.baseState;for(i=0,u=l=s=null,c=a;;){var p=c.lane,f=c.eventTime;if((r&p)===p){null!==u&&(u=u.next={eventTime:f,lane:0,tag:c.tag,payload:c.payload,callback:c.callback,next:null});e:{var m=e,g=c;switch(p=t,f=n,g.tag){case 1:if("function"==typeof(m=g.payload)){d=m.call(f,d,p);break e}d=m;break e;case 3:m.flags=-65537&m.flags|128;case 0:if(null==(p="function"==typeof(m=g.payload)?m.call(f,d,p):m))break e;d=M({},d,p);break e;case 2:La=!0}}null!==c.callback&&0!==c.lane&&(e.flags|=64,null===(p=o.effects)?o.effects=[c]:p.push(c))}else f={eventTime:f,lane:p,tag:c.tag,payload:c.payload,callback:c.callback,next:null},null===u?(l=u=f,s=d):u=u.next=f,i|=p;if(null===(c=c.next)){if(null===(c=o.shared.pending))break;c=(p=c).next,p.next=null,o.lastBaseUpdate=p,o.shared.pending=null}}if(null===u&&(s=d),o.baseState=s,o.firstBaseUpdate=l,o.lastBaseUpdate=u,null!==(t=o.shared.interleaved)){o=t;do{i|=o.lane,o=o.next}while(o!==t)}else null===a&&(o.shared.lanes=0);Ls|=i,e.lanes=i,e.memoizedState=d}}function qa(e,t,n){if(e=t.effects,t.effects=null,null!==e)for(t=0;t<e.length;t++){var r=e[t],o=r.callback;if(null!==o){if(r.callback=null,r=n,"function"!=typeof o)throw Error(a(191,o));o.call(r)}}}var Va={},Wa=Co(Va),Ga=Co(Va),Ka=Co(Va);function Ya(e){if(e===Va)throw Error(a(174));return e}function Qa(e,t){switch(Do(Ka,t),Do(Ga,e),Do(Wa,Va),e=t.nodeType){case 9:case 11:t=(t=t.documentElement)?t.namespaceURI:se(null,"");break;default:t=se(t=(e=8===e?t.parentNode:t).namespaceURI||null,e=e.tagName)}Eo(Wa),Do(Wa,t)}function Za(){Eo(Wa),Eo(Ga),Eo(Ka)}function Xa(e){Ya(Ka.current);var t=Ya(Wa.current),n=se(t,e.type);t!==n&&(Do(Ga,e),Do(Wa,n))}function Ja(e){Ga.current===e&&(Eo(Wa),Eo(Ga))}var ei=Co(0);function ti(e){for(var t=e;null!==t;){if(13===t.tag){var n=t.memoizedState;if(null!==n&&(null===(n=n.dehydrated)||"$?"===n.data||"$!"===n.data))return t}else if(19===t.tag&&void 0!==t.memoizedProps.revealOrder){if(128&t.flags)return t}else if(null!==t.child){t.child.return=t,t=t.child;continue}if(t===e)break;for(;null===t.sibling;){if(null===t.return||t.return===e)return null;t=t.return}t.sibling.return=t.return,t=t.sibling}return null}var ni=[];function ri(){for(var e=0;e<ni.length;e++)ni[e]._workInProgressVersionPrimary=null;ni.length=0}var oi=w.ReactCurrentDispatcher,ai=w.ReactCurrentBatchConfig,ii=0,ci=null,si=null,li=null,ui=!1,di=!1,pi=0,fi=0;function mi(){throw Error(a(321))}function gi(e,t){if(null===t)return!1;for(var n=0;n<t.length&&n<e.length;n++)if(!cr(e[n],t[n]))return!1;return!0}function hi(e,t,n,r,o,i){if(ii=i,ci=t,t.memoizedState=null,t.updateQueue=null,t.lanes=0,oi.current=null===e||null===e.memoizedState?Ji:ec,e=n(r,o),di){i=0;do{if(di=!1,pi=0,25<=i)throw Error(a(301));i+=1,li=si=null,t.updateQueue=null,oi.current=tc,e=n(r,o)}while(di)}if(oi.current=Xi,t=null!==si&&null!==si.next,ii=0,li=si=ci=null,ui=!1,t)throw Error(a(300));return e}function bi(){var e=0!==pi;return pi=0,e}function yi(){var e={memoizedState:null,baseState:null,baseQueue:null,queue:null,next:null};return null===li?ci.memoizedState=li=e:li=li.next=e,li}function vi(){if(null===si){var e=ci.alternate;e=null!==e?e.memoizedState:null}else e=si.next;var t=null===li?ci.memoizedState:li.next;if(null!==t)li=t,si=e;else{if(null===e)throw Error(a(310));e={memoizedState:(si=e).memoizedState,baseState:si.baseState,baseQueue:si.baseQueue,queue:si.queue,next:null},null===li?ci.memoizedState=li=e:li=li.next=e}return li}function wi(e,t){return"function"==typeof t?t(e):t}function Si(e){var t=vi(),n=t.queue;if(null===n)throw Error(a(311));n.lastRenderedReducer=e;var r=si,o=r.baseQueue,i=n.pending;if(null!==i){if(null!==o){var c=o.next;o.next=i.next,i.next=c}r.baseQueue=o=i,n.pending=null}if(null!==o){i=o.next,r=r.baseState;var s=c=null,l=null,u=i;do{var d=u.lane;if((ii&d)===d)null!==l&&(l=l.next={lane:0,action:u.action,hasEagerState:u.hasEagerState,eagerState:u.eagerState,next:null}),r=u.hasEagerState?u.eagerState:e(r,u.action);else{var p={lane:d,action:u.action,hasEagerState:u.hasEagerState,eagerState:u.eagerState,next:null};null===l?(s=l=p,c=r):l=l.next=p,ci.lanes|=d,Ls|=d}u=u.next}while(null!==u&&u!==i);null===l?c=r:l.next=s,cr(r,t.memoizedState)||(vc=!0),t.memoizedState=r,t.baseState=c,t.baseQueue=l,n.lastRenderedState=r}if(null!==(e=n.interleaved)){o=e;do{i=o.lane,ci.lanes|=i,Ls|=i,o=o.next}while(o!==e)}else null===o&&(n.lanes=0);return[t.memoizedState,n.dispatch]}function ki(e){var t=vi(),n=t.queue;if(null===n)throw Error(a(311));n.lastRenderedReducer=e;var r=n.dispatch,o=n.pending,i=t.memoizedState;if(null!==o){n.pending=null;var c=o=o.next;do{i=e(i,c.action),c=c.next}while(c!==o);cr(i,t.memoizedState)||(vc=!0),t.memoizedState=i,null===t.baseQueue&&(t.baseState=i),n.lastRenderedState=i}return[i,r]}function xi(){}function _i(e,t){var n=ci,r=vi(),o=t(),i=!cr(r.memoizedState,o);if(i&&(r.memoizedState=o,vc=!0),r=r.queue,Li(Di.bind(null,n,r,e),[e]),r.getSnapshot!==t||i||null!==li&&1&li.memoizedState.tag){if(n.flags|=2048,Ti(9,Ei.bind(null,n,r,o,t),void 0,null),null===Os)throw Error(a(349));30&ii||Ci(n,t,o)}return o}function Ci(e,t,n){e.flags|=16384,e={getSnapshot:t,value:n},null===(t=ci.updateQueue)?(t={lastEffect:null,stores:null},ci.updateQueue=t,t.stores=[e]):null===(n=t.stores)?t.stores=[e]:n.push(e)}function Ei(e,t,n,r){t.value=n,t.getSnapshot=r,ji(t)&&Oi(e)}function Di(e,t,n){return n((function(){ji(t)&&Oi(e)}))}function ji(e){var t=e.getSnapshot;e=e.value;try{var n=t();return!cr(e,n)}catch(r){return!0}}function Oi(e){var t=Ra(e,1);null!==t&&nl(t,e,1,-1)}function Ai(e){var t=yi();return"function"==typeof e&&(e=e()),t.memoizedState=t.baseState=e,e={pending:null,interleaved:null,lanes:0,dispatch:null,lastRenderedReducer:wi,lastRenderedState:e},t.queue=e,e=e.dispatch=Ki.bind(null,ci,e),[t.memoizedState,e]}function Ti(e,t,n,r){return e={tag:e,create:t,destroy:n,deps:r,next:null},null===(t=ci.updateQueue)?(t={lastEffect:null,stores:null},ci.updateQueue=t,t.lastEffect=e.next=e):null===(n=t.lastEffect)?t.lastEffect=e.next=e:(r=n.next,n.next=e,e.next=r,t.lastEffect=e),e}function Pi(){return vi().memoizedState}function Ii(e,t,n,r){var o=yi();ci.flags|=e,o.memoizedState=Ti(1|t,n,void 0,void 0===r?null:r)}function Ni(e,t,n,r){var o=vi();r=void 0===r?null:r;var a=void 0;if(null!==si){var i=si.memoizedState;if(a=i.destroy,null!==r&&gi(r,i.deps))return void(o.memoizedState=Ti(t,n,a,r))}ci.flags|=e,o.memoizedState=Ti(1|t,n,a,r)}function Ri(e,t){return Ii(8390656,8,e,t)}function Li(e,t){return Ni(2048,8,e,t)}function Mi(e,t){return Ni(4,2,e,t)}function Fi(e,t){return Ni(4,4,e,t)}function Bi(e,t){return"function"==typeof t?(e=e(),t(e),function(){t(null)}):null!=t?(e=e(),t.current=e,function(){t.current=null}):void 0}function zi(e,t,n){return n=null!=n?n.concat([e]):null,Ni(4,4,Bi.bind(null,t,e),n)}function $i(){}function Ui(e,t){var n=vi();t=void 0===t?null:t;var r=n.memoizedState;return null!==r&&null!==t&&gi(t,r[1])?r[0]:(n.memoizedState=[e,t],e)}function Hi(e,t){var n=vi();t=void 0===t?null:t;var r=n.memoizedState;return null!==r&&null!==t&&gi(t,r[1])?r[0]:(e=e(),n.memoizedState=[e,t],e)}function qi(e,t,n){return 21&ii?(cr(n,t)||(n=gt(),ci.lanes|=n,Ls|=n,e.baseState=!0),t):(e.baseState&&(e.baseState=!1,vc=!0),e.memoizedState=n)}function Vi(e,t){var n=vt;vt=0!==n&&4>n?n:4,e(!0);var r=ai.transition;ai.transition={};try{e(!1),t()}finally{vt=n,ai.transition=r}}function Wi(){return vi().memoizedState}function Gi(e,t,n){var r=tl(e);if(n={lane:r,action:n,hasEagerState:!1,eagerState:null,next:null},Yi(e))Qi(t,n);else if(null!==(n=Na(e,t,n,r))){nl(n,e,r,el()),Zi(n,t,r)}}function Ki(e,t,n){var r=tl(e),o={lane:r,action:n,hasEagerState:!1,eagerState:null,next:null};if(Yi(e))Qi(t,o);else{var a=e.alternate;if(0===e.lanes&&(null===a||0===a.lanes)&&null!==(a=t.lastRenderedReducer))try{var i=t.lastRenderedState,c=a(i,n);if(o.hasEagerState=!0,o.eagerState=c,cr(c,i)){var s=t.interleaved;return null===s?(o.next=o,Ia(t)):(o.next=s.next,s.next=o),void(t.interleaved=o)}}catch(l){}null!==(n=Na(e,t,o,r))&&(nl(n,e,r,o=el()),Zi(n,t,r))}}function Yi(e){var t=e.alternate;return e===ci||null!==t&&t===ci}function Qi(e,t){di=ui=!0;var n=e.pending;null===n?t.next=t:(t.next=n.next,n.next=t),e.pending=t}function Zi(e,t,n){if(4194240&n){var r=t.lanes;n|=r&=e.pendingLanes,t.lanes=n,yt(e,n)}}var Xi={readContext:Ta,useCallback:mi,useContext:mi,useEffect:mi,useImperativeHandle:mi,useInsertionEffect:mi,useLayoutEffect:mi,useMemo:mi,useReducer:mi,useRef:mi,useState:mi,useDebugValue:mi,useDeferredValue:mi,useTransition:mi,useMutableSource:mi,useSyncExternalStore:mi,useId:mi,unstable_isNewReconciler:!1},Ji={readContext:Ta,useCallback:function(e,t){return yi().memoizedState=[e,void 0===t?null:t],e},useContext:Ta,useEffect:Ri,useImperativeHandle:function(e,t,n){return n=null!=n?n.concat([e]):null,Ii(4194308,4,Bi.bind(null,t,e),n)},useLayoutEffect:function(e,t){return Ii(4194308,4,e,t)},useInsertionEffect:function(e,t){return Ii(4,2,e,t)},useMemo:function(e,t){var n=yi();return t=void 0===t?null:t,e=e(),n.memoizedState=[e,t],e},useReducer:function(e,t,n){var r=yi();return t=void 0!==n?n(t):t,r.memoizedState=r.baseState=t,e={pending:null,interleaved:null,lanes:0,dispatch:null,lastRenderedReducer:e,lastRenderedState:t},r.queue=e,e=e.dispatch=Gi.bind(null,ci,e),[r.memoizedState,e]},useRef:function(e){return e={current:e},yi().memoizedState=e},useState:Ai,useDebugValue:$i,useDeferredValue:function(e){return yi().memoizedState=e},useTransition:function(){var e=Ai(!1),t=e[0];return e=Vi.bind(null,e[1]),yi().memoizedState=e,[t,e]},useMutableSource:function(){},useSyncExternalStore:function(e,t,n){var r=ci,o=yi();if(aa){if(void 0===n)throw Error(a(407));n=n()}else{if(n=t(),null===Os)throw Error(a(349));30&ii||Ci(r,t,n)}o.memoizedState=n;var i={value:n,getSnapshot:t};return o.queue=i,Ri(Di.bind(null,r,i,e),[e]),r.flags|=2048,Ti(9,Ei.bind(null,r,i,n,t),void 0,null),n},useId:function(){var e=yi(),t=Os.identifierPrefix;if(aa){var n=Xo;t=":"+t+"R"+(n=(Zo&~(1<<32-it(Zo)-1)).toString(32)+n),0<(n=pi++)&&(t+="H"+n.toString(32)),t+=":"}else t=":"+t+"r"+(n=fi++).toString(32)+":";return e.memoizedState=t},unstable_isNewReconciler:!1},ec={readContext:Ta,useCallback:Ui,useContext:Ta,useEffect:Li,useImperativeHandle:zi,useInsertionEffect:Mi,useLayoutEffect:Fi,useMemo:Hi,useReducer:Si,useRef:Pi,useState:function(){return Si(wi)},useDebugValue:$i,useDeferredValue:function(e){return qi(vi(),si.memoizedState,e)},useTransition:function(){return[Si(wi)[0],vi().memoizedState]},useMutableSource:xi,useSyncExternalStore:_i,useId:Wi,unstable_isNewReconciler:!1},tc={readContext:Ta,useCallback:Ui,useContext:Ta,useEffect:Li,useImperativeHandle:zi,useInsertionEffect:Mi,useLayoutEffect:Fi,useMemo:Hi,useReducer:ki,useRef:Pi,useState:function(){return ki(wi)},useDebugValue:$i,useDeferredValue:function(e){var t=vi();return null===si?t.memoizedState=e:qi(t,si.memoizedState,e)},useTransition:function(){return[ki(wi)[0],vi().memoizedState]},useMutableSource:xi,useSyncExternalStore:_i,useId:Wi,unstable_isNewReconciler:!1};function nc(e,t){if(e&&e.defaultProps){for(var n in t=M({},t),e=e.defaultProps)void 0===t[n]&&(t[n]=e[n]);return t}return t}function rc(e,t,n,r){n=null==(n=n(r,t=e.memoizedState))?t:M({},t,n),e.memoizedState=n,0===e.lanes&&(e.updateQueue.baseState=n)}var oc={isMounted:function(e){return!!(e=e._reactInternals)&&Ue(e)===e},enqueueSetState:function(e,t,n){e=e._reactInternals;var r=el(),o=tl(e),a=Ba(r,o);a.payload=t,null!=n&&(a.callback=n),null!==(t=za(e,a,o))&&(nl(t,e,o,r),$a(t,e,o))},enqueueReplaceState:function(e,t,n){e=e._reactInternals;var r=el(),o=tl(e),a=Ba(r,o);a.tag=1,a.payload=t,null!=n&&(a.callback=n),null!==(t=za(e,a,o))&&(nl(t,e,o,r),$a(t,e,o))},enqueueForceUpdate:function(e,t){e=e._reactInternals;var n=el(),r=tl(e),o=Ba(n,r);o.tag=2,null!=t&&(o.callback=t),null!==(t=za(e,o,r))&&(nl(t,e,r,n),$a(t,e,r))}};function ac(e,t,n,r,o,a,i){return"function"==typeof(e=e.stateNode).shouldComponentUpdate?e.shouldComponentUpdate(r,a,i):!t.prototype||!t.prototype.isPureReactComponent||(!sr(n,r)||!sr(o,a))}function ic(e,t,n){var r=!1,o=jo,a=t.contextType;return"object"==typeof a&&null!==a?a=Ta(a):(o=Io(t)?To:Oo.current,a=(r=null!=(r=t.contextTypes))?Po(e,o):jo),t=new t(n,a),e.memoizedState=null!==t.state&&void 0!==t.state?t.state:null,t.updater=oc,e.stateNode=t,t._reactInternals=e,r&&((e=e.stateNode).__reactInternalMemoizedUnmaskedChildContext=o,e.__reactInternalMemoizedMaskedChildContext=a),t}function cc(e,t,n,r){e=t.state,"function"==typeof t.componentWillReceiveProps&&t.componentWillReceiveProps(n,r),"function"==typeof t.UNSAFE_componentWillReceiveProps&&t.UNSAFE_componentWillReceiveProps(n,r),t.state!==e&&oc.enqueueReplaceState(t,t.state,null)}function sc(e,t,n,r){var o=e.stateNode;o.props=n,o.state=e.memoizedState,o.refs={},Ma(e);var a=t.contextType;"object"==typeof a&&null!==a?o.context=Ta(a):(a=Io(t)?To:Oo.current,o.context=Po(e,a)),o.state=e.memoizedState,"function"==typeof(a=t.getDerivedStateFromProps)&&(rc(e,t,a,n),o.state=e.memoizedState),"function"==typeof t.getDerivedStateFromProps||"function"==typeof o.getSnapshotBeforeUpdate||"function"!=typeof o.UNSAFE_componentWillMount&&"function"!=typeof o.componentWillMount||(t=o.state,"function"==typeof o.componentWillMount&&o.componentWillMount(),"function"==typeof o.UNSAFE_componentWillMount&&o.UNSAFE_componentWillMount(),t!==o.state&&oc.enqueueReplaceState(o,o.state,null),Ha(e,n,o,r),o.state=e.memoizedState),"function"==typeof o.componentDidMount&&(e.flags|=4194308)}function lc(e,t){try{var n="",r=t;do{n+=$(r),r=r.return}while(r);var o=n}catch(a){o="\nError generating stack: "+a.message+"\n"+a.stack}return{value:e,source:t,stack:o,digest:null}}function uc(e,t,n){return{value:e,source:null,stack:null!=n?n:null,digest:null!=t?t:null}}function dc(e,t){try{console.error(t.value)}catch(n){setTimeout((function(){throw n}))}}var pc="function"==typeof WeakMap?WeakMap:Map;function fc(e,t,n){(n=Ba(-1,n)).tag=3,n.payload={element:null};var r=t.value;return n.callback=function(){qs||(qs=!0,Vs=r),dc(0,t)},n}function mc(e,t,n){(n=Ba(-1,n)).tag=3;var r=e.type.getDerivedStateFromError;if("function"==typeof r){var o=t.value;n.payload=function(){return r(o)},n.callback=function(){dc(0,t)}}var a=e.stateNode;return null!==a&&"function"==typeof a.componentDidCatch&&(n.callback=function(){dc(0,t),"function"!=typeof r&&(null===Ws?Ws=new Set([this]):Ws.add(this));var e=t.stack;this.componentDidCatch(t.value,{componentStack:null!==e?e:""})}),n}function gc(e,t,n){var r=e.pingCache;if(null===r){r=e.pingCache=new pc;var o=new Set;r.set(t,o)}else void 0===(o=r.get(t))&&(o=new Set,r.set(t,o));o.has(n)||(o.add(n),e=Cl.bind(null,e,t,n),t.then(e,e))}function hc(e){do{var t;if((t=13===e.tag)&&(t=null===(t=e.memoizedState)||null!==t.dehydrated),t)return e;e=e.return}while(null!==e);return null}function bc(e,t,n,r,o){return 1&e.mode?(e.flags|=65536,e.lanes=o,e):(e===t?e.flags|=65536:(e.flags|=128,n.flags|=131072,n.flags&=-52805,1===n.tag&&(null===n.alternate?n.tag=17:((t=Ba(-1,1)).tag=2,za(n,t,1))),n.lanes|=1),e)}var yc=w.ReactCurrentOwner,vc=!1;function wc(e,t,n,r){t.child=null===e?ka(t,null,n,r):Sa(t,e.child,n,r)}function Sc(e,t,n,r,o){n=n.render;var a=t.ref;return Aa(t,o),r=hi(e,t,n,r,a,o),n=bi(),null===e||vc?(aa&&n&&ta(t),t.flags|=1,wc(e,t,r,o),t.child):(t.updateQueue=e.updateQueue,t.flags&=-2053,e.lanes&=~o,qc(e,t,o))}function kc(e,t,n,r,o){if(null===e){var a=n.type;return"function"!=typeof a||Pl(a)||void 0!==a.defaultProps||null!==n.compare||void 0!==n.defaultProps?((e=Nl(n.type,null,r,t,t.mode,o)).ref=t.ref,e.return=t,t.child=e):(t.tag=15,t.type=a,xc(e,t,a,r,o))}if(a=e.child,!(e.lanes&o)){var i=a.memoizedProps;if((n=null!==(n=n.compare)?n:sr)(i,r)&&e.ref===t.ref)return qc(e,t,o)}return t.flags|=1,(e=Il(a,r)).ref=t.ref,e.return=t,t.child=e}function xc(e,t,n,r,o){if(null!==e){var a=e.memoizedProps;if(sr(a,r)&&e.ref===t.ref){if(vc=!1,t.pendingProps=r=a,!(e.lanes&o))return t.lanes=e.lanes,qc(e,t,o);131072&e.flags&&(vc=!0)}}return Ec(e,t,n,r,o)}function _c(e,t,n){var r=t.pendingProps,o=r.children,a=null!==e?e.memoizedState:null;if("hidden"===r.mode)if(1&t.mode){if(!(1073741824&n))return e=null!==a?a.baseLanes|n:n,t.lanes=t.childLanes=1073741824,t.memoizedState={baseLanes:e,cachePool:null,transitions:null},t.updateQueue=null,Do(Is,Ps),Ps|=e,null;t.memoizedState={baseLanes:0,cachePool:null,transitions:null},r=null!==a?a.baseLanes:n,Do(Is,Ps),Ps|=r}else t.memoizedState={baseLanes:0,cachePool:null,transitions:null},Do(Is,Ps),Ps|=n;else null!==a?(r=a.baseLanes|n,t.memoizedState=null):r=n,Do(Is,Ps),Ps|=r;return wc(e,t,o,n),t.child}function Cc(e,t){var n=t.ref;(null===e&&null!==n||null!==e&&e.ref!==n)&&(t.flags|=512,t.flags|=2097152)}function Ec(e,t,n,r,o){var a=Io(n)?To:Oo.current;return a=Po(t,a),Aa(t,o),n=hi(e,t,n,r,a,o),r=bi(),null===e||vc?(aa&&r&&ta(t),t.flags|=1,wc(e,t,n,o),t.child):(t.updateQueue=e.updateQueue,t.flags&=-2053,e.lanes&=~o,qc(e,t,o))}function Dc(e,t,n,r,o){if(Io(n)){var a=!0;Mo(t)}else a=!1;if(Aa(t,o),null===t.stateNode)Hc(e,t),ic(t,n,r),sc(t,n,r,o),r=!0;else if(null===e){var i=t.stateNode,c=t.memoizedProps;i.props=c;var s=i.context,l=n.contextType;"object"==typeof l&&null!==l?l=Ta(l):l=Po(t,l=Io(n)?To:Oo.current);var u=n.getDerivedStateFromProps,d="function"==typeof u||"function"==typeof i.getSnapshotBeforeUpdate;d||"function"!=typeof i.UNSAFE_componentWillReceiveProps&&"function"!=typeof i.componentWillReceiveProps||(c!==r||s!==l)&&cc(t,i,r,l),La=!1;var p=t.memoizedState;i.state=p,Ha(t,r,i,o),s=t.memoizedState,c!==r||p!==s||Ao.current||La?("function"==typeof u&&(rc(t,n,u,r),s=t.memoizedState),(c=La||ac(t,n,c,r,p,s,l))?(d||"function"!=typeof i.UNSAFE_componentWillMount&&"function"!=typeof i.componentWillMount||("function"==typeof i.componentWillMount&&i.componentWillMount(),"function"==typeof i.UNSAFE_componentWillMount&&i.UNSAFE_componentWillMount()),"function"==typeof i.componentDidMount&&(t.flags|=4194308)):("function"==typeof i.componentDidMount&&(t.flags|=4194308),t.memoizedProps=r,t.memoizedState=s),i.props=r,i.state=s,i.context=l,r=c):("function"==typeof i.componentDidMount&&(t.flags|=4194308),r=!1)}else{i=t.stateNode,Fa(e,t),c=t.memoizedProps,l=t.type===t.elementType?c:nc(t.type,c),i.props=l,d=t.pendingProps,p=i.context,"object"==typeof(s=n.contextType)&&null!==s?s=Ta(s):s=Po(t,s=Io(n)?To:Oo.current);var f=n.getDerivedStateFromProps;(u="function"==typeof f||"function"==typeof i.getSnapshotBeforeUpdate)||"function"!=typeof i.UNSAFE_componentWillReceiveProps&&"function"!=typeof i.componentWillReceiveProps||(c!==d||p!==s)&&cc(t,i,r,s),La=!1,p=t.memoizedState,i.state=p,Ha(t,r,i,o);var m=t.memoizedState;c!==d||p!==m||Ao.current||La?("function"==typeof f&&(rc(t,n,f,r),m=t.memoizedState),(l=La||ac(t,n,l,r,p,m,s)||!1)?(u||"function"!=typeof i.UNSAFE_componentWillUpdate&&"function"!=typeof i.componentWillUpdate||("function"==typeof i.componentWillUpdate&&i.componentWillUpdate(r,m,s),"function"==typeof i.UNSAFE_componentWillUpdate&&i.UNSAFE_componentWillUpdate(r,m,s)),"function"==typeof i.componentDidUpdate&&(t.flags|=4),"function"==typeof i.getSnapshotBeforeUpdate&&(t.flags|=1024)):("function"!=typeof i.componentDidUpdate||c===e.memoizedProps&&p===e.memoizedState||(t.flags|=4),"function"!=typeof i.getSnapshotBeforeUpdate||c===e.memoizedProps&&p===e.memoizedState||(t.flags|=1024),t.memoizedProps=r,t.memoizedState=m),i.props=r,i.state=m,i.context=s,r=l):("function"!=typeof i.componentDidUpdate||c===e.memoizedProps&&p===e.memoizedState||(t.flags|=4),"function"!=typeof i.getSnapshotBeforeUpdate||c===e.memoizedProps&&p===e.memoizedState||(t.flags|=1024),r=!1)}return jc(e,t,n,r,a,o)}function jc(e,t,n,r,o,a){Cc(e,t);var i=!!(128&t.flags);if(!r&&!i)return o&&Fo(t,n,!1),qc(e,t,a);r=t.stateNode,yc.current=t;var c=i&&"function"!=typeof n.getDerivedStateFromError?null:r.render();return t.flags|=1,null!==e&&i?(t.child=Sa(t,e.child,null,a),t.child=Sa(t,null,c,a)):wc(e,t,c,a),t.memoizedState=r.state,o&&Fo(t,n,!0),t.child}function Oc(e){var t=e.stateNode;t.pendingContext?Ro(0,t.pendingContext,t.pendingContext!==t.context):t.context&&Ro(0,t.context,!1),Qa(e,t.containerInfo)}function Ac(e,t,n,r,o){return ma(),ga(o),t.flags|=256,wc(e,t,n,r),t.child}var Tc,Pc,Ic,Nc,Rc={dehydrated:null,treeContext:null,retryLane:0};function Lc(e){return{baseLanes:e,cachePool:null,transitions:null}}function Mc(e,t,n){var r,o=t.pendingProps,i=ei.current,c=!1,s=!!(128&t.flags);if((r=s)||(r=(null===e||null!==e.memoizedState)&&!!(2&i)),r?(c=!0,t.flags&=-129):null!==e&&null===e.memoizedState||(i|=1),Do(ei,1&i),null===e)return ua(t),null!==(e=t.memoizedState)&&null!==(e=e.dehydrated)?(1&t.mode?"$!"===e.data?t.lanes=8:t.lanes=1073741824:t.lanes=1,null):(s=o.children,e=o.fallback,c?(o=t.mode,c=t.child,s={mode:"hidden",children:s},1&o||null===c?c=Ll(s,o,0,null):(c.childLanes=0,c.pendingProps=s),e=Rl(e,o,n,null),c.return=t,e.return=t,c.sibling=e,t.child=c,t.child.memoizedState=Lc(n),t.memoizedState=Rc,e):Fc(t,s));if(null!==(i=e.memoizedState)&&null!==(r=i.dehydrated))return function(e,t,n,r,o,i,c){if(n)return 256&t.flags?(t.flags&=-257,Bc(e,t,c,r=uc(Error(a(422))))):null!==t.memoizedState?(t.child=e.child,t.flags|=128,null):(i=r.fallback,o=t.mode,r=Ll({mode:"visible",children:r.children},o,0,null),(i=Rl(i,o,c,null)).flags|=2,r.return=t,i.return=t,r.sibling=i,t.child=r,1&t.mode&&Sa(t,e.child,null,c),t.child.memoizedState=Lc(c),t.memoizedState=Rc,i);if(!(1&t.mode))return Bc(e,t,c,null);if("$!"===o.data){if(r=o.nextSibling&&o.nextSibling.dataset)var s=r.dgst;return r=s,Bc(e,t,c,r=uc(i=Error(a(419)),r,void 0))}if(s=!!(c&e.childLanes),vc||s){if(null!==(r=Os)){switch(c&-c){case 4:o=2;break;case 16:o=8;break;case 64:case 128:case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:case 262144:case 524288:case 1048576:case 2097152:case 4194304:case 8388608:case 16777216:case 33554432:case 67108864:o=32;break;case 536870912:o=268435456;break;default:o=0}0!==(o=o&(r.suspendedLanes|c)?0:o)&&o!==i.retryLane&&(i.retryLane=o,Ra(e,o),nl(r,e,o,-1))}return gl(),Bc(e,t,c,r=uc(Error(a(421))))}return"$?"===o.data?(t.flags|=128,t.child=e.child,t=Dl.bind(null,e),o._reactRetry=t,null):(e=i.treeContext,oa=lo(o.nextSibling),ra=t,aa=!0,ia=null,null!==e&&(Ko[Yo++]=Zo,Ko[Yo++]=Xo,Ko[Yo++]=Qo,Zo=e.id,Xo=e.overflow,Qo=t),t=Fc(t,r.children),t.flags|=4096,t)}(e,t,s,o,r,i,n);if(c){c=o.fallback,s=t.mode,r=(i=e.child).sibling;var l={mode:"hidden",children:o.children};return 1&s||t.child===i?(o=Il(i,l)).subtreeFlags=14680064&i.subtreeFlags:((o=t.child).childLanes=0,o.pendingProps=l,t.deletions=null),null!==r?c=Il(r,c):(c=Rl(c,s,n,null)).flags|=2,c.return=t,o.return=t,o.sibling=c,t.child=o,o=c,c=t.child,s=null===(s=e.child.memoizedState)?Lc(n):{baseLanes:s.baseLanes|n,cachePool:null,transitions:s.transitions},c.memoizedState=s,c.childLanes=e.childLanes&~n,t.memoizedState=Rc,o}return e=(c=e.child).sibling,o=Il(c,{mode:"visible",children:o.children}),!(1&t.mode)&&(o.lanes=n),o.return=t,o.sibling=null,null!==e&&(null===(n=t.deletions)?(t.deletions=[e],t.flags|=16):n.push(e)),t.child=o,t.memoizedState=null,o}function Fc(e,t){return(t=Ll({mode:"visible",children:t},e.mode,0,null)).return=e,e.child=t}function Bc(e,t,n,r){return null!==r&&ga(r),Sa(t,e.child,null,n),(e=Fc(t,t.pendingProps.children)).flags|=2,t.memoizedState=null,e}function zc(e,t,n){e.lanes|=t;var r=e.alternate;null!==r&&(r.lanes|=t),Oa(e.return,t,n)}function $c(e,t,n,r,o){var a=e.memoizedState;null===a?e.memoizedState={isBackwards:t,rendering:null,renderingStartTime:0,last:r,tail:n,tailMode:o}:(a.isBackwards=t,a.rendering=null,a.renderingStartTime=0,a.last=r,a.tail=n,a.tailMode=o)}function Uc(e,t,n){var r=t.pendingProps,o=r.revealOrder,a=r.tail;if(wc(e,t,r.children,n),2&(r=ei.current))r=1&r|2,t.flags|=128;else{if(null!==e&&128&e.flags)e:for(e=t.child;null!==e;){if(13===e.tag)null!==e.memoizedState&&zc(e,n,t);else if(19===e.tag)zc(e,n,t);else if(null!==e.child){e.child.return=e,e=e.child;continue}if(e===t)break e;for(;null===e.sibling;){if(null===e.return||e.return===t)break e;e=e.return}e.sibling.return=e.return,e=e.sibling}r&=1}if(Do(ei,r),1&t.mode)switch(o){case"forwards":for(n=t.child,o=null;null!==n;)null!==(e=n.alternate)&&null===ti(e)&&(o=n),n=n.sibling;null===(n=o)?(o=t.child,t.child=null):(o=n.sibling,n.sibling=null),$c(t,!1,o,n,a);break;case"backwards":for(n=null,o=t.child,t.child=null;null!==o;){if(null!==(e=o.alternate)&&null===ti(e)){t.child=o;break}e=o.sibling,o.sibling=n,n=o,o=e}$c(t,!0,n,null,a);break;case"together":$c(t,!1,null,null,void 0);break;default:t.memoizedState=null}else t.memoizedState=null;return t.child}function Hc(e,t){!(1&t.mode)&&null!==e&&(e.alternate=null,t.alternate=null,t.flags|=2)}function qc(e,t,n){if(null!==e&&(t.dependencies=e.dependencies),Ls|=t.lanes,!(n&t.childLanes))return null;if(null!==e&&t.child!==e.child)throw Error(a(153));if(null!==t.child){for(n=Il(e=t.child,e.pendingProps),t.child=n,n.return=t;null!==e.sibling;)e=e.sibling,(n=n.sibling=Il(e,e.pendingProps)).return=t;n.sibling=null}return t.child}function Vc(e,t){if(!aa)switch(e.tailMode){case"hidden":t=e.tail;for(var n=null;null!==t;)null!==t.alternate&&(n=t),t=t.sibling;null===n?e.tail=null:n.sibling=null;break;case"collapsed":n=e.tail;for(var r=null;null!==n;)null!==n.alternate&&(r=n),n=n.sibling;null===r?t||null===e.tail?e.tail=null:e.tail.sibling=null:r.sibling=null}}function Wc(e){var t=null!==e.alternate&&e.alternate.child===e.child,n=0,r=0;if(t)for(var o=e.child;null!==o;)n|=o.lanes|o.childLanes,r|=14680064&o.subtreeFlags,r|=14680064&o.flags,o.return=e,o=o.sibling;else for(o=e.child;null!==o;)n|=o.lanes|o.childLanes,r|=o.subtreeFlags,r|=o.flags,o.return=e,o=o.sibling;return e.subtreeFlags|=r,e.childLanes=n,t}function Gc(e,t,n){var r=t.pendingProps;switch(na(t),t.tag){case 2:case 16:case 15:case 0:case 11:case 7:case 8:case 12:case 9:case 14:return Wc(t),null;case 1:case 17:return Io(t.type)&&No(),Wc(t),null;case 3:return r=t.stateNode,Za(),Eo(Ao),Eo(Oo),ri(),r.pendingContext&&(r.context=r.pendingContext,r.pendingContext=null),null!==e&&null!==e.child||(pa(t)?t.flags|=4:null===e||e.memoizedState.isDehydrated&&!(256&t.flags)||(t.flags|=1024,null!==ia&&(il(ia),ia=null))),Pc(e,t),Wc(t),null;case 5:Ja(t);var o=Ya(Ka.current);if(n=t.type,null!==e&&null!=t.stateNode)Ic(e,t,n,r,o),e.ref!==t.ref&&(t.flags|=512,t.flags|=2097152);else{if(!r){if(null===t.stateNode)throw Error(a(166));return Wc(t),null}if(e=Ya(Wa.current),pa(t)){r=t.stateNode,n=t.type;var i=t.memoizedProps;switch(r[fo]=t,r[mo]=i,e=!!(1&t.mode),n){case"dialog":Br("cancel",r),Br("close",r);break;case"iframe":case"object":case"embed":Br("load",r);break;case"video":case"audio":for(o=0;o<Rr.length;o++)Br(Rr[o],r);break;case"source":Br("error",r);break;case"img":case"image":case"link":Br("error",r),Br("load",r);break;case"details":Br("toggle",r);break;case"input":Q(r,i),Br("invalid",r);break;case"select":r._wrapperState={wasMultiple:!!i.multiple},Br("invalid",r);break;case"textarea":oe(r,i),Br("invalid",r)}for(var s in ye(n,i),o=null,i)if(i.hasOwnProperty(s)){var l=i[s];"children"===s?"string"==typeof l?r.textContent!==l&&(!0!==i.suppressHydrationWarning&&Xr(r.textContent,l,e),o=["children",l]):"number"==typeof l&&r.textContent!==""+l&&(!0!==i.suppressHydrationWarning&&Xr(r.textContent,l,e),o=["children",""+l]):c.hasOwnProperty(s)&&null!=l&&"onScroll"===s&&Br("scroll",r)}switch(n){case"input":W(r),J(r,i,!0);break;case"textarea":W(r),ie(r);break;case"select":case"option":break;default:"function"==typeof i.onClick&&(r.onclick=Jr)}r=o,t.updateQueue=r,null!==r&&(t.flags|=4)}else{s=9===o.nodeType?o:o.ownerDocument,"http://www.w3.org/1999/xhtml"===e&&(e=ce(n)),"http://www.w3.org/1999/xhtml"===e?"script"===n?((e=s.createElement("div")).innerHTML="<script><\/script>",e=e.removeChild(e.firstChild)):"string"==typeof r.is?e=s.createElement(n,{is:r.is}):(e=s.createElement(n),"select"===n&&(s=e,r.multiple?s.multiple=!0:r.size&&(s.size=r.size))):e=s.createElementNS(e,n),e[fo]=t,e[mo]=r,Tc(e,t,!1,!1),t.stateNode=e;e:{switch(s=ve(n,r),n){case"dialog":Br("cancel",e),Br("close",e),o=r;break;case"iframe":case"object":case"embed":Br("load",e),o=r;break;case"video":case"audio":for(o=0;o<Rr.length;o++)Br(Rr[o],e);o=r;break;case"source":Br("error",e),o=r;break;case"img":case"image":case"link":Br("error",e),Br("load",e),o=r;break;case"details":Br("toggle",e),o=r;break;case"input":Q(e,r),o=Y(e,r),Br("invalid",e);break;case"option":default:o=r;break;case"select":e._wrapperState={wasMultiple:!!r.multiple},o=M({},r,{value:void 0}),Br("invalid",e);break;case"textarea":oe(e,r),o=re(e,r),Br("invalid",e)}for(i in ye(n,o),l=o)if(l.hasOwnProperty(i)){var u=l[i];"style"===i?he(e,u):"dangerouslySetInnerHTML"===i?null!=(u=u?u.__html:void 0)&&de(e,u):"children"===i?"string"==typeof u?("textarea"!==n||""!==u)&&pe(e,u):"number"==typeof u&&pe(e,""+u):"suppressContentEditableWarning"!==i&&"suppressHydrationWarning"!==i&&"autoFocus"!==i&&(c.hasOwnProperty(i)?null!=u&&"onScroll"===i&&Br("scroll",e):null!=u&&v(e,i,u,s))}switch(n){case"input":W(e),J(e,r,!1);break;case"textarea":W(e),ie(e);break;case"option":null!=r.value&&e.setAttribute("value",""+q(r.value));break;case"select":e.multiple=!!r.multiple,null!=(i=r.value)?ne(e,!!r.multiple,i,!1):null!=r.defaultValue&&ne(e,!!r.multiple,r.defaultValue,!0);break;default:"function"==typeof o.onClick&&(e.onclick=Jr)}switch(n){case"button":case"input":case"select":case"textarea":r=!!r.autoFocus;break e;case"img":r=!0;break e;default:r=!1}}r&&(t.flags|=4)}null!==t.ref&&(t.flags|=512,t.flags|=2097152)}return Wc(t),null;case 6:if(e&&null!=t.stateNode)Nc(e,t,e.memoizedProps,r);else{if("string"!=typeof r&&null===t.stateNode)throw Error(a(166));if(n=Ya(Ka.current),Ya(Wa.current),pa(t)){if(r=t.stateNode,n=t.memoizedProps,r[fo]=t,(i=r.nodeValue!==n)&&null!==(e=ra))switch(e.tag){case 3:Xr(r.nodeValue,n,!!(1&e.mode));break;case 5:!0!==e.memoizedProps.suppressHydrationWarning&&Xr(r.nodeValue,n,!!(1&e.mode))}i&&(t.flags|=4)}else(r=(9===n.nodeType?n:n.ownerDocument).createTextNode(r))[fo]=t,t.stateNode=r}return Wc(t),null;case 13:if(Eo(ei),r=t.memoizedState,null===e||null!==e.memoizedState&&null!==e.memoizedState.dehydrated){if(aa&&null!==oa&&1&t.mode&&!(128&t.flags))fa(),ma(),t.flags|=98560,i=!1;else if(i=pa(t),null!==r&&null!==r.dehydrated){if(null===e){if(!i)throw Error(a(318));if(!(i=null!==(i=t.memoizedState)?i.dehydrated:null))throw Error(a(317));i[fo]=t}else ma(),!(128&t.flags)&&(t.memoizedState=null),t.flags|=4;Wc(t),i=!1}else null!==ia&&(il(ia),ia=null),i=!0;if(!i)return 65536&t.flags?t:null}return 128&t.flags?(t.lanes=n,t):((r=null!==r)!==(null!==e&&null!==e.memoizedState)&&r&&(t.child.flags|=8192,1&t.mode&&(null===e||1&ei.current?0===Ns&&(Ns=3):gl())),null!==t.updateQueue&&(t.flags|=4),Wc(t),null);case 4:return Za(),Pc(e,t),null===e&&Ur(t.stateNode.containerInfo),Wc(t),null;case 10:return ja(t.type._context),Wc(t),null;case 19:if(Eo(ei),null===(i=t.memoizedState))return Wc(t),null;if(r=!!(128&t.flags),null===(s=i.rendering))if(r)Vc(i,!1);else{if(0!==Ns||null!==e&&128&e.flags)for(e=t.child;null!==e;){if(null!==(s=ti(e))){for(t.flags|=128,Vc(i,!1),null!==(r=s.updateQueue)&&(t.updateQueue=r,t.flags|=4),t.subtreeFlags=0,r=n,n=t.child;null!==n;)e=r,(i=n).flags&=14680066,null===(s=i.alternate)?(i.childLanes=0,i.lanes=e,i.child=null,i.subtreeFlags=0,i.memoizedProps=null,i.memoizedState=null,i.updateQueue=null,i.dependencies=null,i.stateNode=null):(i.childLanes=s.childLanes,i.lanes=s.lanes,i.child=s.child,i.subtreeFlags=0,i.deletions=null,i.memoizedProps=s.memoizedProps,i.memoizedState=s.memoizedState,i.updateQueue=s.updateQueue,i.type=s.type,e=s.dependencies,i.dependencies=null===e?null:{lanes:e.lanes,firstContext:e.firstContext}),n=n.sibling;return Do(ei,1&ei.current|2),t.child}e=e.sibling}null!==i.tail&&Ze()>Us&&(t.flags|=128,r=!0,Vc(i,!1),t.lanes=4194304)}else{if(!r)if(null!==(e=ti(s))){if(t.flags|=128,r=!0,null!==(n=e.updateQueue)&&(t.updateQueue=n,t.flags|=4),Vc(i,!0),null===i.tail&&"hidden"===i.tailMode&&!s.alternate&&!aa)return Wc(t),null}else 2*Ze()-i.renderingStartTime>Us&&1073741824!==n&&(t.flags|=128,r=!0,Vc(i,!1),t.lanes=4194304);i.isBackwards?(s.sibling=t.child,t.child=s):(null!==(n=i.last)?n.sibling=s:t.child=s,i.last=s)}return null!==i.tail?(t=i.tail,i.rendering=t,i.tail=t.sibling,i.renderingStartTime=Ze(),t.sibling=null,n=ei.current,Do(ei,r?1&n|2:1&n),t):(Wc(t),null);case 22:case 23:return dl(),r=null!==t.memoizedState,null!==e&&null!==e.memoizedState!==r&&(t.flags|=8192),r&&1&t.mode?!!(1073741824&Ps)&&(Wc(t),6&t.subtreeFlags&&(t.flags|=8192)):Wc(t),null;case 24:case 25:return null}throw Error(a(156,t.tag))}function Kc(e,t){switch(na(t),t.tag){case 1:return Io(t.type)&&No(),65536&(e=t.flags)?(t.flags=-65537&e|128,t):null;case 3:return Za(),Eo(Ao),Eo(Oo),ri(),65536&(e=t.flags)&&!(128&e)?(t.flags=-65537&e|128,t):null;case 5:return Ja(t),null;case 13:if(Eo(ei),null!==(e=t.memoizedState)&&null!==e.dehydrated){if(null===t.alternate)throw Error(a(340));ma()}return 65536&(e=t.flags)?(t.flags=-65537&e|128,t):null;case 19:return Eo(ei),null;case 4:return Za(),null;case 10:return ja(t.type._context),null;case 22:case 23:return dl(),null;default:return null}}Tc=function(e,t){for(var n=t.child;null!==n;){if(5===n.tag||6===n.tag)e.appendChild(n.stateNode);else if(4!==n.tag&&null!==n.child){n.child.return=n,n=n.child;continue}if(n===t)break;for(;null===n.sibling;){if(null===n.return||n.return===t)return;n=n.return}n.sibling.return=n.return,n=n.sibling}},Pc=function(){},Ic=function(e,t,n,r){var o=e.memoizedProps;if(o!==r){e=t.stateNode,Ya(Wa.current);var a,i=null;switch(n){case"input":o=Y(e,o),r=Y(e,r),i=[];break;case"select":o=M({},o,{value:void 0}),r=M({},r,{value:void 0}),i=[];break;case"textarea":o=re(e,o),r=re(e,r),i=[];break;default:"function"!=typeof o.onClick&&"function"==typeof r.onClick&&(e.onclick=Jr)}for(u in ye(n,r),n=null,o)if(!r.hasOwnProperty(u)&&o.hasOwnProperty(u)&&null!=o[u])if("style"===u){var s=o[u];for(a in s)s.hasOwnProperty(a)&&(n||(n={}),n[a]="")}else"dangerouslySetInnerHTML"!==u&&"children"!==u&&"suppressContentEditableWarning"!==u&&"suppressHydrationWarning"!==u&&"autoFocus"!==u&&(c.hasOwnProperty(u)?i||(i=[]):(i=i||[]).push(u,null));for(u in r){var l=r[u];if(s=null!=o?o[u]:void 0,r.hasOwnProperty(u)&&l!==s&&(null!=l||null!=s))if("style"===u)if(s){for(a in s)!s.hasOwnProperty(a)||l&&l.hasOwnProperty(a)||(n||(n={}),n[a]="");for(a in l)l.hasOwnProperty(a)&&s[a]!==l[a]&&(n||(n={}),n[a]=l[a])}else n||(i||(i=[]),i.push(u,n)),n=l;else"dangerouslySetInnerHTML"===u?(l=l?l.__html:void 0,s=s?s.__html:void 0,null!=l&&s!==l&&(i=i||[]).push(u,l)):"children"===u?"string"!=typeof l&&"number"!=typeof l||(i=i||[]).push(u,""+l):"suppressContentEditableWarning"!==u&&"suppressHydrationWarning"!==u&&(c.hasOwnProperty(u)?(null!=l&&"onScroll"===u&&Br("scroll",e),i||s===l||(i=[])):(i=i||[]).push(u,l))}n&&(i=i||[]).push("style",n);var u=i;(t.updateQueue=u)&&(t.flags|=4)}},Nc=function(e,t,n,r){n!==r&&(t.flags|=4)};var Yc=!1,Qc=!1,Zc="function"==typeof WeakSet?WeakSet:Set,Xc=null;function Jc(e,t){var n=e.ref;if(null!==n)if("function"==typeof n)try{n(null)}catch(r){_l(e,t,r)}else n.current=null}function es(e,t,n){try{n()}catch(r){_l(e,t,r)}}var ts=!1;function ns(e,t,n){var r=t.updateQueue;if(null!==(r=null!==r?r.lastEffect:null)){var o=r=r.next;do{if((o.tag&e)===e){var a=o.destroy;o.destroy=void 0,void 0!==a&&es(t,n,a)}o=o.next}while(o!==r)}}function rs(e,t){if(null!==(t=null!==(t=t.updateQueue)?t.lastEffect:null)){var n=t=t.next;do{if((n.tag&e)===e){var r=n.create;n.destroy=r()}n=n.next}while(n!==t)}}function os(e){var t=e.ref;if(null!==t){var n=e.stateNode;e.tag,e=n,"function"==typeof t?t(e):t.current=e}}function as(e){var t=e.alternate;null!==t&&(e.alternate=null,as(t)),e.child=null,e.deletions=null,e.sibling=null,5===e.tag&&(null!==(t=e.stateNode)&&(delete t[fo],delete t[mo],delete t[ho],delete t[bo],delete t[yo])),e.stateNode=null,e.return=null,e.dependencies=null,e.memoizedProps=null,e.memoizedState=null,e.pendingProps=null,e.stateNode=null,e.updateQueue=null}function is(e){return 5===e.tag||3===e.tag||4===e.tag}function cs(e){e:for(;;){for(;null===e.sibling;){if(null===e.return||is(e.return))return null;e=e.return}for(e.sibling.return=e.return,e=e.sibling;5!==e.tag&&6!==e.tag&&18!==e.tag;){if(2&e.flags)continue e;if(null===e.child||4===e.tag)continue e;e.child.return=e,e=e.child}if(!(2&e.flags))return e.stateNode}}function ss(e,t,n){var r=e.tag;if(5===r||6===r)e=e.stateNode,t?8===n.nodeType?n.parentNode.insertBefore(e,t):n.insertBefore(e,t):(8===n.nodeType?(t=n.parentNode).insertBefore(e,n):(t=n).appendChild(e),null!=(n=n._reactRootContainer)||null!==t.onclick||(t.onclick=Jr));else if(4!==r&&null!==(e=e.child))for(ss(e,t,n),e=e.sibling;null!==e;)ss(e,t,n),e=e.sibling}function ls(e,t,n){var r=e.tag;if(5===r||6===r)e=e.stateNode,t?n.insertBefore(e,t):n.appendChild(e);else if(4!==r&&null!==(e=e.child))for(ls(e,t,n),e=e.sibling;null!==e;)ls(e,t,n),e=e.sibling}var us=null,ds=!1;function ps(e,t,n){for(n=n.child;null!==n;)fs(e,t,n),n=n.sibling}function fs(e,t,n){if(at&&"function"==typeof at.onCommitFiberUnmount)try{at.onCommitFiberUnmount(ot,n)}catch(c){}switch(n.tag){case 5:Qc||Jc(n,t);case 6:var r=us,o=ds;us=null,ps(e,t,n),ds=o,null!==(us=r)&&(ds?(e=us,n=n.stateNode,8===e.nodeType?e.parentNode.removeChild(n):e.removeChild(n)):us.removeChild(n.stateNode));break;case 18:null!==us&&(ds?(e=us,n=n.stateNode,8===e.nodeType?so(e.parentNode,n):1===e.nodeType&&so(e,n),Ut(e)):so(us,n.stateNode));break;case 4:r=us,o=ds,us=n.stateNode.containerInfo,ds=!0,ps(e,t,n),us=r,ds=o;break;case 0:case 11:case 14:case 15:if(!Qc&&(null!==(r=n.updateQueue)&&null!==(r=r.lastEffect))){o=r=r.next;do{var a=o,i=a.destroy;a=a.tag,void 0!==i&&(2&a||4&a)&&es(n,t,i),o=o.next}while(o!==r)}ps(e,t,n);break;case 1:if(!Qc&&(Jc(n,t),"function"==typeof(r=n.stateNode).componentWillUnmount))try{r.props=n.memoizedProps,r.state=n.memoizedState,r.componentWillUnmount()}catch(c){_l(n,t,c)}ps(e,t,n);break;case 21:ps(e,t,n);break;case 22:1&n.mode?(Qc=(r=Qc)||null!==n.memoizedState,ps(e,t,n),Qc=r):ps(e,t,n);break;default:ps(e,t,n)}}function ms(e){var t=e.updateQueue;if(null!==t){e.updateQueue=null;var n=e.stateNode;null===n&&(n=e.stateNode=new Zc),t.forEach((function(t){var r=jl.bind(null,e,t);n.has(t)||(n.add(t),t.then(r,r))}))}}function gs(e,t){var n=t.deletions;if(null!==n)for(var r=0;r<n.length;r++){var o=n[r];try{var i=e,c=t,s=c;e:for(;null!==s;){switch(s.tag){case 5:us=s.stateNode,ds=!1;break e;case 3:case 4:us=s.stateNode.containerInfo,ds=!0;break e}s=s.return}if(null===us)throw Error(a(160));fs(i,c,o),us=null,ds=!1;var l=o.alternate;null!==l&&(l.return=null),o.return=null}catch(u){_l(o,t,u)}}if(12854&t.subtreeFlags)for(t=t.child;null!==t;)hs(t,e),t=t.sibling}function hs(e,t){var n=e.alternate,r=e.flags;switch(e.tag){case 0:case 11:case 14:case 15:if(gs(t,e),bs(e),4&r){try{ns(3,e,e.return),rs(3,e)}catch(h){_l(e,e.return,h)}try{ns(5,e,e.return)}catch(h){_l(e,e.return,h)}}break;case 1:gs(t,e),bs(e),512&r&&null!==n&&Jc(n,n.return);break;case 5:if(gs(t,e),bs(e),512&r&&null!==n&&Jc(n,n.return),32&e.flags){var o=e.stateNode;try{pe(o,"")}catch(h){_l(e,e.return,h)}}if(4&r&&null!=(o=e.stateNode)){var i=e.memoizedProps,c=null!==n?n.memoizedProps:i,s=e.type,l=e.updateQueue;if(e.updateQueue=null,null!==l)try{"input"===s&&"radio"===i.type&&null!=i.name&&Z(o,i),ve(s,c);var u=ve(s,i);for(c=0;c<l.length;c+=2){var d=l[c],p=l[c+1];"style"===d?he(o,p):"dangerouslySetInnerHTML"===d?de(o,p):"children"===d?pe(o,p):v(o,d,p,u)}switch(s){case"input":X(o,i);break;case"textarea":ae(o,i);break;case"select":var f=o._wrapperState.wasMultiple;o._wrapperState.wasMultiple=!!i.multiple;var m=i.value;null!=m?ne(o,!!i.multiple,m,!1):f!==!!i.multiple&&(null!=i.defaultValue?ne(o,!!i.multiple,i.defaultValue,!0):ne(o,!!i.multiple,i.multiple?[]:"",!1))}o[mo]=i}catch(h){_l(e,e.return,h)}}break;case 6:if(gs(t,e),bs(e),4&r){if(null===e.stateNode)throw Error(a(162));o=e.stateNode,i=e.memoizedProps;try{o.nodeValue=i}catch(h){_l(e,e.return,h)}}break;case 3:if(gs(t,e),bs(e),4&r&&null!==n&&n.memoizedState.isDehydrated)try{Ut(t.containerInfo)}catch(h){_l(e,e.return,h)}break;case 4:default:gs(t,e),bs(e);break;case 13:gs(t,e),bs(e),8192&(o=e.child).flags&&(i=null!==o.memoizedState,o.stateNode.isHidden=i,!i||null!==o.alternate&&null!==o.alternate.memoizedState||($s=Ze())),4&r&&ms(e);break;case 22:if(d=null!==n&&null!==n.memoizedState,1&e.mode?(Qc=(u=Qc)||d,gs(t,e),Qc=u):gs(t,e),bs(e),8192&r){if(u=null!==e.memoizedState,(e.stateNode.isHidden=u)&&!d&&1&e.mode)for(Xc=e,d=e.child;null!==d;){for(p=Xc=d;null!==Xc;){switch(m=(f=Xc).child,f.tag){case 0:case 11:case 14:case 15:ns(4,f,f.return);break;case 1:Jc(f,f.return);var g=f.stateNode;if("function"==typeof g.componentWillUnmount){r=f,n=f.return;try{t=r,g.props=t.memoizedProps,g.state=t.memoizedState,g.componentWillUnmount()}catch(h){_l(r,n,h)}}break;case 5:Jc(f,f.return);break;case 22:if(null!==f.memoizedState){Ss(p);continue}}null!==m?(m.return=f,Xc=m):Ss(p)}d=d.sibling}e:for(d=null,p=e;;){if(5===p.tag){if(null===d){d=p;try{o=p.stateNode,u?"function"==typeof(i=o.style).setProperty?i.setProperty("display","none","important"):i.display="none":(s=p.stateNode,c=null!=(l=p.memoizedProps.style)&&l.hasOwnProperty("display")?l.display:null,s.style.display=ge("display",c))}catch(h){_l(e,e.return,h)}}}else if(6===p.tag){if(null===d)try{p.stateNode.nodeValue=u?"":p.memoizedProps}catch(h){_l(e,e.return,h)}}else if((22!==p.tag&&23!==p.tag||null===p.memoizedState||p===e)&&null!==p.child){p.child.return=p,p=p.child;continue}if(p===e)break e;for(;null===p.sibling;){if(null===p.return||p.return===e)break e;d===p&&(d=null),p=p.return}d===p&&(d=null),p.sibling.return=p.return,p=p.sibling}}break;case 19:gs(t,e),bs(e),4&r&&ms(e);case 21:}}function bs(e){var t=e.flags;if(2&t){try{e:{for(var n=e.return;null!==n;){if(is(n)){var r=n;break e}n=n.return}throw Error(a(160))}switch(r.tag){case 5:var o=r.stateNode;32&r.flags&&(pe(o,""),r.flags&=-33),ls(e,cs(e),o);break;case 3:case 4:var i=r.stateNode.containerInfo;ss(e,cs(e),i);break;default:throw Error(a(161))}}catch(c){_l(e,e.return,c)}e.flags&=-3}4096&t&&(e.flags&=-4097)}function ys(e,t,n){Xc=e,vs(e,t,n)}function vs(e,t,n){for(var r=!!(1&e.mode);null!==Xc;){var o=Xc,a=o.child;if(22===o.tag&&r){var i=null!==o.memoizedState||Yc;if(!i){var c=o.alternate,s=null!==c&&null!==c.memoizedState||Qc;c=Yc;var l=Qc;if(Yc=i,(Qc=s)&&!l)for(Xc=o;null!==Xc;)s=(i=Xc).child,22===i.tag&&null!==i.memoizedState?ks(o):null!==s?(s.return=i,Xc=s):ks(o);for(;null!==a;)Xc=a,vs(a,t,n),a=a.sibling;Xc=o,Yc=c,Qc=l}ws(e)}else 8772&o.subtreeFlags&&null!==a?(a.return=o,Xc=a):ws(e)}}function ws(e){for(;null!==Xc;){var t=Xc;if(8772&t.flags){var n=t.alternate;try{if(8772&t.flags)switch(t.tag){case 0:case 11:case 15:Qc||rs(5,t);break;case 1:var r=t.stateNode;if(4&t.flags&&!Qc)if(null===n)r.componentDidMount();else{var o=t.elementType===t.type?n.memoizedProps:nc(t.type,n.memoizedProps);r.componentDidUpdate(o,n.memoizedState,r.__reactInternalSnapshotBeforeUpdate)}var i=t.updateQueue;null!==i&&qa(t,i,r);break;case 3:var c=t.updateQueue;if(null!==c){if(n=null,null!==t.child)switch(t.child.tag){case 5:case 1:n=t.child.stateNode}qa(t,c,n)}break;case 5:var s=t.stateNode;if(null===n&&4&t.flags){n=s;var l=t.memoizedProps;switch(t.type){case"button":case"input":case"select":case"textarea":l.autoFocus&&n.focus();break;case"img":l.src&&(n.src=l.src)}}break;case 6:case 4:case 12:case 19:case 17:case 21:case 22:case 23:case 25:break;case 13:if(null===t.memoizedState){var u=t.alternate;if(null!==u){var d=u.memoizedState;if(null!==d){var p=d.dehydrated;null!==p&&Ut(p)}}}break;default:throw Error(a(163))}Qc||512&t.flags&&os(t)}catch(f){_l(t,t.return,f)}}if(t===e){Xc=null;break}if(null!==(n=t.sibling)){n.return=t.return,Xc=n;break}Xc=t.return}}function Ss(e){for(;null!==Xc;){var t=Xc;if(t===e){Xc=null;break}var n=t.sibling;if(null!==n){n.return=t.return,Xc=n;break}Xc=t.return}}function ks(e){for(;null!==Xc;){var t=Xc;try{switch(t.tag){case 0:case 11:case 15:var n=t.return;try{rs(4,t)}catch(s){_l(t,n,s)}break;case 1:var r=t.stateNode;if("function"==typeof r.componentDidMount){var o=t.return;try{r.componentDidMount()}catch(s){_l(t,o,s)}}var a=t.return;try{os(t)}catch(s){_l(t,a,s)}break;case 5:var i=t.return;try{os(t)}catch(s){_l(t,i,s)}}}catch(s){_l(t,t.return,s)}if(t===e){Xc=null;break}var c=t.sibling;if(null!==c){c.return=t.return,Xc=c;break}Xc=t.return}}var xs,_s=Math.ceil,Cs=w.ReactCurrentDispatcher,Es=w.ReactCurrentOwner,Ds=w.ReactCurrentBatchConfig,js=0,Os=null,As=null,Ts=0,Ps=0,Is=Co(0),Ns=0,Rs=null,Ls=0,Ms=0,Fs=0,Bs=null,zs=null,$s=0,Us=1/0,Hs=null,qs=!1,Vs=null,Ws=null,Gs=!1,Ks=null,Ys=0,Qs=0,Zs=null,Xs=-1,Js=0;function el(){return 6&js?Ze():-1!==Xs?Xs:Xs=Ze()}function tl(e){return 1&e.mode?2&js&&0!==Ts?Ts&-Ts:null!==ha.transition?(0===Js&&(Js=gt()),Js):0!==(e=vt)?e:e=void 0===(e=window.event)?16:Qt(e.type):1}function nl(e,t,n,r){if(50<Qs)throw Qs=0,Zs=null,Error(a(185));bt(e,n,r),2&js&&e===Os||(e===Os&&(!(2&js)&&(Ms|=n),4===Ns&&cl(e,Ts)),rl(e,r),1===n&&0===js&&!(1&t.mode)&&(Us=Ze()+500,zo&&Ho()))}function rl(e,t){var n=e.callbackNode;!function(e,t){for(var n=e.suspendedLanes,r=e.pingedLanes,o=e.expirationTimes,a=e.pendingLanes;0<a;){var i=31-it(a),c=1<<i,s=o[i];-1===s?c&n&&!(c&r)||(o[i]=ft(c,t)):s<=t&&(e.expiredLanes|=c),a&=~c}}(e,t);var r=pt(e,e===Os?Ts:0);if(0===r)null!==n&&Ke(n),e.callbackNode=null,e.callbackPriority=0;else if(t=r&-r,e.callbackPriority!==t){if(null!=n&&Ke(n),1===t)0===e.tag?function(e){zo=!0,Uo(e)}(sl.bind(null,e)):Uo(sl.bind(null,e)),io((function(){!(6&js)&&Ho()})),n=null;else{switch(wt(r)){case 1:n=Je;break;case 4:n=et;break;case 16:default:n=tt;break;case 536870912:n=rt}n=Ol(n,ol.bind(null,e))}e.callbackPriority=t,e.callbackNode=n}}function ol(e,t){if(Xs=-1,Js=0,6&js)throw Error(a(327));var n=e.callbackNode;if(kl()&&e.callbackNode!==n)return null;var r=pt(e,e===Os?Ts:0);if(0===r)return null;if(30&r||r&e.expiredLanes||t)t=hl(e,r);else{t=r;var o=js;js|=2;var i=ml();for(Os===e&&Ts===t||(Hs=null,Us=Ze()+500,pl(e,t));;)try{yl();break}catch(s){fl(e,s)}Da(),Cs.current=i,js=o,null!==As?t=0:(Os=null,Ts=0,t=Ns)}if(0!==t){if(2===t&&(0!==(o=mt(e))&&(r=o,t=al(e,o))),1===t)throw n=Rs,pl(e,0),cl(e,r),rl(e,Ze()),n;if(6===t)cl(e,r);else{if(o=e.current.alternate,!(30&r||function(e){for(var t=e;;){if(16384&t.flags){var n=t.updateQueue;if(null!==n&&null!==(n=n.stores))for(var r=0;r<n.length;r++){var o=n[r],a=o.getSnapshot;o=o.value;try{if(!cr(a(),o))return!1}catch(c){return!1}}}if(n=t.child,16384&t.subtreeFlags&&null!==n)n.return=t,t=n;else{if(t===e)break;for(;null===t.sibling;){if(null===t.return||t.return===e)return!0;t=t.return}t.sibling.return=t.return,t=t.sibling}}return!0}(o)||(t=hl(e,r),2===t&&(i=mt(e),0!==i&&(r=i,t=al(e,i))),1!==t)))throw n=Rs,pl(e,0),cl(e,r),rl(e,Ze()),n;switch(e.finishedWork=o,e.finishedLanes=r,t){case 0:case 1:throw Error(a(345));case 2:case 5:Sl(e,zs,Hs);break;case 3:if(cl(e,r),(130023424&r)===r&&10<(t=$s+500-Ze())){if(0!==pt(e,0))break;if(((o=e.suspendedLanes)&r)!==r){el(),e.pingedLanes|=e.suspendedLanes&o;break}e.timeoutHandle=ro(Sl.bind(null,e,zs,Hs),t);break}Sl(e,zs,Hs);break;case 4:if(cl(e,r),(4194240&r)===r)break;for(t=e.eventTimes,o=-1;0<r;){var c=31-it(r);i=1<<c,(c=t[c])>o&&(o=c),r&=~i}if(r=o,10<(r=(120>(r=Ze()-r)?120:480>r?480:1080>r?1080:1920>r?1920:3e3>r?3e3:4320>r?4320:1960*_s(r/1960))-r)){e.timeoutHandle=ro(Sl.bind(null,e,zs,Hs),r);break}Sl(e,zs,Hs);break;default:throw Error(a(329))}}}return rl(e,Ze()),e.callbackNode===n?ol.bind(null,e):null}function al(e,t){var n=Bs;return e.current.memoizedState.isDehydrated&&(pl(e,t).flags|=256),2!==(e=hl(e,t))&&(t=zs,zs=n,null!==t&&il(t)),e}function il(e){null===zs?zs=e:zs.push.apply(zs,e)}function cl(e,t){for(t&=~Fs,t&=~Ms,e.suspendedLanes|=t,e.pingedLanes&=~t,e=e.expirationTimes;0<t;){var n=31-it(t),r=1<<n;e[n]=-1,t&=~r}}function sl(e){if(6&js)throw Error(a(327));kl();var t=pt(e,0);if(!(1&t))return rl(e,Ze()),null;var n=hl(e,t);if(0!==e.tag&&2===n){var r=mt(e);0!==r&&(t=r,n=al(e,r))}if(1===n)throw n=Rs,pl(e,0),cl(e,t),rl(e,Ze()),n;if(6===n)throw Error(a(345));return e.finishedWork=e.current.alternate,e.finishedLanes=t,Sl(e,zs,Hs),rl(e,Ze()),null}function ll(e,t){var n=js;js|=1;try{return e(t)}finally{0===(js=n)&&(Us=Ze()+500,zo&&Ho())}}function ul(e){null!==Ks&&0===Ks.tag&&!(6&js)&&kl();var t=js;js|=1;var n=Ds.transition,r=vt;try{if(Ds.transition=null,vt=1,e)return e()}finally{vt=r,Ds.transition=n,!(6&(js=t))&&Ho()}}function dl(){Ps=Is.current,Eo(Is)}function pl(e,t){e.finishedWork=null,e.finishedLanes=0;var n=e.timeoutHandle;if(-1!==n&&(e.timeoutHandle=-1,oo(n)),null!==As)for(n=As.return;null!==n;){var r=n;switch(na(r),r.tag){case 1:null!=(r=r.type.childContextTypes)&&No();break;case 3:Za(),Eo(Ao),Eo(Oo),ri();break;case 5:Ja(r);break;case 4:Za();break;case 13:case 19:Eo(ei);break;case 10:ja(r.type._context);break;case 22:case 23:dl()}n=n.return}if(Os=e,As=e=Il(e.current,null),Ts=Ps=t,Ns=0,Rs=null,Fs=Ms=Ls=0,zs=Bs=null,null!==Pa){for(t=0;t<Pa.length;t++)if(null!==(r=(n=Pa[t]).interleaved)){n.interleaved=null;var o=r.next,a=n.pending;if(null!==a){var i=a.next;a.next=o,r.next=i}n.pending=r}Pa=null}return e}function fl(e,t){for(;;){var n=As;try{if(Da(),oi.current=Xi,ui){for(var r=ci.memoizedState;null!==r;){var o=r.queue;null!==o&&(o.pending=null),r=r.next}ui=!1}if(ii=0,li=si=ci=null,di=!1,pi=0,Es.current=null,null===n||null===n.return){Ns=1,Rs=t,As=null;break}e:{var i=e,c=n.return,s=n,l=t;if(t=Ts,s.flags|=32768,null!==l&&"object"==typeof l&&"function"==typeof l.then){var u=l,d=s,p=d.tag;if(!(1&d.mode||0!==p&&11!==p&&15!==p)){var f=d.alternate;f?(d.updateQueue=f.updateQueue,d.memoizedState=f.memoizedState,d.lanes=f.lanes):(d.updateQueue=null,d.memoizedState=null)}var m=hc(c);if(null!==m){m.flags&=-257,bc(m,c,s,0,t),1&m.mode&&gc(i,u,t),l=u;var g=(t=m).updateQueue;if(null===g){var h=new Set;h.add(l),t.updateQueue=h}else g.add(l);break e}if(!(1&t)){gc(i,u,t),gl();break e}l=Error(a(426))}else if(aa&&1&s.mode){var b=hc(c);if(null!==b){!(65536&b.flags)&&(b.flags|=256),bc(b,c,s,0,t),ga(lc(l,s));break e}}i=l=lc(l,s),4!==Ns&&(Ns=2),null===Bs?Bs=[i]:Bs.push(i),i=c;do{switch(i.tag){case 3:i.flags|=65536,t&=-t,i.lanes|=t,Ua(i,fc(0,l,t));break e;case 1:s=l;var y=i.type,v=i.stateNode;if(!(128&i.flags||"function"!=typeof y.getDerivedStateFromError&&(null===v||"function"!=typeof v.componentDidCatch||null!==Ws&&Ws.has(v)))){i.flags|=65536,t&=-t,i.lanes|=t,Ua(i,mc(i,s,t));break e}}i=i.return}while(null!==i)}wl(n)}catch(w){t=w,As===n&&null!==n&&(As=n=n.return);continue}break}}function ml(){var e=Cs.current;return Cs.current=Xi,null===e?Xi:e}function gl(){0!==Ns&&3!==Ns&&2!==Ns||(Ns=4),null===Os||!(268435455&Ls)&&!(268435455&Ms)||cl(Os,Ts)}function hl(e,t){var n=js;js|=2;var r=ml();for(Os===e&&Ts===t||(Hs=null,pl(e,t));;)try{bl();break}catch(o){fl(e,o)}if(Da(),js=n,Cs.current=r,null!==As)throw Error(a(261));return Os=null,Ts=0,Ns}function bl(){for(;null!==As;)vl(As)}function yl(){for(;null!==As&&!Ye();)vl(As)}function vl(e){var t=xs(e.alternate,e,Ps);e.memoizedProps=e.pendingProps,null===t?wl(e):As=t,Es.current=null}function wl(e){var t=e;do{var n=t.alternate;if(e=t.return,32768&t.flags){if(null!==(n=Kc(n,t)))return n.flags&=32767,void(As=n);if(null===e)return Ns=6,void(As=null);e.flags|=32768,e.subtreeFlags=0,e.deletions=null}else if(null!==(n=Gc(n,t,Ps)))return void(As=n);if(null!==(t=t.sibling))return void(As=t);As=t=e}while(null!==t);0===Ns&&(Ns=5)}function Sl(e,t,n){var r=vt,o=Ds.transition;try{Ds.transition=null,vt=1,function(e,t,n,r){do{kl()}while(null!==Ks);if(6&js)throw Error(a(327));n=e.finishedWork;var o=e.finishedLanes;if(null===n)return null;if(e.finishedWork=null,e.finishedLanes=0,n===e.current)throw Error(a(177));e.callbackNode=null,e.callbackPriority=0;var i=n.lanes|n.childLanes;if(function(e,t){var n=e.pendingLanes&~t;e.pendingLanes=t,e.suspendedLanes=0,e.pingedLanes=0,e.expiredLanes&=t,e.mutableReadLanes&=t,e.entangledLanes&=t,t=e.entanglements;var r=e.eventTimes;for(e=e.expirationTimes;0<n;){var o=31-it(n),a=1<<o;t[o]=0,r[o]=-1,e[o]=-1,n&=~a}}(e,i),e===Os&&(As=Os=null,Ts=0),!(2064&n.subtreeFlags)&&!(2064&n.flags)||Gs||(Gs=!0,Ol(tt,(function(){return kl(),null}))),i=!!(15990&n.flags),!!(15990&n.subtreeFlags)||i){i=Ds.transition,Ds.transition=null;var c=vt;vt=1;var s=js;js|=4,Es.current=null,function(e,t){if(eo=qt,fr(e=pr())){if("selectionStart"in e)var n={start:e.selectionStart,end:e.selectionEnd};else e:{var r=(n=(n=e.ownerDocument)&&n.defaultView||window).getSelection&&n.getSelection();if(r&&0!==r.rangeCount){n=r.anchorNode;var o=r.anchorOffset,i=r.focusNode;r=r.focusOffset;try{n.nodeType,i.nodeType}catch(S){n=null;break e}var c=0,s=-1,l=-1,u=0,d=0,p=e,f=null;t:for(;;){for(var m;p!==n||0!==o&&3!==p.nodeType||(s=c+o),p!==i||0!==r&&3!==p.nodeType||(l=c+r),3===p.nodeType&&(c+=p.nodeValue.length),null!==(m=p.firstChild);)f=p,p=m;for(;;){if(p===e)break t;if(f===n&&++u===o&&(s=c),f===i&&++d===r&&(l=c),null!==(m=p.nextSibling))break;f=(p=f).parentNode}p=m}n=-1===s||-1===l?null:{start:s,end:l}}else n=null}n=n||{start:0,end:0}}else n=null;for(to={focusedElem:e,selectionRange:n},qt=!1,Xc=t;null!==Xc;)if(e=(t=Xc).child,1028&t.subtreeFlags&&null!==e)e.return=t,Xc=e;else for(;null!==Xc;){t=Xc;try{var g=t.alternate;if(1024&t.flags)switch(t.tag){case 0:case 11:case 15:case 5:case 6:case 4:case 17:break;case 1:if(null!==g){var h=g.memoizedProps,b=g.memoizedState,y=t.stateNode,v=y.getSnapshotBeforeUpdate(t.elementType===t.type?h:nc(t.type,h),b);y.__reactInternalSnapshotBeforeUpdate=v}break;case 3:var w=t.stateNode.containerInfo;1===w.nodeType?w.textContent="":9===w.nodeType&&w.documentElement&&w.removeChild(w.documentElement);break;default:throw Error(a(163))}}catch(S){_l(t,t.return,S)}if(null!==(e=t.sibling)){e.return=t.return,Xc=e;break}Xc=t.return}g=ts,ts=!1}(e,n),hs(n,e),mr(to),qt=!!eo,to=eo=null,e.current=n,ys(n,e,o),Qe(),js=s,vt=c,Ds.transition=i}else e.current=n;if(Gs&&(Gs=!1,Ks=e,Ys=o),i=e.pendingLanes,0===i&&(Ws=null),function(e){if(at&&"function"==typeof at.onCommitFiberRoot)try{at.onCommitFiberRoot(ot,e,void 0,!(128&~e.current.flags))}catch(t){}}(n.stateNode),rl(e,Ze()),null!==t)for(r=e.onRecoverableError,n=0;n<t.length;n++)o=t[n],r(o.value,{componentStack:o.stack,digest:o.digest});if(qs)throw qs=!1,e=Vs,Vs=null,e;!!(1&Ys)&&0!==e.tag&&kl(),i=e.pendingLanes,1&i?e===Zs?Qs++:(Qs=0,Zs=e):Qs=0,Ho()}(e,t,n,r)}finally{Ds.transition=o,vt=r}return null}function kl(){if(null!==Ks){var e=wt(Ys),t=Ds.transition,n=vt;try{if(Ds.transition=null,vt=16>e?16:e,null===Ks)var r=!1;else{if(e=Ks,Ks=null,Ys=0,6&js)throw Error(a(331));var o=js;for(js|=4,Xc=e.current;null!==Xc;){var i=Xc,c=i.child;if(16&Xc.flags){var s=i.deletions;if(null!==s){for(var l=0;l<s.length;l++){var u=s[l];for(Xc=u;null!==Xc;){var d=Xc;switch(d.tag){case 0:case 11:case 15:ns(8,d,i)}var p=d.child;if(null!==p)p.return=d,Xc=p;else for(;null!==Xc;){var f=(d=Xc).sibling,m=d.return;if(as(d),d===u){Xc=null;break}if(null!==f){f.return=m,Xc=f;break}Xc=m}}}var g=i.alternate;if(null!==g){var h=g.child;if(null!==h){g.child=null;do{var b=h.sibling;h.sibling=null,h=b}while(null!==h)}}Xc=i}}if(2064&i.subtreeFlags&&null!==c)c.return=i,Xc=c;else e:for(;null!==Xc;){if(2048&(i=Xc).flags)switch(i.tag){case 0:case 11:case 15:ns(9,i,i.return)}var y=i.sibling;if(null!==y){y.return=i.return,Xc=y;break e}Xc=i.return}}var v=e.current;for(Xc=v;null!==Xc;){var w=(c=Xc).child;if(2064&c.subtreeFlags&&null!==w)w.return=c,Xc=w;else e:for(c=v;null!==Xc;){if(2048&(s=Xc).flags)try{switch(s.tag){case 0:case 11:case 15:rs(9,s)}}catch(k){_l(s,s.return,k)}if(s===c){Xc=null;break e}var S=s.sibling;if(null!==S){S.return=s.return,Xc=S;break e}Xc=s.return}}if(js=o,Ho(),at&&"function"==typeof at.onPostCommitFiberRoot)try{at.onPostCommitFiberRoot(ot,e)}catch(k){}r=!0}return r}finally{vt=n,Ds.transition=t}}return!1}function xl(e,t,n){e=za(e,t=fc(0,t=lc(n,t),1),1),t=el(),null!==e&&(bt(e,1,t),rl(e,t))}function _l(e,t,n){if(3===e.tag)xl(e,e,n);else for(;null!==t;){if(3===t.tag){xl(t,e,n);break}if(1===t.tag){var r=t.stateNode;if("function"==typeof t.type.getDerivedStateFromError||"function"==typeof r.componentDidCatch&&(null===Ws||!Ws.has(r))){t=za(t,e=mc(t,e=lc(n,e),1),1),e=el(),null!==t&&(bt(t,1,e),rl(t,e));break}}t=t.return}}function Cl(e,t,n){var r=e.pingCache;null!==r&&r.delete(t),t=el(),e.pingedLanes|=e.suspendedLanes&n,Os===e&&(Ts&n)===n&&(4===Ns||3===Ns&&(130023424&Ts)===Ts&&500>Ze()-$s?pl(e,0):Fs|=n),rl(e,t)}function El(e,t){0===t&&(1&e.mode?(t=ut,!(130023424&(ut<<=1))&&(ut=4194304)):t=1);var n=el();null!==(e=Ra(e,t))&&(bt(e,t,n),rl(e,n))}function Dl(e){var t=e.memoizedState,n=0;null!==t&&(n=t.retryLane),El(e,n)}function jl(e,t){var n=0;switch(e.tag){case 13:var r=e.stateNode,o=e.memoizedState;null!==o&&(n=o.retryLane);break;case 19:r=e.stateNode;break;default:throw Error(a(314))}null!==r&&r.delete(t),El(e,n)}function Ol(e,t){return Ge(e,t)}function Al(e,t,n,r){this.tag=e,this.key=n,this.sibling=this.child=this.return=this.stateNode=this.type=this.elementType=null,this.index=0,this.ref=null,this.pendingProps=t,this.dependencies=this.memoizedState=this.updateQueue=this.memoizedProps=null,this.mode=r,this.subtreeFlags=this.flags=0,this.deletions=null,this.childLanes=this.lanes=0,this.alternate=null}function Tl(e,t,n,r){return new Al(e,t,n,r)}function Pl(e){return!(!(e=e.prototype)||!e.isReactComponent)}function Il(e,t){var n=e.alternate;return null===n?((n=Tl(e.tag,t,e.key,e.mode)).elementType=e.elementType,n.type=e.type,n.stateNode=e.stateNode,n.alternate=e,e.alternate=n):(n.pendingProps=t,n.type=e.type,n.flags=0,n.subtreeFlags=0,n.deletions=null),n.flags=14680064&e.flags,n.childLanes=e.childLanes,n.lanes=e.lanes,n.child=e.child,n.memoizedProps=e.memoizedProps,n.memoizedState=e.memoizedState,n.updateQueue=e.updateQueue,t=e.dependencies,n.dependencies=null===t?null:{lanes:t.lanes,firstContext:t.firstContext},n.sibling=e.sibling,n.index=e.index,n.ref=e.ref,n}function Nl(e,t,n,r,o,i){var c=2;if(r=e,"function"==typeof e)Pl(e)&&(c=1);else if("string"==typeof e)c=5;else e:switch(e){case x:return Rl(n.children,o,i,t);case _:c=8,o|=8;break;case C:return(e=Tl(12,n,t,2|o)).elementType=C,e.lanes=i,e;case O:return(e=Tl(13,n,t,o)).elementType=O,e.lanes=i,e;case A:return(e=Tl(19,n,t,o)).elementType=A,e.lanes=i,e;case I:return Ll(n,o,i,t);default:if("object"==typeof e&&null!==e)switch(e.$$typeof){case E:c=10;break e;case D:c=9;break e;case j:c=11;break e;case T:c=14;break e;case P:c=16,r=null;break e}throw Error(a(130,null==e?e:typeof e,""))}return(t=Tl(c,n,t,o)).elementType=e,t.type=r,t.lanes=i,t}function Rl(e,t,n,r){return(e=Tl(7,e,r,t)).lanes=n,e}function Ll(e,t,n,r){return(e=Tl(22,e,r,t)).elementType=I,e.lanes=n,e.stateNode={isHidden:!1},e}function Ml(e,t,n){return(e=Tl(6,e,null,t)).lanes=n,e}function Fl(e,t,n){return(t=Tl(4,null!==e.children?e.children:[],e.key,t)).lanes=n,t.stateNode={containerInfo:e.containerInfo,pendingChildren:null,implementation:e.implementation},t}function Bl(e,t,n,r,o){this.tag=t,this.containerInfo=e,this.finishedWork=this.pingCache=this.current=this.pendingChildren=null,this.timeoutHandle=-1,this.callbackNode=this.pendingContext=this.context=null,this.callbackPriority=0,this.eventTimes=ht(0),this.expirationTimes=ht(-1),this.entangledLanes=this.finishedLanes=this.mutableReadLanes=this.expiredLanes=this.pingedLanes=this.suspendedLanes=this.pendingLanes=0,this.entanglements=ht(0),this.identifierPrefix=r,this.onRecoverableError=o,this.mutableSourceEagerHydrationData=null}function zl(e,t,n,r,o,a,i,c,s){return e=new Bl(e,t,n,c,s),1===t?(t=1,!0===a&&(t|=8)):t=0,a=Tl(3,null,null,t),e.current=a,a.stateNode=e,a.memoizedState={element:r,isDehydrated:n,cache:null,transitions:null,pendingSuspenseBoundaries:null},Ma(a),e}function $l(e){if(!e)return jo;e:{if(Ue(e=e._reactInternals)!==e||1!==e.tag)throw Error(a(170));var t=e;do{switch(t.tag){case 3:t=t.stateNode.context;break e;case 1:if(Io(t.type)){t=t.stateNode.__reactInternalMemoizedMergedChildContext;break e}}t=t.return}while(null!==t);throw Error(a(171))}if(1===e.tag){var n=e.type;if(Io(n))return Lo(e,n,t)}return t}function Ul(e,t,n,r,o,a,i,c,s){return(e=zl(n,r,!0,e,0,a,0,c,s)).context=$l(null),n=e.current,(a=Ba(r=el(),o=tl(n))).callback=null!=t?t:null,za(n,a,o),e.current.lanes=o,bt(e,o,r),rl(e,r),e}function Hl(e,t,n,r){var o=t.current,a=el(),i=tl(o);return n=$l(n),null===t.context?t.context=n:t.pendingContext=n,(t=Ba(a,i)).payload={element:e},null!==(r=void 0===r?null:r)&&(t.callback=r),null!==(e=za(o,t,i))&&(nl(e,o,i,a),$a(e,o,i)),i}function ql(e){return(e=e.current).child?(e.child.tag,e.child.stateNode):null}function Vl(e,t){if(null!==(e=e.memoizedState)&&null!==e.dehydrated){var n=e.retryLane;e.retryLane=0!==n&&n<t?n:t}}function Wl(e,t){Vl(e,t),(e=e.alternate)&&Vl(e,t)}xs=function(e,t,n){if(null!==e)if(e.memoizedProps!==t.pendingProps||Ao.current)vc=!0;else{if(!(e.lanes&n||128&t.flags))return vc=!1,function(e,t,n){switch(t.tag){case 3:Oc(t),ma();break;case 5:Xa(t);break;case 1:Io(t.type)&&Mo(t);break;case 4:Qa(t,t.stateNode.containerInfo);break;case 10:var r=t.type._context,o=t.memoizedProps.value;Do(xa,r._currentValue),r._currentValue=o;break;case 13:if(null!==(r=t.memoizedState))return null!==r.dehydrated?(Do(ei,1&ei.current),t.flags|=128,null):n&t.child.childLanes?Mc(e,t,n):(Do(ei,1&ei.current),null!==(e=qc(e,t,n))?e.sibling:null);Do(ei,1&ei.current);break;case 19:if(r=!!(n&t.childLanes),128&e.flags){if(r)return Uc(e,t,n);t.flags|=128}if(null!==(o=t.memoizedState)&&(o.rendering=null,o.tail=null,o.lastEffect=null),Do(ei,ei.current),r)break;return null;case 22:case 23:return t.lanes=0,_c(e,t,n)}return qc(e,t,n)}(e,t,n);vc=!!(131072&e.flags)}else vc=!1,aa&&1048576&t.flags&&ea(t,Go,t.index);switch(t.lanes=0,t.tag){case 2:var r=t.type;Hc(e,t),e=t.pendingProps;var o=Po(t,Oo.current);Aa(t,n),o=hi(null,t,r,e,o,n);var i=bi();return t.flags|=1,"object"==typeof o&&null!==o&&"function"==typeof o.render&&void 0===o.$$typeof?(t.tag=1,t.memoizedState=null,t.updateQueue=null,Io(r)?(i=!0,Mo(t)):i=!1,t.memoizedState=null!==o.state&&void 0!==o.state?o.state:null,Ma(t),o.updater=oc,t.stateNode=o,o._reactInternals=t,sc(t,r,e,n),t=jc(null,t,r,!0,i,n)):(t.tag=0,aa&&i&&ta(t),wc(null,t,o,n),t=t.child),t;case 16:r=t.elementType;e:{switch(Hc(e,t),e=t.pendingProps,r=(o=r._init)(r._payload),t.type=r,o=t.tag=function(e){if("function"==typeof e)return Pl(e)?1:0;if(null!=e){if((e=e.$$typeof)===j)return 11;if(e===T)return 14}return 2}(r),e=nc(r,e),o){case 0:t=Ec(null,t,r,e,n);break e;case 1:t=Dc(null,t,r,e,n);break e;case 11:t=Sc(null,t,r,e,n);break e;case 14:t=kc(null,t,r,nc(r.type,e),n);break e}throw Error(a(306,r,""))}return t;case 0:return r=t.type,o=t.pendingProps,Ec(e,t,r,o=t.elementType===r?o:nc(r,o),n);case 1:return r=t.type,o=t.pendingProps,Dc(e,t,r,o=t.elementType===r?o:nc(r,o),n);case 3:e:{if(Oc(t),null===e)throw Error(a(387));r=t.pendingProps,o=(i=t.memoizedState).element,Fa(e,t),Ha(t,r,null,n);var c=t.memoizedState;if(r=c.element,i.isDehydrated){if(i={element:r,isDehydrated:!1,cache:c.cache,pendingSuspenseBoundaries:c.pendingSuspenseBoundaries,transitions:c.transitions},t.updateQueue.baseState=i,t.memoizedState=i,256&t.flags){t=Ac(e,t,r,n,o=lc(Error(a(423)),t));break e}if(r!==o){t=Ac(e,t,r,n,o=lc(Error(a(424)),t));break e}for(oa=lo(t.stateNode.containerInfo.firstChild),ra=t,aa=!0,ia=null,n=ka(t,null,r,n),t.child=n;n;)n.flags=-3&n.flags|4096,n=n.sibling}else{if(ma(),r===o){t=qc(e,t,n);break e}wc(e,t,r,n)}t=t.child}return t;case 5:return Xa(t),null===e&&ua(t),r=t.type,o=t.pendingProps,i=null!==e?e.memoizedProps:null,c=o.children,no(r,o)?c=null:null!==i&&no(r,i)&&(t.flags|=32),Cc(e,t),wc(e,t,c,n),t.child;case 6:return null===e&&ua(t),null;case 13:return Mc(e,t,n);case 4:return Qa(t,t.stateNode.containerInfo),r=t.pendingProps,null===e?t.child=Sa(t,null,r,n):wc(e,t,r,n),t.child;case 11:return r=t.type,o=t.pendingProps,Sc(e,t,r,o=t.elementType===r?o:nc(r,o),n);case 7:return wc(e,t,t.pendingProps,n),t.child;case 8:case 12:return wc(e,t,t.pendingProps.children,n),t.child;case 10:e:{if(r=t.type._context,o=t.pendingProps,i=t.memoizedProps,c=o.value,Do(xa,r._currentValue),r._currentValue=c,null!==i)if(cr(i.value,c)){if(i.children===o.children&&!Ao.current){t=qc(e,t,n);break e}}else for(null!==(i=t.child)&&(i.return=t);null!==i;){var s=i.dependencies;if(null!==s){c=i.child;for(var l=s.firstContext;null!==l;){if(l.context===r){if(1===i.tag){(l=Ba(-1,n&-n)).tag=2;var u=i.updateQueue;if(null!==u){var d=(u=u.shared).pending;null===d?l.next=l:(l.next=d.next,d.next=l),u.pending=l}}i.lanes|=n,null!==(l=i.alternate)&&(l.lanes|=n),Oa(i.return,n,t),s.lanes|=n;break}l=l.next}}else if(10===i.tag)c=i.type===t.type?null:i.child;else if(18===i.tag){if(null===(c=i.return))throw Error(a(341));c.lanes|=n,null!==(s=c.alternate)&&(s.lanes|=n),Oa(c,n,t),c=i.sibling}else c=i.child;if(null!==c)c.return=i;else for(c=i;null!==c;){if(c===t){c=null;break}if(null!==(i=c.sibling)){i.return=c.return,c=i;break}c=c.return}i=c}wc(e,t,o.children,n),t=t.child}return t;case 9:return o=t.type,r=t.pendingProps.children,Aa(t,n),r=r(o=Ta(o)),t.flags|=1,wc(e,t,r,n),t.child;case 14:return o=nc(r=t.type,t.pendingProps),kc(e,t,r,o=nc(r.type,o),n);case 15:return xc(e,t,t.type,t.pendingProps,n);case 17:return r=t.type,o=t.pendingProps,o=t.elementType===r?o:nc(r,o),Hc(e,t),t.tag=1,Io(r)?(e=!0,Mo(t)):e=!1,Aa(t,n),ic(t,r,o),sc(t,r,o,n),jc(null,t,r,!0,e,n);case 19:return Uc(e,t,n);case 22:return _c(e,t,n)}throw Error(a(156,t.tag))};var Gl="function"==typeof reportError?reportError:function(e){console.error(e)};function Kl(e){this._internalRoot=e}function Yl(e){this._internalRoot=e}function Ql(e){return!(!e||1!==e.nodeType&&9!==e.nodeType&&11!==e.nodeType)}function Zl(e){return!(!e||1!==e.nodeType&&9!==e.nodeType&&11!==e.nodeType&&(8!==e.nodeType||" react-mount-point-unstable "!==e.nodeValue))}function Xl(){}function Jl(e,t,n,r,o){var a=n._reactRootContainer;if(a){var i=a;if("function"==typeof o){var c=o;o=function(){var e=ql(i);c.call(e)}}Hl(t,i,e,o)}else i=function(e,t,n,r,o){if(o){if("function"==typeof r){var a=r;r=function(){var e=ql(i);a.call(e)}}var i=Ul(t,r,e,0,null,!1,0,"",Xl);return e._reactRootContainer=i,e[go]=i.current,Ur(8===e.nodeType?e.parentNode:e),ul(),i}for(;o=e.lastChild;)e.removeChild(o);if("function"==typeof r){var c=r;r=function(){var e=ql(s);c.call(e)}}var s=zl(e,0,!1,null,0,!1,0,"",Xl);return e._reactRootContainer=s,e[go]=s.current,Ur(8===e.nodeType?e.parentNode:e),ul((function(){Hl(t,s,n,r)})),s}(n,t,e,o,r);return ql(i)}Yl.prototype.render=Kl.prototype.render=function(e){var t=this._internalRoot;if(null===t)throw Error(a(409));Hl(e,t,null,null)},Yl.prototype.unmount=Kl.prototype.unmount=function(){var e=this._internalRoot;if(null!==e){this._internalRoot=null;var t=e.containerInfo;ul((function(){Hl(null,e,null,null)})),t[go]=null}},Yl.prototype.unstable_scheduleHydration=function(e){if(e){var t=_t();e={blockedOn:null,target:e,priority:t};for(var n=0;n<It.length&&0!==t&&t<It[n].priority;n++);It.splice(n,0,e),0===n&&Mt(e)}},St=function(e){switch(e.tag){case 3:var t=e.stateNode;if(t.current.memoizedState.isDehydrated){var n=dt(t.pendingLanes);0!==n&&(yt(t,1|n),rl(t,Ze()),!(6&js)&&(Us=Ze()+500,Ho()))}break;case 13:ul((function(){var t=Ra(e,1);if(null!==t){var n=el();nl(t,e,1,n)}})),Wl(e,1)}},kt=function(e){if(13===e.tag){var t=Ra(e,134217728);if(null!==t)nl(t,e,134217728,el());Wl(e,134217728)}},xt=function(e){if(13===e.tag){var t=tl(e),n=Ra(e,t);if(null!==n)nl(n,e,t,el());Wl(e,t)}},_t=function(){return vt},Ct=function(e,t){var n=vt;try{return vt=e,t()}finally{vt=n}},ke=function(e,t,n){switch(t){case"input":if(X(e,n),t=n.name,"radio"===n.type&&null!=t){for(n=e;n.parentNode;)n=n.parentNode;for(n=n.querySelectorAll("input[name="+JSON.stringify(""+t)+'][type="radio"]'),t=0;t<n.length;t++){var r=n[t];if(r!==e&&r.form===e.form){var o=ko(r);if(!o)throw Error(a(90));G(r),X(r,o)}}}break;case"textarea":ae(e,n);break;case"select":null!=(t=n.value)&&ne(e,!!n.multiple,t,!1)}},je=ll,Oe=ul;var eu={usingClientEntryPoint:!1,Events:[wo,So,ko,Ee,De,ll]},tu={findFiberByHostInstance:vo,bundleType:0,version:"18.3.1",rendererPackageName:"react-dom"},nu={bundleType:tu.bundleType,version:tu.version,rendererPackageName:tu.rendererPackageName,rendererConfig:tu.rendererConfig,overrideHookState:null,overrideHookStateDeletePath:null,overrideHookStateRenamePath:null,overrideProps:null,overridePropsDeletePath:null,overridePropsRenamePath:null,setErrorHandler:null,setSuspenseHandler:null,scheduleUpdate:null,currentDispatcherRef:w.ReactCurrentDispatcher,findHostInstanceByFiber:function(e){return null===(e=Ve(e))?null:e.stateNode},findFiberByHostInstance:tu.findFiberByHostInstance||function(){return null},findHostInstancesForRefresh:null,scheduleRefresh:null,scheduleRoot:null,setRefreshHandler:null,getCurrentFiber:null,reconcilerVersion:"18.3.1-next-f1338f8080-20240426"};if("undefined"!=typeof __REACT_DEVTOOLS_GLOBAL_HOOK__){var ru=__REACT_DEVTOOLS_GLOBAL_HOOK__;if(!ru.isDisabled&&ru.supportsFiber)try{ot=ru.inject(nu),at=ru}catch(ue){}}t.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED=eu,t.createPortal=function(e,t){var n=2<arguments.length&&void 0!==arguments[2]?arguments[2]:null;if(!Ql(t))throw Error(a(200));return function(e,t,n){var r=3<arguments.length&&void 0!==arguments[3]?arguments[3]:null;return{$$typeof:k,key:null==r?null:""+r,children:e,containerInfo:t,implementation:n}}(e,t,null,n)},t.createRoot=function(e,t){if(!Ql(e))throw Error(a(299));var n=!1,r="",o=Gl;return null!=t&&(!0===t.unstable_strictMode&&(n=!0),void 0!==t.identifierPrefix&&(r=t.identifierPrefix),void 0!==t.onRecoverableError&&(o=t.onRecoverableError)),t=zl(e,1,!1,null,0,n,0,r,o),e[go]=t.current,Ur(8===e.nodeType?e.parentNode:e),new Kl(t)},t.findDOMNode=function(e){if(null==e)return null;if(1===e.nodeType)return e;var t=e._reactInternals;if(void 0===t){if("function"==typeof e.render)throw Error(a(188));throw e=Object.keys(e).join(","),Error(a(268,e))}return e=null===(e=Ve(t))?null:e.stateNode},t.flushSync=function(e){return ul(e)},t.hydrate=function(e,t,n){if(!Zl(t))throw Error(a(200));return Jl(null,e,t,!0,n)},t.hydrateRoot=function(e,t,n){if(!Ql(e))throw Error(a(405));var r=null!=n&&n.hydratedSources||null,o=!1,i="",c=Gl;if(null!=n&&(!0===n.unstable_strictMode&&(o=!0),void 0!==n.identifierPrefix&&(i=n.identifierPrefix),void 0!==n.onRecoverableError&&(c=n.onRecoverableError)),t=Ul(t,null,e,1,null!=n?n:null,o,0,i,c),e[go]=t.current,Ur(e),r)for(e=0;e<r.length;e++)o=(o=(n=r[e])._getVersion)(n._source),null==t.mutableSourceEagerHydrationData?t.mutableSourceEagerHydrationData=[n,o]:t.mutableSourceEagerHydrationData.push(n,o);return new Yl(t)},t.render=function(e,t,n){if(!Zl(t))throw Error(a(200));return Jl(null,e,t,!1,n)},t.unmountComponentAtNode=function(e){if(!Zl(e))throw Error(a(40));return!!e._reactRootContainer&&(ul((function(){Jl(null,null,e,!1,(function(){e._reactRootContainer=null,e[go]=null}))})),!0)},t.unstable_batchedUpdates=ll,t.unstable_renderSubtreeIntoContainer=function(e,t,n,r){if(!Zl(n))throw Error(a(200));if(null==e||void 0===e._reactInternals)throw Error(a(38));return Jl(e,t,n,!1,r)},t.version="18.3.1-next-f1338f8080-20240426"},5338:(e,t,n)=>{"use strict";var r=n(961);t.createRoot=r.createRoot,t.hydrateRoot=r.hydrateRoot},961:(e,t,n)=>{"use strict";!function e(){if("undefined"!=typeof __REACT_DEVTOOLS_GLOBAL_HOOK__&&"function"==typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE)try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(e)}catch(t){console.error(t)}}(),e.exports=n(2551)},115:e=>{var t="undefined"!=typeof Element,n="function"==typeof Map,r="function"==typeof Set,o="function"==typeof ArrayBuffer&&!!ArrayBuffer.isView;function a(e,i){if(e===i)return!0;if(e&&i&&"object"==typeof e&&"object"==typeof i){if(e.constructor!==i.constructor)return!1;var c,s,l,u;if(Array.isArray(e)){if((c=e.length)!=i.length)return!1;for(s=c;0!=s--;)if(!a(e[s],i[s]))return!1;return!0}if(n&&e instanceof Map&&i instanceof Map){if(e.size!==i.size)return!1;for(u=e.entries();!(s=u.next()).done;)if(!i.has(s.value[0]))return!1;for(u=e.entries();!(s=u.next()).done;)if(!a(s.value[1],i.get(s.value[0])))return!1;return!0}if(r&&e instanceof Set&&i instanceof Set){if(e.size!==i.size)return!1;for(u=e.entries();!(s=u.next()).done;)if(!i.has(s.value[0]))return!1;return!0}if(o&&ArrayBuffer.isView(e)&&ArrayBuffer.isView(i)){if((c=e.length)!=i.length)return!1;for(s=c;0!=s--;)if(e[s]!==i[s])return!1;return!0}if(e.constructor===RegExp)return e.source===i.source&&e.flags===i.flags;if(e.valueOf!==Object.prototype.valueOf&&"function"==typeof e.valueOf&&"function"==typeof i.valueOf)return e.valueOf()===i.valueOf();if(e.toString!==Object.prototype.toString&&"function"==typeof e.toString&&"function"==typeof i.toString)return e.toString()===i.toString();if((c=(l=Object.keys(e)).length)!==Object.keys(i).length)return!1;for(s=c;0!=s--;)if(!Object.prototype.hasOwnProperty.call(i,l[s]))return!1;if(t&&e instanceof Element)return!1;for(s=c;0!=s--;)if(("_owner"!==l[s]&&"__v"!==l[s]&&"__o"!==l[s]||!e.$$typeof)&&!a(e[l[s]],i[l[s]]))return!1;return!0}return e!=e&&i!=i}e.exports=function(e,t){try{return a(e,t)}catch(n){if((n.message||"").match(/stack|recursion/i))return console.warn("react-fast-compare cannot handle circular refs"),!1;throw n}}},545:(e,t,n)=>{"use strict";n.d(t,{mg:()=>J,vd:()=>V});var r=n(6540),o=n(5556),a=n.n(o),i=n(115),c=n.n(i),s=n(311),l=n.n(s),u=n(2833),d=n.n(u);function p(){return p=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var r in n)Object.prototype.hasOwnProperty.call(n,r)&&(e[r]=n[r])}return e},p.apply(this,arguments)}function f(e,t){e.prototype=Object.create(t.prototype),e.prototype.constructor=e,m(e,t)}function m(e,t){return m=Object.setPrototypeOf||function(e,t){return e.__proto__=t,e},m(e,t)}function g(e,t){if(null==e)return{};var n,r,o={},a=Object.keys(e);for(r=0;r<a.length;r++)t.indexOf(n=a[r])>=0||(o[n]=e[n]);return o}var h={BASE:"base",BODY:"body",HEAD:"head",HTML:"html",LINK:"link",META:"meta",NOSCRIPT:"noscript",SCRIPT:"script",STYLE:"style",TITLE:"title",FRAGMENT:"Symbol(react.fragment)"},b={rel:["amphtml","canonical","alternate"]},y={type:["application/ld+json"]},v={charset:"",name:["robots","description"],property:["og:type","og:title","og:url","og:image","og:image:alt","og:description","twitter:url","twitter:title","twitter:description","twitter:image","twitter:image:alt","twitter:card","twitter:site"]},w=Object.keys(h).map((function(e){return h[e]})),S={accesskey:"accessKey",charset:"charSet",class:"className",contenteditable:"contentEditable",contextmenu:"contextMenu","http-equiv":"httpEquiv",itemprop:"itemProp",tabindex:"tabIndex"},k=Object.keys(S).reduce((function(e,t){return e[S[t]]=t,e}),{}),x=function(e,t){for(var n=e.length-1;n>=0;n-=1){var r=e[n];if(Object.prototype.hasOwnProperty.call(r,t))return r[t]}return null},_=function(e){var t=x(e,h.TITLE),n=x(e,"titleTemplate");if(Array.isArray(t)&&(t=t.join("")),n&&t)return n.replace(/%s/g,(function(){return t}));var r=x(e,"defaultTitle");return t||r||void 0},C=function(e){return x(e,"onChangeClientState")||function(){}},E=function(e,t){return t.filter((function(t){return void 0!==t[e]})).map((function(t){return t[e]})).reduce((function(e,t){return p({},e,t)}),{})},D=function(e,t){return t.filter((function(e){return void 0!==e[h.BASE]})).map((function(e){return e[h.BASE]})).reverse().reduce((function(t,n){if(!t.length)for(var r=Object.keys(n),o=0;o<r.length;o+=1){var a=r[o].toLowerCase();if(-1!==e.indexOf(a)&&n[a])return t.concat(n)}return t}),[])},j=function(e,t,n){var r={};return n.filter((function(t){return!!Array.isArray(t[e])||(void 0!==t[e]&&console&&"function"==typeof console.warn&&console.warn("Helmet: "+e+' should be of type "Array". Instead found type "'+typeof t[e]+'"'),!1)})).map((function(t){return t[e]})).reverse().reduce((function(e,n){var o={};n.filter((function(e){for(var n,a=Object.keys(e),i=0;i<a.length;i+=1){var c=a[i],s=c.toLowerCase();-1===t.indexOf(s)||"rel"===n&&"canonical"===e[n].toLowerCase()||"rel"===s&&"stylesheet"===e[s].toLowerCase()||(n=s),-1===t.indexOf(c)||"innerHTML"!==c&&"cssText"!==c&&"itemprop"!==c||(n=c)}if(!n||!e[n])return!1;var l=e[n].toLowerCase();return r[n]||(r[n]={}),o[n]||(o[n]={}),!r[n][l]&&(o[n][l]=!0,!0)})).reverse().forEach((function(t){return e.push(t)}));for(var a=Object.keys(o),i=0;i<a.length;i+=1){var c=a[i],s=p({},r[c],o[c]);r[c]=s}return e}),[]).reverse()},O=function(e,t){if(Array.isArray(e)&&e.length)for(var n=0;n<e.length;n+=1)if(e[n][t])return!0;return!1},A=function(e){return Array.isArray(e)?e.join(""):e},T=function(e,t){return Array.isArray(e)?e.reduce((function(e,n){return function(e,t){for(var n=Object.keys(e),r=0;r<n.length;r+=1)if(t[n[r]]&&t[n[r]].includes(e[n[r]]))return!0;return!1}(n,t)?e.priority.push(n):e.default.push(n),e}),{priority:[],default:[]}):{default:e}},P=function(e,t){var n;return p({},e,((n={})[t]=void 0,n))},I=[h.NOSCRIPT,h.SCRIPT,h.STYLE],N=function(e,t){return void 0===t&&(t=!0),!1===t?String(e):String(e).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'")},R=function(e){return Object.keys(e).reduce((function(t,n){var r=void 0!==e[n]?n+'="'+e[n]+'"':""+n;return t?t+" "+r:r}),"")},L=function(e,t){return void 0===t&&(t={}),Object.keys(e).reduce((function(t,n){return t[S[n]||n]=e[n],t}),t)},M=function(e,t){return t.map((function(t,n){var o,a=((o={key:n})["data-rh"]=!0,o);return Object.keys(t).forEach((function(e){var n=S[e]||e;"innerHTML"===n||"cssText"===n?a.dangerouslySetInnerHTML={__html:t.innerHTML||t.cssText}:a[n]=t[e]})),r.createElement(e,a)}))},F=function(e,t,n){switch(e){case h.TITLE:return{toComponent:function(){return n=t.titleAttributes,(o={key:e=t.title})["data-rh"]=!0,a=L(n,o),[r.createElement(h.TITLE,a,e)];var e,n,o,a},toString:function(){return function(e,t,n,r){var o=R(n),a=A(t);return o?"<"+e+' data-rh="true" '+o+">"+N(a,r)+"</"+e+">":"<"+e+' data-rh="true">'+N(a,r)+"</"+e+">"}(e,t.title,t.titleAttributes,n)}};case"bodyAttributes":case"htmlAttributes":return{toComponent:function(){return L(t)},toString:function(){return R(t)}};default:return{toComponent:function(){return M(e,t)},toString:function(){return function(e,t,n){return t.reduce((function(t,r){var o=Object.keys(r).filter((function(e){return!("innerHTML"===e||"cssText"===e)})).reduce((function(e,t){var o=void 0===r[t]?t:t+'="'+N(r[t],n)+'"';return e?e+" "+o:o}),""),a=r.innerHTML||r.cssText||"",i=-1===I.indexOf(e);return t+"<"+e+' data-rh="true" '+o+(i?"/>":">"+a+"</"+e+">")}),"")}(e,t,n)}}}},B=function(e){var t=e.baseTag,n=e.bodyAttributes,r=e.encode,o=e.htmlAttributes,a=e.noscriptTags,i=e.styleTags,c=e.title,s=void 0===c?"":c,l=e.titleAttributes,u=e.linkTags,d=e.metaTags,p=e.scriptTags,f={toComponent:function(){},toString:function(){return""}};if(e.prioritizeSeoTags){var m=function(e){var t=e.linkTags,n=e.scriptTags,r=e.encode,o=T(e.metaTags,v),a=T(t,b),i=T(n,y);return{priorityMethods:{toComponent:function(){return[].concat(M(h.META,o.priority),M(h.LINK,a.priority),M(h.SCRIPT,i.priority))},toString:function(){return F(h.META,o.priority,r)+" "+F(h.LINK,a.priority,r)+" "+F(h.SCRIPT,i.priority,r)}},metaTags:o.default,linkTags:a.default,scriptTags:i.default}}(e);f=m.priorityMethods,u=m.linkTags,d=m.metaTags,p=m.scriptTags}return{priority:f,base:F(h.BASE,t,r),bodyAttributes:F("bodyAttributes",n,r),htmlAttributes:F("htmlAttributes",o,r),link:F(h.LINK,u,r),meta:F(h.META,d,r),noscript:F(h.NOSCRIPT,a,r),script:F(h.SCRIPT,p,r),style:F(h.STYLE,i,r),title:F(h.TITLE,{title:s,titleAttributes:l},r)}},z=[],$=function(e,t){var n=this;void 0===t&&(t="undefined"!=typeof document),this.instances=[],this.value={setHelmet:function(e){n.context.helmet=e},helmetInstances:{get:function(){return n.canUseDOM?z:n.instances},add:function(e){(n.canUseDOM?z:n.instances).push(e)},remove:function(e){var t=(n.canUseDOM?z:n.instances).indexOf(e);(n.canUseDOM?z:n.instances).splice(t,1)}}},this.context=e,this.canUseDOM=t,t||(e.helmet=B({baseTag:[],bodyAttributes:{},encodeSpecialCharacters:!0,htmlAttributes:{},linkTags:[],metaTags:[],noscriptTags:[],scriptTags:[],styleTags:[],title:"",titleAttributes:{}}))},U=r.createContext({}),H=a().shape({setHelmet:a().func,helmetInstances:a().shape({get:a().func,add:a().func,remove:a().func})}),q="undefined"!=typeof document,V=function(e){function t(n){var r;return(r=e.call(this,n)||this).helmetData=new $(r.props.context,t.canUseDOM),r}return f(t,e),t.prototype.render=function(){return r.createElement(U.Provider,{value:this.helmetData.value},this.props.children)},t}(r.Component);V.canUseDOM=q,V.propTypes={context:a().shape({helmet:a().shape()}),children:a().node.isRequired},V.defaultProps={context:{}},V.displayName="HelmetProvider";var W=function(e,t){var n,r=document.head||document.querySelector(h.HEAD),o=r.querySelectorAll(e+"[data-rh]"),a=[].slice.call(o),i=[];return t&&t.length&&t.forEach((function(t){var r=document.createElement(e);for(var o in t)Object.prototype.hasOwnProperty.call(t,o)&&("innerHTML"===o?r.innerHTML=t.innerHTML:"cssText"===o?r.styleSheet?r.styleSheet.cssText=t.cssText:r.appendChild(document.createTextNode(t.cssText)):r.setAttribute(o,void 0===t[o]?"":t[o]));r.setAttribute("data-rh","true"),a.some((function(e,t){return n=t,r.isEqualNode(e)}))?a.splice(n,1):i.push(r)})),a.forEach((function(e){return e.parentNode.removeChild(e)})),i.forEach((function(e){return r.appendChild(e)})),{oldTags:a,newTags:i}},G=function(e,t){var n=document.getElementsByTagName(e)[0];if(n){for(var r=n.getAttribute("data-rh"),o=r?r.split(","):[],a=[].concat(o),i=Object.keys(t),c=0;c<i.length;c+=1){var s=i[c],l=t[s]||"";n.getAttribute(s)!==l&&n.setAttribute(s,l),-1===o.indexOf(s)&&o.push(s);var u=a.indexOf(s);-1!==u&&a.splice(u,1)}for(var d=a.length-1;d>=0;d-=1)n.removeAttribute(a[d]);o.length===a.length?n.removeAttribute("data-rh"):n.getAttribute("data-rh")!==i.join(",")&&n.setAttribute("data-rh",i.join(","))}},K=function(e,t){var n=e.baseTag,r=e.htmlAttributes,o=e.linkTags,a=e.metaTags,i=e.noscriptTags,c=e.onChangeClientState,s=e.scriptTags,l=e.styleTags,u=e.title,d=e.titleAttributes;G(h.BODY,e.bodyAttributes),G(h.HTML,r),function(e,t){void 0!==e&&document.title!==e&&(document.title=A(e)),G(h.TITLE,t)}(u,d);var p={baseTag:W(h.BASE,n),linkTags:W(h.LINK,o),metaTags:W(h.META,a),noscriptTags:W(h.NOSCRIPT,i),scriptTags:W(h.SCRIPT,s),styleTags:W(h.STYLE,l)},f={},m={};Object.keys(p).forEach((function(e){var t=p[e],n=t.newTags,r=t.oldTags;n.length&&(f[e]=n),r.length&&(m[e]=p[e].oldTags)})),t&&t(),c(e,f,m)},Y=null,Q=function(e){function t(){for(var t,n=arguments.length,r=new Array(n),o=0;o<n;o++)r[o]=arguments[o];return(t=e.call.apply(e,[this].concat(r))||this).rendered=!1,t}f(t,e);var n=t.prototype;return n.shouldComponentUpdate=function(e){return!d()(e,this.props)},n.componentDidUpdate=function(){this.emitChange()},n.componentWillUnmount=function(){this.props.context.helmetInstances.remove(this),this.emitChange()},n.emitChange=function(){var e,t,n=this.props.context,r=n.setHelmet,o=null,a=(e=n.helmetInstances.get().map((function(e){var t=p({},e.props);return delete t.context,t})),{baseTag:D(["href"],e),bodyAttributes:E("bodyAttributes",e),defer:x(e,"defer"),encode:x(e,"encodeSpecialCharacters"),htmlAttributes:E("htmlAttributes",e),linkTags:j(h.LINK,["rel","href"],e),metaTags:j(h.META,["name","charset","http-equiv","property","itemprop"],e),noscriptTags:j(h.NOSCRIPT,["innerHTML"],e),onChangeClientState:C(e),scriptTags:j(h.SCRIPT,["src","innerHTML"],e),styleTags:j(h.STYLE,["cssText"],e),title:_(e),titleAttributes:E("titleAttributes",e),prioritizeSeoTags:O(e,"prioritizeSeoTags")});V.canUseDOM?(t=a,Y&&cancelAnimationFrame(Y),t.defer?Y=requestAnimationFrame((function(){K(t,(function(){Y=null}))})):(K(t),Y=null)):B&&(o=B(a)),r(o)},n.init=function(){this.rendered||(this.rendered=!0,this.props.context.helmetInstances.add(this),this.emitChange())},n.render=function(){return this.init(),null},t}(r.Component);Q.propTypes={context:H.isRequired},Q.displayName="HelmetDispatcher";var Z=["children"],X=["children"],J=function(e){function t(){return e.apply(this,arguments)||this}f(t,e);var n=t.prototype;return n.shouldComponentUpdate=function(e){return!c()(P(this.props,"helmetData"),P(e,"helmetData"))},n.mapNestedChildrenToProps=function(e,t){if(!t)return null;switch(e.type){case h.SCRIPT:case h.NOSCRIPT:return{innerHTML:t};case h.STYLE:return{cssText:t};default:throw new Error("<"+e.type+" /> elements are self-closing and can not contain children. Refer to our API for more information.")}},n.flattenArrayTypeChildren=function(e){var t,n=e.child,r=e.arrayTypeChildren;return p({},r,((t={})[n.type]=[].concat(r[n.type]||[],[p({},e.newChildProps,this.mapNestedChildrenToProps(n,e.nestedChildren))]),t))},n.mapObjectTypeChildren=function(e){var t,n,r=e.child,o=e.newProps,a=e.newChildProps,i=e.nestedChildren;switch(r.type){case h.TITLE:return p({},o,((t={})[r.type]=i,t.titleAttributes=p({},a),t));case h.BODY:return p({},o,{bodyAttributes:p({},a)});case h.HTML:return p({},o,{htmlAttributes:p({},a)});default:return p({},o,((n={})[r.type]=p({},a),n))}},n.mapArrayTypeChildrenToProps=function(e,t){var n=p({},t);return Object.keys(e).forEach((function(t){var r;n=p({},n,((r={})[t]=e[t],r))})),n},n.warnOnInvalidChildren=function(e,t){return l()(w.some((function(t){return e.type===t})),"function"==typeof e.type?"You may be attempting to nest <Helmet> components within each other, which is not allowed. Refer to our API for more information.":"Only elements types "+w.join(", ")+" are allowed. Helmet does not support rendering <"+e.type+"> elements. Refer to our API for more information."),l()(!t||"string"==typeof t||Array.isArray(t)&&!t.some((function(e){return"string"!=typeof e})),"Helmet expects a string as a child of <"+e.type+">. Did you forget to wrap your children in braces? ( <"+e.type+">{``}</"+e.type+"> ) Refer to our API for more information."),!0},n.mapChildrenToProps=function(e,t){var n=this,o={};return r.Children.forEach(e,(function(e){if(e&&e.props){var r=e.props,a=r.children,i=g(r,Z),c=Object.keys(i).reduce((function(e,t){return e[k[t]||t]=i[t],e}),{}),s=e.type;switch("symbol"==typeof s?s=s.toString():n.warnOnInvalidChildren(e,a),s){case h.FRAGMENT:t=n.mapChildrenToProps(a,t);break;case h.LINK:case h.META:case h.NOSCRIPT:case h.SCRIPT:case h.STYLE:o=n.flattenArrayTypeChildren({child:e,arrayTypeChildren:o,newChildProps:c,nestedChildren:a});break;default:t=n.mapObjectTypeChildren({child:e,newProps:t,newChildProps:c,nestedChildren:a})}}})),this.mapArrayTypeChildrenToProps(o,t)},n.render=function(){var e=this.props,t=e.children,n=g(e,X),o=p({},n),a=n.helmetData;return t&&(o=this.mapChildrenToProps(t,o)),!a||a instanceof $||(a=new $(a.context,a.instances)),a?r.createElement(Q,p({},o,{context:a.value,helmetData:void 0})):r.createElement(U.Consumer,null,(function(e){return r.createElement(Q,p({},o,{context:e}))}))},t}(r.Component);J.propTypes={base:a().object,bodyAttributes:a().object,children:a().oneOfType([a().arrayOf(a().node),a().node]),defaultTitle:a().string,defer:a().bool,encodeSpecialCharacters:a().bool,htmlAttributes:a().object,link:a().arrayOf(a().object),meta:a().arrayOf(a().object),noscript:a().arrayOf(a().object),onChangeClientState:a().func,script:a().arrayOf(a().object),style:a().arrayOf(a().object),title:a().string,titleAttributes:a().object,titleTemplate:a().string,prioritizeSeoTags:a().bool,helmetData:a().object},J.defaultProps={defer:!0,encodeSpecialCharacters:!0,prioritizeSeoTags:!1},J.displayName="Helmet"},2799:(e,t)=>{"use strict";var n="function"==typeof Symbol&&Symbol.for,r=n?Symbol.for("react.element"):60103,o=n?Symbol.for("react.portal"):60106,a=n?Symbol.for("react.fragment"):60107,i=n?Symbol.for("react.strict_mode"):60108,c=n?Symbol.for("react.profiler"):60114,s=n?Symbol.for("react.provider"):60109,l=n?Symbol.for("react.context"):60110,u=n?Symbol.for("react.async_mode"):60111,d=n?Symbol.for("react.concurrent_mode"):60111,p=n?Symbol.for("react.forward_ref"):60112,f=n?Symbol.for("react.suspense"):60113,m=n?Symbol.for("react.suspense_list"):60120,g=n?Symbol.for("react.memo"):60115,h=n?Symbol.for("react.lazy"):60116,b=n?Symbol.for("react.block"):60121,y=n?Symbol.for("react.fundamental"):60117,v=n?Symbol.for("react.responder"):60118,w=n?Symbol.for("react.scope"):60119;function S(e){if("object"==typeof e&&null!==e){var t=e.$$typeof;switch(t){case r:switch(e=e.type){case u:case d:case a:case c:case i:case f:return e;default:switch(e=e&&e.$$typeof){case l:case p:case h:case g:case s:return e;default:return t}}case o:return t}}}function k(e){return S(e)===d}t.AsyncMode=u,t.ConcurrentMode=d,t.ContextConsumer=l,t.ContextProvider=s,t.Element=r,t.ForwardRef=p,t.Fragment=a,t.Lazy=h,t.Memo=g,t.Portal=o,t.Profiler=c,t.StrictMode=i,t.Suspense=f,t.isAsyncMode=function(e){return k(e)||S(e)===u},t.isConcurrentMode=k,t.isContextConsumer=function(e){return S(e)===l},t.isContextProvider=function(e){return S(e)===s},t.isElement=function(e){return"object"==typeof e&&null!==e&&e.$$typeof===r},t.isForwardRef=function(e){return S(e)===p},t.isFragment=function(e){return S(e)===a},t.isLazy=function(e){return S(e)===h},t.isMemo=function(e){return S(e)===g},t.isPortal=function(e){return S(e)===o},t.isProfiler=function(e){return S(e)===c},t.isStrictMode=function(e){return S(e)===i},t.isSuspense=function(e){return S(e)===f},t.isValidElementType=function(e){return"string"==typeof e||"function"==typeof e||e===a||e===d||e===c||e===i||e===f||e===m||"object"==typeof e&&null!==e&&(e.$$typeof===h||e.$$typeof===g||e.$$typeof===s||e.$$typeof===l||e.$$typeof===p||e.$$typeof===y||e.$$typeof===v||e.$$typeof===w||e.$$typeof===b)},t.typeOf=S},4363:(e,t,n)=>{"use strict";e.exports=n(2799)},3259:(e,t,n)=>{"use strict";function r(e,t){e.prototype=Object.create(t.prototype),e.prototype.constructor=e,e.__proto__=t}function o(e){if(void 0===e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return e}function a(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function i(){return i=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var r in n)Object.prototype.hasOwnProperty.call(n,r)&&(e[r]=n[r])}return e},i.apply(this,arguments)}var c=n(6540),s=[],l=[];var u=c.createContext(null);function d(e){var t=e(),n={loading:!0,loaded:null,error:null};return n.promise=t.then((function(e){return n.loading=!1,n.loaded=e,e})).catch((function(e){throw n.loading=!1,n.error=e,e})),n}function p(e){var t={loading:!1,loaded:{},error:null},n=[];try{Object.keys(e).forEach((function(r){var o=d(e[r]);o.loading?t.loading=!0:(t.loaded[r]=o.loaded,t.error=o.error),n.push(o.promise),o.promise.then((function(e){t.loaded[r]=e})).catch((function(e){t.error=e}))}))}catch(r){t.error=r}return t.promise=Promise.all(n).then((function(e){return t.loading=!1,e})).catch((function(e){throw t.loading=!1,e})),t}function f(e,t){return c.createElement((n=e)&&n.__esModule?n.default:n,t);var n}function m(e,t){var d,p;if(!t.loading)throw new Error("react-loadable requires a `loading` component");var m=i({loader:null,loading:null,delay:200,timeout:null,render:f,webpack:null,modules:null},t),g=null;function h(){return g||(g=e(m.loader)),g.promise}return s.push(h),"function"==typeof m.webpack&&l.push((function(){if((0,m.webpack)().every((function(e){return void 0!==e&&void 0!==n.m[e]})))return h()})),p=d=function(t){function n(n){var r;return a(o(o(r=t.call(this,n)||this)),"retry",(function(){r.setState({error:null,loading:!0,timedOut:!1}),g=e(m.loader),r._loadModule()})),h(),r.state={error:g.error,pastDelay:!1,timedOut:!1,loading:g.loading,loaded:g.loaded},r}r(n,t),n.preload=function(){return h()};var i=n.prototype;return i.UNSAFE_componentWillMount=function(){this._loadModule()},i.componentDidMount=function(){this._mounted=!0},i._loadModule=function(){var e=this;if(this.context&&Array.isArray(m.modules)&&m.modules.forEach((function(t){e.context.report(t)})),g.loading){var t=function(t){e._mounted&&e.setState(t)};"number"==typeof m.delay&&(0===m.delay?this.setState({pastDelay:!0}):this._delay=setTimeout((function(){t({pastDelay:!0})}),m.delay)),"number"==typeof m.timeout&&(this._timeout=setTimeout((function(){t({timedOut:!0})}),m.timeout));var n=function(){t({error:g.error,loaded:g.loaded,loading:g.loading}),e._clearTimeouts()};g.promise.then((function(){return n(),null})).catch((function(e){return n(),null}))}},i.componentWillUnmount=function(){this._mounted=!1,this._clearTimeouts()},i._clearTimeouts=function(){clearTimeout(this._delay),clearTimeout(this._timeout)},i.render=function(){return this.state.loading||this.state.error?c.createElement(m.loading,{isLoading:this.state.loading,pastDelay:this.state.pastDelay,timedOut:this.state.timedOut,error:this.state.error,retry:this.retry}):this.state.loaded?m.render(this.state.loaded,this.props):null},n}(c.Component),a(d,"contextType",u),p}function g(e){return m(d,e)}g.Map=function(e){if("function"!=typeof e.render)throw new Error("LoadableMap requires a `render(loaded, props)` function");return m(p,e)};var h=function(e){function t(){return e.apply(this,arguments)||this}return r(t,e),t.prototype.render=function(){return c.createElement(u.Provider,{value:{report:this.props.report}},c.Children.only(this.props.children))},t}(c.Component);function b(e){for(var t=[];e.length;){var n=e.pop();t.push(n())}return Promise.all(t).then((function(){if(e.length)return b(e)}))}g.Capture=h,g.preloadAll=function(){return new Promise((function(e,t){b(s).then(e,t)}))},g.preloadReady=function(){return new Promise((function(e,t){b(l).then(e,e)}))},e.exports=g},2831:(e,t,n)=>{"use strict";n.d(t,{u:()=>i,v:()=>c});var r=n(6347),o=n(8168),a=n(6540);function i(e,t,n){return void 0===n&&(n=[]),e.some((function(e){var o=e.path?(0,r.B6)(t,e):n.length?n[n.length-1].match:r.Ix.computeRootMatch(t);return o&&(n.push({route:e,match:o}),e.routes&&i(e.routes,t,n)),o})),n}function c(e,t,n){return void 0===t&&(t={}),void 0===n&&(n={}),e?a.createElement(r.dO,n,e.map((function(e,n){return a.createElement(r.qh,{key:e.key||n,path:e.path,exact:e.exact,strict:e.strict,render:function(n){return e.render?e.render((0,o.A)({},n,{},t,{route:e})):a.createElement(e.component,(0,o.A)({},n,t,{route:e}))}})}))):null}},4625:(e,t,n)=>{"use strict";n.d(t,{I9:()=>d,Kd:()=>u,N_:()=>b,k2:()=>w});var r=n(6347),o=n(2892),a=n(6540),i=n(1513),c=n(8168),s=n(8587),l=n(1561),u=function(e){function t(){for(var t,n=arguments.length,r=new Array(n),o=0;o<n;o++)r[o]=arguments[o];return(t=e.call.apply(e,[this].concat(r))||this).history=(0,i.zR)(t.props),t}return(0,o.A)(t,e),t.prototype.render=function(){return a.createElement(r.Ix,{history:this.history,children:this.props.children})},t}(a.Component);var d=function(e){function t(){for(var t,n=arguments.length,r=new Array(n),o=0;o<n;o++)r[o]=arguments[o];return(t=e.call.apply(e,[this].concat(r))||this).history=(0,i.TM)(t.props),t}return(0,o.A)(t,e),t.prototype.render=function(){return a.createElement(r.Ix,{history:this.history,children:this.props.children})},t}(a.Component);var p=function(e,t){return"function"==typeof e?e(t):e},f=function(e,t){return"string"==typeof e?(0,i.yJ)(e,null,null,t):e},m=function(e){return e},g=a.forwardRef;void 0===g&&(g=m);var h=g((function(e,t){var n=e.innerRef,r=e.navigate,o=e.onClick,i=(0,s.A)(e,["innerRef","navigate","onClick"]),l=i.target,u=(0,c.A)({},i,{onClick:function(e){try{o&&o(e)}catch(t){throw e.preventDefault(),t}e.defaultPrevented||0!==e.button||l&&"_self"!==l||function(e){return!!(e.metaKey||e.altKey||e.ctrlKey||e.shiftKey)}(e)||(e.preventDefault(),r())}});return u.ref=m!==g&&t||n,a.createElement("a",u)}));var b=g((function(e,t){var n=e.component,o=void 0===n?h:n,u=e.replace,d=e.to,b=e.innerRef,y=(0,s.A)(e,["component","replace","to","innerRef"]);return a.createElement(r.XZ.Consumer,null,(function(e){e||(0,l.A)(!1);var n=e.history,r=f(p(d,e.location),e.location),s=r?n.createHref(r):"",h=(0,c.A)({},y,{href:s,navigate:function(){var t=p(d,e.location),r=(0,i.AO)(e.location)===(0,i.AO)(f(t));(u||r?n.replace:n.push)(t)}});return m!==g?h.ref=t||b:h.innerRef=b,a.createElement(o,h)}))})),y=function(e){return e},v=a.forwardRef;void 0===v&&(v=y);var w=v((function(e,t){var n=e["aria-current"],o=void 0===n?"page":n,i=e.activeClassName,u=void 0===i?"active":i,d=e.activeStyle,m=e.className,g=e.exact,h=e.isActive,w=e.location,S=e.sensitive,k=e.strict,x=e.style,_=e.to,C=e.innerRef,E=(0,s.A)(e,["aria-current","activeClassName","activeStyle","className","exact","isActive","location","sensitive","strict","style","to","innerRef"]);return a.createElement(r.XZ.Consumer,null,(function(e){e||(0,l.A)(!1);var n=w||e.location,i=f(p(_,n),n),s=i.pathname,D=s&&s.replace(/([.+*?=^!:${}()[\]|/\\])/g,"\\$1"),j=D?(0,r.B6)(n.pathname,{path:D,exact:g,sensitive:S,strict:k}):null,O=!!(h?h(j,n):j),A="function"==typeof m?m(O):m,T="function"==typeof x?x(O):x;O&&(A=function(){for(var e=arguments.length,t=new Array(e),n=0;n<e;n++)t[n]=arguments[n];return t.filter((function(e){return e})).join(" ")}(A,u),T=(0,c.A)({},T,d));var P=(0,c.A)({"aria-current":O&&o||null,className:A,style:T,to:i},E);return y!==v?P.ref=t||C:P.innerRef=C,a.createElement(b,P)}))}))},6347:(e,t,n)=>{"use strict";n.d(t,{B6:()=>x,Ix:()=>v,W6:()=>P,XZ:()=>y,dO:()=>A,qh:()=>_,zy:()=>I});var r=n(2892),o=n(6540),a=n(5556),i=n.n(a),c=n(1513),s=n(1561),l=n(8168),u=n(5302),d=n.n(u),p=(n(4363),n(8587)),f=(n(4146),1073741823),m="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof window?window:void 0!==n.g?n.g:{};var g=o.createContext||function(e,t){var n,a,c="__create-react-context-"+function(){var e="__global_unique_id__";return m[e]=(m[e]||0)+1}()+"__",s=function(e){function n(){for(var t,n,r,o=arguments.length,a=new Array(o),i=0;i<o;i++)a[i]=arguments[i];return(t=e.call.apply(e,[this].concat(a))||this).emitter=(n=t.props.value,r=[],{on:function(e){r.push(e)},off:function(e){r=r.filter((function(t){return t!==e}))},get:function(){return n},set:function(e,t){n=e,r.forEach((function(e){return e(n,t)}))}}),t}(0,r.A)(n,e);var o=n.prototype;return o.getChildContext=function(){var e;return(e={})[c]=this.emitter,e},o.componentWillReceiveProps=function(e){if(this.props.value!==e.value){var n,r=this.props.value,o=e.value;((a=r)===(i=o)?0!==a||1/a==1/i:a!=a&&i!=i)?n=0:(n="function"==typeof t?t(r,o):f,0!==(n|=0)&&this.emitter.set(e.value,n))}var a,i},o.render=function(){return this.props.children},n}(o.Component);s.childContextTypes=((n={})[c]=i().object.isRequired,n);var l=function(t){function n(){for(var e,n=arguments.length,r=new Array(n),o=0;o<n;o++)r[o]=arguments[o];return(e=t.call.apply(t,[this].concat(r))||this).observedBits=void 0,e.state={value:e.getValue()},e.onUpdate=function(t,n){(0|e.observedBits)&n&&e.setState({value:e.getValue()})},e}(0,r.A)(n,t);var o=n.prototype;return o.componentWillReceiveProps=function(e){var t=e.observedBits;this.observedBits=null==t?f:t},o.componentDidMount=function(){this.context[c]&&this.context[c].on(this.onUpdate);var e=this.props.observedBits;this.observedBits=null==e?f:e},o.componentWillUnmount=function(){this.context[c]&&this.context[c].off(this.onUpdate)},o.getValue=function(){return this.context[c]?this.context[c].get():e},o.render=function(){return(e=this.props.children,Array.isArray(e)?e[0]:e)(this.state.value);var e},n}(o.Component);return l.contextTypes=((a={})[c]=i().object,a),{Provider:s,Consumer:l}},h=function(e){var t=g();return t.displayName=e,t},b=h("Router-History"),y=h("Router"),v=function(e){function t(t){var n;return(n=e.call(this,t)||this).state={location:t.history.location},n._isMounted=!1,n._pendingLocation=null,t.staticContext||(n.unlisten=t.history.listen((function(e){n._pendingLocation=e}))),n}(0,r.A)(t,e),t.computeRootMatch=function(e){return{path:"/",url:"/",params:{},isExact:"/"===e}};var n=t.prototype;return n.componentDidMount=function(){var e=this;this._isMounted=!0,this.unlisten&&this.unlisten(),this.props.staticContext||(this.unlisten=this.props.history.listen((function(t){e._isMounted&&e.setState({location:t})}))),this._pendingLocation&&this.setState({location:this._pendingLocation})},n.componentWillUnmount=function(){this.unlisten&&(this.unlisten(),this._isMounted=!1,this._pendingLocation=null)},n.render=function(){return o.createElement(y.Provider,{value:{history:this.props.history,location:this.state.location,match:t.computeRootMatch(this.state.location.pathname),staticContext:this.props.staticContext}},o.createElement(b.Provider,{children:this.props.children||null,value:this.props.history}))},t}(o.Component);o.Component;o.Component;var w={},S=1e4,k=0;function x(e,t){void 0===t&&(t={}),("string"==typeof t||Array.isArray(t))&&(t={path:t});var n=t,r=n.path,o=n.exact,a=void 0!==o&&o,i=n.strict,c=void 0!==i&&i,s=n.sensitive,l=void 0!==s&&s;return[].concat(r).reduce((function(t,n){if(!n&&""!==n)return null;if(t)return t;var r=function(e,t){var n=""+t.end+t.strict+t.sensitive,r=w[n]||(w[n]={});if(r[e])return r[e];var o=[],a={regexp:d()(e,o,t),keys:o};return k<S&&(r[e]=a,k++),a}(n,{end:a,strict:c,sensitive:l}),o=r.regexp,i=r.keys,s=o.exec(e);if(!s)return null;var u=s[0],p=s.slice(1),f=e===u;return a&&!f?null:{path:n,url:"/"===n&&""===u?"/":u,isExact:f,params:i.reduce((function(e,t,n){return e[t.name]=p[n],e}),{})}}),null)}var _=function(e){function t(){return e.apply(this,arguments)||this}return(0,r.A)(t,e),t.prototype.render=function(){var e=this;return o.createElement(y.Consumer,null,(function(t){t||(0,s.A)(!1);var n=e.props.location||t.location,r=e.props.computedMatch?e.props.computedMatch:e.props.path?x(n.pathname,e.props):t.match,a=(0,l.A)({},t,{location:n,match:r}),i=e.props,c=i.children,u=i.component,d=i.render;return Array.isArray(c)&&function(e){return 0===o.Children.count(e)}(c)&&(c=null),o.createElement(y.Provider,{value:a},a.match?c?"function"==typeof c?c(a):c:u?o.createElement(u,a):d?d(a):null:"function"==typeof c?c(a):null)}))},t}(o.Component);function C(e){return"/"===e.charAt(0)?e:"/"+e}function E(e,t){if(!e)return t;var n=C(e);return 0!==t.pathname.indexOf(n)?t:(0,l.A)({},t,{pathname:t.pathname.substr(n.length)})}function D(e){return"string"==typeof e?e:(0,c.AO)(e)}function j(e){return function(){(0,s.A)(!1)}}function O(){}o.Component;var A=function(e){function t(){return e.apply(this,arguments)||this}return(0,r.A)(t,e),t.prototype.render=function(){var e=this;return o.createElement(y.Consumer,null,(function(t){t||(0,s.A)(!1);var n,r,a=e.props.location||t.location;return o.Children.forEach(e.props.children,(function(e){if(null==r&&o.isValidElement(e)){n=e;var i=e.props.path||e.props.from;r=i?x(a.pathname,(0,l.A)({},e.props,{path:i})):t.match}})),r?o.cloneElement(n,{location:a,computedMatch:r}):null}))},t}(o.Component);var T=o.useContext;function P(){return T(b)}function I(){return T(y).location}},1020:(e,t,n)=>{"use strict";var r=n(6540),o=Symbol.for("react.element"),a=Symbol.for("react.fragment"),i=Object.prototype.hasOwnProperty,c=r.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.ReactCurrentOwner,s={key:!0,ref:!0,__self:!0,__source:!0};function l(e,t,n){var r,a={},l=null,u=null;for(r in void 0!==n&&(l=""+n),void 0!==t.key&&(l=""+t.key),void 0!==t.ref&&(u=t.ref),t)i.call(t,r)&&!s.hasOwnProperty(r)&&(a[r]=t[r]);if(e&&e.defaultProps)for(r in t=e.defaultProps)void 0===a[r]&&(a[r]=t[r]);return{$$typeof:o,type:e,key:l,ref:u,props:a,_owner:c.current}}t.Fragment=a,t.jsx=l,t.jsxs=l},5287:(e,t)=>{"use strict";var n=Symbol.for("react.element"),r=Symbol.for("react.portal"),o=Symbol.for("react.fragment"),a=Symbol.for("react.strict_mode"),i=Symbol.for("react.profiler"),c=Symbol.for("react.provider"),s=Symbol.for("react.context"),l=Symbol.for("react.forward_ref"),u=Symbol.for("react.suspense"),d=Symbol.for("react.memo"),p=Symbol.for("react.lazy"),f=Symbol.iterator;var m={isMounted:function(){return!1},enqueueForceUpdate:function(){},enqueueReplaceState:function(){},enqueueSetState:function(){}},g=Object.assign,h={};function b(e,t,n){this.props=e,this.context=t,this.refs=h,this.updater=n||m}function y(){}function v(e,t,n){this.props=e,this.context=t,this.refs=h,this.updater=n||m}b.prototype.isReactComponent={},b.prototype.setState=function(e,t){if("object"!=typeof e&&"function"!=typeof e&&null!=e)throw Error("setState(...): takes an object of state variables to update or a function which returns an object of state variables.");this.updater.enqueueSetState(this,e,t,"setState")},b.prototype.forceUpdate=function(e){this.updater.enqueueForceUpdate(this,e,"forceUpdate")},y.prototype=b.prototype;var w=v.prototype=new y;w.constructor=v,g(w,b.prototype),w.isPureReactComponent=!0;var S=Array.isArray,k=Object.prototype.hasOwnProperty,x={current:null},_={key:!0,ref:!0,__self:!0,__source:!0};function C(e,t,r){var o,a={},i=null,c=null;if(null!=t)for(o in void 0!==t.ref&&(c=t.ref),void 0!==t.key&&(i=""+t.key),t)k.call(t,o)&&!_.hasOwnProperty(o)&&(a[o]=t[o]);var s=arguments.length-2;if(1===s)a.children=r;else if(1<s){for(var l=Array(s),u=0;u<s;u++)l[u]=arguments[u+2];a.children=l}if(e&&e.defaultProps)for(o in s=e.defaultProps)void 0===a[o]&&(a[o]=s[o]);return{$$typeof:n,type:e,key:i,ref:c,props:a,_owner:x.current}}function E(e){return"object"==typeof e&&null!==e&&e.$$typeof===n}var D=/\/+/g;function j(e,t){return"object"==typeof e&&null!==e&&null!=e.key?function(e){var t={"=":"=0",":":"=2"};return"$"+e.replace(/[=:]/g,(function(e){return t[e]}))}(""+e.key):t.toString(36)}function O(e,t,o,a,i){var c=typeof e;"undefined"!==c&&"boolean"!==c||(e=null);var s=!1;if(null===e)s=!0;else switch(c){case"string":case"number":s=!0;break;case"object":switch(e.$$typeof){case n:case r:s=!0}}if(s)return i=i(s=e),e=""===a?"."+j(s,0):a,S(i)?(o="",null!=e&&(o=e.replace(D,"$&/")+"/"),O(i,t,o,"",(function(e){return e}))):null!=i&&(E(i)&&(i=function(e,t){return{$$typeof:n,type:e.type,key:t,ref:e.ref,props:e.props,_owner:e._owner}}(i,o+(!i.key||s&&s.key===i.key?"":(""+i.key).replace(D,"$&/")+"/")+e)),t.push(i)),1;if(s=0,a=""===a?".":a+":",S(e))for(var l=0;l<e.length;l++){var u=a+j(c=e[l],l);s+=O(c,t,o,u,i)}else if(u=function(e){return null===e||"object"!=typeof e?null:"function"==typeof(e=f&&e[f]||e["@@iterator"])?e:null}(e),"function"==typeof u)for(e=u.call(e),l=0;!(c=e.next()).done;)s+=O(c=c.value,t,o,u=a+j(c,l++),i);else if("object"===c)throw t=String(e),Error("Objects are not valid as a React child (found: "+("[object Object]"===t?"object with keys {"+Object.keys(e).join(", ")+"}":t)+"). If you meant to render a collection of children, use an array instead.");return s}function A(e,t,n){if(null==e)return e;var r=[],o=0;return O(e,r,"","",(function(e){return t.call(n,e,o++)})),r}function T(e){if(-1===e._status){var t=e._result;(t=t()).then((function(t){0!==e._status&&-1!==e._status||(e._status=1,e._result=t)}),(function(t){0!==e._status&&-1!==e._status||(e._status=2,e._result=t)})),-1===e._status&&(e._status=0,e._result=t)}if(1===e._status)return e._result.default;throw e._result}var P={current:null},I={transition:null},N={ReactCurrentDispatcher:P,ReactCurrentBatchConfig:I,ReactCurrentOwner:x};function R(){throw Error("act(...) is not supported in production builds of React.")}t.Children={map:A,forEach:function(e,t,n){A(e,(function(){t.apply(this,arguments)}),n)},count:function(e){var t=0;return A(e,(function(){t++})),t},toArray:function(e){return A(e,(function(e){return e}))||[]},only:function(e){if(!E(e))throw Error("React.Children.only expected to receive a single React element child.");return e}},t.Component=b,t.Fragment=o,t.Profiler=i,t.PureComponent=v,t.StrictMode=a,t.Suspense=u,t.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED=N,t.act=R,t.cloneElement=function(e,t,r){if(null==e)throw Error("React.cloneElement(...): The argument must be a React element, but you passed "+e+".");var o=g({},e.props),a=e.key,i=e.ref,c=e._owner;if(null!=t){if(void 0!==t.ref&&(i=t.ref,c=x.current),void 0!==t.key&&(a=""+t.key),e.type&&e.type.defaultProps)var s=e.type.defaultProps;for(l in t)k.call(t,l)&&!_.hasOwnProperty(l)&&(o[l]=void 0===t[l]&&void 0!==s?s[l]:t[l])}var l=arguments.length-2;if(1===l)o.children=r;else if(1<l){s=Array(l);for(var u=0;u<l;u++)s[u]=arguments[u+2];o.children=s}return{$$typeof:n,type:e.type,key:a,ref:i,props:o,_owner:c}},t.createContext=function(e){return(e={$$typeof:s,_currentValue:e,_currentValue2:e,_threadCount:0,Provider:null,Consumer:null,_defaultValue:null,_globalName:null}).Provider={$$typeof:c,_context:e},e.Consumer=e},t.createElement=C,t.createFactory=function(e){var t=C.bind(null,e);return t.type=e,t},t.createRef=function(){return{current:null}},t.forwardRef=function(e){return{$$typeof:l,render:e}},t.isValidElement=E,t.lazy=function(e){return{$$typeof:p,_payload:{_status:-1,_result:e},_init:T}},t.memo=function(e,t){return{$$typeof:d,type:e,compare:void 0===t?null:t}},t.startTransition=function(e){var t=I.transition;I.transition={};try{e()}finally{I.transition=t}},t.unstable_act=R,t.useCallback=function(e,t){return P.current.useCallback(e,t)},t.useContext=function(e){return P.current.useContext(e)},t.useDebugValue=function(){},t.useDeferredValue=function(e){return P.current.useDeferredValue(e)},t.useEffect=function(e,t){return P.current.useEffect(e,t)},t.useId=function(){return P.current.useId()},t.useImperativeHandle=function(e,t,n){return P.current.useImperativeHandle(e,t,n)},t.useInsertionEffect=function(e,t){return P.current.useInsertionEffect(e,t)},t.useLayoutEffect=function(e,t){return P.current.useLayoutEffect(e,t)},t.useMemo=function(e,t){return P.current.useMemo(e,t)},t.useReducer=function(e,t,n){return P.current.useReducer(e,t,n)},t.useRef=function(e){return P.current.useRef(e)},t.useState=function(e){return P.current.useState(e)},t.useSyncExternalStore=function(e,t,n){return P.current.useSyncExternalStore(e,t,n)},t.useTransition=function(){return P.current.useTransition()},t.version="18.3.1"},6540:(e,t,n)=>{"use strict";e.exports=n(5287)},4848:(e,t,n)=>{"use strict";e.exports=n(1020)},7463:(e,t)=>{"use strict";function n(e,t){var n=e.length;e.push(t);e:for(;0<n;){var r=n-1>>>1,o=e[r];if(!(0<a(o,t)))break e;e[r]=t,e[n]=o,n=r}}function r(e){return 0===e.length?null:e[0]}function o(e){if(0===e.length)return null;var t=e[0],n=e.pop();if(n!==t){e[0]=n;e:for(var r=0,o=e.length,i=o>>>1;r<i;){var c=2*(r+1)-1,s=e[c],l=c+1,u=e[l];if(0>a(s,n))l<o&&0>a(u,s)?(e[r]=u,e[l]=n,r=l):(e[r]=s,e[c]=n,r=c);else{if(!(l<o&&0>a(u,n)))break e;e[r]=u,e[l]=n,r=l}}}return t}function a(e,t){var n=e.sortIndex-t.sortIndex;return 0!==n?n:e.id-t.id}if("object"==typeof performance&&"function"==typeof performance.now){var i=performance;t.unstable_now=function(){return i.now()}}else{var c=Date,s=c.now();t.unstable_now=function(){return c.now()-s}}var l=[],u=[],d=1,p=null,f=3,m=!1,g=!1,h=!1,b="function"==typeof setTimeout?setTimeout:null,y="function"==typeof clearTimeout?clearTimeout:null,v="undefined"!=typeof setImmediate?setImmediate:null;function w(e){for(var t=r(u);null!==t;){if(null===t.callback)o(u);else{if(!(t.startTime<=e))break;o(u),t.sortIndex=t.expirationTime,n(l,t)}t=r(u)}}function S(e){if(h=!1,w(e),!g)if(null!==r(l))g=!0,I(k);else{var t=r(u);null!==t&&N(S,t.startTime-e)}}function k(e,n){g=!1,h&&(h=!1,y(E),E=-1),m=!0;var a=f;try{for(w(n),p=r(l);null!==p&&(!(p.expirationTime>n)||e&&!O());){var i=p.callback;if("function"==typeof i){p.callback=null,f=p.priorityLevel;var c=i(p.expirationTime<=n);n=t.unstable_now(),"function"==typeof c?p.callback=c:p===r(l)&&o(l),w(n)}else o(l);p=r(l)}if(null!==p)var s=!0;else{var d=r(u);null!==d&&N(S,d.startTime-n),s=!1}return s}finally{p=null,f=a,m=!1}}"undefined"!=typeof navigator&&void 0!==navigator.scheduling&&void 0!==navigator.scheduling.isInputPending&&navigator.scheduling.isInputPending.bind(navigator.scheduling);var x,_=!1,C=null,E=-1,D=5,j=-1;function O(){return!(t.unstable_now()-j<D)}function A(){if(null!==C){var e=t.unstable_now();j=e;var n=!0;try{n=C(!0,e)}finally{n?x():(_=!1,C=null)}}else _=!1}if("function"==typeof v)x=function(){v(A)};else if("undefined"!=typeof MessageChannel){var T=new MessageChannel,P=T.port2;T.port1.onmessage=A,x=function(){P.postMessage(null)}}else x=function(){b(A,0)};function I(e){C=e,_||(_=!0,x())}function N(e,n){E=b((function(){e(t.unstable_now())}),n)}t.unstable_IdlePriority=5,t.unstable_ImmediatePriority=1,t.unstable_LowPriority=4,t.unstable_NormalPriority=3,t.unstable_Profiling=null,t.unstable_UserBlockingPriority=2,t.unstable_cancelCallback=function(e){e.callback=null},t.unstable_continueExecution=function(){g||m||(g=!0,I(k))},t.unstable_forceFrameRate=function(e){0>e||125<e?console.error("forceFrameRate takes a positive int between 0 and 125, forcing frame rates higher than 125 fps is not supported"):D=0<e?Math.floor(1e3/e):5},t.unstable_getCurrentPriorityLevel=function(){return f},t.unstable_getFirstCallbackNode=function(){return r(l)},t.unstable_next=function(e){switch(f){case 1:case 2:case 3:var t=3;break;default:t=f}var n=f;f=t;try{return e()}finally{f=n}},t.unstable_pauseExecution=function(){},t.unstable_requestPaint=function(){},t.unstable_runWithPriority=function(e,t){switch(e){case 1:case 2:case 3:case 4:case 5:break;default:e=3}var n=f;f=e;try{return t()}finally{f=n}},t.unstable_scheduleCallback=function(e,o,a){var i=t.unstable_now();switch("object"==typeof a&&null!==a?a="number"==typeof(a=a.delay)&&0<a?i+a:i:a=i,e){case 1:var c=-1;break;case 2:c=250;break;case 5:c=1073741823;break;case 4:c=1e4;break;default:c=5e3}return e={id:d++,callback:o,priorityLevel:e,startTime:a,expirationTime:c=a+c,sortIndex:-1},a>i?(e.sortIndex=a,n(u,e),null===r(l)&&e===r(u)&&(h?(y(E),E=-1):h=!0,N(S,a-i))):(e.sortIndex=c,n(l,e),g||m||(g=!0,I(k))),e},t.unstable_shouldYield=O,t.unstable_wrapCallback=function(e){var t=f;return function(){var n=f;f=t;try{return e.apply(this,arguments)}finally{f=n}}}},9982:(e,t,n)=>{"use strict";e.exports=n(7463)},2833:e=>{e.exports=function(e,t,n,r){var o=n?n.call(r,e,t):void 0;if(void 0!==o)return!!o;if(e===t)return!0;if("object"!=typeof e||!e||"object"!=typeof t||!t)return!1;var a=Object.keys(e),i=Object.keys(t);if(a.length!==i.length)return!1;for(var c=Object.prototype.hasOwnProperty.bind(t),s=0;s<a.length;s++){var l=a[s];if(!c(l))return!1;var u=e[l],d=t[l];if(!1===(o=n?n.call(r,u,d,l):void 0)||void 0===o&&u!==d)return!1}return!0}},4784:(e,t,n)=>{"use strict";n.r(t),n.d(t,{default:()=>r});const r={title:"Cadence",tagline:"Orchestrate with Confidence: The Open-Source Workflow Engine for Tomorrow",favicon:"img/favicon.ico",url:"https://cadenceworkflow.io",baseUrl:"/Cadence-Docs/",organizationName:"cadence-workflow",projectName:"Cadence-Docs",trailingSlash:!1,onBrokenLinks:"throw",onBrokenMarkdownLinks:"warn",i18n:{defaultLocale:"en",locales:["en"],path:"i18n",localeConfigs:{}},presets:[["@docusaurus/preset-classic",{docs:{sidebarPath:"./sidebars.ts",editUrl:"https://github.com/cadence-workflow/Cadence-Docs/tree/master/",remarkPlugins:[null]},blog:{blogTitle:"Cadence Blog",blogDescription:"The latest news and updates from the Cadence team",showReadingTime:!0,feedOptions:{type:["rss","atom"],xslt:!0},blogSidebarTitle:"Recent Posts",editUrl:"https://github.com/cadence-workflow/Cadence-Docs/tree/master/",onInlineTags:"warn",onInlineAuthors:"warn",onUntruncatedBlogPosts:"warn",blogSidebarCount:"ALL"},theme:{customCss:"./src/css/custom.css"},googleTagManager:{containerId:"G-W63QD8QE6E"},gtag:{trackingID:"G-W63QD8QE6E",anonymizeIP:!0}}]],plugins:[["./src/plugins/changelog/index.js",{blogTitle:"Cadence changelog",blogDescription:"Keep yourself up-to-date about new features in every release",blogSidebarCount:"ALL",blogSidebarTitle:"Changelog",routeBasePath:"/changelog",showReadingTime:!1,postsPerPage:20,archiveBasePath:null,authorsMapPath:"authors.json",feedOptions:{type:"all",title:"Cadence Docs changelog",description:"Keep yourself up-to-date about new features in every release",copyright:"Copyright \xa9 2024 Uber Technologies, Inc.",language:"en"},onInlineAuthors:"warn"}],["@docusaurus/plugin-content-docs",{id:"community",path:"community",routeBasePath:"community",editUrl:"https://github.com/cadence-workflow/Cadence-Docs/edit/master/",remarkPlugins:[null],sidebarPath:"./sidebarsCommunity.js",showLastUpdateAuthor:!0,showLastUpdateTime:!0}],["@docusaurus/plugin-client-redirects",{fromExtensions:["html"],redirects:[{from:["/docs/support","/docs/next/support"],to:"/community/support"},{from:["/docs/team","/docs/next/team"],to:"/community/team"},{from:["/docs/resources","/docs/next/resources"],to:"/community/resources"}]}]],themeConfig:{announcementBar:{id:"survey_announcement",content:'We are looking to hear your feedback, please fill the <a target="_blank" rel="noopener noreferrer" href="https://www.surveymonkey.com/r/9RL7YX9">Cadence 2024 OSS community survey</a>',backgroundColor:"#fafbfc",textColor:"#091E42",isCloseable:!0},algolia:{appId:"J7SVDVT89Z",apiKey:"e96333af9178875d6417a55ac276d718",indexName:"cadenceworkflow",contextualSearch:!1,externalUrlRegex:"external\\.com|domain\\.com",searchParameters:{},searchPagePath:"search",insights:!0},image:"img/social-card-min.jpg",navbar:{title:"",logo:{alt:"Cadence Logo",src:"img/cadence-logo.svg",srcDark:"img/logo-white.svg"},items:[{type:"docSidebar",sidebarId:"docsSidebar",position:"left",label:"Docs"},{to:"/blog",label:"Blog",position:"left"},{to:"/community/support",label:"Community",position:"left",activeBaseRegex:"/community/"},{type:"dropdown",position:"right",label:"Repositories",items:[{label:"Cadence Service",href:"https://github.com/cadence-workflow/cadence"},{label:"Go Client",href:"https://github.com/cadence-workflow/cadence-go-client"},{label:"Java Client",href:"https://github.com/cadence-workflow/cadence-java-client"},{label:"Go Samples",href:"https://github.com/cadence-workflow/cadence-samples"},{label:"Java Samples",href:"https://github.com/cadence-workflow/cadence-java-samples"},{label:"Cadence Web",href:"https://github.com/cadence-workflow/cadence-web"},{label:"Cadence IDLs",href:"https://github.com/cadence-workflow/cadence-idl"},{label:"Helm Charts",href:"https://github.com/cadence-workflow/cadence-charts"}]}],hideOnScroll:!1},footer:{style:"dark",links:[{title:"Docs",items:[{label:"Getting Started",to:"docs/get-started/"},{label:"Go Client",to:"docs/go-client/"},{label:"Java Client",to:"docs/java-client/"},{label:"Command Line Interface",to:"docs/cli/"},{label:"Operation Guide",to:"docs/operation-guide/"}]},{title:"Community",items:[{label:"Stack Overflow",href:"https://stackoverflow.com/questions/tagged/cadence-workflow+uber-cadence"},{label:"Cadence Community Slack",href:"http://t.uber.com/cadence-slack"},{label:"LinkedIn",href:"https://www.linkedin.com/company/cadenceworkflow/"}]},{title:"More",items:[{label:"Blog",to:"/blog"},{label:"GitHub",href:"https://github.com/cadence-workflow/cadence"}]}],copyright:"Copyright \xa9 2024 Uber Technologies, Inc."},prism:{theme:{plain:{color:"#393A34",backgroundColor:"#f6f8fa"},styles:[{types:["comment","prolog","doctype","cdata"],style:{color:"#999988",fontStyle:"italic"}},{types:["namespace"],style:{opacity:.7}},{types:["string","attr-value"],style:{color:"#e3116c"}},{types:["punctuation","operator"],style:{color:"#393A34"}},{types:["entity","url","symbol","number","boolean","variable","constant","property","regex","inserted"],style:{color:"#36acaa"}},{types:["atrule","keyword","attr-name","selector"],style:{color:"#00a4db"}},{types:["function","deleted","tag"],style:{color:"#d73a49"}},{types:["function-variable"],style:{color:"#6f42c1"}},{types:["tag","selector","keyword"],style:{color:"#00009f"}}]},darkTheme:{plain:{color:"#F8F8F2",backgroundColor:"#282A36"},styles:[{types:["prolog","constant","builtin"],style:{color:"rgb(189, 147, 249)"}},{types:["inserted","function"],style:{color:"rgb(80, 250, 123)"}},{types:["deleted"],style:{color:"rgb(255, 85, 85)"}},{types:["changed"],style:{color:"rgb(255, 184, 108)"}},{types:["punctuation","symbol"],style:{color:"rgb(248, 248, 242)"}},{types:["string","char","tag","selector"],style:{color:"rgb(255, 121, 198)"}},{types:["keyword","variable"],style:{color:"rgb(189, 147, 249)",fontStyle:"italic"}},{types:["comment"],style:{color:"rgb(98, 114, 164)"}},{types:["attr-name"],style:{color:"rgb(241, 250, 140)"}}]},additionalLanguages:["go","java","bash","markup","json","shell-session","yaml","gradle","log"],magicComments:[{className:"theme-code-block-highlighted-line",line:"highlight-next-line",block:{start:"highlight-start",end:"highlight-end"}}]},colorMode:{defaultMode:"light",disableSwitch:!1,respectPrefersColorScheme:!1},docs:{versionPersistence:"localStorage",sidebar:{hideable:!1,autoCollapseCategories:!1}},blog:{sidebar:{groupByYear:!0}},metadata:[],tableOfContents:{minHeadingLevel:2,maxHeadingLevel:3}},baseUrlIssueBanner:!0,future:{experimental_faster:{swcJsLoader:!1,swcJsMinimizer:!1,swcHtmlMinimizer:!1,lightningCssMinimizer:!1,mdxCrossCompilerCache:!1,rspackBundler:!1},experimental_storage:{type:"localStorage",namespace:!1},experimental_router:"browser"},onBrokenAnchors:"warn",onDuplicateRoutes:"warn",staticDirectories:["static"],customFields:{},themes:[],scripts:[],headTags:[],stylesheets:[],clientModules:[],titleDelimiter:"|",noIndex:!1,markdown:{format:"mdx",mermaid:!1,mdx1Compat:{comments:!0,admonitions:!0,headingIds:!0},anchors:{maintainCase:!1}}}},8168:(e,t,n)=>{"use strict";function r(){return r=Object.assign?Object.assign.bind():function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var r in n)({}).hasOwnProperty.call(n,r)&&(e[r]=n[r])}return e},r.apply(null,arguments)}n.d(t,{A:()=>r})},2892:(e,t,n)=>{"use strict";function r(e,t){return r=Object.setPrototypeOf?Object.setPrototypeOf.bind():function(e,t){return e.__proto__=t,e},r(e,t)}function o(e,t){e.prototype=Object.create(t.prototype),e.prototype.constructor=e,r(e,t)}n.d(t,{A:()=>o})},8587:(e,t,n)=>{"use strict";function r(e,t){if(null==e)return{};var n={};for(var r in e)if({}.hasOwnProperty.call(e,r)){if(t.includes(r))continue;n[r]=e[r]}return n}n.d(t,{A:()=>r})},4164:(e,t,n)=>{"use strict";function r(e){var t,n,o="";if("string"==typeof e||"number"==typeof e)o+=e;else if("object"==typeof e)if(Array.isArray(e)){var a=e.length;for(t=0;t<a;t++)e[t]&&(n=r(e[t]))&&(o&&(o+=" "),o+=n)}else for(n in e)e[n]&&(o&&(o+=" "),o+=n);return o}n.d(t,{A:()=>o});const o=function(){for(var e,t,n=0,o="",a=arguments.length;n<a;n++)(e=arguments[n])&&(t=r(e))&&(o&&(o+=" "),o+=t);return o}},1765:(e,t,n)=>{"use strict";n.d(t,{My:()=>S,f4:()=>Q});var r,o,a=n(6540),i=n(4164),c=Object.create,s=Object.defineProperty,l=Object.defineProperties,u=Object.getOwnPropertyDescriptor,d=Object.getOwnPropertyDescriptors,p=Object.getOwnPropertyNames,f=Object.getOwnPropertySymbols,m=Object.getPrototypeOf,g=Object.prototype.hasOwnProperty,h=Object.prototype.propertyIsEnumerable,b=(e,t,n)=>t in e?s(e,t,{enumerable:!0,configurable:!0,writable:!0,value:n}):e[t]=n,y=(e,t)=>{for(var n in t||(t={}))g.call(t,n)&&b(e,n,t[n]);if(f)for(var n of f(t))h.call(t,n)&&b(e,n,t[n]);return e},v=(e,t)=>l(e,d(t)),w=(e,t)=>{var n={};for(var r in e)g.call(e,r)&&t.indexOf(r)<0&&(n[r]=e[r]);if(null!=e&&f)for(var r of f(e))t.indexOf(r)<0&&h.call(e,r)&&(n[r]=e[r]);return n},S=((e,t,n)=>(n=null!=e?c(m(e)):{},((e,t,n,r)=>{if(t&&"object"==typeof t||"function"==typeof t)for(let o of p(t))g.call(e,o)||o===n||s(e,o,{get:()=>t[o],enumerable:!(r=u(t,o))||r.enumerable});return e})(!t&&e&&e.__esModule?n:s(n,"default",{value:e,enumerable:!0}),e)))((r={"../../node_modules/.pnpm/prismjs@1.29.0_patch_hash=vrxx3pzkik6jpmgpayxfjunetu/node_modules/prismjs/prism.js"(e,t){var n=function(){var e=/(?:^|\s)lang(?:uage)?-([\w-]+)(?=\s|$)/i,t=0,n={},r={util:{encode:function e(t){return t instanceof o?new o(t.type,e(t.content),t.alias):Array.isArray(t)?t.map(e):t.replace(/&/g,"&").replace(/</g,"<").replace(/\u00a0/g," ")},type:function(e){return Object.prototype.toString.call(e).slice(8,-1)},objId:function(e){return e.__id||Object.defineProperty(e,"__id",{value:++t}),e.__id},clone:function e(t,n){var o,a;switch(n=n||{},r.util.type(t)){case"Object":if(a=r.util.objId(t),n[a])return n[a];for(var i in o={},n[a]=o,t)t.hasOwnProperty(i)&&(o[i]=e(t[i],n));return o;case"Array":return a=r.util.objId(t),n[a]?n[a]:(o=[],n[a]=o,t.forEach((function(t,r){o[r]=e(t,n)})),o);default:return t}},getLanguage:function(t){for(;t;){var n=e.exec(t.className);if(n)return n[1].toLowerCase();t=t.parentElement}return"none"},setLanguage:function(t,n){t.className=t.className.replace(RegExp(e,"gi"),""),t.classList.add("language-"+n)},isActive:function(e,t,n){for(var r="no-"+t;e;){var o=e.classList;if(o.contains(t))return!0;if(o.contains(r))return!1;e=e.parentElement}return!!n}},languages:{plain:n,plaintext:n,text:n,txt:n,extend:function(e,t){var n=r.util.clone(r.languages[e]);for(var o in t)n[o]=t[o];return n},insertBefore:function(e,t,n,o){var a=(o=o||r.languages)[e],i={};for(var c in a)if(a.hasOwnProperty(c)){if(c==t)for(var s in n)n.hasOwnProperty(s)&&(i[s]=n[s]);n.hasOwnProperty(c)||(i[c]=a[c])}var l=o[e];return o[e]=i,r.languages.DFS(r.languages,(function(t,n){n===l&&t!=e&&(this[t]=i)})),i},DFS:function e(t,n,o,a){a=a||{};var i=r.util.objId;for(var c in t)if(t.hasOwnProperty(c)){n.call(t,c,t[c],o||c);var s=t[c],l=r.util.type(s);"Object"!==l||a[i(s)]?"Array"!==l||a[i(s)]||(a[i(s)]=!0,e(s,n,c,a)):(a[i(s)]=!0,e(s,n,null,a))}}},plugins:{},highlight:function(e,t,n){var a={code:e,grammar:t,language:n};if(r.hooks.run("before-tokenize",a),!a.grammar)throw new Error('The language "'+a.language+'" has no grammar.');return a.tokens=r.tokenize(a.code,a.grammar),r.hooks.run("after-tokenize",a),o.stringify(r.util.encode(a.tokens),a.language)},tokenize:function(e,t){var n=t.rest;if(n){for(var r in n)t[r]=n[r];delete t.rest}var o=new c;return s(o,o.head,e),i(e,o,t,o.head,0),function(e){for(var t=[],n=e.head.next;n!==e.tail;)t.push(n.value),n=n.next;return t}(o)},hooks:{all:{},add:function(e,t){var n=r.hooks.all;n[e]=n[e]||[],n[e].push(t)},run:function(e,t){var n=r.hooks.all[e];if(n&&n.length)for(var o,a=0;o=n[a++];)o(t)}},Token:o};function o(e,t,n,r){this.type=e,this.content=t,this.alias=n,this.length=0|(r||"").length}function a(e,t,n,r){e.lastIndex=t;var o=e.exec(n);if(o&&r&&o[1]){var a=o[1].length;o.index+=a,o[0]=o[0].slice(a)}return o}function i(e,t,n,c,u,d){for(var p in n)if(n.hasOwnProperty(p)&&n[p]){var f=n[p];f=Array.isArray(f)?f:[f];for(var m=0;m<f.length;++m){if(d&&d.cause==p+","+m)return;var g=f[m],h=g.inside,b=!!g.lookbehind,y=!!g.greedy,v=g.alias;if(y&&!g.pattern.global){var w=g.pattern.toString().match(/[imsuy]*$/)[0];g.pattern=RegExp(g.pattern.source,w+"g")}for(var S=g.pattern||g,k=c.next,x=u;k!==t.tail&&!(d&&x>=d.reach);x+=k.value.length,k=k.next){var _=k.value;if(t.length>e.length)return;if(!(_ instanceof o)){var C,E=1;if(y){if(!(C=a(S,x,e,b))||C.index>=e.length)break;var D=C.index,j=C.index+C[0].length,O=x;for(O+=k.value.length;D>=O;)O+=(k=k.next).value.length;if(x=O-=k.value.length,k.value instanceof o)continue;for(var A=k;A!==t.tail&&(O<j||"string"==typeof A.value);A=A.next)E++,O+=A.value.length;E--,_=e.slice(x,O),C.index-=x}else if(!(C=a(S,0,_,b)))continue;D=C.index;var T=C[0],P=_.slice(0,D),I=_.slice(D+T.length),N=x+_.length;d&&N>d.reach&&(d.reach=N);var R=k.prev;if(P&&(R=s(t,R,P),x+=P.length),l(t,R,E),k=s(t,R,new o(p,h?r.tokenize(T,h):T,v,T)),I&&s(t,k,I),E>1){var L={cause:p+","+m,reach:N};i(e,t,n,k.prev,x,L),d&&L.reach>d.reach&&(d.reach=L.reach)}}}}}}function c(){var e={value:null,prev:null,next:null},t={value:null,prev:e,next:null};e.next=t,this.head=e,this.tail=t,this.length=0}function s(e,t,n){var r=t.next,o={value:n,prev:t,next:r};return t.next=o,r.prev=o,e.length++,o}function l(e,t,n){for(var r=t.next,o=0;o<n&&r!==e.tail;o++)r=r.next;t.next=r,r.prev=t,e.length-=o}return o.stringify=function e(t,n){if("string"==typeof t)return t;if(Array.isArray(t)){var o="";return t.forEach((function(t){o+=e(t,n)})),o}var a={type:t.type,content:e(t.content,n),tag:"span",classes:["token",t.type],attributes:{},language:n},i=t.alias;i&&(Array.isArray(i)?Array.prototype.push.apply(a.classes,i):a.classes.push(i)),r.hooks.run("wrap",a);var c="";for(var s in a.attributes)c+=" "+s+'="'+(a.attributes[s]||"").replace(/"/g,""")+'"';return"<"+a.tag+' class="'+a.classes.join(" ")+'"'+c+">"+a.content+"</"+a.tag+">"},r}();t.exports=n,n.default=n}},function(){return o||(0,r[p(r)[0]])((o={exports:{}}).exports,o),o.exports})());S.languages.markup={comment:{pattern:/<!--(?:(?!<!--)[\s\S])*?-->/,greedy:!0},prolog:{pattern:/<\?[\s\S]+?\?>/,greedy:!0},doctype:{pattern:/<!DOCTYPE(?:[^>"'[\]]|"[^"]*"|'[^']*')+(?:\[(?:[^<"'\]]|"[^"]*"|'[^']*'|<(?!!--)|<!--(?:[^-]|-(?!->))*-->)*\]\s*)?>/i,greedy:!0,inside:{"internal-subset":{pattern:/(^[^\[]*\[)[\s\S]+(?=\]>$)/,lookbehind:!0,greedy:!0,inside:null},string:{pattern:/"[^"]*"|'[^']*'/,greedy:!0},punctuation:/^<!|>$|[[\]]/,"doctype-tag":/^DOCTYPE/i,name:/[^\s<>'"]+/}},cdata:{pattern:/<!\[CDATA\[[\s\S]*?\]\]>/i,greedy:!0},tag:{pattern:/<\/?(?!\d)[^\s>\/=$<%]+(?:\s(?:\s*[^\s>\/=]+(?:\s*=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+(?=[\s>]))|(?=[\s/>])))+)?\s*\/?>/,greedy:!0,inside:{tag:{pattern:/^<\/?[^\s>\/]+/,inside:{punctuation:/^<\/?/,namespace:/^[^\s>\/:]+:/}},"special-attr":[],"attr-value":{pattern:/=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+)/,inside:{punctuation:[{pattern:/^=/,alias:"attr-equals"},{pattern:/^(\s*)["']|["']$/,lookbehind:!0}]}},punctuation:/\/?>/,"attr-name":{pattern:/[^\s>\/]+/,inside:{namespace:/^[^\s>\/:]+:/}}}},entity:[{pattern:/&[\da-z]{1,8};/i,alias:"named-entity"},/&#x?[\da-f]{1,8};/i]},S.languages.markup.tag.inside["attr-value"].inside.entity=S.languages.markup.entity,S.languages.markup.doctype.inside["internal-subset"].inside=S.languages.markup,S.hooks.add("wrap",(function(e){"entity"===e.type&&(e.attributes.title=e.content.replace(/&/,"&"))})),Object.defineProperty(S.languages.markup.tag,"addInlined",{value:function(e,t){var n;(t=((n=((n={})["language-"+t]={pattern:/(^<!\[CDATA\[)[\s\S]+?(?=\]\]>$)/i,lookbehind:!0,inside:S.languages[t]},n.cdata=/^<!\[CDATA\[|\]\]>$/i,{"included-cdata":{pattern:/<!\[CDATA\[[\s\S]*?\]\]>/i,inside:n}}))["language-"+t]={pattern:/[\s\S]+/,inside:S.languages[t]},{}))[e]={pattern:RegExp(/(<__[^>]*>)(?:<!\[CDATA\[(?:[^\]]|\](?!\]>))*\]\]>|(?!<!\[CDATA\[)[\s\S])*?(?=<\/__>)/.source.replace(/__/g,(function(){return e})),"i"),lookbehind:!0,greedy:!0,inside:n},S.languages.insertBefore("markup","cdata",t)}}),Object.defineProperty(S.languages.markup.tag,"addAttribute",{value:function(e,t){S.languages.markup.tag.inside["special-attr"].push({pattern:RegExp(/(^|["'\s])/.source+"(?:"+e+")"+/\s*=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+(?=[\s>]))/.source,"i"),lookbehind:!0,inside:{"attr-name":/^[^\s=]+/,"attr-value":{pattern:/=[\s\S]+/,inside:{value:{pattern:/(^=\s*(["']|(?!["'])))\S[\s\S]*(?=\2$)/,lookbehind:!0,alias:[t,"language-"+t],inside:S.languages[t]},punctuation:[{pattern:/^=/,alias:"attr-equals"},/"|'/]}}}})}}),S.languages.html=S.languages.markup,S.languages.mathml=S.languages.markup,S.languages.svg=S.languages.markup,S.languages.xml=S.languages.extend("markup",{}),S.languages.ssml=S.languages.xml,S.languages.atom=S.languages.xml,S.languages.rss=S.languages.xml,function(e){var t={pattern:/\\[\\(){}[\]^$+*?|.]/,alias:"escape"},n=/\\(?:x[\da-fA-F]{2}|u[\da-fA-F]{4}|u\{[\da-fA-F]+\}|0[0-7]{0,2}|[123][0-7]{2}|c[a-zA-Z]|.)/,r="(?:[^\\\\-]|"+n.source+")",o=(r=RegExp(r+"-"+r),{pattern:/(<|')[^<>']+(?=[>']$)/,lookbehind:!0,alias:"variable"});e.languages.regex={"char-class":{pattern:/((?:^|[^\\])(?:\\\\)*)\[(?:[^\\\]]|\\[\s\S])*\]/,lookbehind:!0,inside:{"char-class-negation":{pattern:/(^\[)\^/,lookbehind:!0,alias:"operator"},"char-class-punctuation":{pattern:/^\[|\]$/,alias:"punctuation"},range:{pattern:r,inside:{escape:n,"range-punctuation":{pattern:/-/,alias:"operator"}}},"special-escape":t,"char-set":{pattern:/\\[wsd]|\\p\{[^{}]+\}/i,alias:"class-name"},escape:n}},"special-escape":t,"char-set":{pattern:/\.|\\[wsd]|\\p\{[^{}]+\}/i,alias:"class-name"},backreference:[{pattern:/\\(?![123][0-7]{2})[1-9]/,alias:"keyword"},{pattern:/\\k<[^<>']+>/,alias:"keyword",inside:{"group-name":o}}],anchor:{pattern:/[$^]|\\[ABbGZz]/,alias:"function"},escape:n,group:[{pattern:/\((?:\?(?:<[^<>']+>|'[^<>']+'|[>:]|<?[=!]|[idmnsuxU]+(?:-[idmnsuxU]+)?:?))?/,alias:"punctuation",inside:{"group-name":o}},{pattern:/\)/,alias:"punctuation"}],quantifier:{pattern:/(?:[+*?]|\{\d+(?:,\d*)?\})[?+]?/,alias:"number"},alternation:{pattern:/\|/,alias:"keyword"}}}(S),S.languages.clike={comment:[{pattern:/(^|[^\\])\/\*[\s\S]*?(?:\*\/|$)/,lookbehind:!0,greedy:!0},{pattern:/(^|[^\\:])\/\/.*/,lookbehind:!0,greedy:!0}],string:{pattern:/(["'])(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,greedy:!0},"class-name":{pattern:/(\b(?:class|extends|implements|instanceof|interface|new|trait)\s+|\bcatch\s+\()[\w.\\]+/i,lookbehind:!0,inside:{punctuation:/[.\\]/}},keyword:/\b(?:break|catch|continue|do|else|finally|for|function|if|in|instanceof|new|null|return|throw|try|while)\b/,boolean:/\b(?:false|true)\b/,function:/\b\w+(?=\()/,number:/\b0x[\da-f]+\b|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:e[+-]?\d+)?/i,operator:/[<>]=?|[!=]=?=?|--?|\+\+?|&&?|\|\|?|[?*/~^%]/,punctuation:/[{}[\];(),.:]/},S.languages.javascript=S.languages.extend("clike",{"class-name":[S.languages.clike["class-name"],{pattern:/(^|[^$\w\xA0-\uFFFF])(?!\s)[_$A-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\.(?:constructor|prototype))/,lookbehind:!0}],keyword:[{pattern:/((?:^|\})\s*)catch\b/,lookbehind:!0},{pattern:/(^|[^.]|\.\.\.\s*)\b(?:as|assert(?=\s*\{)|async(?=\s*(?:function\b|\(|[$\w\xA0-\uFFFF]|$))|await|break|case|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally(?=\s*(?:\{|$))|for|from(?=\s*(?:['"]|$))|function|(?:get|set)(?=\s*(?:[#\[$\w\xA0-\uFFFF]|$))|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)\b/,lookbehind:!0}],function:/#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*(?:\.\s*(?:apply|bind|call)\s*)?\()/,number:{pattern:RegExp(/(^|[^\w$])/.source+"(?:"+/NaN|Infinity/.source+"|"+/0[bB][01]+(?:_[01]+)*n?/.source+"|"+/0[oO][0-7]+(?:_[0-7]+)*n?/.source+"|"+/0[xX][\dA-Fa-f]+(?:_[\dA-Fa-f]+)*n?/.source+"|"+/\d+(?:_\d+)*n/.source+"|"+/(?:\d+(?:_\d+)*(?:\.(?:\d+(?:_\d+)*)?)?|\.\d+(?:_\d+)*)(?:[Ee][+-]?\d+(?:_\d+)*)?/.source+")"+/(?![\w$])/.source),lookbehind:!0},operator:/--|\+\+|\*\*=?|=>|&&=?|\|\|=?|[!=]==|<<=?|>>>?=?|[-+*/%&|^!=<>]=?|\.{3}|\?\?=?|\?\.?|[~:]/}),S.languages.javascript["class-name"][0].pattern=/(\b(?:class|extends|implements|instanceof|interface|new)\s+)[\w.\\]+/,S.languages.insertBefore("javascript","keyword",{regex:{pattern:RegExp(/((?:^|[^$\w\xA0-\uFFFF."'\])\s]|\b(?:return|yield))\s*)/.source+/\//.source+"(?:"+/(?:\[(?:[^\]\\\r\n]|\\.)*\]|\\.|[^/\\\[\r\n])+\/[dgimyus]{0,7}/.source+"|"+/(?:\[(?:[^[\]\\\r\n]|\\.|\[(?:[^[\]\\\r\n]|\\.|\[(?:[^[\]\\\r\n]|\\.)*\])*\])*\]|\\.|[^/\\\[\r\n])+\/[dgimyus]{0,7}v[dgimyus]{0,7}/.source+")"+/(?=(?:\s|\/\*(?:[^*]|\*(?!\/))*\*\/)*(?:$|[\r\n,.;:})\]]|\/\/))/.source),lookbehind:!0,greedy:!0,inside:{"regex-source":{pattern:/^(\/)[\s\S]+(?=\/[a-z]*$)/,lookbehind:!0,alias:"language-regex",inside:S.languages.regex},"regex-delimiter":/^\/|\/$/,"regex-flags":/^[a-z]+$/}},"function-variable":{pattern:/#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*[=:]\s*(?:async\s*)?(?:\bfunction\b|(?:\((?:[^()]|\([^()]*\))*\)|(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*)\s*=>))/,alias:"function"},parameter:[{pattern:/(function(?:\s+(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*)?\s*\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\))/,lookbehind:!0,inside:S.languages.javascript},{pattern:/(^|[^$\w\xA0-\uFFFF])(?!\s)[_$a-z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*=>)/i,lookbehind:!0,inside:S.languages.javascript},{pattern:/(\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\)\s*=>)/,lookbehind:!0,inside:S.languages.javascript},{pattern:/((?:\b|\s|^)(?!(?:as|async|await|break|case|catch|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally|for|from|function|get|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|set|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)(?![$\w\xA0-\uFFFF]))(?:(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*\s*)\(\s*|\]\s*\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\)\s*\{)/,lookbehind:!0,inside:S.languages.javascript}],constant:/\b[A-Z](?:[A-Z_]|\dx?)*\b/}),S.languages.insertBefore("javascript","string",{hashbang:{pattern:/^#!.*/,greedy:!0,alias:"comment"},"template-string":{pattern:/`(?:\\[\s\S]|\$\{(?:[^{}]|\{(?:[^{}]|\{[^}]*\})*\})+\}|(?!\$\{)[^\\`])*`/,greedy:!0,inside:{"template-punctuation":{pattern:/^`|`$/,alias:"string"},interpolation:{pattern:/((?:^|[^\\])(?:\\{2})*)\$\{(?:[^{}]|\{(?:[^{}]|\{[^}]*\})*\})+\}/,lookbehind:!0,inside:{"interpolation-punctuation":{pattern:/^\$\{|\}$/,alias:"punctuation"},rest:S.languages.javascript}},string:/[\s\S]+/}},"string-property":{pattern:/((?:^|[,{])[ \t]*)(["'])(?:\\(?:\r\n|[\s\S])|(?!\2)[^\\\r\n])*\2(?=\s*:)/m,lookbehind:!0,greedy:!0,alias:"property"}}),S.languages.insertBefore("javascript","operator",{"literal-property":{pattern:/((?:^|[,{])[ \t]*)(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*:)/m,lookbehind:!0,alias:"property"}}),S.languages.markup&&(S.languages.markup.tag.addInlined("script","javascript"),S.languages.markup.tag.addAttribute(/on(?:abort|blur|change|click|composition(?:end|start|update)|dblclick|error|focus(?:in|out)?|key(?:down|up)|load|mouse(?:down|enter|leave|move|out|over|up)|reset|resize|scroll|select|slotchange|submit|unload|wheel)/.source,"javascript")),S.languages.js=S.languages.javascript,S.languages.actionscript=S.languages.extend("javascript",{keyword:/\b(?:as|break|case|catch|class|const|default|delete|do|dynamic|each|else|extends|final|finally|for|function|get|if|implements|import|in|include|instanceof|interface|internal|is|namespace|native|new|null|override|package|private|protected|public|return|set|static|super|switch|this|throw|try|typeof|use|var|void|while|with)\b/,operator:/\+\+|--|(?:[+\-*\/%^]|&&?|\|\|?|<<?|>>?>?|[!=]=?)=?|[~?@]/}),S.languages.actionscript["class-name"].alias="function",delete S.languages.actionscript.parameter,delete S.languages.actionscript["literal-property"],S.languages.markup&&S.languages.insertBefore("actionscript","string",{xml:{pattern:/(^|[^.])<\/?\w+(?:\s+[^\s>\/=]+=("|')(?:\\[\s\S]|(?!\2)[^\\])*\2)*\s*\/?>/,lookbehind:!0,inside:S.languages.markup}}),function(e){var t=/#(?!\{).+/,n={pattern:/#\{[^}]+\}/,alias:"variable"};e.languages.coffeescript=e.languages.extend("javascript",{comment:t,string:[{pattern:/'(?:\\[\s\S]|[^\\'])*'/,greedy:!0},{pattern:/"(?:\\[\s\S]|[^\\"])*"/,greedy:!0,inside:{interpolation:n}}],keyword:/\b(?:and|break|by|catch|class|continue|debugger|delete|do|each|else|extend|extends|false|finally|for|if|in|instanceof|is|isnt|let|loop|namespace|new|no|not|null|of|off|on|or|own|return|super|switch|then|this|throw|true|try|typeof|undefined|unless|until|when|while|window|with|yes|yield)\b/,"class-member":{pattern:/@(?!\d)\w+/,alias:"variable"}}),e.languages.insertBefore("coffeescript","comment",{"multiline-comment":{pattern:/###[\s\S]+?###/,alias:"comment"},"block-regex":{pattern:/\/{3}[\s\S]*?\/{3}/,alias:"regex",inside:{comment:t,interpolation:n}}}),e.languages.insertBefore("coffeescript","string",{"inline-javascript":{pattern:/`(?:\\[\s\S]|[^\\`])*`/,inside:{delimiter:{pattern:/^`|`$/,alias:"punctuation"},script:{pattern:/[\s\S]+/,alias:"language-javascript",inside:e.languages.javascript}}},"multiline-string":[{pattern:/'''[\s\S]*?'''/,greedy:!0,alias:"string"},{pattern:/"""[\s\S]*?"""/,greedy:!0,alias:"string",inside:{interpolation:n}}]}),e.languages.insertBefore("coffeescript","keyword",{property:/(?!\d)\w+(?=\s*:(?!:))/}),delete e.languages.coffeescript["template-string"],e.languages.coffee=e.languages.coffeescript}(S),function(e){var t=e.languages.javadoclike={parameter:{pattern:/(^[\t ]*(?:\/{3}|\*|\/\*\*)\s*@(?:arg|arguments|param)\s+)\w+/m,lookbehind:!0},keyword:{pattern:/(^[\t ]*(?:\/{3}|\*|\/\*\*)\s*|\{)@[a-z][a-zA-Z-]+\b/m,lookbehind:!0},punctuation:/[{}]/};Object.defineProperty(t,"addSupport",{value:function(t,n){(t="string"==typeof t?[t]:t).forEach((function(t){var r=function(e){e.inside||(e.inside={}),e.inside.rest=n},o="doc-comment";if(a=e.languages[t]){var a,i=a[o];if((i=i||(a=e.languages.insertBefore(t,"comment",{"doc-comment":{pattern:/(^|[^\\])\/\*\*[^/][\s\S]*?(?:\*\/|$)/,lookbehind:!0,alias:"comment"}}))[o])instanceof RegExp&&(i=a[o]={pattern:i}),Array.isArray(i))for(var c=0,s=i.length;c<s;c++)i[c]instanceof RegExp&&(i[c]={pattern:i[c]}),r(i[c]);else r(i)}}))}}),t.addSupport(["java","javascript","php"],t)}(S),function(e){var t=/(?:"(?:\\(?:\r\n|[\s\S])|[^"\\\r\n])*"|'(?:\\(?:\r\n|[\s\S])|[^'\\\r\n])*')/;(t=(e.languages.css={comment:/\/\*[\s\S]*?\*\//,atrule:{pattern:RegExp("@[\\w-](?:"+/[^;{\s"']|\s+(?!\s)/.source+"|"+t.source+")*?"+/(?:;|(?=\s*\{))/.source),inside:{rule:/^@[\w-]+/,"selector-function-argument":{pattern:/(\bselector\s*\(\s*(?![\s)]))(?:[^()\s]|\s+(?![\s)])|\((?:[^()]|\([^()]*\))*\))+(?=\s*\))/,lookbehind:!0,alias:"selector"},keyword:{pattern:/(^|[^\w-])(?:and|not|only|or)(?![\w-])/,lookbehind:!0}}},url:{pattern:RegExp("\\burl\\((?:"+t.source+"|"+/(?:[^\\\r\n()"']|\\[\s\S])*/.source+")\\)","i"),greedy:!0,inside:{function:/^url/i,punctuation:/^\(|\)$/,string:{pattern:RegExp("^"+t.source+"$"),alias:"url"}}},selector:{pattern:RegExp("(^|[{}\\s])[^{}\\s](?:[^{};\"'\\s]|\\s+(?![\\s{])|"+t.source+")*(?=\\s*\\{)"),lookbehind:!0},string:{pattern:t,greedy:!0},property:{pattern:/(^|[^-\w\xA0-\uFFFF])(?!\s)[-_a-z\xA0-\uFFFF](?:(?!\s)[-\w\xA0-\uFFFF])*(?=\s*:)/i,lookbehind:!0},important:/!important\b/i,function:{pattern:/(^|[^-a-z0-9])[-a-z0-9]+(?=\()/i,lookbehind:!0},punctuation:/[(){};:,]/},e.languages.css.atrule.inside.rest=e.languages.css,e.languages.markup))&&(t.tag.addInlined("style","css"),t.tag.addAttribute("style","css"))}(S),function(e){var t=/("|')(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,n=(t=(e.languages.css.selector={pattern:e.languages.css.selector.pattern,lookbehind:!0,inside:t={"pseudo-element":/:(?:after|before|first-letter|first-line|selection)|::[-\w]+/,"pseudo-class":/:[-\w]+/,class:/\.[-\w]+/,id:/#[-\w]+/,attribute:{pattern:RegExp("\\[(?:[^[\\]\"']|"+t.source+")*\\]"),greedy:!0,inside:{punctuation:/^\[|\]$/,"case-sensitivity":{pattern:/(\s)[si]$/i,lookbehind:!0,alias:"keyword"},namespace:{pattern:/^(\s*)(?:(?!\s)[-*\w\xA0-\uFFFF])*\|(?!=)/,lookbehind:!0,inside:{punctuation:/\|$/}},"attr-name":{pattern:/^(\s*)(?:(?!\s)[-\w\xA0-\uFFFF])+/,lookbehind:!0},"attr-value":[t,{pattern:/(=\s*)(?:(?!\s)[-\w\xA0-\uFFFF])+(?=\s*$)/,lookbehind:!0}],operator:/[|~*^$]?=/}},"n-th":[{pattern:/(\(\s*)[+-]?\d*[\dn](?:\s*[+-]\s*\d+)?(?=\s*\))/,lookbehind:!0,inside:{number:/[\dn]+/,operator:/[+-]/}},{pattern:/(\(\s*)(?:even|odd)(?=\s*\))/i,lookbehind:!0}],combinator:/>|\+|~|\|\|/,punctuation:/[(),]/}},e.languages.css.atrule.inside["selector-function-argument"].inside=t,e.languages.insertBefore("css","property",{variable:{pattern:/(^|[^-\w\xA0-\uFFFF])--(?!\s)[-_a-z\xA0-\uFFFF](?:(?!\s)[-\w\xA0-\uFFFF])*/i,lookbehind:!0}}),{pattern:/(\b\d+)(?:%|[a-z]+(?![\w-]))/,lookbehind:!0}),{pattern:/(^|[^\w.-])-?(?:\d+(?:\.\d+)?|\.\d+)/,lookbehind:!0});e.languages.insertBefore("css","function",{operator:{pattern:/(\s)[+\-*\/](?=\s)/,lookbehind:!0},hexcode:{pattern:/\B#[\da-f]{3,8}\b/i,alias:"color"},color:[{pattern:/(^|[^\w-])(?:AliceBlue|AntiqueWhite|Aqua|Aquamarine|Azure|Beige|Bisque|Black|BlanchedAlmond|Blue|BlueViolet|Brown|BurlyWood|CadetBlue|Chartreuse|Chocolate|Coral|CornflowerBlue|Cornsilk|Crimson|Cyan|DarkBlue|DarkCyan|DarkGoldenRod|DarkGr[ae]y|DarkGreen|DarkKhaki|DarkMagenta|DarkOliveGreen|DarkOrange|DarkOrchid|DarkRed|DarkSalmon|DarkSeaGreen|DarkSlateBlue|DarkSlateGr[ae]y|DarkTurquoise|DarkViolet|DeepPink|DeepSkyBlue|DimGr[ae]y|DodgerBlue|FireBrick|FloralWhite|ForestGreen|Fuchsia|Gainsboro|GhostWhite|Gold|GoldenRod|Gr[ae]y|Green|GreenYellow|HoneyDew|HotPink|IndianRed|Indigo|Ivory|Khaki|Lavender|LavenderBlush|LawnGreen|LemonChiffon|LightBlue|LightCoral|LightCyan|LightGoldenRodYellow|LightGr[ae]y|LightGreen|LightPink|LightSalmon|LightSeaGreen|LightSkyBlue|LightSlateGr[ae]y|LightSteelBlue|LightYellow|Lime|LimeGreen|Linen|Magenta|Maroon|MediumAquaMarine|MediumBlue|MediumOrchid|MediumPurple|MediumSeaGreen|MediumSlateBlue|MediumSpringGreen|MediumTurquoise|MediumVioletRed|MidnightBlue|MintCream|MistyRose|Moccasin|NavajoWhite|Navy|OldLace|Olive|OliveDrab|Orange|OrangeRed|Orchid|PaleGoldenRod|PaleGreen|PaleTurquoise|PaleVioletRed|PapayaWhip|PeachPuff|Peru|Pink|Plum|PowderBlue|Purple|RebeccaPurple|Red|RosyBrown|RoyalBlue|SaddleBrown|Salmon|SandyBrown|SeaGreen|SeaShell|Sienna|Silver|SkyBlue|SlateBlue|SlateGr[ae]y|Snow|SpringGreen|SteelBlue|Tan|Teal|Thistle|Tomato|Transparent|Turquoise|Violet|Wheat|White|WhiteSmoke|Yellow|YellowGreen)(?![\w-])/i,lookbehind:!0},{pattern:/\b(?:hsl|rgb)\(\s*\d{1,3}\s*,\s*\d{1,3}%?\s*,\s*\d{1,3}%?\s*\)\B|\b(?:hsl|rgb)a\(\s*\d{1,3}\s*,\s*\d{1,3}%?\s*,\s*\d{1,3}%?\s*,\s*(?:0|0?\.\d+|1)\s*\)\B/i,inside:{unit:t,number:n,function:/[\w-]+(?=\()/,punctuation:/[(),]/}}],entity:/\\[\da-f]{1,8}/i,unit:t,number:n})}(S),function(e){var t=/[*&][^\s[\]{},]+/,n=/!(?:<[\w\-%#;/?:@&=+$,.!~*'()[\]]+>|(?:[a-zA-Z\d-]*!)?[\w\-%#;/?:@&=+$.~*'()]+)?/,r="(?:"+n.source+"(?:[ \t]+"+t.source+")?|"+t.source+"(?:[ \t]+"+n.source+")?)",o=/(?:[^\s\x00-\x08\x0e-\x1f!"#%&'*,\-:>?@[\]`{|}\x7f-\x84\x86-\x9f\ud800-\udfff\ufffe\uffff]|[?:-]<PLAIN>)(?:[ \t]*(?:(?![#:])<PLAIN>|:<PLAIN>))*/.source.replace(/<PLAIN>/g,(function(){return/[^\s\x00-\x08\x0e-\x1f,[\]{}\x7f-\x84\x86-\x9f\ud800-\udfff\ufffe\uffff]/.source})),a=/"(?:[^"\\\r\n]|\\.)*"|'(?:[^'\\\r\n]|\\.)*'/.source;function i(e,t){t=(t||"").replace(/m/g,"")+"m";var n=/([:\-,[{]\s*(?:\s<<prop>>[ \t]+)?)(?:<<value>>)(?=[ \t]*(?:$|,|\]|\}|(?:[\r\n]\s*)?#))/.source.replace(/<<prop>>/g,(function(){return r})).replace(/<<value>>/g,(function(){return e}));return RegExp(n,t)}e.languages.yaml={scalar:{pattern:RegExp(/([\-:]\s*(?:\s<<prop>>[ \t]+)?[|>])[ \t]*(?:((?:\r?\n|\r)[ \t]+)\S[^\r\n]*(?:\2[^\r\n]+)*)/.source.replace(/<<prop>>/g,(function(){return r}))),lookbehind:!0,alias:"string"},comment:/#.*/,key:{pattern:RegExp(/((?:^|[:\-,[{\r\n?])[ \t]*(?:<<prop>>[ \t]+)?)<<key>>(?=\s*:\s)/.source.replace(/<<prop>>/g,(function(){return r})).replace(/<<key>>/g,(function(){return"(?:"+o+"|"+a+")"}))),lookbehind:!0,greedy:!0,alias:"atrule"},directive:{pattern:/(^[ \t]*)%.+/m,lookbehind:!0,alias:"important"},datetime:{pattern:i(/\d{4}-\d\d?-\d\d?(?:[tT]|[ \t]+)\d\d?:\d{2}:\d{2}(?:\.\d*)?(?:[ \t]*(?:Z|[-+]\d\d?(?::\d{2})?))?|\d{4}-\d{2}-\d{2}|\d\d?:\d{2}(?::\d{2}(?:\.\d*)?)?/.source),lookbehind:!0,alias:"number"},boolean:{pattern:i(/false|true/.source,"i"),lookbehind:!0,alias:"important"},null:{pattern:i(/null|~/.source,"i"),lookbehind:!0,alias:"important"},string:{pattern:i(a),lookbehind:!0,greedy:!0},number:{pattern:i(/[+-]?(?:0x[\da-f]+|0o[0-7]+|(?:\d+(?:\.\d*)?|\.\d+)(?:e[+-]?\d+)?|\.inf|\.nan)/.source,"i"),lookbehind:!0},tag:n,important:t,punctuation:/---|[:[\]{}\-,|>?]|\.\.\./},e.languages.yml=e.languages.yaml}(S),function(e){var t=/(?:\\.|[^\\\n\r]|(?:\n|\r\n?)(?![\r\n]))/.source;function n(e){return e=e.replace(/<inner>/g,(function(){return t})),RegExp(/((?:^|[^\\])(?:\\{2})*)/.source+"(?:"+e+")")}var r=/(?:\\.|``(?:[^`\r\n]|`(?!`))+``|`[^`\r\n]+`|[^\\|\r\n`])+/.source,o=/\|?__(?:\|__)+\|?(?:(?:\n|\r\n?)|(?![\s\S]))/.source.replace(/__/g,(function(){return r})),a=/\|?[ \t]*:?-{3,}:?[ \t]*(?:\|[ \t]*:?-{3,}:?[ \t]*)+\|?(?:\n|\r\n?)/.source,i=(e.languages.markdown=e.languages.extend("markup",{}),e.languages.insertBefore("markdown","prolog",{"front-matter-block":{pattern:/(^(?:\s*[\r\n])?)---(?!.)[\s\S]*?[\r\n]---(?!.)/,lookbehind:!0,greedy:!0,inside:{punctuation:/^---|---$/,"front-matter":{pattern:/\S+(?:\s+\S+)*/,alias:["yaml","language-yaml"],inside:e.languages.yaml}}},blockquote:{pattern:/^>(?:[\t ]*>)*/m,alias:"punctuation"},table:{pattern:RegExp("^"+o+a+"(?:"+o+")*","m"),inside:{"table-data-rows":{pattern:RegExp("^("+o+a+")(?:"+o+")*$"),lookbehind:!0,inside:{"table-data":{pattern:RegExp(r),inside:e.languages.markdown},punctuation:/\|/}},"table-line":{pattern:RegExp("^("+o+")"+a+"$"),lookbehind:!0,inside:{punctuation:/\||:?-{3,}:?/}},"table-header-row":{pattern:RegExp("^"+o+"$"),inside:{"table-header":{pattern:RegExp(r),alias:"important",inside:e.languages.markdown},punctuation:/\|/}}}},code:[{pattern:/((?:^|\n)[ \t]*\n|(?:^|\r\n?)[ \t]*\r\n?)(?: {4}|\t).+(?:(?:\n|\r\n?)(?: {4}|\t).+)*/,lookbehind:!0,alias:"keyword"},{pattern:/^```[\s\S]*?^```$/m,greedy:!0,inside:{"code-block":{pattern:/^(```.*(?:\n|\r\n?))[\s\S]+?(?=(?:\n|\r\n?)^```$)/m,lookbehind:!0},"code-language":{pattern:/^(```).+/,lookbehind:!0},punctuation:/```/}}],title:[{pattern:/\S.*(?:\n|\r\n?)(?:==+|--+)(?=[ \t]*$)/m,alias:"important",inside:{punctuation:/==+$|--+$/}},{pattern:/(^\s*)#.+/m,lookbehind:!0,alias:"important",inside:{punctuation:/^#+|#+$/}}],hr:{pattern:/(^\s*)([*-])(?:[\t ]*\2){2,}(?=\s*$)/m,lookbehind:!0,alias:"punctuation"},list:{pattern:/(^\s*)(?:[*+-]|\d+\.)(?=[\t ].)/m,lookbehind:!0,alias:"punctuation"},"url-reference":{pattern:/!?\[[^\]]+\]:[\t ]+(?:\S+|<(?:\\.|[^>\\])+>)(?:[\t ]+(?:"(?:\\.|[^"\\])*"|'(?:\\.|[^'\\])*'|\((?:\\.|[^)\\])*\)))?/,inside:{variable:{pattern:/^(!?\[)[^\]]+/,lookbehind:!0},string:/(?:"(?:\\.|[^"\\])*"|'(?:\\.|[^'\\])*'|\((?:\\.|[^)\\])*\))$/,punctuation:/^[\[\]!:]|[<>]/},alias:"url"},bold:{pattern:n(/\b__(?:(?!_)<inner>|_(?:(?!_)<inner>)+_)+__\b|\*\*(?:(?!\*)<inner>|\*(?:(?!\*)<inner>)+\*)+\*\*/.source),lookbehind:!0,greedy:!0,inside:{content:{pattern:/(^..)[\s\S]+(?=..$)/,lookbehind:!0,inside:{}},punctuation:/\*\*|__/}},italic:{pattern:n(/\b_(?:(?!_)<inner>|__(?:(?!_)<inner>)+__)+_\b|\*(?:(?!\*)<inner>|\*\*(?:(?!\*)<inner>)+\*\*)+\*/.source),lookbehind:!0,greedy:!0,inside:{content:{pattern:/(^.)[\s\S]+(?=.$)/,lookbehind:!0,inside:{}},punctuation:/[*_]/}},strike:{pattern:n(/(~~?)(?:(?!~)<inner>)+\2/.source),lookbehind:!0,greedy:!0,inside:{content:{pattern:/(^~~?)[\s\S]+(?=\1$)/,lookbehind:!0,inside:{}},punctuation:/~~?/}},"code-snippet":{pattern:/(^|[^\\`])(?:``[^`\r\n]+(?:`[^`\r\n]+)*``(?!`)|`[^`\r\n]+`(?!`))/,lookbehind:!0,greedy:!0,alias:["code","keyword"]},url:{pattern:n(/!?\[(?:(?!\])<inner>)+\](?:\([^\s)]+(?:[\t ]+"(?:\\.|[^"\\])*")?\)|[ \t]?\[(?:(?!\])<inner>)+\])/.source),lookbehind:!0,greedy:!0,inside:{operator:/^!/,content:{pattern:/(^\[)[^\]]+(?=\])/,lookbehind:!0,inside:{}},variable:{pattern:/(^\][ \t]?\[)[^\]]+(?=\]$)/,lookbehind:!0},url:{pattern:/(^\]\()[^\s)]+/,lookbehind:!0},string:{pattern:/(^[ \t]+)"(?:\\.|[^"\\])*"(?=\)$)/,lookbehind:!0}}}}),["url","bold","italic","strike"].forEach((function(t){["url","bold","italic","strike","code-snippet"].forEach((function(n){t!==n&&(e.languages.markdown[t].inside.content.inside[n]=e.languages.markdown[n])}))})),e.hooks.add("after-tokenize",(function(e){"markdown"!==e.language&&"md"!==e.language||function e(t){if(t&&"string"!=typeof t)for(var n=0,r=t.length;n<r;n++){var o,a=t[n];"code"!==a.type?e(a.content):(o=a.content[1],a=a.content[3],o&&a&&"code-language"===o.type&&"code-block"===a.type&&"string"==typeof o.content&&(o=o.content.replace(/\b#/g,"sharp").replace(/\b\+\+/g,"pp"),o="language-"+(o=(/[a-z][\w-]*/i.exec(o)||[""])[0].toLowerCase()),a.alias?"string"==typeof a.alias?a.alias=[a.alias,o]:a.alias.push(o):a.alias=[o]))}}(e.tokens)})),e.hooks.add("wrap",(function(t){if("code-block"===t.type){for(var n="",r=0,o=t.classes.length;r<o;r++){var a=t.classes[r];if(a=/language-(.+)/.exec(a)){n=a[1];break}}var l,u=e.languages[n];u?t.content=e.highlight(t.content.replace(i,"").replace(/&(\w{1,8}|#x?[\da-f]{1,8});/gi,(function(e,t){var n;return"#"===(t=t.toLowerCase())[0]?(n="x"===t[1]?parseInt(t.slice(2),16):Number(t.slice(1)),s(n)):c[t]||e})),u,n):n&&"none"!==n&&e.plugins.autoloader&&(l="md-"+(new Date).valueOf()+"-"+Math.floor(1e16*Math.random()),t.attributes.id=l,e.plugins.autoloader.loadLanguages(n,(function(){var t=document.getElementById(l);t&&(t.innerHTML=e.highlight(t.textContent,e.languages[n],n))})))}})),RegExp(e.languages.markup.tag.pattern.source,"gi")),c={amp:"&",lt:"<",gt:">",quot:'"'},s=String.fromCodePoint||String.fromCharCode;e.languages.md=e.languages.markdown}(S),S.languages.graphql={comment:/#.*/,description:{pattern:/(?:"""(?:[^"]|(?!""")")*"""|"(?:\\.|[^\\"\r\n])*")(?=\s*[a-z_])/i,greedy:!0,alias:"string",inside:{"language-markdown":{pattern:/(^"(?:"")?)(?!\1)[\s\S]+(?=\1$)/,lookbehind:!0,inside:S.languages.markdown}}},string:{pattern:/"""(?:[^"]|(?!""")")*"""|"(?:\\.|[^\\"\r\n])*"/,greedy:!0},number:/(?:\B-|\b)\d+(?:\.\d+)?(?:e[+-]?\d+)?\b/i,boolean:/\b(?:false|true)\b/,variable:/\$[a-z_]\w*/i,directive:{pattern:/@[a-z_]\w*/i,alias:"function"},"attr-name":{pattern:/\b[a-z_]\w*(?=\s*(?:\((?:[^()"]|"(?:\\.|[^\\"\r\n])*")*\))?:)/i,greedy:!0},"atom-input":{pattern:/\b[A-Z]\w*Input\b/,alias:"class-name"},scalar:/\b(?:Boolean|Float|ID|Int|String)\b/,constant:/\b[A-Z][A-Z_\d]*\b/,"class-name":{pattern:/(\b(?:enum|implements|interface|on|scalar|type|union)\s+|&\s*|:\s*|\[)[A-Z_]\w*/,lookbehind:!0},fragment:{pattern:/(\bfragment\s+|\.{3}\s*(?!on\b))[a-zA-Z_]\w*/,lookbehind:!0,alias:"function"},"definition-mutation":{pattern:/(\bmutation\s+)[a-zA-Z_]\w*/,lookbehind:!0,alias:"function"},"definition-query":{pattern:/(\bquery\s+)[a-zA-Z_]\w*/,lookbehind:!0,alias:"function"},keyword:/\b(?:directive|enum|extend|fragment|implements|input|interface|mutation|on|query|repeatable|scalar|schema|subscription|type|union)\b/,operator:/[!=|&]|\.{3}/,"property-query":/\w+(?=\s*\()/,object:/\w+(?=\s*\{)/,punctuation:/[!(){}\[\]:=,]/,property:/\w+/},S.hooks.add("after-tokenize",(function(e){if("graphql"===e.language)for(var t=e.tokens.filter((function(e){return"string"!=typeof e&&"comment"!==e.type&&"scalar"!==e.type})),n=0;n<t.length;){var r=t[n++];if("keyword"===r.type&&"mutation"===r.content){var o=[];if(d(["definition-mutation","punctuation"])&&"("===u(1).content){n+=2;var a=p(/^\($/,/^\)$/);if(-1===a)continue;for(;n<a;n++){var i=u(0);"variable"===i.type&&(f(i,"variable-input"),o.push(i.content))}n=a+1}if(d(["punctuation","property-query"])&&"{"===u(0).content&&(n++,f(u(0),"property-mutation"),0<o.length)){var c=p(/^\{$/,/^\}$/);if(-1!==c)for(var s=n;s<c;s++){var l=t[s];"variable"===l.type&&0<=o.indexOf(l.content)&&f(l,"variable-input")}}}}function u(e){return t[n+e]}function d(e,t){t=t||0;for(var n=0;n<e.length;n++){var r=u(n+t);if(!r||r.type!==e[n])return}return 1}function p(e,r){for(var o=1,a=n;a<t.length;a++){var i=t[a],c=i.content;if("punctuation"===i.type&&"string"==typeof c)if(e.test(c))o++;else if(r.test(c)&&0==--o)return a}return-1}function f(e,t){var n=e.alias;n?Array.isArray(n)||(e.alias=n=[n]):e.alias=n=[],n.push(t)}})),S.languages.sql={comment:{pattern:/(^|[^\\])(?:\/\*[\s\S]*?\*\/|(?:--|\/\/|#).*)/,lookbehind:!0},variable:[{pattern:/@(["'`])(?:\\[\s\S]|(?!\1)[^\\])+\1/,greedy:!0},/@[\w.$]+/],string:{pattern:/(^|[^@\\])("|')(?:\\[\s\S]|(?!\2)[^\\]|\2\2)*\2/,greedy:!0,lookbehind:!0},identifier:{pattern:/(^|[^@\\])`(?:\\[\s\S]|[^`\\]|``)*`/,greedy:!0,lookbehind:!0,inside:{punctuation:/^`|`$/}},function:/\b(?:AVG|COUNT|FIRST|FORMAT|LAST|LCASE|LEN|MAX|MID|MIN|MOD|NOW|ROUND|SUM|UCASE)(?=\s*\()/i,keyword:/\b(?:ACTION|ADD|AFTER|ALGORITHM|ALL|ALTER|ANALYZE|ANY|APPLY|AS|ASC|AUTHORIZATION|AUTO_INCREMENT|BACKUP|BDB|BEGIN|BERKELEYDB|BIGINT|BINARY|BIT|BLOB|BOOL|BOOLEAN|BREAK|BROWSE|BTREE|BULK|BY|CALL|CASCADED?|CASE|CHAIN|CHAR(?:ACTER|SET)?|CHECK(?:POINT)?|CLOSE|CLUSTERED|COALESCE|COLLATE|COLUMNS?|COMMENT|COMMIT(?:TED)?|COMPUTE|CONNECT|CONSISTENT|CONSTRAINT|CONTAINS(?:TABLE)?|CONTINUE|CONVERT|CREATE|CROSS|CURRENT(?:_DATE|_TIME|_TIMESTAMP|_USER)?|CURSOR|CYCLE|DATA(?:BASES?)?|DATE(?:TIME)?|DAY|DBCC|DEALLOCATE|DEC|DECIMAL|DECLARE|DEFAULT|DEFINER|DELAYED|DELETE|DELIMITERS?|DENY|DESC|DESCRIBE|DETERMINISTIC|DISABLE|DISCARD|DISK|DISTINCT|DISTINCTROW|DISTRIBUTED|DO|DOUBLE|DROP|DUMMY|DUMP(?:FILE)?|DUPLICATE|ELSE(?:IF)?|ENABLE|ENCLOSED|END|ENGINE|ENUM|ERRLVL|ERRORS|ESCAPED?|EXCEPT|EXEC(?:UTE)?|EXISTS|EXIT|EXPLAIN|EXTENDED|FETCH|FIELDS|FILE|FILLFACTOR|FIRST|FIXED|FLOAT|FOLLOWING|FOR(?: EACH ROW)?|FORCE|FOREIGN|FREETEXT(?:TABLE)?|FROM|FULL|FUNCTION|GEOMETRY(?:COLLECTION)?|GLOBAL|GOTO|GRANT|GROUP|HANDLER|HASH|HAVING|HOLDLOCK|HOUR|IDENTITY(?:COL|_INSERT)?|IF|IGNORE|IMPORT|INDEX|INFILE|INNER|INNODB|INOUT|INSERT|INT|INTEGER|INTERSECT|INTERVAL|INTO|INVOKER|ISOLATION|ITERATE|JOIN|KEYS?|KILL|LANGUAGE|LAST|LEAVE|LEFT|LEVEL|LIMIT|LINENO|LINES|LINESTRING|LOAD|LOCAL|LOCK|LONG(?:BLOB|TEXT)|LOOP|MATCH(?:ED)?|MEDIUM(?:BLOB|INT|TEXT)|MERGE|MIDDLEINT|MINUTE|MODE|MODIFIES|MODIFY|MONTH|MULTI(?:LINESTRING|POINT|POLYGON)|NATIONAL|NATURAL|NCHAR|NEXT|NO|NONCLUSTERED|NULLIF|NUMERIC|OFF?|OFFSETS?|ON|OPEN(?:DATASOURCE|QUERY|ROWSET)?|OPTIMIZE|OPTION(?:ALLY)?|ORDER|OUT(?:ER|FILE)?|OVER|PARTIAL|PARTITION|PERCENT|PIVOT|PLAN|POINT|POLYGON|PRECEDING|PRECISION|PREPARE|PREV|PRIMARY|PRINT|PRIVILEGES|PROC(?:EDURE)?|PUBLIC|PURGE|QUICK|RAISERROR|READS?|REAL|RECONFIGURE|REFERENCES|RELEASE|RENAME|REPEAT(?:ABLE)?|REPLACE|REPLICATION|REQUIRE|RESIGNAL|RESTORE|RESTRICT|RETURN(?:ING|S)?|REVOKE|RIGHT|ROLLBACK|ROUTINE|ROW(?:COUNT|GUIDCOL|S)?|RTREE|RULE|SAVE(?:POINT)?|SCHEMA|SECOND|SELECT|SERIAL(?:IZABLE)?|SESSION(?:_USER)?|SET(?:USER)?|SHARE|SHOW|SHUTDOWN|SIMPLE|SMALLINT|SNAPSHOT|SOME|SONAME|SQL|START(?:ING)?|STATISTICS|STATUS|STRIPED|SYSTEM_USER|TABLES?|TABLESPACE|TEMP(?:ORARY|TABLE)?|TERMINATED|TEXT(?:SIZE)?|THEN|TIME(?:STAMP)?|TINY(?:BLOB|INT|TEXT)|TOP?|TRAN(?:SACTIONS?)?|TRIGGER|TRUNCATE|TSEQUAL|TYPES?|UNBOUNDED|UNCOMMITTED|UNDEFINED|UNION|UNIQUE|UNLOCK|UNPIVOT|UNSIGNED|UPDATE(?:TEXT)?|USAGE|USE|USER|USING|VALUES?|VAR(?:BINARY|CHAR|CHARACTER|YING)|VIEW|WAITFOR|WARNINGS|WHEN|WHERE|WHILE|WITH(?: ROLLUP|IN)?|WORK|WRITE(?:TEXT)?|YEAR)\b/i,boolean:/\b(?:FALSE|NULL|TRUE)\b/i,number:/\b0x[\da-f]+\b|\b\d+(?:\.\d*)?|\B\.\d+\b/i,operator:/[-+*\/=%^~]|&&?|\|\|?|!=?|<(?:=>?|<|>)?|>[>=]?|\b(?:AND|BETWEEN|DIV|ILIKE|IN|IS|LIKE|NOT|OR|REGEXP|RLIKE|SOUNDS LIKE|XOR)\b/i,punctuation:/[;[\]()`,.]/},function(e){var t=e.languages.javascript["template-string"],n=t.pattern.source,r=t.inside.interpolation,o=r.inside["interpolation-punctuation"],a=r.pattern.source;function i(t,r){if(e.languages[t])return{pattern:RegExp("((?:"+r+")\\s*)"+n),lookbehind:!0,greedy:!0,inside:{"template-punctuation":{pattern:/^`|`$/,alias:"string"},"embedded-code":{pattern:/[\s\S]+/,alias:t}}}}function c(t,n,r){return t={code:t,grammar:n,language:r},e.hooks.run("before-tokenize",t),t.tokens=e.tokenize(t.code,t.grammar),e.hooks.run("after-tokenize",t),t.tokens}function s(t,n,i){var s=e.tokenize(t,{interpolation:{pattern:RegExp(a),lookbehind:!0}}),l=0,u={},d=(s=c(s.map((function(e){if("string"==typeof e)return e;var n,r;for(e=e.content;-1!==t.indexOf((r=l++,n="___"+i.toUpperCase()+"_"+r+"___")););return u[n]=e,n})).join(""),n,i),Object.keys(u));return l=0,function t(n){for(var a=0;a<n.length;a++){if(l>=d.length)return;var i,s,p,f,m,g,h,b=n[a];"string"==typeof b||"string"==typeof b.content?(i=d[l],-1!==(h=(g="string"==typeof b?b:b.content).indexOf(i))&&(++l,s=g.substring(0,h),m=u[i],p=void 0,(f={})["interpolation-punctuation"]=o,3===(f=e.tokenize(m,f)).length&&((p=[1,1]).push.apply(p,c(f[1],e.languages.javascript,"javascript")),f.splice.apply(f,p)),p=new e.Token("interpolation",f,r.alias,m),f=g.substring(h+i.length),m=[],s&&m.push(s),m.push(p),f&&(t(g=[f]),m.push.apply(m,g)),"string"==typeof b?(n.splice.apply(n,[a,1].concat(m)),a+=m.length-1):b.content=m)):(h=b.content,Array.isArray(h)?t(h):t([h]))}}(s),new e.Token(i,s,"language-"+i,t)}e.languages.javascript["template-string"]=[i("css",/\b(?:styled(?:\([^)]*\))?(?:\s*\.\s*\w+(?:\([^)]*\))*)*|css(?:\s*\.\s*(?:global|resolve))?|createGlobalStyle|keyframes)/.source),i("html",/\bhtml|\.\s*(?:inner|outer)HTML\s*\+?=/.source),i("svg",/\bsvg/.source),i("markdown",/\b(?:markdown|md)/.source),i("graphql",/\b(?:gql|graphql(?:\s*\.\s*experimental)?)/.source),i("sql",/\bsql/.source),t].filter(Boolean);var l={javascript:!0,js:!0,typescript:!0,ts:!0,jsx:!0,tsx:!0};function u(e){return"string"==typeof e?e:Array.isArray(e)?e.map(u).join(""):u(e.content)}e.hooks.add("after-tokenize",(function(t){t.language in l&&function t(n){for(var r=0,o=n.length;r<o;r++){var a,i,c,l=n[r];"string"!=typeof l&&(a=l.content,Array.isArray(a)?"template-string"===l.type?(l=a[1],3===a.length&&"string"!=typeof l&&"embedded-code"===l.type&&(i=u(l),l=l.alias,l=Array.isArray(l)?l[0]:l,c=e.languages[l])&&(a[1]=s(i,c,l))):t(a):"string"!=typeof a&&t([a]))}}(t.tokens)}))}(S),function(e){e.languages.typescript=e.languages.extend("javascript",{"class-name":{pattern:/(\b(?:class|extends|implements|instanceof|interface|new|type)\s+)(?!keyof\b)(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?:\s*<(?:[^<>]|<(?:[^<>]|<[^<>]*>)*>)*>)?/,lookbehind:!0,greedy:!0,inside:null},builtin:/\b(?:Array|Function|Promise|any|boolean|console|never|number|string|symbol|unknown)\b/}),e.languages.typescript.keyword.push(/\b(?:abstract|declare|is|keyof|readonly|require)\b/,/\b(?:asserts|infer|interface|module|namespace|type)\b(?=\s*(?:[{_$a-zA-Z\xA0-\uFFFF]|$))/,/\btype\b(?=\s*(?:[\{*]|$))/),delete e.languages.typescript.parameter,delete e.languages.typescript["literal-property"];var t=e.languages.extend("typescript",{});delete t["class-name"],e.languages.typescript["class-name"].inside=t,e.languages.insertBefore("typescript","function",{decorator:{pattern:/@[$\w\xA0-\uFFFF]+/,inside:{at:{pattern:/^@/,alias:"operator"},function:/^[\s\S]+/}},"generic-function":{pattern:/#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*\s*<(?:[^<>]|<(?:[^<>]|<[^<>]*>)*>)*>(?=\s*\()/,greedy:!0,inside:{function:/^#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*/,generic:{pattern:/<[\s\S]+/,alias:"class-name",inside:t}}}}),e.languages.ts=e.languages.typescript}(S),function(e){var t=e.languages.javascript,n=/\{(?:[^{}]|\{(?:[^{}]|\{[^{}]*\})*\})+\}/.source,r="(@(?:arg|argument|param|property)\\s+(?:"+n+"\\s+)?)";e.languages.jsdoc=e.languages.extend("javadoclike",{parameter:{pattern:RegExp(r+/(?:(?!\s)[$\w\xA0-\uFFFF.])+(?=\s|$)/.source),lookbehind:!0,inside:{punctuation:/\./}}}),e.languages.insertBefore("jsdoc","keyword",{"optional-parameter":{pattern:RegExp(r+/\[(?:(?!\s)[$\w\xA0-\uFFFF.])+(?:=[^[\]]+)?\](?=\s|$)/.source),lookbehind:!0,inside:{parameter:{pattern:/(^\[)[$\w\xA0-\uFFFF\.]+/,lookbehind:!0,inside:{punctuation:/\./}},code:{pattern:/(=)[\s\S]*(?=\]$)/,lookbehind:!0,inside:t,alias:"language-javascript"},punctuation:/[=[\]]/}},"class-name":[{pattern:RegExp(/(@(?:augments|class|extends|interface|memberof!?|template|this|typedef)\s+(?:<TYPE>\s+)?)[A-Z]\w*(?:\.[A-Z]\w*)*/.source.replace(/<TYPE>/g,(function(){return n}))),lookbehind:!0,inside:{punctuation:/\./}},{pattern:RegExp("(@[a-z]+\\s+)"+n),lookbehind:!0,inside:{string:t.string,number:t.number,boolean:t.boolean,keyword:e.languages.typescript.keyword,operator:/=>|\.\.\.|[&|?:*]/,punctuation:/[.,;=<>{}()[\]]/}}],example:{pattern:/(@example\s+(?!\s))(?:[^@\s]|\s+(?!\s))+?(?=\s*(?:\*\s*)?(?:@\w|\*\/))/,lookbehind:!0,inside:{code:{pattern:/^([\t ]*(?:\*\s*)?)\S.*$/m,lookbehind:!0,inside:t,alias:"language-javascript"}}}}),e.languages.javadoclike.addSupport("javascript",e.languages.jsdoc)}(S),function(e){e.languages.flow=e.languages.extend("javascript",{}),e.languages.insertBefore("flow","keyword",{type:[{pattern:/\b(?:[Bb]oolean|Function|[Nn]umber|[Ss]tring|[Ss]ymbol|any|mixed|null|void)\b/,alias:"class-name"}]}),e.languages.flow["function-variable"].pattern=/(?!\s)[_$a-z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*=\s*(?:function\b|(?:\([^()]*\)(?:\s*:\s*\w+)?|(?!\s)[_$a-z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*)\s*=>))/i,delete e.languages.flow.parameter,e.languages.insertBefore("flow","operator",{"flow-punctuation":{pattern:/\{\||\|\}/,alias:"punctuation"}}),Array.isArray(e.languages.flow.keyword)||(e.languages.flow.keyword=[e.languages.flow.keyword]),e.languages.flow.keyword.unshift({pattern:/(^|[^$]\b)(?:Class|declare|opaque|type)\b(?!\$)/,lookbehind:!0},{pattern:/(^|[^$]\B)\$(?:Diff|Enum|Exact|Keys|ObjMap|PropertyType|Record|Shape|Subtype|Supertype|await)\b(?!\$)/,lookbehind:!0})}(S),S.languages.n4js=S.languages.extend("javascript",{keyword:/\b(?:Array|any|boolean|break|case|catch|class|const|constructor|continue|debugger|declare|default|delete|do|else|enum|export|extends|false|finally|for|from|function|get|if|implements|import|in|instanceof|interface|let|module|new|null|number|package|private|protected|public|return|set|static|string|super|switch|this|throw|true|try|typeof|var|void|while|with|yield)\b/}),S.languages.insertBefore("n4js","constant",{annotation:{pattern:/@+\w+/,alias:"operator"}}),S.languages.n4jsd=S.languages.n4js,function(e){function t(e,t){return RegExp(e.replace(/<ID>/g,(function(){return/(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*/.source})),t)}e.languages.insertBefore("javascript","function-variable",{"method-variable":{pattern:RegExp("(\\.\\s*)"+e.languages.javascript["function-variable"].pattern.source),lookbehind:!0,alias:["function-variable","method","function","property-access"]}}),e.languages.insertBefore("javascript","function",{method:{pattern:RegExp("(\\.\\s*)"+e.languages.javascript.function.source),lookbehind:!0,alias:["function","property-access"]}}),e.languages.insertBefore("javascript","constant",{"known-class-name":[{pattern:/\b(?:(?:Float(?:32|64)|(?:Int|Uint)(?:8|16|32)|Uint8Clamped)?Array|ArrayBuffer|BigInt|Boolean|DataView|Date|Error|Function|Intl|JSON|(?:Weak)?(?:Map|Set)|Math|Number|Object|Promise|Proxy|Reflect|RegExp|String|Symbol|WebAssembly)\b/,alias:"class-name"},{pattern:/\b(?:[A-Z]\w*)Error\b/,alias:"class-name"}]}),e.languages.insertBefore("javascript","keyword",{imports:{pattern:t(/(\bimport\b\s*)(?:<ID>(?:\s*,\s*(?:\*\s*as\s+<ID>|\{[^{}]*\}))?|\*\s*as\s+<ID>|\{[^{}]*\})(?=\s*\bfrom\b)/.source),lookbehind:!0,inside:e.languages.javascript},exports:{pattern:t(/(\bexport\b\s*)(?:\*(?:\s*as\s+<ID>)?(?=\s*\bfrom\b)|\{[^{}]*\})/.source),lookbehind:!0,inside:e.languages.javascript}}),e.languages.javascript.keyword.unshift({pattern:/\b(?:as|default|export|from|import)\b/,alias:"module"},{pattern:/\b(?:await|break|catch|continue|do|else|finally|for|if|return|switch|throw|try|while|yield)\b/,alias:"control-flow"},{pattern:/\bnull\b/,alias:["null","nil"]},{pattern:/\bundefined\b/,alias:"nil"}),e.languages.insertBefore("javascript","operator",{spread:{pattern:/\.{3}/,alias:"operator"},arrow:{pattern:/=>/,alias:"operator"}}),e.languages.insertBefore("javascript","punctuation",{"property-access":{pattern:t(/(\.\s*)#?<ID>/.source),lookbehind:!0},"maybe-class-name":{pattern:/(^|[^$\w\xA0-\uFFFF])[A-Z][$\w\xA0-\uFFFF]+/,lookbehind:!0},dom:{pattern:/\b(?:document|(?:local|session)Storage|location|navigator|performance|window)\b/,alias:"variable"},console:{pattern:/\bconsole(?=\s*\.)/,alias:"class-name"}});for(var n=["function","function-variable","method","method-variable","property-access"],r=0;r<n.length;r++){var o=n[r],a=e.languages.javascript[o];o=(a="RegExp"===e.util.type(a)?e.languages.javascript[o]={pattern:a}:a).inside||{};(a.inside=o)["maybe-class-name"]=/^[A-Z][\s\S]*/}}(S),function(e){var t=e.util.clone(e.languages.javascript),n=/(?:\s|\/\/.*(?!.)|\/\*(?:[^*]|\*(?!\/))\*\/)/.source,r=/(?:\{(?:\{(?:\{[^{}]*\}|[^{}])*\}|[^{}])*\})/.source,o=/(?:\{<S>*\.{3}(?:[^{}]|<BRACES>)*\})/.source;function a(e,t){return e=e.replace(/<S>/g,(function(){return n})).replace(/<BRACES>/g,(function(){return r})).replace(/<SPREAD>/g,(function(){return o})),RegExp(e,t)}function i(t){for(var n=[],r=0;r<t.length;r++){var o=t[r],a=!1;"string"!=typeof o&&("tag"===o.type&&o.content[0]&&"tag"===o.content[0].type?"</"===o.content[0].content[0].content?0<n.length&&n[n.length-1].tagName===c(o.content[0].content[1])&&n.pop():"/>"!==o.content[o.content.length-1].content&&n.push({tagName:c(o.content[0].content[1]),openedBraces:0}):0<n.length&&"punctuation"===o.type&&"{"===o.content?n[n.length-1].openedBraces++:0<n.length&&0<n[n.length-1].openedBraces&&"punctuation"===o.type&&"}"===o.content?n[n.length-1].openedBraces--:a=!0),(a||"string"==typeof o)&&0<n.length&&0===n[n.length-1].openedBraces&&(a=c(o),r<t.length-1&&("string"==typeof t[r+1]||"plain-text"===t[r+1].type)&&(a+=c(t[r+1]),t.splice(r+1,1)),0<r&&("string"==typeof t[r-1]||"plain-text"===t[r-1].type)&&(a=c(t[r-1])+a,t.splice(r-1,1),r--),t[r]=new e.Token("plain-text",a,null,a)),o.content&&"string"!=typeof o.content&&i(o.content)}}o=a(o).source,e.languages.jsx=e.languages.extend("markup",t),e.languages.jsx.tag.pattern=a(/<\/?(?:[\w.:-]+(?:<S>+(?:[\w.:$-]+(?:=(?:"(?:\\[\s\S]|[^\\"])*"|'(?:\\[\s\S]|[^\\'])*'|[^\s{'"/>=]+|<BRACES>))?|<SPREAD>))*<S>*\/?)?>/.source),e.languages.jsx.tag.inside.tag.pattern=/^<\/?[^\s>\/]*/,e.languages.jsx.tag.inside["attr-value"].pattern=/=(?!\{)(?:"(?:\\[\s\S]|[^\\"])*"|'(?:\\[\s\S]|[^\\'])*'|[^\s'">]+)/,e.languages.jsx.tag.inside.tag.inside["class-name"]=/^[A-Z]\w*(?:\.[A-Z]\w*)*$/,e.languages.jsx.tag.inside.comment=t.comment,e.languages.insertBefore("inside","attr-name",{spread:{pattern:a(/<SPREAD>/.source),inside:e.languages.jsx}},e.languages.jsx.tag),e.languages.insertBefore("inside","special-attr",{script:{pattern:a(/=<BRACES>/.source),alias:"language-javascript",inside:{"script-punctuation":{pattern:/^=(?=\{)/,alias:"punctuation"},rest:e.languages.jsx}}},e.languages.jsx.tag);var c=function(e){return e?"string"==typeof e?e:"string"==typeof e.content?e.content:e.content.map(c).join(""):""};e.hooks.add("after-tokenize",(function(e){"jsx"!==e.language&&"tsx"!==e.language||i(e.tokens)}))}(S),function(e){var t=e.util.clone(e.languages.typescript);(t=(e.languages.tsx=e.languages.extend("jsx",t),delete e.languages.tsx.parameter,delete e.languages.tsx["literal-property"],e.languages.tsx.tag)).pattern=RegExp(/(^|[^\w$]|(?=<\/))/.source+"(?:"+t.pattern.source+")",t.pattern.flags),t.lookbehind=!0}(S),S.languages.swift={comment:{pattern:/(^|[^\\:])(?:\/\/.*|\/\*(?:[^/*]|\/(?!\*)|\*(?!\/)|\/\*(?:[^*]|\*(?!\/))*\*\/)*\*\/)/,lookbehind:!0,greedy:!0},"string-literal":[{pattern:RegExp(/(^|[^"#])/.source+"(?:"+/"(?:\\(?:\((?:[^()]|\([^()]*\))*\)|\r\n|[^(])|[^\\\r\n"])*"/.source+"|"+/"""(?:\\(?:\((?:[^()]|\([^()]*\))*\)|[^(])|[^\\"]|"(?!""))*"""/.source+")"+/(?!["#])/.source),lookbehind:!0,greedy:!0,inside:{interpolation:{pattern:/(\\\()(?:[^()]|\([^()]*\))*(?=\))/,lookbehind:!0,inside:null},"interpolation-punctuation":{pattern:/^\)|\\\($/,alias:"punctuation"},punctuation:/\\(?=[\r\n])/,string:/[\s\S]+/}},{pattern:RegExp(/(^|[^"#])(#+)/.source+"(?:"+/"(?:\\(?:#+\((?:[^()]|\([^()]*\))*\)|\r\n|[^#])|[^\\\r\n])*?"/.source+"|"+/"""(?:\\(?:#+\((?:[^()]|\([^()]*\))*\)|[^#])|[^\\])*?"""/.source+")\\2"),lookbehind:!0,greedy:!0,inside:{interpolation:{pattern:/(\\#+\()(?:[^()]|\([^()]*\))*(?=\))/,lookbehind:!0,inside:null},"interpolation-punctuation":{pattern:/^\)|\\#+\($/,alias:"punctuation"},string:/[\s\S]+/}}],directive:{pattern:RegExp(/#/.source+"(?:"+/(?:elseif|if)\b/.source+"(?:[ \t]*"+/(?:![ \t]*)?(?:\b\w+\b(?:[ \t]*\((?:[^()]|\([^()]*\))*\))?|\((?:[^()]|\([^()]*\))*\))(?:[ \t]*(?:&&|\|\|))?/.source+")+|"+/(?:else|endif)\b/.source+")"),alias:"property",inside:{"directive-name":/^#\w+/,boolean:/\b(?:false|true)\b/,number:/\b\d+(?:\.\d+)*\b/,operator:/!|&&|\|\||[<>]=?/,punctuation:/[(),]/}},literal:{pattern:/#(?:colorLiteral|column|dsohandle|file(?:ID|Literal|Path)?|function|imageLiteral|line)\b/,alias:"constant"},"other-directive":{pattern:/#\w+\b/,alias:"property"},attribute:{pattern:/@\w+/,alias:"atrule"},"function-definition":{pattern:/(\bfunc\s+)\w+/,lookbehind:!0,alias:"function"},label:{pattern:/\b(break|continue)\s+\w+|\b[a-zA-Z_]\w*(?=\s*:\s*(?:for|repeat|while)\b)/,lookbehind:!0,alias:"important"},keyword:/\b(?:Any|Protocol|Self|Type|actor|as|assignment|associatedtype|associativity|async|await|break|case|catch|class|continue|convenience|default|defer|deinit|didSet|do|dynamic|else|enum|extension|fallthrough|fileprivate|final|for|func|get|guard|higherThan|if|import|in|indirect|infix|init|inout|internal|is|isolated|lazy|left|let|lowerThan|mutating|none|nonisolated|nonmutating|open|operator|optional|override|postfix|precedencegroup|prefix|private|protocol|public|repeat|required|rethrows|return|right|safe|self|set|some|static|struct|subscript|super|switch|throw|throws|try|typealias|unowned|unsafe|var|weak|where|while|willSet)\b/,boolean:/\b(?:false|true)\b/,nil:{pattern:/\bnil\b/,alias:"constant"},"short-argument":/\$\d+\b/,omit:{pattern:/\b_\b/,alias:"keyword"},number:/\b(?:[\d_]+(?:\.[\de_]+)?|0x[a-f0-9_]+(?:\.[a-f0-9p_]+)?|0b[01_]+|0o[0-7_]+)\b/i,"class-name":/\b[A-Z](?:[A-Z_\d]*[a-z]\w*)?\b/,function:/\b[a-z_]\w*(?=\s*\()/i,constant:/\b(?:[A-Z_]{2,}|k[A-Z][A-Za-z_]+)\b/,operator:/[-+*/%=!<>&|^~?]+|\.[.\-+*/%=!<>&|^~?]+/,punctuation:/[{}[\]();,.:\\]/},S.languages.swift["string-literal"].forEach((function(e){e.inside.interpolation.inside=S.languages.swift})),function(e){e.languages.kotlin=e.languages.extend("clike",{keyword:{pattern:/(^|[^.])\b(?:abstract|actual|annotation|as|break|by|catch|class|companion|const|constructor|continue|crossinline|data|do|dynamic|else|enum|expect|external|final|finally|for|fun|get|if|import|in|infix|init|inline|inner|interface|internal|is|lateinit|noinline|null|object|open|operator|out|override|package|private|protected|public|reified|return|sealed|set|super|suspend|tailrec|this|throw|to|try|typealias|val|var|vararg|when|where|while)\b/,lookbehind:!0},function:[{pattern:/(?:`[^\r\n`]+`|\b\w+)(?=\s*\()/,greedy:!0},{pattern:/(\.)(?:`[^\r\n`]+`|\w+)(?=\s*\{)/,lookbehind:!0,greedy:!0}],number:/\b(?:0[xX][\da-fA-F]+(?:_[\da-fA-F]+)*|0[bB][01]+(?:_[01]+)*|\d+(?:_\d+)*(?:\.\d+(?:_\d+)*)?(?:[eE][+-]?\d+(?:_\d+)*)?[fFL]?)\b/,operator:/\+[+=]?|-[-=>]?|==?=?|!(?:!|==?)?|[\/*%<>]=?|[?:]:?|\.\.|&&|\|\||\b(?:and|inv|or|shl|shr|ushr|xor)\b/}),delete e.languages.kotlin["class-name"];var t={"interpolation-punctuation":{pattern:/^\$\{?|\}$/,alias:"punctuation"},expression:{pattern:/[\s\S]+/,inside:e.languages.kotlin}};e.languages.insertBefore("kotlin","string",{"string-literal":[{pattern:/"""(?:[^$]|\$(?:(?!\{)|\{[^{}]*\}))*?"""/,alias:"multiline",inside:{interpolation:{pattern:/\$(?:[a-z_]\w*|\{[^{}]*\})/i,inside:t},string:/[\s\S]+/}},{pattern:/"(?:[^"\\\r\n$]|\\.|\$(?:(?!\{)|\{[^{}]*\}))*"/,alias:"singleline",inside:{interpolation:{pattern:/((?:^|[^\\])(?:\\{2})*)\$(?:[a-z_]\w*|\{[^{}]*\})/i,lookbehind:!0,inside:t},string:/[\s\S]+/}}],char:{pattern:/'(?:[^'\\\r\n]|\\(?:.|u[a-fA-F0-9]{0,4}))'/,greedy:!0}}),delete e.languages.kotlin.string,e.languages.insertBefore("kotlin","keyword",{annotation:{pattern:/\B@(?:\w+:)?(?:[A-Z]\w*|\[[^\]]+\])/,alias:"builtin"}}),e.languages.insertBefore("kotlin","function",{label:{pattern:/\b\w+@|@\w+\b/,alias:"symbol"}}),e.languages.kt=e.languages.kotlin,e.languages.kts=e.languages.kotlin}(S),S.languages.c=S.languages.extend("clike",{comment:{pattern:/\/\/(?:[^\r\n\\]|\\(?:\r\n?|\n|(?![\r\n])))*|\/\*[\s\S]*?(?:\*\/|$)/,greedy:!0},string:{pattern:/"(?:\\(?:\r\n|[\s\S])|[^"\\\r\n])*"/,greedy:!0},"class-name":{pattern:/(\b(?:enum|struct)\s+(?:__attribute__\s*\(\([\s\S]*?\)\)\s*)?)\w+|\b[a-z]\w*_t\b/,lookbehind:!0},keyword:/\b(?:_Alignas|_Alignof|_Atomic|_Bool|_Complex|_Generic|_Imaginary|_Noreturn|_Static_assert|_Thread_local|__attribute__|asm|auto|break|case|char|const|continue|default|do|double|else|enum|extern|float|for|goto|if|inline|int|long|register|return|short|signed|sizeof|static|struct|switch|typedef|typeof|union|unsigned|void|volatile|while)\b/,function:/\b[a-z_]\w*(?=\s*\()/i,number:/(?:\b0x(?:[\da-f]+(?:\.[\da-f]*)?|\.[\da-f]+)(?:p[+-]?\d+)?|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:e[+-]?\d+)?)[ful]{0,4}/i,operator:/>>=?|<<=?|->|([-+&|:])\1|[?:~]|[-+*/%&|^!=<>]=?/}),S.languages.insertBefore("c","string",{char:{pattern:/'(?:\\(?:\r\n|[\s\S])|[^'\\\r\n]){0,32}'/,greedy:!0}}),S.languages.insertBefore("c","string",{macro:{pattern:/(^[\t ]*)#\s*[a-z](?:[^\r\n\\/]|\/(?!\*)|\/\*(?:[^*]|\*(?!\/))*\*\/|\\(?:\r\n|[\s\S]))*/im,lookbehind:!0,greedy:!0,alias:"property",inside:{string:[{pattern:/^(#\s*include\s*)<[^>]+>/,lookbehind:!0},S.languages.c.string],char:S.languages.c.char,comment:S.languages.c.comment,"macro-name":[{pattern:/(^#\s*define\s+)\w+\b(?!\()/i,lookbehind:!0},{pattern:/(^#\s*define\s+)\w+\b(?=\()/i,lookbehind:!0,alias:"function"}],directive:{pattern:/^(#\s*)[a-z]+/,lookbehind:!0,alias:"keyword"},"directive-hash":/^#/,punctuation:/##|\\(?=[\r\n])/,expression:{pattern:/\S[\s\S]*/,inside:S.languages.c}}}}),S.languages.insertBefore("c","function",{constant:/\b(?:EOF|NULL|SEEK_CUR|SEEK_END|SEEK_SET|__DATE__|__FILE__|__LINE__|__TIMESTAMP__|__TIME__|__func__|stderr|stdin|stdout)\b/}),delete S.languages.c.boolean,S.languages.objectivec=S.languages.extend("c",{string:{pattern:/@?"(?:\\(?:\r\n|[\s\S])|[^"\\\r\n])*"/,greedy:!0},keyword:/\b(?:asm|auto|break|case|char|const|continue|default|do|double|else|enum|extern|float|for|goto|if|in|inline|int|long|register|return|self|short|signed|sizeof|static|struct|super|switch|typedef|typeof|union|unsigned|void|volatile|while)\b|(?:@interface|@end|@implementation|@protocol|@class|@public|@protected|@private|@property|@try|@catch|@finally|@throw|@synthesize|@dynamic|@selector)\b/,operator:/-[->]?|\+\+?|!=?|<<?=?|>>?=?|==?|&&?|\|\|?|[~^%?*\/@]/}),delete S.languages.objectivec["class-name"],S.languages.objc=S.languages.objectivec,S.languages.reason=S.languages.extend("clike",{string:{pattern:/"(?:\\(?:\r\n|[\s\S])|[^\\\r\n"])*"/,greedy:!0},"class-name":/\b[A-Z]\w*/,keyword:/\b(?:and|as|assert|begin|class|constraint|do|done|downto|else|end|exception|external|for|fun|function|functor|if|in|include|inherit|initializer|lazy|let|method|module|mutable|new|nonrec|object|of|open|or|private|rec|sig|struct|switch|then|to|try|type|val|virtual|when|while|with)\b/,operator:/\.{3}|:[:=]|\|>|->|=(?:==?|>)?|<=?|>=?|[|^?'#!~`]|[+\-*\/]\.?|\b(?:asr|land|lor|lsl|lsr|lxor|mod)\b/}),S.languages.insertBefore("reason","class-name",{char:{pattern:/'(?:\\x[\da-f]{2}|\\o[0-3][0-7][0-7]|\\\d{3}|\\.|[^'\\\r\n])'/,greedy:!0},constructor:/\b[A-Z]\w*\b(?!\s*\.)/,label:{pattern:/\b[a-z]\w*(?=::)/,alias:"symbol"}}),delete S.languages.reason.function,function(e){for(var t=/\/\*(?:[^*/]|\*(?!\/)|\/(?!\*)|<self>)*\*\//.source,n=0;n<2;n++)t=t.replace(/<self>/g,(function(){return t}));t=t.replace(/<self>/g,(function(){return/[^\s\S]/.source})),e.languages.rust={comment:[{pattern:RegExp(/(^|[^\\])/.source+t),lookbehind:!0,greedy:!0},{pattern:/(^|[^\\:])\/\/.*/,lookbehind:!0,greedy:!0}],string:{pattern:/b?"(?:\\[\s\S]|[^\\"])*"|b?r(#*)"(?:[^"]|"(?!\1))*"\1/,greedy:!0},char:{pattern:/b?'(?:\\(?:x[0-7][\da-fA-F]|u\{(?:[\da-fA-F]_*){1,6}\}|.)|[^\\\r\n\t'])'/,greedy:!0},attribute:{pattern:/#!?\[(?:[^\[\]"]|"(?:\\[\s\S]|[^\\"])*")*\]/,greedy:!0,alias:"attr-name",inside:{string:null}},"closure-params":{pattern:/([=(,:]\s*|\bmove\s*)\|[^|]*\||\|[^|]*\|(?=\s*(?:\{|->))/,lookbehind:!0,greedy:!0,inside:{"closure-punctuation":{pattern:/^\||\|$/,alias:"punctuation"},rest:null}},"lifetime-annotation":{pattern:/'\w+/,alias:"symbol"},"fragment-specifier":{pattern:/(\$\w+:)[a-z]+/,lookbehind:!0,alias:"punctuation"},variable:/\$\w+/,"function-definition":{pattern:/(\bfn\s+)\w+/,lookbehind:!0,alias:"function"},"type-definition":{pattern:/(\b(?:enum|struct|trait|type|union)\s+)\w+/,lookbehind:!0,alias:"class-name"},"module-declaration":[{pattern:/(\b(?:crate|mod)\s+)[a-z][a-z_\d]*/,lookbehind:!0,alias:"namespace"},{pattern:/(\b(?:crate|self|super)\s*)::\s*[a-z][a-z_\d]*\b(?:\s*::(?:\s*[a-z][a-z_\d]*\s*::)*)?/,lookbehind:!0,alias:"namespace",inside:{punctuation:/::/}}],keyword:[/\b(?:Self|abstract|as|async|await|become|box|break|const|continue|crate|do|dyn|else|enum|extern|final|fn|for|if|impl|in|let|loop|macro|match|mod|move|mut|override|priv|pub|ref|return|self|static|struct|super|trait|try|type|typeof|union|unsafe|unsized|use|virtual|where|while|yield)\b/,/\b(?:bool|char|f(?:32|64)|[ui](?:8|16|32|64|128|size)|str)\b/],function:/\b[a-z_]\w*(?=\s*(?:::\s*<|\())/,macro:{pattern:/\b\w+!/,alias:"property"},constant:/\b[A-Z_][A-Z_\d]+\b/,"class-name":/\b[A-Z]\w*\b/,namespace:{pattern:/(?:\b[a-z][a-z_\d]*\s*::\s*)*\b[a-z][a-z_\d]*\s*::(?!\s*<)/,inside:{punctuation:/::/}},number:/\b(?:0x[\dA-Fa-f](?:_?[\dA-Fa-f])*|0o[0-7](?:_?[0-7])*|0b[01](?:_?[01])*|(?:(?:\d(?:_?\d)*)?\.)?\d(?:_?\d)*(?:[Ee][+-]?\d+)?)(?:_?(?:f32|f64|[iu](?:8|16|32|64|size)?))?\b/,boolean:/\b(?:false|true)\b/,punctuation:/->|\.\.=|\.{1,3}|::|[{}[\];(),:]/,operator:/[-+*\/%!^]=?|=[=>]?|&[&=]?|\|[|=]?|<<?=?|>>?=?|[@?]/},e.languages.rust["closure-params"].inside.rest=e.languages.rust,e.languages.rust.attribute.inside.string=e.languages.rust.string}(S),S.languages.go=S.languages.extend("clike",{string:{pattern:/(^|[^\\])"(?:\\.|[^"\\\r\n])*"|`[^`]*`/,lookbehind:!0,greedy:!0},keyword:/\b(?:break|case|chan|const|continue|default|defer|else|fallthrough|for|func|go(?:to)?|if|import|interface|map|package|range|return|select|struct|switch|type|var)\b/,boolean:/\b(?:_|false|iota|nil|true)\b/,number:[/\b0(?:b[01_]+|o[0-7_]+)i?\b/i,/\b0x(?:[a-f\d_]+(?:\.[a-f\d_]*)?|\.[a-f\d_]+)(?:p[+-]?\d+(?:_\d+)*)?i?(?!\w)/i,/(?:\b\d[\d_]*(?:\.[\d_]*)?|\B\.\d[\d_]*)(?:e[+-]?[\d_]+)?i?(?!\w)/i],operator:/[*\/%^!=]=?|\+[=+]?|-[=-]?|\|[=|]?|&(?:=|&|\^=?)?|>(?:>=?|=)?|<(?:<=?|=|-)?|:=|\.\.\./,builtin:/\b(?:append|bool|byte|cap|close|complex|complex(?:64|128)|copy|delete|error|float(?:32|64)|u?int(?:8|16|32|64)?|imag|len|make|new|panic|print(?:ln)?|real|recover|rune|string|uintptr)\b/}),S.languages.insertBefore("go","string",{char:{pattern:/'(?:\\.|[^'\\\r\n]){0,10}'/,greedy:!0}}),delete S.languages.go["class-name"],function(e){var t=/\b(?:alignas|alignof|asm|auto|bool|break|case|catch|char|char16_t|char32_t|char8_t|class|co_await|co_return|co_yield|compl|concept|const|const_cast|consteval|constexpr|constinit|continue|decltype|default|delete|do|double|dynamic_cast|else|enum|explicit|export|extern|final|float|for|friend|goto|if|import|inline|int|int16_t|int32_t|int64_t|int8_t|long|module|mutable|namespace|new|noexcept|nullptr|operator|override|private|protected|public|register|reinterpret_cast|requires|return|short|signed|sizeof|static|static_assert|static_cast|struct|switch|template|this|thread_local|throw|try|typedef|typeid|typename|uint16_t|uint32_t|uint64_t|uint8_t|union|unsigned|using|virtual|void|volatile|wchar_t|while)\b/,n=/\b(?!<keyword>)\w+(?:\s*\.\s*\w+)*\b/.source.replace(/<keyword>/g,(function(){return t.source}));e.languages.cpp=e.languages.extend("c",{"class-name":[{pattern:RegExp(/(\b(?:class|concept|enum|struct|typename)\s+)(?!<keyword>)\w+/.source.replace(/<keyword>/g,(function(){return t.source}))),lookbehind:!0},/\b[A-Z]\w*(?=\s*::\s*\w+\s*\()/,/\b[A-Z_]\w*(?=\s*::\s*~\w+\s*\()/i,/\b\w+(?=\s*<(?:[^<>]|<(?:[^<>]|<[^<>]*>)*>)*>\s*::\s*\w+\s*\()/],keyword:t,number:{pattern:/(?:\b0b[01']+|\b0x(?:[\da-f']+(?:\.[\da-f']*)?|\.[\da-f']+)(?:p[+-]?[\d']+)?|(?:\b[\d']+(?:\.[\d']*)?|\B\.[\d']+)(?:e[+-]?[\d']+)?)[ful]{0,4}/i,greedy:!0},operator:/>>=?|<<=?|->|--|\+\+|&&|\|\||[?:~]|<=>|[-+*/%&|^!=<>]=?|\b(?:and|and_eq|bitand|bitor|not|not_eq|or|or_eq|xor|xor_eq)\b/,boolean:/\b(?:false|true)\b/}),e.languages.insertBefore("cpp","string",{module:{pattern:RegExp(/(\b(?:import|module)\s+)/.source+"(?:"+/"(?:\\(?:\r\n|[\s\S])|[^"\\\r\n])*"|<[^<>\r\n]*>/.source+"|"+/<mod-name>(?:\s*:\s*<mod-name>)?|:\s*<mod-name>/.source.replace(/<mod-name>/g,(function(){return n}))+")"),lookbehind:!0,greedy:!0,inside:{string:/^[<"][\s\S]+/,operator:/:/,punctuation:/\./}},"raw-string":{pattern:/R"([^()\\ ]{0,16})\([\s\S]*?\)\1"/,alias:"string",greedy:!0}}),e.languages.insertBefore("cpp","keyword",{"generic-function":{pattern:/\b(?!operator\b)[a-z_]\w*\s*<(?:[^<>]|<[^<>]*>)*>(?=\s*\()/i,inside:{function:/^\w+/,generic:{pattern:/<[\s\S]+/,alias:"class-name",inside:e.languages.cpp}}}}),e.languages.insertBefore("cpp","operator",{"double-colon":{pattern:/::/,alias:"punctuation"}}),e.languages.insertBefore("cpp","class-name",{"base-clause":{pattern:/(\b(?:class|struct)\s+\w+\s*:\s*)[^;{}"'\s]+(?:\s+[^;{}"'\s]+)*(?=\s*[;{])/,lookbehind:!0,greedy:!0,inside:e.languages.extend("cpp",{})}}),e.languages.insertBefore("inside","double-colon",{"class-name":/\b[a-z_]\w*\b(?!\s*::)/i},e.languages.cpp["base-clause"])}(S),S.languages.python={comment:{pattern:/(^|[^\\])#.*/,lookbehind:!0,greedy:!0},"string-interpolation":{pattern:/(?:f|fr|rf)(?:("""|''')[\s\S]*?\1|("|')(?:\\.|(?!\2)[^\\\r\n])*\2)/i,greedy:!0,inside:{interpolation:{pattern:/((?:^|[^{])(?:\{\{)*)\{(?!\{)(?:[^{}]|\{(?!\{)(?:[^{}]|\{(?!\{)(?:[^{}])+\})+\})+\}/,lookbehind:!0,inside:{"format-spec":{pattern:/(:)[^:(){}]+(?=\}$)/,lookbehind:!0},"conversion-option":{pattern:/![sra](?=[:}]$)/,alias:"punctuation"},rest:null}},string:/[\s\S]+/}},"triple-quoted-string":{pattern:/(?:[rub]|br|rb)?("""|''')[\s\S]*?\1/i,greedy:!0,alias:"string"},string:{pattern:/(?:[rub]|br|rb)?("|')(?:\\.|(?!\1)[^\\\r\n])*\1/i,greedy:!0},function:{pattern:/((?:^|\s)def[ \t]+)[a-zA-Z_]\w*(?=\s*\()/g,lookbehind:!0},"class-name":{pattern:/(\bclass\s+)\w+/i,lookbehind:!0},decorator:{pattern:/(^[\t ]*)@\w+(?:\.\w+)*/m,lookbehind:!0,alias:["annotation","punctuation"],inside:{punctuation:/\./}},keyword:/\b(?:_(?=\s*:)|and|as|assert|async|await|break|case|class|continue|def|del|elif|else|except|exec|finally|for|from|global|if|import|in|is|lambda|match|nonlocal|not|or|pass|print|raise|return|try|while|with|yield)\b/,builtin:/\b(?:__import__|abs|all|any|apply|ascii|basestring|bin|bool|buffer|bytearray|bytes|callable|chr|classmethod|cmp|coerce|compile|complex|delattr|dict|dir|divmod|enumerate|eval|execfile|file|filter|float|format|frozenset|getattr|globals|hasattr|hash|help|hex|id|input|int|intern|isinstance|issubclass|iter|len|list|locals|long|map|max|memoryview|min|next|object|oct|open|ord|pow|property|range|raw_input|reduce|reload|repr|reversed|round|set|setattr|slice|sorted|staticmethod|str|sum|super|tuple|type|unichr|unicode|vars|xrange|zip)\b/,boolean:/\b(?:False|None|True)\b/,number:/\b0(?:b(?:_?[01])+|o(?:_?[0-7])+|x(?:_?[a-f0-9])+)\b|(?:\b\d+(?:_\d+)*(?:\.(?:\d+(?:_\d+)*)?)?|\B\.\d+(?:_\d+)*)(?:e[+-]?\d+(?:_\d+)*)?j?(?!\w)/i,operator:/[-+%=]=?|!=|:=|\*\*?=?|\/\/?=?|<[<=>]?|>[=>]?|[&|^~]/,punctuation:/[{}[\];(),.:]/},S.languages.python["string-interpolation"].inside.interpolation.inside.rest=S.languages.python,S.languages.py=S.languages.python,S.languages.json={property:{pattern:/(^|[^\\])"(?:\\.|[^\\"\r\n])*"(?=\s*:)/,lookbehind:!0,greedy:!0},string:{pattern:/(^|[^\\])"(?:\\.|[^\\"\r\n])*"(?!\s*:)/,lookbehind:!0,greedy:!0},comment:{pattern:/\/\/.*|\/\*[\s\S]*?(?:\*\/|$)/,greedy:!0},number:/-?\b\d+(?:\.\d+)?(?:e[+-]?\d+)?\b/i,punctuation:/[{}[\],]/,operator:/:/,boolean:/\b(?:false|true)\b/,null:{pattern:/\bnull\b/,alias:"keyword"}},S.languages.webmanifest=S.languages.json;((e,t)=>{for(var n in t)s(e,n,{get:t[n],enumerable:!0})})({},{dracula:()=>k,duotoneDark:()=>x,duotoneLight:()=>_,github:()=>C,gruvboxMaterialDark:()=>U,gruvboxMaterialLight:()=>H,jettwaveDark:()=>F,jettwaveLight:()=>B,nightOwl:()=>E,nightOwlLight:()=>D,oceanicNext:()=>A,okaidia:()=>T,oneDark:()=>z,oneLight:()=>$,palenight:()=>P,shadesOfPurple:()=>I,synthwave84:()=>N,ultramin:()=>R,vsDark:()=>L,vsLight:()=>M});var k={plain:{color:"#F8F8F2",backgroundColor:"#282A36"},styles:[{types:["prolog","constant","builtin"],style:{color:"rgb(189, 147, 249)"}},{types:["inserted","function"],style:{color:"rgb(80, 250, 123)"}},{types:["deleted"],style:{color:"rgb(255, 85, 85)"}},{types:["changed"],style:{color:"rgb(255, 184, 108)"}},{types:["punctuation","symbol"],style:{color:"rgb(248, 248, 242)"}},{types:["string","char","tag","selector"],style:{color:"rgb(255, 121, 198)"}},{types:["keyword","variable"],style:{color:"rgb(189, 147, 249)",fontStyle:"italic"}},{types:["comment"],style:{color:"rgb(98, 114, 164)"}},{types:["attr-name"],style:{color:"rgb(241, 250, 140)"}}]},x={plain:{backgroundColor:"#2a2734",color:"#9a86fd"},styles:[{types:["comment","prolog","doctype","cdata","punctuation"],style:{color:"#6c6783"}},{types:["namespace"],style:{opacity:.7}},{types:["tag","operator","number"],style:{color:"#e09142"}},{types:["property","function"],style:{color:"#9a86fd"}},{types:["tag-id","selector","atrule-id"],style:{color:"#eeebff"}},{types:["attr-name"],style:{color:"#c4b9fe"}},{types:["boolean","string","entity","url","attr-value","keyword","control","directive","unit","statement","regex","atrule","placeholder","variable"],style:{color:"#ffcc99"}},{types:["deleted"],style:{textDecorationLine:"line-through"}},{types:["inserted"],style:{textDecorationLine:"underline"}},{types:["italic"],style:{fontStyle:"italic"}},{types:["important","bold"],style:{fontWeight:"bold"}},{types:["important"],style:{color:"#c4b9fe"}}]},_={plain:{backgroundColor:"#faf8f5",color:"#728fcb"},styles:[{types:["comment","prolog","doctype","cdata","punctuation"],style:{color:"#b6ad9a"}},{types:["namespace"],style:{opacity:.7}},{types:["tag","operator","number"],style:{color:"#063289"}},{types:["property","function"],style:{color:"#b29762"}},{types:["tag-id","selector","atrule-id"],style:{color:"#2d2006"}},{types:["attr-name"],style:{color:"#896724"}},{types:["boolean","string","entity","url","attr-value","keyword","control","directive","unit","statement","regex","atrule"],style:{color:"#728fcb"}},{types:["placeholder","variable"],style:{color:"#93abdc"}},{types:["deleted"],style:{textDecorationLine:"line-through"}},{types:["inserted"],style:{textDecorationLine:"underline"}},{types:["italic"],style:{fontStyle:"italic"}},{types:["important","bold"],style:{fontWeight:"bold"}},{types:["important"],style:{color:"#896724"}}]},C={plain:{color:"#393A34",backgroundColor:"#f6f8fa"},styles:[{types:["comment","prolog","doctype","cdata"],style:{color:"#999988",fontStyle:"italic"}},{types:["namespace"],style:{opacity:.7}},{types:["string","attr-value"],style:{color:"#e3116c"}},{types:["punctuation","operator"],style:{color:"#393A34"}},{types:["entity","url","symbol","number","boolean","variable","constant","property","regex","inserted"],style:{color:"#36acaa"}},{types:["atrule","keyword","attr-name","selector"],style:{color:"#00a4db"}},{types:["function","deleted","tag"],style:{color:"#d73a49"}},{types:["function-variable"],style:{color:"#6f42c1"}},{types:["tag","selector","keyword"],style:{color:"#00009f"}}]},E={plain:{color:"#d6deeb",backgroundColor:"#011627"},styles:[{types:["changed"],style:{color:"rgb(162, 191, 252)",fontStyle:"italic"}},{types:["deleted"],style:{color:"rgba(239, 83, 80, 0.56)",fontStyle:"italic"}},{types:["inserted","attr-name"],style:{color:"rgb(173, 219, 103)",fontStyle:"italic"}},{types:["comment"],style:{color:"rgb(99, 119, 119)",fontStyle:"italic"}},{types:["string","url"],style:{color:"rgb(173, 219, 103)"}},{types:["variable"],style:{color:"rgb(214, 222, 235)"}},{types:["number"],style:{color:"rgb(247, 140, 108)"}},{types:["builtin","char","constant","function"],style:{color:"rgb(130, 170, 255)"}},{types:["punctuation"],style:{color:"rgb(199, 146, 234)"}},{types:["selector","doctype"],style:{color:"rgb(199, 146, 234)",fontStyle:"italic"}},{types:["class-name"],style:{color:"rgb(255, 203, 139)"}},{types:["tag","operator","keyword"],style:{color:"rgb(127, 219, 202)"}},{types:["boolean"],style:{color:"rgb(255, 88, 116)"}},{types:["property"],style:{color:"rgb(128, 203, 196)"}},{types:["namespace"],style:{color:"rgb(178, 204, 214)"}}]},D={plain:{color:"#403f53",backgroundColor:"#FBFBFB"},styles:[{types:["changed"],style:{color:"rgb(162, 191, 252)",fontStyle:"italic"}},{types:["deleted"],style:{color:"rgba(239, 83, 80, 0.56)",fontStyle:"italic"}},{types:["inserted","attr-name"],style:{color:"rgb(72, 118, 214)",fontStyle:"italic"}},{types:["comment"],style:{color:"rgb(152, 159, 177)",fontStyle:"italic"}},{types:["string","builtin","char","constant","url"],style:{color:"rgb(72, 118, 214)"}},{types:["variable"],style:{color:"rgb(201, 103, 101)"}},{types:["number"],style:{color:"rgb(170, 9, 130)"}},{types:["punctuation"],style:{color:"rgb(153, 76, 195)"}},{types:["function","selector","doctype"],style:{color:"rgb(153, 76, 195)",fontStyle:"italic"}},{types:["class-name"],style:{color:"rgb(17, 17, 17)"}},{types:["tag"],style:{color:"rgb(153, 76, 195)"}},{types:["operator","property","keyword","namespace"],style:{color:"rgb(12, 150, 155)"}},{types:["boolean"],style:{color:"rgb(188, 84, 84)"}}]},j="#c5a5c5",O="#8dc891",A={plain:{backgroundColor:"#282c34",color:"#ffffff"},styles:[{types:["attr-name"],style:{color:j}},{types:["attr-value"],style:{color:O}},{types:["comment","block-comment","prolog","doctype","cdata","shebang"],style:{color:"#999999"}},{types:["property","number","function-name","constant","symbol","deleted"],style:{color:"#5a9bcf"}},{types:["boolean"],style:{color:"#ff8b50"}},{types:["tag"],style:{color:"#fc929e"}},{types:["string"],style:{color:O}},{types:["punctuation"],style:{color:O}},{types:["selector","char","builtin","inserted"],style:{color:"#D8DEE9"}},{types:["function"],style:{color:"#79b6f2"}},{types:["operator","entity","url","variable"],style:{color:"#d7deea"}},{types:["keyword"],style:{color:j}},{types:["atrule","class-name"],style:{color:"#FAC863"}},{types:["important"],style:{fontWeight:"400"}},{types:["bold"],style:{fontWeight:"bold"}},{types:["italic"],style:{fontStyle:"italic"}},{types:["namespace"],style:{opacity:.7}}]},T={plain:{color:"#f8f8f2",backgroundColor:"#272822"},styles:[{types:["changed"],style:{color:"rgb(162, 191, 252)",fontStyle:"italic"}},{types:["deleted"],style:{color:"#f92672",fontStyle:"italic"}},{types:["inserted"],style:{color:"rgb(173, 219, 103)",fontStyle:"italic"}},{types:["comment"],style:{color:"#8292a2",fontStyle:"italic"}},{types:["string","url"],style:{color:"#a6e22e"}},{types:["variable"],style:{color:"#f8f8f2"}},{types:["number"],style:{color:"#ae81ff"}},{types:["builtin","char","constant","function","class-name"],style:{color:"#e6db74"}},{types:["punctuation"],style:{color:"#f8f8f2"}},{types:["selector","doctype"],style:{color:"#a6e22e",fontStyle:"italic"}},{types:["tag","operator","keyword"],style:{color:"#66d9ef"}},{types:["boolean"],style:{color:"#ae81ff"}},{types:["namespace"],style:{color:"rgb(178, 204, 214)",opacity:.7}},{types:["tag","property"],style:{color:"#f92672"}},{types:["attr-name"],style:{color:"#a6e22e !important"}},{types:["doctype"],style:{color:"#8292a2"}},{types:["rule"],style:{color:"#e6db74"}}]},P={plain:{color:"#bfc7d5",backgroundColor:"#292d3e"},styles:[{types:["comment"],style:{color:"rgb(105, 112, 152)",fontStyle:"italic"}},{types:["string","inserted"],style:{color:"rgb(195, 232, 141)"}},{types:["number"],style:{color:"rgb(247, 140, 108)"}},{types:["builtin","char","constant","function"],style:{color:"rgb(130, 170, 255)"}},{types:["punctuation","selector"],style:{color:"rgb(199, 146, 234)"}},{types:["variable"],style:{color:"rgb(191, 199, 213)"}},{types:["class-name","attr-name"],style:{color:"rgb(255, 203, 107)"}},{types:["tag","deleted"],style:{color:"rgb(255, 85, 114)"}},{types:["operator"],style:{color:"rgb(137, 221, 255)"}},{types:["boolean"],style:{color:"rgb(255, 88, 116)"}},{types:["keyword"],style:{fontStyle:"italic"}},{types:["doctype"],style:{color:"rgb(199, 146, 234)",fontStyle:"italic"}},{types:["namespace"],style:{color:"rgb(178, 204, 214)"}},{types:["url"],style:{color:"rgb(221, 221, 221)"}}]},I={plain:{color:"#9EFEFF",backgroundColor:"#2D2A55"},styles:[{types:["changed"],style:{color:"rgb(255, 238, 128)"}},{types:["deleted"],style:{color:"rgba(239, 83, 80, 0.56)"}},{types:["inserted"],style:{color:"rgb(173, 219, 103)"}},{types:["comment"],style:{color:"rgb(179, 98, 255)",fontStyle:"italic"}},{types:["punctuation"],style:{color:"rgb(255, 255, 255)"}},{types:["constant"],style:{color:"rgb(255, 98, 140)"}},{types:["string","url"],style:{color:"rgb(165, 255, 144)"}},{types:["variable"],style:{color:"rgb(255, 238, 128)"}},{types:["number","boolean"],style:{color:"rgb(255, 98, 140)"}},{types:["attr-name"],style:{color:"rgb(255, 180, 84)"}},{types:["keyword","operator","property","namespace","tag","selector","doctype"],style:{color:"rgb(255, 157, 0)"}},{types:["builtin","char","constant","function","class-name"],style:{color:"rgb(250, 208, 0)"}}]},N={plain:{backgroundColor:"linear-gradient(to bottom, #2a2139 75%, #34294f)",backgroundImage:"#34294f",color:"#f92aad",textShadow:"0 0 2px #100c0f, 0 0 5px #dc078e33, 0 0 10px #fff3"},styles:[{types:["comment","block-comment","prolog","doctype","cdata"],style:{color:"#495495",fontStyle:"italic"}},{types:["punctuation"],style:{color:"#ccc"}},{types:["tag","attr-name","namespace","number","unit","hexcode","deleted"],style:{color:"#e2777a"}},{types:["property","selector"],style:{color:"#72f1b8",textShadow:"0 0 2px #100c0f, 0 0 10px #257c5575, 0 0 35px #21272475"}},{types:["function-name"],style:{color:"#6196cc"}},{types:["boolean","selector-id","function"],style:{color:"#fdfdfd",textShadow:"0 0 2px #001716, 0 0 3px #03edf975, 0 0 5px #03edf975, 0 0 8px #03edf975"}},{types:["class-name","maybe-class-name","builtin"],style:{color:"#fff5f6",textShadow:"0 0 2px #000, 0 0 10px #fc1f2c75, 0 0 5px #fc1f2c75, 0 0 25px #fc1f2c75"}},{types:["constant","symbol"],style:{color:"#f92aad",textShadow:"0 0 2px #100c0f, 0 0 5px #dc078e33, 0 0 10px #fff3"}},{types:["important","atrule","keyword","selector-class"],style:{color:"#f4eee4",textShadow:"0 0 2px #393a33, 0 0 8px #f39f0575, 0 0 2px #f39f0575"}},{types:["string","char","attr-value","regex","variable"],style:{color:"#f87c32"}},{types:["parameter"],style:{fontStyle:"italic"}},{types:["entity","url"],style:{color:"#67cdcc"}},{types:["operator"],style:{color:"ffffffee"}},{types:["important","bold"],style:{fontWeight:"bold"}},{types:["italic"],style:{fontStyle:"italic"}},{types:["entity"],style:{cursor:"help"}},{types:["inserted"],style:{color:"green"}}]},R={plain:{color:"#282a2e",backgroundColor:"#ffffff"},styles:[{types:["comment"],style:{color:"rgb(197, 200, 198)"}},{types:["string","number","builtin","variable"],style:{color:"rgb(150, 152, 150)"}},{types:["class-name","function","tag","attr-name"],style:{color:"rgb(40, 42, 46)"}}]},L={plain:{color:"#9CDCFE",backgroundColor:"#1E1E1E"},styles:[{types:["prolog"],style:{color:"rgb(0, 0, 128)"}},{types:["comment"],style:{color:"rgb(106, 153, 85)"}},{types:["builtin","changed","keyword","interpolation-punctuation"],style:{color:"rgb(86, 156, 214)"}},{types:["number","inserted"],style:{color:"rgb(181, 206, 168)"}},{types:["constant"],style:{color:"rgb(100, 102, 149)"}},{types:["attr-name","variable"],style:{color:"rgb(156, 220, 254)"}},{types:["deleted","string","attr-value","template-punctuation"],style:{color:"rgb(206, 145, 120)"}},{types:["selector"],style:{color:"rgb(215, 186, 125)"}},{types:["tag"],style:{color:"rgb(78, 201, 176)"}},{types:["tag"],languages:["markup"],style:{color:"rgb(86, 156, 214)"}},{types:["punctuation","operator"],style:{color:"rgb(212, 212, 212)"}},{types:["punctuation"],languages:["markup"],style:{color:"#808080"}},{types:["function"],style:{color:"rgb(220, 220, 170)"}},{types:["class-name"],style:{color:"rgb(78, 201, 176)"}},{types:["char"],style:{color:"rgb(209, 105, 105)"}}]},M={plain:{color:"#000000",backgroundColor:"#ffffff"},styles:[{types:["comment"],style:{color:"rgb(0, 128, 0)"}},{types:["builtin"],style:{color:"rgb(0, 112, 193)"}},{types:["number","variable","inserted"],style:{color:"rgb(9, 134, 88)"}},{types:["operator"],style:{color:"rgb(0, 0, 0)"}},{types:["constant","char"],style:{color:"rgb(129, 31, 63)"}},{types:["tag"],style:{color:"rgb(128, 0, 0)"}},{types:["attr-name"],style:{color:"rgb(255, 0, 0)"}},{types:["deleted","string"],style:{color:"rgb(163, 21, 21)"}},{types:["changed","punctuation"],style:{color:"rgb(4, 81, 165)"}},{types:["function","keyword"],style:{color:"rgb(0, 0, 255)"}},{types:["class-name"],style:{color:"rgb(38, 127, 153)"}}]},F={plain:{color:"#f8fafc",backgroundColor:"#011627"},styles:[{types:["prolog"],style:{color:"#000080"}},{types:["comment"],style:{color:"#6A9955"}},{types:["builtin","changed","keyword","interpolation-punctuation"],style:{color:"#569CD6"}},{types:["number","inserted"],style:{color:"#B5CEA8"}},{types:["constant"],style:{color:"#f8fafc"}},{types:["attr-name","variable"],style:{color:"#9CDCFE"}},{types:["deleted","string","attr-value","template-punctuation"],style:{color:"#cbd5e1"}},{types:["selector"],style:{color:"#D7BA7D"}},{types:["tag"],style:{color:"#0ea5e9"}},{types:["tag"],languages:["markup"],style:{color:"#0ea5e9"}},{types:["punctuation","operator"],style:{color:"#D4D4D4"}},{types:["punctuation"],languages:["markup"],style:{color:"#808080"}},{types:["function"],style:{color:"#7dd3fc"}},{types:["class-name"],style:{color:"#0ea5e9"}},{types:["char"],style:{color:"#D16969"}}]},B={plain:{color:"#0f172a",backgroundColor:"#f1f5f9"},styles:[{types:["prolog"],style:{color:"#000080"}},{types:["comment"],style:{color:"#6A9955"}},{types:["builtin","changed","keyword","interpolation-punctuation"],style:{color:"#0c4a6e"}},{types:["number","inserted"],style:{color:"#B5CEA8"}},{types:["constant"],style:{color:"#0f172a"}},{types:["attr-name","variable"],style:{color:"#0c4a6e"}},{types:["deleted","string","attr-value","template-punctuation"],style:{color:"#64748b"}},{types:["selector"],style:{color:"#D7BA7D"}},{types:["tag"],style:{color:"#0ea5e9"}},{types:["tag"],languages:["markup"],style:{color:"#0ea5e9"}},{types:["punctuation","operator"],style:{color:"#475569"}},{types:["punctuation"],languages:["markup"],style:{color:"#808080"}},{types:["function"],style:{color:"#0e7490"}},{types:["class-name"],style:{color:"#0ea5e9"}},{types:["char"],style:{color:"#D16969"}}]},z={plain:{backgroundColor:"hsl(220, 13%, 18%)",color:"hsl(220, 14%, 71%)",textShadow:"0 1px rgba(0, 0, 0, 0.3)"},styles:[{types:["comment","prolog","cdata"],style:{color:"hsl(220, 10%, 40%)"}},{types:["doctype","punctuation","entity"],style:{color:"hsl(220, 14%, 71%)"}},{types:["attr-name","class-name","maybe-class-name","boolean","constant","number","atrule"],style:{color:"hsl(29, 54%, 61%)"}},{types:["keyword"],style:{color:"hsl(286, 60%, 67%)"}},{types:["property","tag","symbol","deleted","important"],style:{color:"hsl(355, 65%, 65%)"}},{types:["selector","string","char","builtin","inserted","regex","attr-value"],style:{color:"hsl(95, 38%, 62%)"}},{types:["variable","operator","function"],style:{color:"hsl(207, 82%, 66%)"}},{types:["url"],style:{color:"hsl(187, 47%, 55%)"}},{types:["deleted"],style:{textDecorationLine:"line-through"}},{types:["inserted"],style:{textDecorationLine:"underline"}},{types:["italic"],style:{fontStyle:"italic"}},{types:["important","bold"],style:{fontWeight:"bold"}},{types:["important"],style:{color:"hsl(220, 14%, 71%)"}}]},$={plain:{backgroundColor:"hsl(230, 1%, 98%)",color:"hsl(230, 8%, 24%)"},styles:[{types:["comment","prolog","cdata"],style:{color:"hsl(230, 4%, 64%)"}},{types:["doctype","punctuation","entity"],style:{color:"hsl(230, 8%, 24%)"}},{types:["attr-name","class-name","boolean","constant","number","atrule"],style:{color:"hsl(35, 99%, 36%)"}},{types:["keyword"],style:{color:"hsl(301, 63%, 40%)"}},{types:["property","tag","symbol","deleted","important"],style:{color:"hsl(5, 74%, 59%)"}},{types:["selector","string","char","builtin","inserted","regex","attr-value","punctuation"],style:{color:"hsl(119, 34%, 47%)"}},{types:["variable","operator","function"],style:{color:"hsl(221, 87%, 60%)"}},{types:["url"],style:{color:"hsl(198, 99%, 37%)"}},{types:["deleted"],style:{textDecorationLine:"line-through"}},{types:["inserted"],style:{textDecorationLine:"underline"}},{types:["italic"],style:{fontStyle:"italic"}},{types:["important","bold"],style:{fontWeight:"bold"}},{types:["important"],style:{color:"hsl(230, 8%, 24%)"}}]},U={plain:{color:"#ebdbb2",backgroundColor:"#292828"},styles:[{types:["imports","class-name","maybe-class-name","constant","doctype","builtin","function"],style:{color:"#d8a657"}},{types:["property-access"],style:{color:"#7daea3"}},{types:["tag"],style:{color:"#e78a4e"}},{types:["attr-name","char","url","regex"],style:{color:"#a9b665"}},{types:["attr-value","string"],style:{color:"#89b482"}},{types:["comment","prolog","cdata","operator","inserted"],style:{color:"#a89984"}},{types:["delimiter","boolean","keyword","selector","important","atrule","property","variable","deleted"],style:{color:"#ea6962"}},{types:["entity","number","symbol"],style:{color:"#d3869b"}}]},H={plain:{color:"#654735",backgroundColor:"#f9f5d7"},styles:[{types:["delimiter","boolean","keyword","selector","important","atrule","property","variable","deleted"],style:{color:"#af2528"}},{types:["imports","class-name","maybe-class-name","constant","doctype","builtin"],style:{color:"#b4730e"}},{types:["string","attr-value"],style:{color:"#477a5b"}},{types:["property-access"],style:{color:"#266b79"}},{types:["function","attr-name","char","url"],style:{color:"#72761e"}},{types:["tag"],style:{color:"#b94c07"}},{types:["comment","prolog","cdata","operator","inserted"],style:{color:"#a89984"}},{types:["entity","number","symbol"],style:{color:"#924f79"}}]},q=(e,t)=>{const{plain:n}=e,r=e.styles.reduce(((e,n)=>{const{languages:r,style:o}=n;return r&&!r.includes(t)||n.types.forEach((t=>{const n=y(y({},e[t]),o);e[t]=n})),e}),{});return r.root=n,r.plain=v(y({},n),{backgroundColor:void 0}),r},V=/\r\n|\r|\n/,W=e=>{0===e.length?e.push({types:["plain"],content:"\n",empty:!0}):1===e.length&&""===e[0].content&&(e[0].content="\n",e[0].empty=!0)},G=(e,t)=>{const n=e.length;return n>0&&e[n-1]===t?e:e.concat(t)},K=e=>{const t=[[]],n=[e],r=[0],o=[e.length];let a=0,i=0,c=[];const s=[c];for(;i>-1;){for(;(a=r[i]++)<o[i];){let e,l=t[i];const u=n[i][a];if("string"==typeof u?(l=i>0?l:["plain"],e=u):(l=G(l,u.type),u.alias&&(l=G(l,u.alias)),e=u.content),"string"!=typeof e){i++,t.push(l),n.push(e),r.push(0),o.push(e.length);continue}const d=e.split(V),p=d.length;c.push({types:l,content:d[0]});for(let t=1;t<p;t++)W(c),s.push(c=[]),c.push({types:l,content:d[t]})}i--,t.pop(),n.pop(),r.pop(),o.pop()}return W(c),s},Y=({children:e,language:t,code:n,theme:r,prism:o})=>{const c=t.toLowerCase(),s=((e,t)=>{const[n,r]=(0,a.useState)(q(t,e)),o=(0,a.useRef)(),i=(0,a.useRef)();return(0,a.useEffect)((()=>{t===o.current&&e===i.current||(o.current=t,i.current=e,r(q(t,e)))}),[e,t]),n})(c,r),l=(e=>(0,a.useCallback)((t=>{var n=t,{className:r,style:o,line:a}=n,c=w(n,["className","style","line"]);const s=v(y({},c),{className:(0,i.A)("token-line",r)});return"object"==typeof e&&"plain"in e&&(s.style=e.plain),"object"==typeof o&&(s.style=y(y({},s.style||{}),o)),s}),[e]))(s),u=(e=>{const t=(0,a.useCallback)((({types:t,empty:n})=>{if(null!=e)return 1===t.length&&"plain"===t[0]?null!=n?{display:"inline-block"}:void 0:1===t.length&&null!=n?e[t[0]]:Object.assign(null!=n?{display:"inline-block"}:{},...t.map((t=>e[t])))}),[e]);return(0,a.useCallback)((e=>{var n=e,{token:r,className:o,style:a}=n,c=w(n,["token","className","style"]);const s=v(y({},c),{className:(0,i.A)("token",...r.types,o),children:r.content,style:t(r)});return null!=a&&(s.style=y(y({},s.style||{}),a)),s}),[t])})(s),d=(({prism:e,code:t,grammar:n,language:r})=>{const o=(0,a.useRef)(e);return(0,a.useMemo)((()=>{if(null==n)return K([t]);const e={code:t,grammar:n,language:r,tokens:[]};return o.current.hooks.run("before-tokenize",e),e.tokens=o.current.tokenize(t,n),o.current.hooks.run("after-tokenize",e),K(e.tokens)}),[t,n,r])})({prism:o,language:c,code:n,grammar:o.languages[c]});return e({tokens:d,className:`prism-code language-${c}`,style:null!=s?s.root:{},getLineProps:l,getTokenProps:u})},Q=e=>(0,a.createElement)(Y,v(y({},e),{prism:e.prism||S,theme:e.theme||L,code:e.code,language:e.language}))},1561:(e,t,n)=>{"use strict";n.d(t,{A:()=>a});var r=!0,o="Invariant failed";function a(e,t){if(!e){if(r)throw new Error(o);var n="function"==typeof t?t():t,a=n?"".concat(o,": ").concat(n):o;throw new Error(a)}}},1635:(e,t,n)=>{"use strict";n.r(t),n.d(t,{__addDisposableResource:()=>R,__assign:()=>a,__asyncDelegator:()=>C,__asyncGenerator:()=>_,__asyncValues:()=>E,__await:()=>x,__awaiter:()=>m,__classPrivateFieldGet:()=>P,__classPrivateFieldIn:()=>N,__classPrivateFieldSet:()=>I,__createBinding:()=>h,__decorate:()=>c,__disposeResources:()=>M,__esDecorate:()=>l,__exportStar:()=>b,__extends:()=>o,__generator:()=>g,__importDefault:()=>T,__importStar:()=>A,__makeTemplateObject:()=>D,__metadata:()=>f,__param:()=>s,__propKey:()=>d,__read:()=>v,__rest:()=>i,__rewriteRelativeImportExtension:()=>F,__runInitializers:()=>u,__setFunctionName:()=>p,__spread:()=>w,__spreadArray:()=>k,__spreadArrays:()=>S,__values:()=>y,default:()=>B});var r=function(e,t){return r=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)Object.prototype.hasOwnProperty.call(t,n)&&(e[n]=t[n])},r(e,t)};function o(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Class extends value "+String(t)+" is not a constructor or null");function n(){this.constructor=e}r(e,t),e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)}var a=function(){return a=Object.assign||function(e){for(var t,n=1,r=arguments.length;n<r;n++)for(var o in t=arguments[n])Object.prototype.hasOwnProperty.call(t,o)&&(e[o]=t[o]);return e},a.apply(this,arguments)};function i(e,t){var n={};for(var r in e)Object.prototype.hasOwnProperty.call(e,r)&&t.indexOf(r)<0&&(n[r]=e[r]);if(null!=e&&"function"==typeof Object.getOwnPropertySymbols){var o=0;for(r=Object.getOwnPropertySymbols(e);o<r.length;o++)t.indexOf(r[o])<0&&Object.prototype.propertyIsEnumerable.call(e,r[o])&&(n[r[o]]=e[r[o]])}return n}function c(e,t,n,r){var o,a=arguments.length,i=a<3?t:null===r?r=Object.getOwnPropertyDescriptor(t,n):r;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)i=Reflect.decorate(e,t,n,r);else for(var c=e.length-1;c>=0;c--)(o=e[c])&&(i=(a<3?o(i):a>3?o(t,n,i):o(t,n))||i);return a>3&&i&&Object.defineProperty(t,n,i),i}function s(e,t){return function(n,r){t(n,r,e)}}function l(e,t,n,r,o,a){function i(e){if(void 0!==e&&"function"!=typeof e)throw new TypeError("Function expected");return e}for(var c,s=r.kind,l="getter"===s?"get":"setter"===s?"set":"value",u=!t&&e?r.static?e:e.prototype:null,d=t||(u?Object.getOwnPropertyDescriptor(u,r.name):{}),p=!1,f=n.length-1;f>=0;f--){var m={};for(var g in r)m[g]="access"===g?{}:r[g];for(var g in r.access)m.access[g]=r.access[g];m.addInitializer=function(e){if(p)throw new TypeError("Cannot add initializers after decoration has completed");a.push(i(e||null))};var h=(0,n[f])("accessor"===s?{get:d.get,set:d.set}:d[l],m);if("accessor"===s){if(void 0===h)continue;if(null===h||"object"!=typeof h)throw new TypeError("Object expected");(c=i(h.get))&&(d.get=c),(c=i(h.set))&&(d.set=c),(c=i(h.init))&&o.unshift(c)}else(c=i(h))&&("field"===s?o.unshift(c):d[l]=c)}u&&Object.defineProperty(u,r.name,d),p=!0}function u(e,t,n){for(var r=arguments.length>2,o=0;o<t.length;o++)n=r?t[o].call(e,n):t[o].call(e);return r?n:void 0}function d(e){return"symbol"==typeof e?e:"".concat(e)}function p(e,t,n){return"symbol"==typeof t&&(t=t.description?"[".concat(t.description,"]"):""),Object.defineProperty(e,"name",{configurable:!0,value:n?"".concat(n," ",t):t})}function f(e,t){if("object"==typeof Reflect&&"function"==typeof Reflect.metadata)return Reflect.metadata(e,t)}function m(e,t,n,r){return new(n||(n=Promise))((function(o,a){function i(e){try{s(r.next(e))}catch(t){a(t)}}function c(e){try{s(r.throw(e))}catch(t){a(t)}}function s(e){var t;e.done?o(e.value):(t=e.value,t instanceof n?t:new n((function(e){e(t)}))).then(i,c)}s((r=r.apply(e,t||[])).next())}))}function g(e,t){var n,r,o,a={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]},i=Object.create(("function"==typeof Iterator?Iterator:Object).prototype);return i.next=c(0),i.throw=c(1),i.return=c(2),"function"==typeof Symbol&&(i[Symbol.iterator]=function(){return this}),i;function c(c){return function(s){return function(c){if(n)throw new TypeError("Generator is already executing.");for(;i&&(i=0,c[0]&&(a=0)),a;)try{if(n=1,r&&(o=2&c[0]?r.return:c[0]?r.throw||((o=r.return)&&o.call(r),0):r.next)&&!(o=o.call(r,c[1])).done)return o;switch(r=0,o&&(c=[2&c[0],o.value]),c[0]){case 0:case 1:o=c;break;case 4:return a.label++,{value:c[1],done:!1};case 5:a.label++,r=c[1],c=[0];continue;case 7:c=a.ops.pop(),a.trys.pop();continue;default:if(!(o=a.trys,(o=o.length>0&&o[o.length-1])||6!==c[0]&&2!==c[0])){a=0;continue}if(3===c[0]&&(!o||c[1]>o[0]&&c[1]<o[3])){a.label=c[1];break}if(6===c[0]&&a.label<o[1]){a.label=o[1],o=c;break}if(o&&a.label<o[2]){a.label=o[2],a.ops.push(c);break}o[2]&&a.ops.pop(),a.trys.pop();continue}c=t.call(e,a)}catch(s){c=[6,s],r=0}finally{n=o=0}if(5&c[0])throw c[1];return{value:c[0]?c[1]:void 0,done:!0}}([c,s])}}}var h=Object.create?function(e,t,n,r){void 0===r&&(r=n);var o=Object.getOwnPropertyDescriptor(t,n);o&&!("get"in o?!t.__esModule:o.writable||o.configurable)||(o={enumerable:!0,get:function(){return t[n]}}),Object.defineProperty(e,r,o)}:function(e,t,n,r){void 0===r&&(r=n),e[r]=t[n]};function b(e,t){for(var n in e)"default"===n||Object.prototype.hasOwnProperty.call(t,n)||h(t,e,n)}function y(e){var t="function"==typeof Symbol&&Symbol.iterator,n=t&&e[t],r=0;if(n)return n.call(e);if(e&&"number"==typeof e.length)return{next:function(){return e&&r>=e.length&&(e=void 0),{value:e&&e[r++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")}function v(e,t){var n="function"==typeof Symbol&&e[Symbol.iterator];if(!n)return e;var r,o,a=n.call(e),i=[];try{for(;(void 0===t||t-- >0)&&!(r=a.next()).done;)i.push(r.value)}catch(c){o={error:c}}finally{try{r&&!r.done&&(n=a.return)&&n.call(a)}finally{if(o)throw o.error}}return i}function w(){for(var e=[],t=0;t<arguments.length;t++)e=e.concat(v(arguments[t]));return e}function S(){for(var e=0,t=0,n=arguments.length;t<n;t++)e+=arguments[t].length;var r=Array(e),o=0;for(t=0;t<n;t++)for(var a=arguments[t],i=0,c=a.length;i<c;i++,o++)r[o]=a[i];return r}function k(e,t,n){if(n||2===arguments.length)for(var r,o=0,a=t.length;o<a;o++)!r&&o in t||(r||(r=Array.prototype.slice.call(t,0,o)),r[o]=t[o]);return e.concat(r||Array.prototype.slice.call(t))}function x(e){return this instanceof x?(this.v=e,this):new x(e)}function _(e,t,n){if(!Symbol.asyncIterator)throw new TypeError("Symbol.asyncIterator is not defined.");var r,o=n.apply(e,t||[]),a=[];return r=Object.create(("function"==typeof AsyncIterator?AsyncIterator:Object).prototype),i("next"),i("throw"),i("return",(function(e){return function(t){return Promise.resolve(t).then(e,l)}})),r[Symbol.asyncIterator]=function(){return this},r;function i(e,t){o[e]&&(r[e]=function(t){return new Promise((function(n,r){a.push([e,t,n,r])>1||c(e,t)}))},t&&(r[e]=t(r[e])))}function c(e,t){try{(n=o[e](t)).value instanceof x?Promise.resolve(n.value.v).then(s,l):u(a[0][2],n)}catch(r){u(a[0][3],r)}var n}function s(e){c("next",e)}function l(e){c("throw",e)}function u(e,t){e(t),a.shift(),a.length&&c(a[0][0],a[0][1])}}function C(e){var t,n;return t={},r("next"),r("throw",(function(e){throw e})),r("return"),t[Symbol.iterator]=function(){return this},t;function r(r,o){t[r]=e[r]?function(t){return(n=!n)?{value:x(e[r](t)),done:!1}:o?o(t):t}:o}}function E(e){if(!Symbol.asyncIterator)throw new TypeError("Symbol.asyncIterator is not defined.");var t,n=e[Symbol.asyncIterator];return n?n.call(e):(e=y(e),t={},r("next"),r("throw"),r("return"),t[Symbol.asyncIterator]=function(){return this},t);function r(n){t[n]=e[n]&&function(t){return new Promise((function(r,o){(function(e,t,n,r){Promise.resolve(r).then((function(t){e({value:t,done:n})}),t)})(r,o,(t=e[n](t)).done,t.value)}))}}}function D(e,t){return Object.defineProperty?Object.defineProperty(e,"raw",{value:t}):e.raw=t,e}var j=Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:!0,value:t})}:function(e,t){e.default=t},O=function(e){return O=Object.getOwnPropertyNames||function(e){var t=[];for(var n in e)Object.prototype.hasOwnProperty.call(e,n)&&(t[t.length]=n);return t},O(e)};function A(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var n=O(e),r=0;r<n.length;r++)"default"!==n[r]&&h(t,e,n[r]);return j(t,e),t}function T(e){return e&&e.__esModule?e:{default:e}}function P(e,t,n,r){if("a"===n&&!r)throw new TypeError("Private accessor was defined without a getter");if("function"==typeof t?e!==t||!r:!t.has(e))throw new TypeError("Cannot read private member from an object whose class did not declare it");return"m"===n?r:"a"===n?r.call(e):r?r.value:t.get(e)}function I(e,t,n,r,o){if("m"===r)throw new TypeError("Private method is not writable");if("a"===r&&!o)throw new TypeError("Private accessor was defined without a setter");if("function"==typeof t?e!==t||!o:!t.has(e))throw new TypeError("Cannot write private member to an object whose class did not declare it");return"a"===r?o.call(e,n):o?o.value=n:t.set(e,n),n}function N(e,t){if(null===t||"object"!=typeof t&&"function"!=typeof t)throw new TypeError("Cannot use 'in' operator on non-object");return"function"==typeof e?t===e:e.has(t)}function R(e,t,n){if(null!=t){if("object"!=typeof t&&"function"!=typeof t)throw new TypeError("Object expected.");var r,o;if(n){if(!Symbol.asyncDispose)throw new TypeError("Symbol.asyncDispose is not defined.");r=t[Symbol.asyncDispose]}if(void 0===r){if(!Symbol.dispose)throw new TypeError("Symbol.dispose is not defined.");r=t[Symbol.dispose],n&&(o=r)}if("function"!=typeof r)throw new TypeError("Object not disposable.");o&&(r=function(){try{o.call(this)}catch(e){return Promise.reject(e)}}),e.stack.push({value:t,dispose:r,async:n})}else n&&e.stack.push({async:!0});return t}var L="function"==typeof SuppressedError?SuppressedError:function(e,t,n){var r=new Error(n);return r.name="SuppressedError",r.error=e,r.suppressed=t,r};function M(e){function t(t){e.error=e.hasError?new L(t,e.error,"An error was suppressed during disposal."):t,e.hasError=!0}var n,r=0;return function o(){for(;n=e.stack.pop();)try{if(!n.async&&1===r)return r=0,e.stack.push(n),Promise.resolve().then(o);if(n.dispose){var a=n.dispose.call(n.value);if(n.async)return r|=2,Promise.resolve(a).then(o,(function(e){return t(e),o()}))}else r|=1}catch(i){t(i)}if(1===r)return e.hasError?Promise.reject(e.error):Promise.resolve();if(e.hasError)throw e.error}()}function F(e,t){return"string"==typeof e&&/^\.\.?\//.test(e)?e.replace(/\.(tsx)$|((?:\.d)?)((?:\.[^./]+?)?)\.([cm]?)ts$/i,(function(e,n,r,o,a){return n?t?".jsx":".js":!r||o&&a?r+o+"."+a.toLowerCase()+"js":e})):e}const B={__extends:o,__assign:a,__rest:i,__decorate:c,__param:s,__esDecorate:l,__runInitializers:u,__propKey:d,__setFunctionName:p,__metadata:f,__awaiter:m,__generator:g,__createBinding:h,__exportStar:b,__values:y,__read:v,__spread:w,__spreadArrays:S,__spreadArray:k,__await:x,__asyncGenerator:_,__asyncDelegator:C,__asyncValues:E,__makeTemplateObject:D,__importStar:A,__importDefault:T,__classPrivateFieldGet:P,__classPrivateFieldSet:I,__classPrivateFieldIn:N,__addDisposableResource:R,__disposeResources:M,__rewriteRelativeImportExtension:F}},2654:e=>{"use strict";e.exports={}},4054:e=>{"use strict";e.exports=JSON.parse('{"/Cadence-Docs/blog-0a6":{"__comp":"a6aa9e1f","__context":{"plugin":"36994c47"},"sidebar":"814f3328","items":[{"content":"31f8b8ae"},{"content":"80e02aec"},{"content":"5806acc5"},{"content":"76dc6352"},{"content":"44d6dde1"},{"content":"9e9bbe09"},{"content":"981d14b8"},{"content":"965c09ae"},{"content":"5b895f91"},{"content":"d70bd24b"}],"__props":"02de9280"},"/Cadence-Docs/blog/2021/09/30/long-term-commitment-and-support-for-the-cadence-project-and-its-community-395":{"__comp":"ccc49370","__context":{"data":{"blogMetadata":"acecf23e"},"plugin":"36994c47"},"sidebar":"814f3328","content":"278bd730"},"/Cadence-Docs/blog/2021/10/13/announcing-cadence-oss-office-hours-and-community-sync-up-a52":{"__comp":"ccc49370","__context":{"data":{"blogMetadata":"acecf23e"},"plugin":"36994c47"},"sidebar":"814f3328","content":"de3708c6"},"/Cadence-Docs/blog/2021/10/19/2021-10-19-moving-to-grpc/moving-to-grpc-864":{"__comp":"ccc49370","__context":{"data":{"blogMetadata":"acecf23e"},"plugin":"36994c47"},"sidebar":"814f3328","content":"177ff540"},"/Cadence-Docs/blog/2022/01/31/community-spotlight-january-2022-71e":{"__comp":"ccc49370","__context":{"data":{"blogMetadata":"acecf23e"},"plugin":"36994c47"},"sidebar":"814f3328","content":"3ca3c927"},"/Cadence-Docs/blog/2022/02/28/community-spotlight-february-2022-6c1":{"__comp":"ccc49370","__context":{"data":{"blogMetadata":"acecf23e"},"plugin":"36994c47"},"sidebar":"814f3328","content":"a3dd65a2"},"/Cadence-Docs/blog/2022/03/31/community-spotlight-update-march-2022-d8b":{"__comp":"ccc49370","__context":{"data":{"blogMetadata":"acecf23e"},"plugin":"36994c47"},"sidebar":"814f3328","content":"88d84d8e"},"/Cadence-Docs/blog/2022/04/30/community-spotlight-update-april-2022-834":{"__comp":"ccc49370","__context":{"data":{"blogMetadata":"acecf23e"},"plugin":"36994c47"},"sidebar":"814f3328","content":"3d5497b2"},"/Cadence-Docs/blog/2022/05/31/community-spotlight-update-may-2022-cc7":{"__comp":"ccc49370","__context":{"data":{"blogMetadata":"acecf23e"},"plugin":"36994c47"},"sidebar":"814f3328","content":"b69803f5"},"/Cadence-Docs/blog/2022/06/30/community-spotlight-update-june-2022-f2b":{"__comp":"ccc49370","__context":{"data":{"blogMetadata":"acecf23e"},"plugin":"36994c47"},"sidebar":"814f3328","content":"4b94b3ad"},"/Cadence-Docs/blog/2022/07/31/community-spotlight-update-july-2022-bfb":{"__comp":"ccc49370","__context":{"data":{"blogMetadata":"acecf23e"},"plugin":"36994c47"},"sidebar":"814f3328","content":"d27d92a2"},"/Cadence-Docs/blog/2022/08/31/community-spotlight-august-2022-a91":{"__comp":"ccc49370","__context":{"data":{"blogMetadata":"acecf23e"},"plugin":"36994c47"},"sidebar":"814f3328","content":"a94774ec"},"/Cadence-Docs/blog/2022/09/30/community-spotlight-september-2022-05f":{"__comp":"ccc49370","__context":{"data":{"blogMetadata":"acecf23e"},"plugin":"36994c47"},"sidebar":"814f3328","content":"6081a96a"},"/Cadence-Docs/blog/2022/10/31/community-spotlight-october-2022-d1d":{"__comp":"ccc49370","__context":{"data":{"blogMetadata":"acecf23e"},"plugin":"36994c47"},"sidebar":"814f3328","content":"ea1e4697"},"/Cadence-Docs/blog/2022/11/30/community-spotlight-november-2022-af1":{"__comp":"ccc49370","__context":{"data":{"blogMetadata":"acecf23e"},"plugin":"36994c47"},"sidebar":"814f3328","content":"e9c26ae5"},"/Cadence-Docs/blog/2022/12/23/community-spotlight-december-2022-c64":{"__comp":"ccc49370","__context":{"data":{"blogMetadata":"acecf23e"},"plugin":"36994c47"},"sidebar":"814f3328","content":"775920c1"},"/Cadence-Docs/blog/2023/01/31/community-spotlight-january-2023-f18":{"__comp":"ccc49370","__context":{"data":{"blogMetadata":"acecf23e"},"plugin":"36994c47"},"sidebar":"814f3328","content":"ef69cbb3"},"/Cadence-Docs/blog/2023/02/28/community-spotlight-february-cac":{"__comp":"ccc49370","__context":{"data":{"blogMetadata":"acecf23e"},"plugin":"36994c47"},"sidebar":"814f3328","content":"7afb0752"},"/Cadence-Docs/blog/2023/03/31/community-spotlight-march-2023-dd0":{"__comp":"ccc49370","__context":{"data":{"blogMetadata":"acecf23e"},"plugin":"36994c47"},"sidebar":"814f3328","content":"9366521c"},"/Cadence-Docs/blog/2023/06/08/2023-06-08-survey-results/survey-results-258":{"__comp":"ccc49370","__context":{"data":{"blogMetadata":"acecf23e"},"plugin":"36994c47"},"sidebar":"814f3328","content":"92ce93dc"},"/Cadence-Docs/blog/2023/06/28/components-of-cadence-application-setup-2f8":{"__comp":"ccc49370","__context":{"data":{"blogMetadata":"acecf23e"},"plugin":"36994c47"},"sidebar":"814f3328","content":"0bc129c0"},"/Cadence-Docs/blog/2023/06/30/community-spotlight-june-2023-589":{"__comp":"ccc49370","__context":{"data":{"blogMetadata":"acecf23e"},"plugin":"36994c47"},"sidebar":"814f3328","content":"98f5ac88"},"/Cadence-Docs/blog/2023/07/05/implement-cadence-worker-from-scratch-96d":{"__comp":"ccc49370","__context":{"data":{"blogMetadata":"acecf23e"},"plugin":"36994c47"},"sidebar":"814f3328","content":"18e1ae2c"},"/Cadence-Docs/blog/2023/07/10/cadence-bad-practices-part-1-147":{"__comp":"ccc49370","__context":{"data":{"blogMetadata":"acecf23e"},"plugin":"36994c47"},"sidebar":"814f3328","content":"5f63c9de"},"/Cadence-Docs/blog/2023/07/16/2023-07-16-write-your-first-workflow-with-cadence/write-your-first-workflow-with-cadence-5c3":{"__comp":"ccc49370","__context":{"data":{"blogMetadata":"acecf23e"},"plugin":"36994c47"},"sidebar":"814f3328","content":"a197b989"},"/Cadence-Docs/blog/2023/07/31/community-spotlight-july-2023-efe":{"__comp":"ccc49370","__context":{"data":{"blogMetadata":"acecf23e"},"plugin":"36994c47"},"sidebar":"814f3328","content":"647edc7e"},"/Cadence-Docs/blog/2023/08/28/nondeterministic-errors-replayers-shadowers-2e2":{"__comp":"ccc49370","__context":{"data":{"blogMetadata":"acecf23e"},"plugin":"36994c47"},"sidebar":"814f3328","content":"2955167d"},"/Cadence-Docs/blog/2023/08/31/community-spotlight-august-2023-978":{"__comp":"ccc49370","__context":{"data":{"blogMetadata":"acecf23e"},"plugin":"36994c47"},"sidebar":"814f3328","content":"f1de825c"},"/Cadence-Docs/blog/2023/11/30/community-spotlight-update-november-2023-a5d":{"__comp":"ccc49370","__context":{"data":{"blogMetadata":"acecf23e"},"plugin":"36994c47"},"sidebar":"814f3328","content":"580cfca3"},"/Cadence-Docs/blog/2024/02/15/cadence-non-deterministic-common-qa-4cd":{"__comp":"ccc49370","__context":{"data":{"blogMetadata":"acecf23e"},"plugin":"36994c47"},"sidebar":"814f3328","content":"7fda255c"},"/Cadence-Docs/blog/2024/07/11/2024-07-11-yearly-roadmap-update/yearly-roadmap-update-1a3":{"__comp":"ccc49370","__context":{"data":{"blogMetadata":"acecf23e"},"plugin":"36994c47"},"sidebar":"814f3328","content":"c47f6b82"},"/Cadence-Docs/blog/2024/09/05/workflow-specific-rate-limits-fa3":{"__comp":"ccc49370","__context":{"data":{"blogMetadata":"acecf23e"},"plugin":"36994c47"},"sidebar":"814f3328","content":"849b28af"},"/Cadence-Docs/blog/2024/10/01/announcing-cadence-helm-charts-v0-b72":{"__comp":"ccc49370","__context":{"data":{"blogMetadata":"acecf23e"},"plugin":"36994c47"},"sidebar":"814f3328","content":"d33895f8"},"/Cadence-Docs/blog/2024/11/18/cadence-workflows-github-organization-d1b":{"__comp":"ccc49370","__context":{"data":{"blogMetadata":"acecf23e"},"plugin":"36994c47"},"sidebar":"814f3328","content":"115ec24d"},"/Cadence-Docs/blog/2024/3/11/community-spotlight-update-march-2024-196":{"__comp":"ccc49370","__context":{"data":{"blogMetadata":"acecf23e"},"plugin":"36994c47"},"sidebar":"814f3328","content":"8edf5fa8"},"/Cadence-Docs/blog/archive-b94":{"__comp":"9e4087bc","__context":{"plugin":"36994c47"},"__props":"4d0beaf2"},"/Cadence-Docs/blog/authors-999":{"__comp":"621db11d","__context":{"data":{"blogMetadata":"acecf23e"},"plugin":"36994c47"},"sidebar":"814f3328","__props":"a844cb54"},"/Cadence-Docs/blog/authors/chopincode-ab3":{"__comp":"33fc5bb8","__context":{"data":{"blogMetadata":"acecf23e"},"plugin":"36994c47"},"items":[{"content":"9e9bbe09"},{"content":"5b895f91"},{"content":"8a72c69a"},{"content":"534a6068"},{"content":"d6960a6f"},{"content":"667be76f"}],"sidebar":"814f3328","__props":"4f20e2dc"},"/Cadence-Docs/blog/authors/enderdemirkaya-a8f":{"__comp":"33fc5bb8","__context":{"data":{"blogMetadata":"acecf23e"},"plugin":"36994c47"},"items":[{"content":"44d6dde1"},{"content":"7613fcd7"}],"sidebar":"814f3328","__props":"91c0087d"},"/Cadence-Docs/blog/authors/ibarrajo-cb3":{"__comp":"33fc5bb8","__context":{"data":{"blogMetadata":"acecf23e"},"plugin":"36994c47"},"items":[{"content":"31f8b8ae"}],"sidebar":"814f3328","__props":"d8ddffe9"},"/Cadence-Docs/blog/authors/jakobht-b6a":{"__comp":"33fc5bb8","__context":{"data":{"blogMetadata":"acecf23e"},"plugin":"36994c47"},"items":[{"content":"76dc6352"}],"sidebar":"814f3328","__props":"4807c528"},"/Cadence-Docs/blog/authors/kcorbett-netapp-b0f":{"__comp":"33fc5bb8","__context":{"data":{"blogMetadata":"acecf23e"},"plugin":"36994c47"},"items":[{"content":"33348b0e"}],"sidebar":"814f3328","__props":"23beb9a4"},"/Cadence-Docs/blog/authors/meiliang-86-1a3":{"__comp":"33fc5bb8","__context":{"data":{"blogMetadata":"acecf23e"},"plugin":"36994c47"},"items":[{"content":"fda2e45a"},{"content":"df4cf6e6"}],"sidebar":"814f3328","__props":"a9771bf1"},"/Cadence-Docs/blog/authors/shaddoll-d51":{"__comp":"33fc5bb8","__context":{"data":{"blogMetadata":"acecf23e"},"plugin":"36994c47"},"items":[{"content":"80e02aec"}],"sidebar":"814f3328","__props":"45f9d173"},"/Cadence-Docs/blog/authors/sharanf-185":{"__comp":"33fc5bb8","__context":{"data":{"blogMetadata":"acecf23e"},"plugin":"36994c47"},"items":[{"content":"981d14b8"},{"content":"965c09ae"},{"content":"d70bd24b"},{"content":"cdf6e634"},{"content":"f7be646d"},{"content":"36aefe7c"},{"content":"33cf8314"},{"content":"87d83cd2"},{"content":"528620f0"},{"content":"dec4f520"}],"sidebar":"814f3328","__props":"0b5e41cc"},"/Cadence-Docs/blog/authors/sharanf/authors/2-558":{"__comp":"33fc5bb8","__context":{"data":{"blogMetadata":"acecf23e"},"plugin":"36994c47"},"items":[{"content":"959827cd"},{"content":"4d332630"},{"content":"cfb807c8"},{"content":"aac593d4"},{"content":"1c90ed0c"},{"content":"98f77afb"},{"content":"d33bd0ff"},{"content":"144c3ace"},{"content":"acfca6f1"}],"sidebar":"814f3328","__props":"c74af710"},"/Cadence-Docs/blog/authors/taylanisikdemir-72b":{"__comp":"33fc5bb8","__context":{"data":{"blogMetadata":"acecf23e"},"plugin":"36994c47"},"items":[{"content":"5806acc5"}],"sidebar":"814f3328","__props":"4c8ff8e7"},"/Cadence-Docs/blog/authors/vytautas-karpavicius-b19":{"__comp":"33fc5bb8","__context":{"data":{"blogMetadata":"acecf23e"},"plugin":"36994c47"},"items":[{"content":"28f6f2b5"}],"sidebar":"814f3328","__props":"08e09fce"},"/Cadence-Docs/blog/page/2-0c8":{"__comp":"a6aa9e1f","__context":{"plugin":"36994c47"},"sidebar":"814f3328","items":[{"content":"8a72c69a"},{"content":"534a6068"},{"content":"d6960a6f"},{"content":"667be76f"},{"content":"cdf6e634"},{"content":"7613fcd7"},{"content":"f7be646d"},{"content":"33348b0e"},{"content":"36aefe7c"},{"content":"33cf8314"}],"__props":"ad4570fb"},"/Cadence-Docs/blog/page/3-d10":{"__comp":"a6aa9e1f","__context":{"plugin":"36994c47"},"sidebar":"814f3328","items":[{"content":"87d83cd2"},{"content":"528620f0"},{"content":"dec4f520"},{"content":"959827cd"},{"content":"4d332630"},{"content":"cfb807c8"},{"content":"aac593d4"},{"content":"1c90ed0c"},{"content":"98f77afb"},{"content":"d33bd0ff"}],"__props":"c7e5f436"},"/Cadence-Docs/blog/page/4-98f":{"__comp":"a6aa9e1f","__context":{"plugin":"36994c47"},"sidebar":"814f3328","items":[{"content":"144c3ace"},{"content":"acfca6f1"},{"content":"28f6f2b5"},{"content":"fda2e45a"},{"content":"df4cf6e6"}],"__props":"533eb95b"},"/Cadence-Docs/blog/tags-529":{"__comp":"01a85c17","__context":{"plugin":"36994c47"},"sidebar":"814f3328","__props":"a17e1a1b"},"/Cadence-Docs/blog/tags/announcements-71a":{"__comp":"6875c492","__context":{"plugin":"36994c47"},"sidebar":"814f3328","items":[{"content":"31f8b8ae"},{"content":"5806acc5"},{"content":"981d14b8"},{"content":"d70bd24b"},{"content":"7613fcd7"},{"content":"fda2e45a"},{"content":"df4cf6e6"}],"__props":"04634098"},"/Cadence-Docs/blog/tags/cadence-operations-5be":{"__comp":"6875c492","__context":{"plugin":"36994c47"},"sidebar":"814f3328","items":[{"content":"80e02aec"},{"content":"28f6f2b5"}],"__props":"e8018edf"},"/Cadence-Docs/blog/tags/community-spotlights-5d5":{"__comp":"6875c492","__context":{"plugin":"36994c47"},"sidebar":"814f3328","items":[{"content":"981d14b8"},{"content":"965c09ae"},{"content":"d70bd24b"},{"content":"cdf6e634"},{"content":"f7be646d"},{"content":"33348b0e"},{"content":"36aefe7c"},{"content":"33cf8314"},{"content":"87d83cd2"},{"content":"528620f0"}],"__props":"d530ea3c"},"/Cadence-Docs/blog/tags/community-spotlights/page/2-aab":{"__comp":"6875c492","__context":{"plugin":"36994c47"},"sidebar":"814f3328","items":[{"content":"dec4f520"},{"content":"959827cd"},{"content":"4d332630"},{"content":"cfb807c8"},{"content":"aac593d4"},{"content":"1c90ed0c"},{"content":"98f77afb"},{"content":"d33bd0ff"},{"content":"144c3ace"},{"content":"acfca6f1"}],"__props":"90ce9713"},"/Cadence-Docs/blog/tags/deep-dives-560":{"__comp":"6875c492","__context":{"plugin":"36994c47"},"sidebar":"814f3328","items":[{"content":"80e02aec"},{"content":"76dc6352"},{"content":"44d6dde1"},{"content":"9e9bbe09"},{"content":"5b895f91"},{"content":"8a72c69a"},{"content":"534a6068"},{"content":"d6960a6f"},{"content":"667be76f"},{"content":"28f6f2b5"}],"__props":"2b6d3152"},"/Cadence-Docs/blog/tags/introduction-to-cadence-012":{"__comp":"6875c492","__context":{"plugin":"36994c47"},"sidebar":"814f3328","items":[{"content":"965c09ae"},{"content":"8a72c69a"},{"content":"534a6068"},{"content":"d6960a6f"},{"content":"667be76f"}],"__props":"a82a64d4"},"/Cadence-Docs/blog/tags/releases-f14":{"__comp":"6875c492","__context":{"plugin":"36994c47"},"sidebar":"814f3328","items":[{"content":"d70bd24b"},{"content":"cdf6e634"}],"__props":"0b21c5b6"},"/Cadence-Docs/blog/tags/roadmap-ab2":{"__comp":"6875c492","__context":{"plugin":"36994c47"},"sidebar":"814f3328","items":[{"content":"44d6dde1"},{"content":"acfca6f1"},{"content":"fda2e45a"}],"__props":"c0e193ae"},"/Cadence-Docs/blog/tags/testing-2a4":{"__comp":"6875c492","__context":{"plugin":"36994c47"},"sidebar":"814f3328","items":[{"content":"5b895f91"}],"__props":"4d8144ae"},"/Cadence-Docs/blog/zonal-isolation-v1/zonal-isolation-v1-4b5":{"__comp":"ccc49370","__context":{"data":{"blogMetadata":"acecf23e"},"plugin":"36994c47"},"sidebar":"814f3328","content":"5cfaf3a2"},"/Cadence-Docs/markdown-page-c55":{"__comp":"1f391b9e","__context":{"plugin":"a7456010"},"content":"393be207"},"/Cadence-Docs/search-7d9":{"__comp":"1a4e3797","__context":{"plugin":"c141421f"}},"/Cadence-Docs/community-e90":{"__comp":"5e95c892","__context":{"plugin":"e0719818"}},"/Cadence-Docs/community-630":{"__comp":"a7bd4aaa","__props":"0b6b8c62"},"/Cadence-Docs/community-852":{"__comp":"a94703ab"},"/Cadence-Docs/community/contributing-908":{"__comp":"17896441","content":"20139c40"},"/Cadence-Docs/community/resources-2a0":{"__comp":"17896441","content":"3ce9624a"},"/Cadence-Docs/community/support-8a6":{"__comp":"17896441","content":"3e206144"},"/Cadence-Docs/community/team-430":{"__comp":"17896441","content":"4c9d8eaa"},"/Cadence-Docs/docs-cbe":{"__comp":"5e95c892","__context":{"plugin":"aba21aa0"}},"/Cadence-Docs/docs-651":{"__comp":"a7bd4aaa","__props":"6abab11b"},"/Cadence-Docs/docs-ae0":{"__comp":"a94703ab"},"/Cadence-Docs/docs/about-a67":{"__comp":"17896441","content":"0b211f8a"},"/Cadence-Docs/docs/about/license-eb7":{"__comp":"17896441","content":"27f46eca"},"/Cadence-Docs/docs/cli-e8a":{"__comp":"17896441","content":"f8f32361"},"/Cadence-Docs/docs/concepts-957":{"__comp":"17896441","content":"99c90dae"},"/Cadence-Docs/docs/concepts/activities-931":{"__comp":"17896441","content":"b4266c8b"},"/Cadence-Docs/docs/concepts/archival-0c8":{"__comp":"17896441","content":"814003d2"},"/Cadence-Docs/docs/concepts/cross-dc-replication-ac4":{"__comp":"17896441","content":"9674d0ef"},"/Cadence-Docs/docs/concepts/events-853":{"__comp":"17896441","content":"3525dd13"},"/Cadence-Docs/docs/concepts/http-api-0df":{"__comp":"17896441","content":"cd7e9a8f"},"/Cadence-Docs/docs/concepts/queries-7a9":{"__comp":"17896441","content":"7373c0c0"},"/Cadence-Docs/docs/concepts/search-workflows-1da":{"__comp":"17896441","content":"fde82b69"},"/Cadence-Docs/docs/concepts/task-lists-e29":{"__comp":"17896441","content":"2a3fd662"},"/Cadence-Docs/docs/concepts/topology-fc5":{"__comp":"17896441","content":"cdada9ee"},"/Cadence-Docs/docs/concepts/workflows-c85":{"__comp":"17896441","content":"02fb669a"},"/Cadence-Docs/docs/get-started-8a0":{"__comp":"17896441","content":"cccd73f1"},"/Cadence-Docs/docs/get-started/golang-hello-world-629":{"__comp":"17896441","content":"28839895"},"/Cadence-Docs/docs/get-started/java-hello-world-d67":{"__comp":"17896441","content":"3408eb41"},"/Cadence-Docs/docs/get-started/server-installation-b6e":{"__comp":"17896441","content":"7f8511d4"},"/Cadence-Docs/docs/get-started/video-tutorials-880":{"__comp":"17896441","content":"ad9e871f"},"/Cadence-Docs/docs/glossary-bdf":{"__comp":"17896441","content":"aeb329ea"},"/Cadence-Docs/docs/go-client-b1e":{"__comp":"17896441","content":"86c2314d"},"/Cadence-Docs/docs/go-client/02.5-starting-workflows-3bb":{"__comp":"17896441","content":"3e30df86"},"/Cadence-Docs/docs/go-client/activities-914":{"__comp":"17896441","content":"ec02fbe0"},"/Cadence-Docs/docs/go-client/activity-async-completion-e7e":{"__comp":"17896441","content":"bde620bf"},"/Cadence-Docs/docs/go-client/child-workflows-53e":{"__comp":"17896441","content":"f0efcb43"},"/Cadence-Docs/docs/go-client/continue-as-new-e73":{"__comp":"17896441","content":"90f276f1"},"/Cadence-Docs/docs/go-client/create-workflows-650":{"__comp":"17896441","content":"643bf5c6"},"/Cadence-Docs/docs/go-client/distributed-cron-40b":{"__comp":"17896441","content":"003b6e74"},"/Cadence-Docs/docs/go-client/error-handling-f2d":{"__comp":"17896441","content":"aacb5a6b"},"/Cadence-Docs/docs/go-client/execute-activity-897":{"__comp":"17896441","content":"69a323c8"},"/Cadence-Docs/docs/go-client/queries-e99":{"__comp":"17896441","content":"e8c8106b"},"/Cadence-Docs/docs/go-client/retries-9e7":{"__comp":"17896441","content":"2bc7f48b"},"/Cadence-Docs/docs/go-client/sessions-676":{"__comp":"17896441","content":"c5abbc6d"},"/Cadence-Docs/docs/go-client/side-effect-dd2":{"__comp":"17896441","content":"eb57c500"},"/Cadence-Docs/docs/go-client/signals-8cf":{"__comp":"17896441","content":"d280f29d"},"/Cadence-Docs/docs/go-client/tracing-dc3":{"__comp":"17896441","content":"0826fbec"},"/Cadence-Docs/docs/go-client/workers-847":{"__comp":"17896441","content":"2b58a6fe"},"/Cadence-Docs/docs/go-client/workflow-non-deterministic-error-e67":{"__comp":"17896441","content":"a4f1f4dd"},"/Cadence-Docs/docs/go-client/workflow-replay-shadowing-0e8":{"__comp":"17896441","content":"95cc356a"},"/Cadence-Docs/docs/go-client/workflow-testing-a23":{"__comp":"17896441","content":"f81e7c5e"},"/Cadence-Docs/docs/go-client/workflow-versioning-c93":{"__comp":"17896441","content":"d67a7980"},"/Cadence-Docs/docs/java-client-0bb":{"__comp":"17896441","content":"61aeb84e"},"/Cadence-Docs/docs/java-client/activity-interface-387":{"__comp":"17896441","content":"d0ac2d40"},"/Cadence-Docs/docs/java-client/child-workflows-a2c":{"__comp":"17896441","content":"6601f8a9"},"/Cadence-Docs/docs/java-client/client-overview-cb9":{"__comp":"17896441","content":"0ece390c"},"/Cadence-Docs/docs/java-client/continue-as-new-a2e":{"__comp":"17896441","content":"47f0ea92"},"/Cadence-Docs/docs/java-client/distributed-cron-e20":{"__comp":"17896441","content":"77a860e9"},"/Cadence-Docs/docs/java-client/exception-handling-c21":{"__comp":"17896441","content":"4c35ffca"},"/Cadence-Docs/docs/java-client/implementing-activities-77e":{"__comp":"17896441","content":"a7552915"},"/Cadence-Docs/docs/java-client/implementing-workflows-b50":{"__comp":"17896441","content":"73759d73"},"/Cadence-Docs/docs/java-client/queries-9e2":{"__comp":"17896441","content":"7a568d1f"},"/Cadence-Docs/docs/java-client/retries-ead":{"__comp":"17896441","content":"67affde7"},"/Cadence-Docs/docs/java-client/side-effect-89d":{"__comp":"17896441","content":"5d1ead22"},"/Cadence-Docs/docs/java-client/signals-855":{"__comp":"17896441","content":"f2a162ea"},"/Cadence-Docs/docs/java-client/starting-workflow-executions-3e8":{"__comp":"17896441","content":"44abbaf5"},"/Cadence-Docs/docs/java-client/testing-a55":{"__comp":"17896441","content":"f5140c76"},"/Cadence-Docs/docs/java-client/versioning-2a1":{"__comp":"17896441","content":"05d44d04"},"/Cadence-Docs/docs/java-client/workers-890":{"__comp":"17896441","content":"848b9863"},"/Cadence-Docs/docs/java-client/workflow-interface-25c":{"__comp":"17896441","content":"1685be14"},"/Cadence-Docs/docs/java-client/workflow-replay-shadowing-991":{"__comp":"17896441","content":"95d054c5"},"/Cadence-Docs/docs/operation-guide-1be":{"__comp":"17896441","content":"f997f9c8"},"/Cadence-Docs/docs/operation-guide/maintain-7a3":{"__comp":"17896441","content":"5450051a"},"/Cadence-Docs/docs/operation-guide/migration-a51":{"__comp":"17896441","content":"3faec549"},"/Cadence-Docs/docs/operation-guide/monitoring-ede":{"__comp":"17896441","content":"6e9b4a66"},"/Cadence-Docs/docs/operation-guide/setup-b7f":{"__comp":"17896441","content":"55db2bea"},"/Cadence-Docs/docs/operation-guide/troubleshooting-116":{"__comp":"17896441","content":"43e9f1b6"},"/Cadence-Docs/docs/use-cases-109":{"__comp":"17896441","content":"cfd61dd5"},"/Cadence-Docs/docs/use-cases/batch-job-476":{"__comp":"17896441","content":"fa0e6b45"},"/Cadence-Docs/docs/use-cases/big-ml-d56":{"__comp":"17896441","content":"79f715ea"},"/Cadence-Docs/docs/use-cases/deployment-c39":{"__comp":"17896441","content":"41417ef6"},"/Cadence-Docs/docs/use-cases/dsl-c1b":{"__comp":"17896441","content":"a7de3fbd"},"/Cadence-Docs/docs/use-cases/event-driven-99c":{"__comp":"17896441","content":"fcdcf093"},"/Cadence-Docs/docs/use-cases/interactive-a3f":{"__comp":"17896441","content":"c4da92db"},"/Cadence-Docs/docs/use-cases/operational-management-7f7":{"__comp":"17896441","content":"d87fba2a"},"/Cadence-Docs/docs/use-cases/orchestration-64a":{"__comp":"17896441","content":"d7b037f3"},"/Cadence-Docs/docs/use-cases/partitioned-scan-f35":{"__comp":"17896441","content":"7684a5b2"},"/Cadence-Docs/docs/use-cases/periodic-execution-a11":{"__comp":"17896441","content":"bc79ac75"},"/Cadence-Docs/docs/use-cases/polling-a3c":{"__comp":"17896441","content":"e1ea741a"},"/Cadence-Docs/docs/use-cases/provisioning-42e":{"__comp":"17896441","content":"5cd48241"},"/Cadence-Docs/docs/workflow-troubleshooting-646":{"__comp":"17896441","content":"8d2e039e"},"/Cadence-Docs/docs/workflow-troubleshooting/activity-failures-d42":{"__comp":"17896441","content":"7d996443"},"/Cadence-Docs/docs/workflow-troubleshooting/retries-c08":{"__comp":"17896441","content":"67d45d0f"},"/Cadence-Docs/docs/workflow-troubleshooting/timeouts-371":{"__comp":"17896441","content":"1dec29fa"},"/Cadence-Docs/-9d2":{"__comp":"1df93b7f","__context":{"plugin":"a7456010"},"config":"5e9f5e1a"}}')}},e=>{e.O(0,[1869],(()=>{return t=8536,e(e.s=t);var t}));e.O()}]); \ No newline at end of file diff --git a/assets/js/main.a916520d.js.LICENSE.txt b/assets/js/main.6e1cf64a.js.LICENSE.txt similarity index 100% rename from assets/js/main.a916520d.js.LICENSE.txt rename to assets/js/main.6e1cf64a.js.LICENSE.txt diff --git a/assets/js/main.a916520d.js b/assets/js/main.a916520d.js deleted file mode 100644 index 81c16a4c4..000000000 --- a/assets/js/main.a916520d.js +++ /dev/null @@ -1,2 +0,0 @@ -/*! For license information please see main.a916520d.js.LICENSE.txt */ -(self.webpackChunkcadence=self.webpackChunkcadence||[]).push([[8792],{3219:(e,t,n)=>{"use strict";n.d(t,{Bc:()=>A,E8:()=>Zn,a1:()=>Qn});var r=n(6540);n(961);function o(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n<t;n++)r[n]=e[n];return r}function a(e,t,n,r,o,a,i){try{var s=e[a](i),c=s.value}catch(e){return void n(e)}s.done?t(c):Promise.resolve(c).then(r,o)}function i(e){return function(){var t=this,n=arguments;return new Promise((function(r,o){var i=e.apply(t,n);function s(e){a(i,r,o,s,c,"next",e)}function c(e){a(i,r,o,s,c,"throw",e)}s(void 0)}))}}function s(e,t,n){return t=p(t),function(e,t){if(t&&("object"==typeof t||"function"==typeof t))return t;if(void 0!==t)throw new TypeError("Derived constructors may only return object or undefined");return function(e){if(void 0===e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return e}(e)}(e,m()?Reflect.construct(t,n||[],p(e).constructor):t.apply(e,n))}function c(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function l(e,t,n){return Object.defineProperty(e,"prototype",{writable:!1}),e}function u(e,t,n){return(t=function(e){var t=function(e){if("object"!=typeof e||!e)return e;var t=e[Symbol.toPrimitive];if(void 0!==t){var n=t.call(e,"string");if("object"!=typeof n)return n;throw new TypeError("@@toPrimitive must return a primitive value.")}return String(e)}(e);return"symbol"==typeof t?t:t+""}(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function d(){return d=Object.assign?Object.assign.bind():function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var r in n)({}).hasOwnProperty.call(n,r)&&(e[r]=n[r])}return e},d.apply(null,arguments)}function p(e){return p=Object.setPrototypeOf?Object.getPrototypeOf.bind():function(e){return e.__proto__||Object.getPrototypeOf(e)},p(e)}function f(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function");e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,writable:!0,configurable:!0}}),Object.defineProperty(e,"prototype",{writable:!1}),t&&v(e,t)}function m(){try{var e=!Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],(function(){})))}catch(e){}return(m=function(){return!!e})()}function g(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function h(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?g(Object(n),!0).forEach((function(t){u(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):g(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}function b(e,t){if(null==e)return{};var n,r,o=function(e,t){if(null==e)return{};var n={};for(var r in e)if({}.hasOwnProperty.call(e,r)){if(t.includes(r))continue;n[r]=e[r]}return n}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(r=0;r<a.length;r++)n=a[r],t.includes(n)||{}.propertyIsEnumerable.call(e,n)&&(o[n]=e[n])}return o}function y(){y=function(){return t};var e,t={},n=Object.prototype,r=n.hasOwnProperty,o=Object.defineProperty||function(e,t,n){e[t]=n.value},a="function"==typeof Symbol?Symbol:{},i=a.iterator||"@@iterator",s=a.asyncIterator||"@@asyncIterator",c=a.toStringTag||"@@toStringTag";function l(e,t,n){return Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}),e[t]}try{l({},"")}catch(e){l=function(e,t,n){return e[t]=n}}function u(e,t,n,r){var a=t&&t.prototype instanceof b?t:b,i=Object.create(a.prototype),s=new P(r||[]);return o(i,"_invoke",{value:O(e,n,s)}),i}function d(e,t,n){try{return{type:"normal",arg:e.call(t,n)}}catch(e){return{type:"throw",arg:e}}}t.wrap=u;var p="suspendedStart",f="suspendedYield",m="executing",g="completed",h={};function b(){}function v(){}function w(){}var S={};l(S,i,(function(){return this}));var k=Object.getPrototypeOf,x=k&&k(k(I([])));x&&x!==n&&r.call(x,i)&&(S=x);var _=w.prototype=b.prototype=Object.create(S);function E(e){["next","throw","return"].forEach((function(t){l(e,t,(function(e){return this._invoke(t,e)}))}))}function j(e,t){function n(o,a,i,s){var c=d(e[o],e,a);if("throw"!==c.type){var l=c.arg,u=l.value;return u&&"object"==typeof u&&r.call(u,"__await")?t.resolve(u.__await).then((function(e){n("next",e,i,s)}),(function(e){n("throw",e,i,s)})):t.resolve(u).then((function(e){l.value=e,i(l)}),(function(e){return n("throw",e,i,s)}))}s(c.arg)}var a;o(this,"_invoke",{value:function(e,r){function o(){return new t((function(t,o){n(e,r,t,o)}))}return a=a?a.then(o,o):o()}})}function O(t,n,r){var o=p;return function(a,i){if(o===m)throw Error("Generator is already running");if(o===g){if("throw"===a)throw i;return{value:e,done:!0}}for(r.method=a,r.arg=i;;){var s=r.delegate;if(s){var c=A(s,r);if(c){if(c===h)continue;return c}}if("next"===r.method)r.sent=r._sent=r.arg;else if("throw"===r.method){if(o===p)throw o=g,r.arg;r.dispatchException(r.arg)}else"return"===r.method&&r.abrupt("return",r.arg);o=m;var l=d(t,n,r);if("normal"===l.type){if(o=r.done?g:f,l.arg===h)continue;return{value:l.arg,done:r.done}}"throw"===l.type&&(o=g,r.method="throw",r.arg=l.arg)}}}function A(t,n){var r=n.method,o=t.iterator[r];if(o===e)return n.delegate=null,"throw"===r&&t.iterator.return&&(n.method="return",n.arg=e,A(t,n),"throw"===n.method)||"return"!==r&&(n.method="throw",n.arg=new TypeError("The iterator does not provide a '"+r+"' method")),h;var a=d(o,t.iterator,n.arg);if("throw"===a.type)return n.method="throw",n.arg=a.arg,n.delegate=null,h;var i=a.arg;return i?i.done?(n[t.resultName]=i.value,n.next=t.nextLoc,"return"!==n.method&&(n.method="next",n.arg=e),n.delegate=null,h):i:(n.method="throw",n.arg=new TypeError("iterator result is not an object"),n.delegate=null,h)}function C(e){var t={tryLoc:e[0]};1 in e&&(t.catchLoc=e[1]),2 in e&&(t.finallyLoc=e[2],t.afterLoc=e[3]),this.tryEntries.push(t)}function T(e){var t=e.completion||{};t.type="normal",delete t.arg,e.completion=t}function P(e){this.tryEntries=[{tryLoc:"root"}],e.forEach(C,this),this.reset(!0)}function I(t){if(t||""===t){var n=t[i];if(n)return n.call(t);if("function"==typeof t.next)return t;if(!isNaN(t.length)){var o=-1,a=function n(){for(;++o<t.length;)if(r.call(t,o))return n.value=t[o],n.done=!1,n;return n.value=e,n.done=!0,n};return a.next=a}}throw new TypeError(typeof t+" is not iterable")}return v.prototype=w,o(_,"constructor",{value:w,configurable:!0}),o(w,"constructor",{value:v,configurable:!0}),v.displayName=l(w,c,"GeneratorFunction"),t.isGeneratorFunction=function(e){var t="function"==typeof e&&e.constructor;return!!t&&(t===v||"GeneratorFunction"===(t.displayName||t.name))},t.mark=function(e){return Object.setPrototypeOf?Object.setPrototypeOf(e,w):(e.__proto__=w,l(e,c,"GeneratorFunction")),e.prototype=Object.create(_),e},t.awrap=function(e){return{__await:e}},E(j.prototype),l(j.prototype,s,(function(){return this})),t.AsyncIterator=j,t.async=function(e,n,r,o,a){void 0===a&&(a=Promise);var i=new j(u(e,n,r,o),a);return t.isGeneratorFunction(n)?i:i.next().then((function(e){return e.done?e.value:i.next()}))},E(_),l(_,c,"Generator"),l(_,i,(function(){return this})),l(_,"toString",(function(){return"[object Generator]"})),t.keys=function(e){var t=Object(e),n=[];for(var r in t)n.push(r);return n.reverse(),function e(){for(;n.length;){var r=n.pop();if(r in t)return e.value=r,e.done=!1,e}return e.done=!0,e}},t.values=I,P.prototype={constructor:P,reset:function(t){if(this.prev=0,this.next=0,this.sent=this._sent=e,this.done=!1,this.delegate=null,this.method="next",this.arg=e,this.tryEntries.forEach(T),!t)for(var n in this)"t"===n.charAt(0)&&r.call(this,n)&&!isNaN(+n.slice(1))&&(this[n]=e)},stop:function(){this.done=!0;var e=this.tryEntries[0].completion;if("throw"===e.type)throw e.arg;return this.rval},dispatchException:function(t){if(this.done)throw t;var n=this;function o(r,o){return s.type="throw",s.arg=t,n.next=r,o&&(n.method="next",n.arg=e),!!o}for(var a=this.tryEntries.length-1;a>=0;--a){var i=this.tryEntries[a],s=i.completion;if("root"===i.tryLoc)return o("end");if(i.tryLoc<=this.prev){var c=r.call(i,"catchLoc"),l=r.call(i,"finallyLoc");if(c&&l){if(this.prev<i.catchLoc)return o(i.catchLoc,!0);if(this.prev<i.finallyLoc)return o(i.finallyLoc)}else if(c){if(this.prev<i.catchLoc)return o(i.catchLoc,!0)}else{if(!l)throw Error("try statement without catch or finally");if(this.prev<i.finallyLoc)return o(i.finallyLoc)}}}},abrupt:function(e,t){for(var n=this.tryEntries.length-1;n>=0;--n){var o=this.tryEntries[n];if(o.tryLoc<=this.prev&&r.call(o,"finallyLoc")&&this.prev<o.finallyLoc){var a=o;break}}a&&("break"===e||"continue"===e)&&a.tryLoc<=t&&t<=a.finallyLoc&&(a=null);var i=a?a.completion:{};return i.type=e,i.arg=t,a?(this.method="next",this.next=a.finallyLoc,h):this.complete(i)},complete:function(e,t){if("throw"===e.type)throw e.arg;return"break"===e.type||"continue"===e.type?this.next=e.arg:"return"===e.type?(this.rval=this.arg=e.arg,this.method="return",this.next="end"):"normal"===e.type&&t&&(this.next=t),h},finish:function(e){for(var t=this.tryEntries.length-1;t>=0;--t){var n=this.tryEntries[t];if(n.finallyLoc===e)return this.complete(n.completion,n.afterLoc),T(n),h}},catch:function(e){for(var t=this.tryEntries.length-1;t>=0;--t){var n=this.tryEntries[t];if(n.tryLoc===e){var r=n.completion;if("throw"===r.type){var o=r.arg;T(n)}return o}}throw Error("illegal catch attempt")},delegateYield:function(t,n,r){return this.delegate={iterator:I(t),resultName:n,nextLoc:r},"next"===this.method&&(this.arg=e),h}},t}function v(e,t){return v=Object.setPrototypeOf?Object.setPrototypeOf.bind():function(e,t){return e.__proto__=t,e},v(e,t)}function w(e,t){return function(e){if(Array.isArray(e))return e}(e)||function(e,t){var n=null==e?null:"undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(null!=n){var r,o,a,i,s=[],c=!0,l=!1;try{if(a=(n=n.call(e)).next,0===t){if(Object(n)!==n)return;c=!1}else for(;!(c=(r=a.call(n)).done)&&(s.push(r.value),s.length!==t);c=!0);}catch(e){l=!0,o=e}finally{try{if(!c&&null!=n.return&&(i=n.return(),Object(i)!==i))return}finally{if(l)throw o}}return s}}(e,t)||k(e,t)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function S(e){return function(e){if(Array.isArray(e))return o(e)}(e)||function(e){if("undefined"!=typeof Symbol&&null!=e[Symbol.iterator]||null!=e["@@iterator"])return Array.from(e)}(e)||k(e)||function(){throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function k(e,t){if(e){if("string"==typeof e)return o(e,t);var n={}.toString.call(e).slice(8,-1);return"Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n?Array.from(e):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?o(e,t):void 0}}function x(e){var t="function"==typeof Map?new Map:void 0;return x=function(e){if(null===e||!function(e){try{return-1!==Function.toString.call(e).indexOf("[native code]")}catch(t){return"function"==typeof e}}(e))return e;if("function"!=typeof e)throw new TypeError("Super expression must either be null or a function");if(void 0!==t){if(t.has(e))return t.get(e);t.set(e,n)}function n(){return function(e,t,n){if(m())return Reflect.construct.apply(null,arguments);var r=[null];r.push.apply(r,t);var o=new(e.bind.apply(e,r));return n&&v(o,n.prototype),o}(e,arguments,p(this).constructor)}return n.prototype=Object.create(e.prototype,{constructor:{value:n,enumerable:!1,writable:!0,configurable:!0}}),v(n,e)},x(e)}function _(){return r.createElement("svg",{width:"15",height:"15",className:"DocSearch-Control-Key-Icon"},r.createElement("path",{d:"M4.505 4.496h2M5.505 5.496v5M8.216 4.496l.055 5.993M10 7.5c.333.333.5.667.5 1v2M12.326 4.5v5.996M8.384 4.496c1.674 0 2.116 0 2.116 1.5s-.442 1.5-2.116 1.5M3.205 9.303c-.09.448-.277 1.21-1.241 1.203C1 10.5.5 9.513.5 8V7c0-1.57.5-2.5 1.464-2.494.964.006 1.134.598 1.24 1.342M12.553 10.5h1.953",strokeWidth:"1.2",stroke:"currentColor",fill:"none",strokeLinecap:"square"}))}function E(){return r.createElement("svg",{width:"20",height:"20",className:"DocSearch-Search-Icon",viewBox:"0 0 20 20","aria-hidden":"true"},r.createElement("path",{d:"M14.386 14.386l4.0877 4.0877-4.0877-4.0877c-2.9418 2.9419-7.7115 2.9419-10.6533 0-2.9419-2.9418-2.9419-7.7115 0-10.6533 2.9418-2.9419 7.7115-2.9419 10.6533 0 2.9419 2.9418 2.9419 7.7115 0 10.6533z",stroke:"currentColor",fill:"none",fillRule:"evenodd",strokeLinecap:"round",strokeLinejoin:"round"}))}var j=["translations"],O="Ctrl",A=r.forwardRef((function(e,t){var n=e.translations,o=void 0===n?{}:n,a=b(e,j),i=o.buttonText,s=void 0===i?"Search":i,c=o.buttonAriaLabel,l=void 0===c?"Search":c,u=w((0,r.useState)(null),2),p=u[0],f=u[1];(0,r.useEffect)((function(){"undefined"!=typeof navigator&&(/(Mac|iPhone|iPod|iPad)/i.test(navigator.platform)?f("\u2318"):f(O))}),[]);var m=w(p===O?[O,"Ctrl",r.createElement(_,null)]:["Meta","Command",p],3),g=m[0],h=m[1],y=m[2];return r.createElement("button",d({type:"button",className:"DocSearch DocSearch-Button","aria-label":"".concat(l," (").concat(h,"+K)")},a,{ref:t}),r.createElement("span",{className:"DocSearch-Button-Container"},r.createElement(E,null),r.createElement("span",{className:"DocSearch-Button-Placeholder"},s)),r.createElement("span",{className:"DocSearch-Button-Keys"},null!==p&&r.createElement(r.Fragment,null,r.createElement(C,{reactsToKey:g},y),r.createElement(C,{reactsToKey:"k"},"K"))))}));function C(e){var t=e.reactsToKey,n=e.children,o=w((0,r.useState)(!1),2),a=o[0],i=o[1];return(0,r.useEffect)((function(){if(t)return window.addEventListener("keydown",e),window.addEventListener("keyup",n),function(){window.removeEventListener("keydown",e),window.removeEventListener("keyup",n)};function e(e){e.key===t&&i(!0)}function n(e){e.key!==t&&"Meta"!==e.key||i(!1)}}),[t]),r.createElement("kbd",{className:a?"DocSearch-Button-Key DocSearch-Button-Key--pressed":"DocSearch-Button-Key"},n)}function T(e,t){var n=void 0;return function(){for(var r=arguments.length,o=new Array(r),a=0;a<r;a++)o[a]=arguments[a];n&&clearTimeout(n),n=setTimeout((function(){return e.apply(void 0,o)}),t)}}function P(e){return e.reduce((function(e,t){return e.concat(t)}),[])}var I=0;function N(e){return 0===e.collections.length?0:e.collections.reduce((function(e,t){return e+t.items.length}),0)}function R(e){return e!==Object(e)}function L(e,t){if(e===t)return!0;if(R(e)||R(t)||"function"==typeof e||"function"==typeof t)return e===t;if(Object.keys(e).length!==Object.keys(t).length)return!1;for(var n=0,r=Object.keys(e);n<r.length;n++){var o=r[n];if(!(o in t))return!1;if(!L(e[o],t[o]))return!1}return!0}var D=function(){},M=[{segment:"autocomplete-core",version:"1.17.7"}];function F(e){var t=e.item,n=e.items,r=void 0===n?[]:n;return{index:t.__autocomplete_indexName,items:[t],positions:[1+r.findIndex((function(e){return e.objectID===t.objectID}))],queryID:t.__autocomplete_queryID,algoliaSource:["autocomplete"]}}function B(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=new Array(t);n<t;n++)r[n]=e[n];return r}var z=["items"],$=["items"];function U(e){return U="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},U(e)}function H(e){return function(e){if(Array.isArray(e))return q(e)}(e)||function(e){if("undefined"!=typeof Symbol&&null!=e[Symbol.iterator]||null!=e["@@iterator"])return Array.from(e)}(e)||function(e,t){if(e){if("string"==typeof e)return q(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);return"Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n?Array.from(e):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?q(e,t):void 0}}(e)||function(){throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function q(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=new Array(t);n<t;n++)r[n]=e[n];return r}function V(e,t){if(null==e)return{};var n,r,o=function(e,t){if(null==e)return{};var n,r,o={},a=Object.keys(e);for(r=0;r<a.length;r++)n=a[r],t.indexOf(n)>=0||(o[n]=e[n]);return o}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(r=0;r<a.length;r++)n=a[r],t.indexOf(n)>=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(o[n]=e[n])}return o}function W(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function G(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?W(Object(n),!0).forEach((function(t){K(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):W(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}function K(e,t,n){return(t=function(e){var t=function(e){if("object"!==U(e)||null===e)return e;var t=e[Symbol.toPrimitive];if(void 0!==t){var n=t.call(e,"string");if("object"!==U(n))return n;throw new TypeError("@@toPrimitive must return a primitive value.")}return String(e)}(e);return"symbol"===U(t)?t:String(t)}(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function Y(e){return e.map((function(e){var t=e.items,n=V(e,z);return G(G({},n),{},{objectIDs:(null==t?void 0:t.map((function(e){return e.objectID})))||n.objectIDs})}))}function Q(e){var t,n,r,o=(t=function(e,t){return function(e){if(Array.isArray(e))return e}(e)||function(e,t){var n=null==e?null:"undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(null!=n){var r,o,a,i,s=[],c=!0,l=!1;try{if(a=(n=n.call(e)).next,0===t);else for(;!(c=(r=a.call(n)).done)&&(s.push(r.value),s.length!==t);c=!0);}catch(e){l=!0,o=e}finally{try{if(!c&&null!=n.return&&(i=n.return(),Object(i)!==i))return}finally{if(l)throw o}}return s}}(e,t)||function(e,t){if(e){if("string"==typeof e)return B(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);return"Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n?Array.from(e):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?B(e,t):void 0}}(e,t)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}((e.version||"").split(".").map(Number),2),n=t[0],r=t[1],n>=3||2===n&&r>=4||1===n&&r>=10);function a(t,n,r){if(o&&void 0!==r){var a=r[0].__autocomplete_algoliaCredentials,i={"X-Algolia-Application-Id":a.appId,"X-Algolia-API-Key":a.apiKey};e.apply(void 0,[t].concat(H(n),[{headers:i}]))}else e.apply(void 0,[t].concat(H(n)))}return{init:function(t,n){e("init",{appId:t,apiKey:n})},setAuthenticatedUserToken:function(t){e("setAuthenticatedUserToken",t)},setUserToken:function(t){e("setUserToken",t)},clickedObjectIDsAfterSearch:function(){for(var e=arguments.length,t=new Array(e),n=0;n<e;n++)t[n]=arguments[n];t.length>0&&a("clickedObjectIDsAfterSearch",Y(t),t[0].items)},clickedObjectIDs:function(){for(var e=arguments.length,t=new Array(e),n=0;n<e;n++)t[n]=arguments[n];t.length>0&&a("clickedObjectIDs",Y(t),t[0].items)},clickedFilters:function(){for(var t=arguments.length,n=new Array(t),r=0;r<t;r++)n[r]=arguments[r];n.length>0&&e.apply(void 0,["clickedFilters"].concat(n))},convertedObjectIDsAfterSearch:function(){for(var e=arguments.length,t=new Array(e),n=0;n<e;n++)t[n]=arguments[n];t.length>0&&a("convertedObjectIDsAfterSearch",Y(t),t[0].items)},convertedObjectIDs:function(){for(var e=arguments.length,t=new Array(e),n=0;n<e;n++)t[n]=arguments[n];t.length>0&&a("convertedObjectIDs",Y(t),t[0].items)},convertedFilters:function(){for(var t=arguments.length,n=new Array(t),r=0;r<t;r++)n[r]=arguments[r];n.length>0&&e.apply(void 0,["convertedFilters"].concat(n))},viewedObjectIDs:function(){for(var e=arguments.length,t=new Array(e),n=0;n<e;n++)t[n]=arguments[n];t.length>0&&t.reduce((function(e,t){var n=t.items,r=V(t,$);return[].concat(H(e),H(function(e){for(var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:20,n=[],r=0;r<e.objectIDs.length;r+=t)n.push(G(G({},e),{},{objectIDs:e.objectIDs.slice(r,r+t)}));return n}(G(G({},r),{},{objectIDs:(null==n?void 0:n.map((function(e){return e.objectID})))||r.objectIDs})).map((function(e){return{items:n,payload:e}}))))}),[]).forEach((function(e){var t=e.items;return a("viewedObjectIDs",[e.payload],t)}))},viewedFilters:function(){for(var t=arguments.length,n=new Array(t),r=0;r<t;r++)n[r]=arguments[r];n.length>0&&e.apply(void 0,["viewedFilters"].concat(n))}}}function Z(e){var t=e.items.reduce((function(e,t){var n;return e[t.__autocomplete_indexName]=(null!==(n=e[t.__autocomplete_indexName])&&void 0!==n?n:[]).concat(t),e}),{});return Object.keys(t).map((function(e){return{index:e,items:t[e],algoliaSource:["autocomplete"]}}))}function X(e){return e.objectID&&e.__autocomplete_indexName&&e.__autocomplete_queryID}function J(e){return J="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},J(e)}function ee(e){return function(e){if(Array.isArray(e))return te(e)}(e)||function(e){if("undefined"!=typeof Symbol&&null!=e[Symbol.iterator]||null!=e["@@iterator"])return Array.from(e)}(e)||function(e,t){if(e){if("string"==typeof e)return te(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);return"Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n?Array.from(e):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?te(e,t):void 0}}(e)||function(){throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function te(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=new Array(t);n<t;n++)r[n]=e[n];return r}function ne(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function re(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?ne(Object(n),!0).forEach((function(t){oe(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):ne(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}function oe(e,t,n){return(t=function(e){var t=function(e){if("object"!==J(e)||null===e)return e;var t=e[Symbol.toPrimitive];if(void 0!==t){var n=t.call(e,"string");if("object"!==J(n))return n;throw new TypeError("@@toPrimitive must return a primitive value.")}return String(e)}(e);return"symbol"===J(t)?t:String(t)}(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}var ae="2.15.0",ie="https://cdn.jsdelivr.net/npm/search-insights@".concat(ae,"/dist/search-insights.min.js"),se=T((function(e){var t=e.onItemsChange,n=e.items,r=e.insights,o=e.state;t({insights:r,insightsEvents:Z({items:n}).map((function(e){return re({eventName:"Items Viewed"},e)})),state:o})}),400);function ce(e){var t=function(e){return re({onItemsChange:function(e){var t=e.insights,n=e.insightsEvents,r=e.state;t.viewedObjectIDs.apply(t,ee(n.map((function(e){return re(re({},e),{},{algoliaSource:le(e.algoliaSource,r.context)})}))))},onSelect:function(e){var t=e.insights,n=e.insightsEvents,r=e.state;t.clickedObjectIDsAfterSearch.apply(t,ee(n.map((function(e){return re(re({},e),{},{algoliaSource:le(e.algoliaSource,r.context)})}))))},onActive:D,__autocomplete_clickAnalytics:!0},e)}(e),n=t.insightsClient,r=t.insightsInitParams,o=t.onItemsChange,a=t.onSelect,i=t.onActive,s=t.__autocomplete_clickAnalytics,c=n;if(n||"undefined"!=typeof window&&function(e){var t=e.window,n=t.AlgoliaAnalyticsObject||"aa";"string"==typeof n&&(c=t[n]),c||(t.AlgoliaAnalyticsObject=n,t[n]||(t[n]=function(){t[n].queue||(t[n].queue=[]);for(var e=arguments.length,r=new Array(e),o=0;o<e;o++)r[o]=arguments[o];t[n].queue.push(r)}),t[n].version=ae,c=t[n],function(e){var t="[Autocomplete]: Could not load search-insights.js. Please load it manually following https://alg.li/insights-autocomplete";try{var n=e.document.createElement("script");n.async=!0,n.src=ie,n.onerror=function(){console.error(t)},document.body.appendChild(n)}catch(e){console.error(t)}}(t))}({window:window}),!c)return{};r&&c("init",re({partial:!0},r));var l=Q(c),u={current:[]},d=T((function(e){var t=e.state;if(t.isOpen){var n=t.collections.reduce((function(e,t){return[].concat(ee(e),ee(t.items))}),[]).filter(X);L(u.current.map((function(e){return e.objectID})),n.map((function(e){return e.objectID})))||(u.current=n,n.length>0&&se({onItemsChange:o,items:n,insights:l,state:t}))}}),0);return{name:"aa.algoliaInsightsPlugin",subscribe:function(e){var t=e.setContext,n=e.onSelect,r=e.onActive,o=!1;function u(e){t({algoliaInsightsPlugin:{__algoliaSearchParameters:re(re({},s?{clickAnalytics:!0}:{}),e?{userToken:ue(e)}:{}),insights:l}})}c("addAlgoliaAgent","insights-plugin"),u(),c("onUserTokenChange",(function(e){o||u(e)})),c("getUserToken",null,(function(e,t){o||u(t)})),c("onAuthenticatedUserTokenChange",(function(e){e?(o=!0,u(e)):(o=!1,c("getUserToken",null,(function(e,t){return u(t)})))})),c("getAuthenticatedUserToken",null,(function(e,t){t&&(o=!0,u(t))})),n((function(e){var t=e.item,n=e.state,r=e.event,o=e.source;X(t)&&a({state:n,event:r,insights:l,item:t,insightsEvents:[re({eventName:"Item Selected"},F({item:t,items:o.getItems().filter(X)}))]})})),r((function(e){var t=e.item,n=e.source,r=e.state,o=e.event;X(t)&&i({state:r,event:o,insights:l,item:t,insightsEvents:[re({eventName:"Item Active"},F({item:t,items:n.getItems().filter(X)}))]})}))},onStateChange:function(e){var t=e.state;d({state:t})},__autocomplete_pluginOptions:e}}function le(){var e,t=arguments.length>1?arguments[1]:void 0;return[].concat(ee(arguments.length>0&&void 0!==arguments[0]?arguments[0]:[]),["autocomplete-internal"],ee(null!==(e=t.algoliaInsightsPlugin)&&void 0!==e&&e.__automaticInsights?["autocomplete-automatic"]:[]))}function ue(e){return"number"==typeof e?e.toString():e}function de(e,t){var n=t;return{then:function(t,r){return de(e.then(fe(t,n,e),fe(r,n,e)),n)},catch:function(t){return de(e.catch(fe(t,n,e)),n)},finally:function(t){return t&&n.onCancelList.push(t),de(e.finally(fe(t&&function(){return n.onCancelList=[],t()},n,e)),n)},cancel:function(){n.isCanceled=!0;var e=n.onCancelList;n.onCancelList=[],e.forEach((function(e){e()}))},isCanceled:function(){return!0===n.isCanceled}}}function pe(e){return de(e,{isCanceled:!1,onCancelList:[]})}function fe(e,t,n){return e?function(n){return t.isCanceled?n:e(n)}:n}function me(e,t,n,r){if(!n)return null;if(e<0&&(null===t||null!==r&&0===t))return n+e;var o=(null===t?-1:t)+e;return o<=-1||o>=n?null===r?null:0:o}function ge(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function he(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?ge(Object(n),!0).forEach((function(t){be(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):ge(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}function be(e,t,n){return(t=function(e){var t=function(e){if("object"!==ye(e)||null===e)return e;var t=e[Symbol.toPrimitive];if(void 0!==t){var n=t.call(e,"string");if("object"!==ye(n))return n;throw new TypeError("@@toPrimitive must return a primitive value.")}return String(e)}(e);return"symbol"===ye(t)?t:String(t)}(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function ye(e){return ye="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},ye(e)}function ve(e){var t=function(e){var t=e.collections.map((function(e){return e.items.length})).reduce((function(e,t,n){var r=(e[n-1]||0)+t;return e.push(r),e}),[]).reduce((function(t,n){return n<=e.activeItemId?t+1:t}),0);return e.collections[t]}(e);if(!t)return null;var n=t.items[function(e){for(var t=e.state,n=e.collection,r=!1,o=0,a=0;!1===r;){var i=t.collections[o];if(i===n){r=!0;break}a+=i.items.length,o++}return t.activeItemId-a}({state:e,collection:t})],r=t.source;return{item:n,itemInputValue:r.getItemInputValue({item:n,state:e}),itemUrl:r.getItemUrl({item:n,state:e}),source:r}}function we(e,t,n){return[e,null==n?void 0:n.sourceId,t].filter(Boolean).join("-").replace(/\s/g,"")}var Se=/((gt|sm)-|galaxy nexus)|samsung[- ]|samsungbrowser/i;function ke(e){return e.nativeEvent||e}function xe(e){return xe="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},xe(e)}function _e(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function Ee(e,t,n){return(t=function(e){var t=function(e){if("object"!==xe(e)||null===e)return e;var t=e[Symbol.toPrimitive];if(void 0!==t){var n=t.call(e,"string");if("object"!==xe(n))return n;throw new TypeError("@@toPrimitive must return a primitive value.")}return String(e)}(e);return"symbol"===xe(t)?t:String(t)}(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function je(e){return je="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},je(e)}function Oe(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function Ae(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?Oe(Object(n),!0).forEach((function(t){Ce(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):Oe(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}function Ce(e,t,n){return(t=function(e){var t=function(e){if("object"!==je(e)||null===e)return e;var t=e[Symbol.toPrimitive];if(void 0!==t){var n=t.call(e,"string");if("object"!==je(n))return n;throw new TypeError("@@toPrimitive must return a primitive value.")}return String(e)}(e);return"symbol"===je(t)?t:String(t)}(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function Te(e){return Te="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},Te(e)}function Pe(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=new Array(t);n<t;n++)r[n]=e[n];return r}function Ie(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function Ne(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?Ie(Object(n),!0).forEach((function(t){Re(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):Ie(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}function Re(e,t,n){return(t=function(e){var t=function(e){if("object"!==Te(e)||null===e)return e;var t=e[Symbol.toPrimitive];if(void 0!==t){var n=t.call(e,"string");if("object"!==Te(n))return n;throw new TypeError("@@toPrimitive must return a primitive value.")}return String(e)}(e);return"symbol"===Te(t)?t:String(t)}(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function Le(e,t){var n,r="undefined"!=typeof window?window:{},o=e.plugins||[];return Ne(Ne({debug:!1,openOnFocus:!1,enterKeyHint:void 0,ignoreCompositionEvents:!1,placeholder:"",autoFocus:!1,defaultActiveItemId:null,stallThreshold:300,insights:void 0,environment:r,shouldPanelOpen:function(e){return N(e.state)>0},reshape:function(e){return e.sources}},e),{},{id:null!==(n=e.id)&&void 0!==n?n:"autocomplete-".concat(I++),plugins:o,initialState:Ne({activeItemId:null,query:"",completion:null,collections:[],isOpen:!1,status:"idle",context:{}},e.initialState),onStateChange:function(t){var n;null===(n=e.onStateChange)||void 0===n||n.call(e,t),o.forEach((function(e){var n;return null===(n=e.onStateChange)||void 0===n?void 0:n.call(e,t)}))},onSubmit:function(t){var n;null===(n=e.onSubmit)||void 0===n||n.call(e,t),o.forEach((function(e){var n;return null===(n=e.onSubmit)||void 0===n?void 0:n.call(e,t)}))},onReset:function(t){var n;null===(n=e.onReset)||void 0===n||n.call(e,t),o.forEach((function(e){var n;return null===(n=e.onReset)||void 0===n?void 0:n.call(e,t)}))},getSources:function(n){return Promise.all([].concat(function(e){return function(e){if(Array.isArray(e))return Pe(e)}(e)||function(e){if("undefined"!=typeof Symbol&&null!=e[Symbol.iterator]||null!=e["@@iterator"])return Array.from(e)}(e)||function(e,t){if(e){if("string"==typeof e)return Pe(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);return"Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n?Array.from(e):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?Pe(e,t):void 0}}(e)||function(){throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}(o.map((function(e){return e.getSources}))),[e.getSources]).filter(Boolean).map((function(e){return function(e,t){var n=[];return Promise.resolve(e(t)).then((function(e){return Promise.all(e.filter((function(e){return Boolean(e)})).map((function(e){if(e.sourceId,n.includes(e.sourceId))throw new Error("[Autocomplete] The `sourceId` ".concat(JSON.stringify(e.sourceId)," is not unique."));n.push(e.sourceId);var t={getItemInputValue:function(e){return e.state.query},getItemUrl:function(){},onSelect:function(e){(0,e.setIsOpen)(!1)},onActive:D,onResolve:D};Object.keys(t).forEach((function(e){t[e].__default=!0}));var r=he(he({},t),e);return Promise.resolve(r)})))}))}(e,n)}))).then((function(e){return P(e)})).then((function(e){return e.map((function(e){return Ne(Ne({},e),{},{onSelect:function(n){e.onSelect(n),t.forEach((function(e){var t;return null===(t=e.onSelect)||void 0===t?void 0:t.call(e,n)}))},onActive:function(n){e.onActive(n),t.forEach((function(e){var t;return null===(t=e.onActive)||void 0===t?void 0:t.call(e,n)}))},onResolve:function(n){e.onResolve(n),t.forEach((function(e){var t;return null===(t=e.onResolve)||void 0===t?void 0:t.call(e,n)}))}})}))}))},navigator:Ne({navigate:function(e){var t=e.itemUrl;r.location.assign(t)},navigateNewTab:function(e){var t=e.itemUrl,n=r.open(t,"_blank","noopener");null==n||n.focus()},navigateNewWindow:function(e){var t=e.itemUrl;r.open(t,"_blank","noopener")}},e.navigator)})}function De(e){return De="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},De(e)}function Me(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function Fe(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?Me(Object(n),!0).forEach((function(t){Be(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):Me(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}function Be(e,t,n){return(t=function(e){var t=function(e){if("object"!==De(e)||null===e)return e;var t=e[Symbol.toPrimitive];if(void 0!==t){var n=t.call(e,"string");if("object"!==De(n))return n;throw new TypeError("@@toPrimitive must return a primitive value.")}return String(e)}(e);return"symbol"===De(t)?t:String(t)}(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function ze(e){return ze="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},ze(e)}function $e(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function Ue(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?$e(Object(n),!0).forEach((function(t){He(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):$e(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}function He(e,t,n){return(t=function(e){var t=function(e){if("object"!==ze(e)||null===e)return e;var t=e[Symbol.toPrimitive];if(void 0!==t){var n=t.call(e,"string");if("object"!==ze(n))return n;throw new TypeError("@@toPrimitive must return a primitive value.")}return String(e)}(e);return"symbol"===ze(t)?t:String(t)}(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function qe(e){return function(e){if(Array.isArray(e))return Ve(e)}(e)||function(e){if("undefined"!=typeof Symbol&&null!=e[Symbol.iterator]||null!=e["@@iterator"])return Array.from(e)}(e)||function(e,t){if(e){if("string"==typeof e)return Ve(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);return"Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n?Array.from(e):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?Ve(e,t):void 0}}(e)||function(){throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function Ve(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=new Array(t);n<t;n++)r[n]=e[n];return r}function We(e){return Boolean(e.execute)}function Ge(e){var t=e.reduce((function(e,t){if(!We(t))return e.push(t),e;var n=t.searchClient,r=t.execute,o=t.requesterId,a=t.requests,i=e.find((function(e){return We(t)&&We(e)&&e.searchClient===n&&Boolean(o)&&e.requesterId===o}));if(i){var s;(s=i.items).push.apply(s,qe(a))}else{var c={execute:r,requesterId:o,items:a,searchClient:n};e.push(c)}return e}),[]).map((function(e){if(!We(e))return Promise.resolve(e);var t=e,n=t.execute,r=t.items;return n({searchClient:t.searchClient,requests:r})}));return Promise.all(t).then((function(e){return P(e)}))}function Ke(e){return Ke="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},Ke(e)}var Ye=["event","nextState","props","query","refresh","store"];function Qe(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function Ze(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?Qe(Object(n),!0).forEach((function(t){Xe(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):Qe(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}function Xe(e,t,n){return(t=function(e){var t=function(e){if("object"!==Ke(e)||null===e)return e;var t=e[Symbol.toPrimitive];if(void 0!==t){var n=t.call(e,"string");if("object"!==Ke(n))return n;throw new TypeError("@@toPrimitive must return a primitive value.")}return String(e)}(e);return"symbol"===Ke(t)?t:String(t)}(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}var Je,et,tt,nt=null,rt=(Je=-1,et=-1,tt=void 0,function(e){var t=++Je;return Promise.resolve(e).then((function(e){return tt&&t<et?tt:(et=t,tt=e,e)}))});function ot(e){var t=e.event,n=e.nextState,r=void 0===n?{}:n,o=e.props,a=e.query,i=e.refresh,s=e.store,c=function(e,t){if(null==e)return{};var n,r,o=function(e,t){if(null==e)return{};var n,r,o={},a=Object.keys(e);for(r=0;r<a.length;r++)n=a[r],t.indexOf(n)>=0||(o[n]=e[n]);return o}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(r=0;r<a.length;r++)n=a[r],t.indexOf(n)>=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(o[n]=e[n])}return o}(e,Ye);nt&&o.environment.clearTimeout(nt);var l=c.setCollections,u=c.setIsOpen,d=c.setQuery,p=c.setActiveItemId,f=c.setStatus,m=c.setContext;if(d(a),p(o.defaultActiveItemId),!a&&!1===o.openOnFocus){var g,h=s.getState().collections.map((function(e){return Ze(Ze({},e),{},{items:[]})}));f("idle"),l(h),u(null!==(g=r.isOpen)&&void 0!==g?g:o.shouldPanelOpen({state:s.getState()}));var b=pe(rt(h).then((function(){return Promise.resolve()})));return s.pendingRequests.add(b)}f("loading"),nt=o.environment.setTimeout((function(){f("stalled")}),o.stallThreshold);var y=pe(rt(o.getSources(Ze({query:a,refresh:i,state:s.getState()},c)).then((function(e){return Promise.all(e.map((function(e){return Promise.resolve(e.getItems(Ze({query:a,refresh:i,state:s.getState()},c))).then((function(t){return function(e,t,n){if(o=e,Boolean(null==o?void 0:o.execute)){var r="algolia"===e.requesterId?Object.assign.apply(Object,[{}].concat(qe(Object.keys(n.context).map((function(e){var t;return null===(t=n.context[e])||void 0===t?void 0:t.__algoliaSearchParameters}))))):{};return Ue(Ue({},e),{},{requests:e.queries.map((function(n){return{query:"algolia"===e.requesterId?Ue(Ue({},n),{},{params:Ue(Ue({},r),n.params)}):n,sourceId:t,transformResponse:e.transformResponse}}))})}var o;return{items:e,sourceId:t}}(t,e.sourceId,s.getState())}))}))).then(Ge).then((function(t){var n,r=t.some((function(e){return function(e){return!Array.isArray(e)&&Boolean(null==e?void 0:e._automaticInsights)}(e.items)}));return r&&m({algoliaInsightsPlugin:Ze(Ze({},(null===(n=s.getState().context)||void 0===n?void 0:n.algoliaInsightsPlugin)||{}),{},{__automaticInsights:r})}),function(e,t,n){return t.map((function(t){var r,o=e.filter((function(e){return e.sourceId===t.sourceId})),a=o.map((function(e){return e.items})),i=o[0].transformResponse,s=i?i({results:r=a,hits:r.map((function(e){return e.hits})).filter(Boolean),facetHits:r.map((function(e){var t;return null===(t=e.facetHits)||void 0===t?void 0:t.map((function(e){return{label:e.value,count:e.count,_highlightResult:{label:{value:e.highlighted}}}}))})).filter(Boolean)}):a;return t.onResolve({source:t,results:a,items:s,state:n.getState()}),s.every(Boolean),'The `getItems` function from source "'.concat(t.sourceId,'" must return an array of items but returned ').concat(JSON.stringify(void 0),".\n\nDid you forget to return items?\n\nSee: https://www.algolia.com/doc/ui-libraries/autocomplete/core-concepts/sources/#param-getitems"),{source:t,items:s}}))}(t,e,s)})).then((function(e){return function(e){var t=e.props,n=e.state,r=e.collections.reduce((function(e,t){return Fe(Fe({},e),{},Be({},t.source.sourceId,Fe(Fe({},t.source),{},{getItems:function(){return P(t.items)}})))}),{}),o=t.plugins.reduce((function(e,t){return t.reshape?t.reshape(e):e}),{sourcesBySourceId:r,state:n}).sourcesBySourceId;return P(t.reshape({sourcesBySourceId:o,sources:Object.values(o),state:n})).filter(Boolean).map((function(e){return{source:e,items:e.getItems()}}))}({collections:e,props:o,state:s.getState()})}))})))).then((function(e){var n;f("idle"),l(e);var d=o.shouldPanelOpen({state:s.getState()});u(null!==(n=r.isOpen)&&void 0!==n?n:o.openOnFocus&&!a&&d||d);var p=ve(s.getState());if(null!==s.getState().activeItemId&&p){var m=p.item,g=p.itemInputValue,h=p.itemUrl,b=p.source;b.onActive(Ze({event:t,item:m,itemInputValue:g,itemUrl:h,refresh:i,source:b,state:s.getState()},c))}})).finally((function(){f("idle"),nt&&o.environment.clearTimeout(nt)}));return s.pendingRequests.add(y)}function at(e){return at="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},at(e)}var it=["event","props","refresh","store"];function st(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function ct(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?st(Object(n),!0).forEach((function(t){lt(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):st(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}function lt(e,t,n){return(t=function(e){var t=function(e){if("object"!==at(e)||null===e)return e;var t=e[Symbol.toPrimitive];if(void 0!==t){var n=t.call(e,"string");if("object"!==at(n))return n;throw new TypeError("@@toPrimitive must return a primitive value.")}return String(e)}(e);return"symbol"===at(t)?t:String(t)}(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function ut(e){return ut="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},ut(e)}var dt=["props","refresh","store"],pt=["inputElement","formElement","panelElement"],ft=["inputElement"],mt=["inputElement","maxLength"],gt=["source"],ht=["item","source"];function bt(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function yt(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?bt(Object(n),!0).forEach((function(t){vt(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):bt(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}function vt(e,t,n){return(t=function(e){var t=function(e){if("object"!==ut(e)||null===e)return e;var t=e[Symbol.toPrimitive];if(void 0!==t){var n=t.call(e,"string");if("object"!==ut(n))return n;throw new TypeError("@@toPrimitive must return a primitive value.")}return String(e)}(e);return"symbol"===ut(t)?t:String(t)}(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function wt(e,t){if(null==e)return{};var n,r,o=function(e,t){if(null==e)return{};var n,r,o={},a=Object.keys(e);for(r=0;r<a.length;r++)n=a[r],t.indexOf(n)>=0||(o[n]=e[n]);return o}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(r=0;r<a.length;r++)n=a[r],t.indexOf(n)>=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(o[n]=e[n])}return o}function St(e){var t=e.props,n=e.refresh,r=e.store,o=wt(e,dt);return{getEnvironmentProps:function(e){var n=e.inputElement,o=e.formElement,a=e.panelElement;function i(e){!r.getState().isOpen&&r.pendingRequests.isEmpty()||e.target===n||!1===[o,a].some((function(t){return(n=t)===(r=e.target)||n.contains(r);var n,r}))&&(r.dispatch("blur",null),t.debug||r.pendingRequests.cancelAll())}return yt({onTouchStart:i,onMouseDown:i,onTouchMove:function(e){!1!==r.getState().isOpen&&n===t.environment.document.activeElement&&e.target!==n&&n.blur()}},wt(e,pt))},getRootProps:function(e){return yt({role:"combobox","aria-expanded":r.getState().isOpen,"aria-haspopup":"listbox","aria-controls":r.getState().isOpen?r.getState().collections.map((function(e){var n=e.source;return we(t.id,"list",n)})).join(" "):void 0,"aria-labelledby":we(t.id,"label")},e)},getFormProps:function(e){return e.inputElement,yt({action:"",noValidate:!0,role:"search",onSubmit:function(a){var i;a.preventDefault(),t.onSubmit(yt({event:a,refresh:n,state:r.getState()},o)),r.dispatch("submit",null),null===(i=e.inputElement)||void 0===i||i.blur()},onReset:function(a){var i;a.preventDefault(),t.onReset(yt({event:a,refresh:n,state:r.getState()},o)),r.dispatch("reset",null),null===(i=e.inputElement)||void 0===i||i.focus()}},wt(e,ft))},getLabelProps:function(e){return yt({htmlFor:we(t.id,"input"),id:we(t.id,"label")},e)},getInputProps:function(e){var a;function i(e){(t.openOnFocus||Boolean(r.getState().query))&&ot(yt({event:e,props:t,query:r.getState().completion||r.getState().query,refresh:n,store:r},o)),r.dispatch("focus",null)}var s=e||{};s.inputElement;var c=s.maxLength,l=void 0===c?512:c,u=wt(s,mt),d=ve(r.getState()),p=function(e){return Boolean(e&&e.match(Se))}((null===(a=t.environment.navigator)||void 0===a?void 0:a.userAgent)||""),f=t.enterKeyHint||(null!=d&&d.itemUrl&&!p?"go":"search");return yt({"aria-autocomplete":"both","aria-activedescendant":r.getState().isOpen&&null!==r.getState().activeItemId?we(t.id,"item-".concat(r.getState().activeItemId),null==d?void 0:d.source):void 0,"aria-controls":r.getState().isOpen?r.getState().collections.map((function(e){var n=e.source;return we(t.id,"list",n)})).join(" "):void 0,"aria-labelledby":we(t.id,"label"),value:r.getState().completion||r.getState().query,id:we(t.id,"input"),autoComplete:"off",autoCorrect:"off",autoCapitalize:"off",enterKeyHint:f,spellCheck:"false",autoFocus:t.autoFocus,placeholder:t.placeholder,maxLength:l,type:"search",onChange:function(e){var a=e.currentTarget.value;t.ignoreCompositionEvents&&ke(e).isComposing?o.setQuery(a):ot(yt({event:e,props:t,query:a.slice(0,l),refresh:n,store:r},o))},onCompositionEnd:function(e){ot(yt({event:e,props:t,query:e.currentTarget.value.slice(0,l),refresh:n,store:r},o))},onKeyDown:function(e){ke(e).isComposing||function(e){var t=e.event,n=e.props,r=e.refresh,o=e.store,a=function(e,t){if(null==e)return{};var n,r,o=function(e,t){if(null==e)return{};var n,r,o={},a=Object.keys(e);for(r=0;r<a.length;r++)n=a[r],t.indexOf(n)>=0||(o[n]=e[n]);return o}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(r=0;r<a.length;r++)n=a[r],t.indexOf(n)>=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(o[n]=e[n])}return o}(e,it);if("ArrowUp"===t.key||"ArrowDown"===t.key){var i=function(){var e=ve(o.getState()),t=n.environment.document.getElementById(we(n.id,"item-".concat(o.getState().activeItemId),null==e?void 0:e.source));t&&(t.scrollIntoViewIfNeeded?t.scrollIntoViewIfNeeded(!1):t.scrollIntoView(!1))},s=function(){var e=ve(o.getState());if(null!==o.getState().activeItemId&&e){var n=e.item,i=e.itemInputValue,s=e.itemUrl,c=e.source;c.onActive(ct({event:t,item:n,itemInputValue:i,itemUrl:s,refresh:r,source:c,state:o.getState()},a))}};t.preventDefault(),!1===o.getState().isOpen&&(n.openOnFocus||Boolean(o.getState().query))?ot(ct({event:t,props:n,query:o.getState().query,refresh:r,store:o},a)).then((function(){o.dispatch(t.key,{nextActiveItemId:n.defaultActiveItemId}),s(),setTimeout(i,0)})):(o.dispatch(t.key,{}),s(),i())}else if("Escape"===t.key)t.preventDefault(),o.dispatch(t.key,null),o.pendingRequests.cancelAll();else if("Tab"===t.key)o.dispatch("blur",null),o.pendingRequests.cancelAll();else if("Enter"===t.key){if(null===o.getState().activeItemId||o.getState().collections.every((function(e){return 0===e.items.length})))return void(n.debug||o.pendingRequests.cancelAll());t.preventDefault();var c=ve(o.getState()),l=c.item,u=c.itemInputValue,d=c.itemUrl,p=c.source;if(t.metaKey||t.ctrlKey)void 0!==d&&(p.onSelect(ct({event:t,item:l,itemInputValue:u,itemUrl:d,refresh:r,source:p,state:o.getState()},a)),n.navigator.navigateNewTab({itemUrl:d,item:l,state:o.getState()}));else if(t.shiftKey)void 0!==d&&(p.onSelect(ct({event:t,item:l,itemInputValue:u,itemUrl:d,refresh:r,source:p,state:o.getState()},a)),n.navigator.navigateNewWindow({itemUrl:d,item:l,state:o.getState()}));else if(t.altKey);else{if(void 0!==d)return p.onSelect(ct({event:t,item:l,itemInputValue:u,itemUrl:d,refresh:r,source:p,state:o.getState()},a)),void n.navigator.navigate({itemUrl:d,item:l,state:o.getState()});ot(ct({event:t,nextState:{isOpen:!1},props:n,query:u,refresh:r,store:o},a)).then((function(){p.onSelect(ct({event:t,item:l,itemInputValue:u,itemUrl:d,refresh:r,source:p,state:o.getState()},a))}))}}}(yt({event:e,props:t,refresh:n,store:r},o))},onFocus:i,onBlur:D,onClick:function(n){e.inputElement!==t.environment.document.activeElement||r.getState().isOpen||i(n)}},u)},getPanelProps:function(e){return yt({onMouseDown:function(e){e.preventDefault()},onMouseLeave:function(){r.dispatch("mouseleave",null)}},e)},getListProps:function(e){var n=e||{},r=n.source,o=wt(n,gt);return yt({role:"listbox","aria-labelledby":we(t.id,"label"),id:we(t.id,"list",r)},o)},getItemProps:function(e){var a=e.item,i=e.source,s=wt(e,ht);return yt({id:we(t.id,"item-".concat(a.__autocomplete_id),i),role:"option","aria-selected":r.getState().activeItemId===a.__autocomplete_id,onMouseMove:function(e){if(a.__autocomplete_id!==r.getState().activeItemId){r.dispatch("mousemove",a.__autocomplete_id);var t=ve(r.getState());if(null!==r.getState().activeItemId&&t){var i=t.item,s=t.itemInputValue,c=t.itemUrl,l=t.source;l.onActive(yt({event:e,item:i,itemInputValue:s,itemUrl:c,refresh:n,source:l,state:r.getState()},o))}}},onMouseDown:function(e){e.preventDefault()},onClick:function(e){var s=i.getItemInputValue({item:a,state:r.getState()}),c=i.getItemUrl({item:a,state:r.getState()});(c?Promise.resolve():ot(yt({event:e,nextState:{isOpen:!1},props:t,query:s,refresh:n,store:r},o))).then((function(){i.onSelect(yt({event:e,item:a,itemInputValue:s,itemUrl:c,refresh:n,source:i,state:r.getState()},o))}))}},s)}}}function kt(e){return kt="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},kt(e)}function xt(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function _t(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?xt(Object(n),!0).forEach((function(t){Et(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):xt(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}function Et(e,t,n){return(t=function(e){var t=function(e){if("object"!==kt(e)||null===e)return e;var t=e[Symbol.toPrimitive];if(void 0!==t){var n=t.call(e,"string");if("object"!==kt(n))return n;throw new TypeError("@@toPrimitive must return a primitive value.")}return String(e)}(e);return"symbol"===kt(t)?t:String(t)}(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function jt(e){var t,n,r,o,a=e.plugins,i=e.options,s=null===(t=((null===(n=i.__autocomplete_metadata)||void 0===n?void 0:n.userAgents)||[])[0])||void 0===t?void 0:t.segment,c=s?Et({},s,Object.keys((null===(r=i.__autocomplete_metadata)||void 0===r?void 0:r.options)||{})):{};return{plugins:a.map((function(e){return{name:e.name,options:Object.keys(e.__autocomplete_pluginOptions||[])}})),options:_t({"autocomplete-core":Object.keys(i)},c),ua:M.concat((null===(o=i.__autocomplete_metadata)||void 0===o?void 0:o.userAgents)||[])}}function Ot(e){var t,n=e.state;return!1===n.isOpen||null===n.activeItemId?null:(null===(t=ve(n))||void 0===t?void 0:t.itemInputValue)||null}function At(e){return At="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},At(e)}function Ct(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function Tt(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?Ct(Object(n),!0).forEach((function(t){Pt(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):Ct(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}function Pt(e,t,n){return(t=function(e){var t=function(e){if("object"!==At(e)||null===e)return e;var t=e[Symbol.toPrimitive];if(void 0!==t){var n=t.call(e,"string");if("object"!==At(n))return n;throw new TypeError("@@toPrimitive must return a primitive value.")}return String(e)}(e);return"symbol"===At(t)?t:String(t)}(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}var It=function(e,t){switch(t.type){case"setActiveItemId":case"mousemove":return Tt(Tt({},e),{},{activeItemId:t.payload});case"setQuery":return Tt(Tt({},e),{},{query:t.payload,completion:null});case"setCollections":return Tt(Tt({},e),{},{collections:t.payload});case"setIsOpen":return Tt(Tt({},e),{},{isOpen:t.payload});case"setStatus":return Tt(Tt({},e),{},{status:t.payload});case"setContext":return Tt(Tt({},e),{},{context:Tt(Tt({},e.context),t.payload)});case"ArrowDown":var n=Tt(Tt({},e),{},{activeItemId:t.payload.hasOwnProperty("nextActiveItemId")?t.payload.nextActiveItemId:me(1,e.activeItemId,N(e),t.props.defaultActiveItemId)});return Tt(Tt({},n),{},{completion:Ot({state:n})});case"ArrowUp":var r=Tt(Tt({},e),{},{activeItemId:me(-1,e.activeItemId,N(e),t.props.defaultActiveItemId)});return Tt(Tt({},r),{},{completion:Ot({state:r})});case"Escape":return e.isOpen?Tt(Tt({},e),{},{activeItemId:null,isOpen:!1,completion:null}):Tt(Tt({},e),{},{activeItemId:null,query:"",status:"idle",collections:[]});case"submit":return Tt(Tt({},e),{},{activeItemId:null,isOpen:!1,status:"idle"});case"reset":return Tt(Tt({},e),{},{activeItemId:!0===t.props.openOnFocus?t.props.defaultActiveItemId:null,status:"idle",completion:null,query:""});case"focus":return Tt(Tt({},e),{},{activeItemId:t.props.defaultActiveItemId,isOpen:(t.props.openOnFocus||Boolean(e.query))&&t.props.shouldPanelOpen({state:e})});case"blur":return t.props.debug?e:Tt(Tt({},e),{},{isOpen:!1,activeItemId:null});case"mouseleave":return Tt(Tt({},e),{},{activeItemId:t.props.defaultActiveItemId});default:return"The reducer action ".concat(JSON.stringify(t.type)," is not supported."),e}};function Nt(e){return Nt="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},Nt(e)}function Rt(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function Lt(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?Rt(Object(n),!0).forEach((function(t){Dt(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):Rt(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}function Dt(e,t,n){return(t=function(e){var t=function(e){if("object"!==Nt(e)||null===e)return e;var t=e[Symbol.toPrimitive];if(void 0!==t){var n=t.call(e,"string");if("object"!==Nt(n))return n;throw new TypeError("@@toPrimitive must return a primitive value.")}return String(e)}(e);return"symbol"===Nt(t)?t:String(t)}(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function Mt(e){var t=[],n=Le(e,t),r=function(e,t,n){var r,o=t.initialState;return{getState:function(){return o},dispatch:function(r,a){var i=function(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?_e(Object(n),!0).forEach((function(t){Ee(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):_e(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}({},o);o=e(o,{type:r,props:t,payload:a}),n({state:o,prevState:i})},pendingRequests:(r=[],{add:function(e){return r.push(e),e.finally((function(){r=r.filter((function(t){return t!==e}))}))},cancelAll:function(){r.forEach((function(e){return e.cancel()}))},isEmpty:function(){return 0===r.length}})}}(It,n,(function(e){var t,r,a=e.prevState,l=e.state;if(n.onStateChange(Lt({prevState:a,state:l,refresh:i,navigator:n.navigator},o)),!c()&&null!==(t=l.context)&&void 0!==t&&null!==(r=t.algoliaInsightsPlugin)&&void 0!==r&&r.__automaticInsights&&!1!==n.insights){var u=ce({__autocomplete_clickAnalytics:!1});n.plugins.push(u),s([u])}})),o=function(e){var t=e.store;return{setActiveItemId:function(e){t.dispatch("setActiveItemId",e)},setQuery:function(e){t.dispatch("setQuery",e)},setCollections:function(e){var n=0,r=e.map((function(e){return Ae(Ae({},e),{},{items:P(e.items).map((function(e){return Ae(Ae({},e),{},{__autocomplete_id:n++})}))})}));t.dispatch("setCollections",r)},setIsOpen:function(e){t.dispatch("setIsOpen",e)},setStatus:function(e){t.dispatch("setStatus",e)},setContext:function(e){t.dispatch("setContext",e)}}}({store:r}),a=St(Lt({props:n,refresh:i,store:r,navigator:n.navigator},o));function i(){return ot(Lt({event:new Event("input"),nextState:{isOpen:r.getState().isOpen},props:n,navigator:n.navigator,query:r.getState().query,refresh:i,store:r},o))}function s(e){e.forEach((function(e){var r;return null===(r=e.subscribe)||void 0===r?void 0:r.call(e,Lt(Lt({},o),{},{navigator:n.navigator,refresh:i,onSelect:function(e){t.push({onSelect:e})},onActive:function(e){t.push({onActive:e})},onResolve:function(e){t.push({onResolve:e})}}))}))}function c(){return n.plugins.some((function(e){return"aa.algoliaInsightsPlugin"===e.name}))}if(n.insights&&!c()){var l="boolean"==typeof n.insights?{}:n.insights;n.plugins.push(ce(l))}return s(n.plugins),function(e){var t,n,r=e.metadata,o=e.environment;if(null===(t=o.navigator)||void 0===t||null===(n=t.userAgent)||void 0===n?void 0:n.includes("Algolia Crawler")){var a=o.document.createElement("meta"),i=o.document.querySelector("head");a.name="algolia:metadata",setTimeout((function(){a.content=JSON.stringify(r),i.appendChild(a)}),0)}}({metadata:jt({plugins:n.plugins,options:e}),environment:n.environment}),Lt(Lt({refresh:i,navigator:n.navigator},a),o)}function Ft(e){var t=e.translations,n=(void 0===t?{}:t).searchByText,o=void 0===n?"Search by":n;return r.createElement("a",{href:"https://www.algolia.com/ref/docsearch/?utm_source=".concat(window.location.hostname,"&utm_medium=referral&utm_content=powered_by&utm_campaign=docsearch"),target:"_blank",rel:"noopener noreferrer"},r.createElement("span",{className:"DocSearch-Label"},o),r.createElement("svg",{width:"77",height:"19","aria-label":"Algolia",role:"img",id:"Layer_1",xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 2196.2 500"},r.createElement("defs",null,r.createElement("style",null,".cls-1,.cls-2{fill:#003dff;}.cls-2{fill-rule:evenodd;}")),r.createElement("path",{className:"cls-2",d:"M1070.38,275.3V5.91c0-3.63-3.24-6.39-6.82-5.83l-50.46,7.94c-2.87,.45-4.99,2.93-4.99,5.84l.17,273.22c0,12.92,0,92.7,95.97,95.49,3.33,.1,6.09-2.58,6.09-5.91v-40.78c0-2.96-2.19-5.51-5.12-5.84-34.85-4.01-34.85-47.57-34.85-54.72Z"}),r.createElement("rect",{className:"cls-1",x:"1845.88",y:"104.73",width:"62.58",height:"277.9",rx:"5.9",ry:"5.9"}),r.createElement("path",{className:"cls-2",d:"M1851.78,71.38h50.77c3.26,0,5.9-2.64,5.9-5.9V5.9c0-3.62-3.24-6.39-6.82-5.83l-50.77,7.95c-2.87,.45-4.99,2.92-4.99,5.83v51.62c0,3.26,2.64,5.9,5.9,5.9Z"}),r.createElement("path",{className:"cls-2",d:"M1764.03,275.3V5.91c0-3.63-3.24-6.39-6.82-5.83l-50.46,7.94c-2.87,.45-4.99,2.93-4.99,5.84l.17,273.22c0,12.92,0,92.7,95.97,95.49,3.33,.1,6.09-2.58,6.09-5.91v-40.78c0-2.96-2.19-5.51-5.12-5.84-34.85-4.01-34.85-47.57-34.85-54.72Z"}),r.createElement("path",{className:"cls-2",d:"M1631.95,142.72c-11.14-12.25-24.83-21.65-40.78-28.31-15.92-6.53-33.26-9.85-52.07-9.85-18.78,0-36.15,3.17-51.92,9.85-15.59,6.66-29.29,16.05-40.76,28.31-11.47,12.23-20.38,26.87-26.76,44.03-6.38,17.17-9.24,37.37-9.24,58.36,0,20.99,3.19,36.87,9.55,54.21,6.38,17.32,15.14,32.11,26.45,44.36,11.29,12.23,24.83,21.62,40.6,28.46,15.77,6.83,40.12,10.33,52.4,10.48,12.25,0,36.78-3.82,52.7-10.48,15.92-6.68,29.46-16.23,40.78-28.46,11.29-12.25,20.05-27.04,26.25-44.36,6.22-17.34,9.24-33.22,9.24-54.21,0-20.99-3.34-41.19-10.03-58.36-6.38-17.17-15.14-31.8-26.43-44.03Zm-44.43,163.75c-11.47,15.75-27.56,23.7-48.09,23.7-20.55,0-36.63-7.8-48.1-23.7-11.47-15.75-17.21-34.01-17.21-61.2,0-26.89,5.59-49.14,17.06-64.87,11.45-15.75,27.54-23.52,48.07-23.52,20.55,0,36.63,7.78,48.09,23.52,11.47,15.57,17.36,37.98,17.36,64.87,0,27.19-5.72,45.3-17.19,61.2Z"}),r.createElement("path",{className:"cls-2",d:"M894.42,104.73h-49.33c-48.36,0-90.91,25.48-115.75,64.1-14.52,22.58-22.99,49.63-22.99,78.73,0,44.89,20.13,84.92,51.59,111.1,2.93,2.6,6.05,4.98,9.31,7.14,12.86,8.49,28.11,13.47,44.52,13.47,1.23,0,2.46-.03,3.68-.09,.36-.02,.71-.05,1.07-.07,.87-.05,1.75-.11,2.62-.2,.34-.03,.68-.08,1.02-.12,.91-.1,1.82-.21,2.73-.34,.21-.03,.42-.07,.63-.1,32.89-5.07,61.56-30.82,70.9-62.81v57.83c0,3.26,2.64,5.9,5.9,5.9h50.42c3.26,0,5.9-2.64,5.9-5.9V110.63c0-3.26-2.64-5.9-5.9-5.9h-56.32Zm0,206.92c-12.2,10.16-27.97,13.98-44.84,15.12-.16,.01-.33,.03-.49,.04-1.12,.07-2.24,.1-3.36,.1-42.24,0-77.12-35.89-77.12-79.37,0-10.25,1.96-20.01,5.42-28.98,11.22-29.12,38.77-49.74,71.06-49.74h49.33v142.83Z"}),r.createElement("path",{className:"cls-2",d:"M2133.97,104.73h-49.33c-48.36,0-90.91,25.48-115.75,64.1-14.52,22.58-22.99,49.63-22.99,78.73,0,44.89,20.13,84.92,51.59,111.1,2.93,2.6,6.05,4.98,9.31,7.14,12.86,8.49,28.11,13.47,44.52,13.47,1.23,0,2.46-.03,3.68-.09,.36-.02,.71-.05,1.07-.07,.87-.05,1.75-.11,2.62-.2,.34-.03,.68-.08,1.02-.12,.91-.1,1.82-.21,2.73-.34,.21-.03,.42-.07,.63-.1,32.89-5.07,61.56-30.82,70.9-62.81v57.83c0,3.26,2.64,5.9,5.9,5.9h50.42c3.26,0,5.9-2.64,5.9-5.9V110.63c0-3.26-2.64-5.9-5.9-5.9h-56.32Zm0,206.92c-12.2,10.16-27.97,13.98-44.84,15.12-.16,.01-.33,.03-.49,.04-1.12,.07-2.24,.1-3.36,.1-42.24,0-77.12-35.89-77.12-79.37,0-10.25,1.96-20.01,5.42-28.98,11.22-29.12,38.77-49.74,71.06-49.74h49.33v142.83Z"}),r.createElement("path",{className:"cls-2",d:"M1314.05,104.73h-49.33c-48.36,0-90.91,25.48-115.75,64.1-11.79,18.34-19.6,39.64-22.11,62.59-.58,5.3-.88,10.68-.88,16.14s.31,11.15,.93,16.59c4.28,38.09,23.14,71.61,50.66,94.52,2.93,2.6,6.05,4.98,9.31,7.14,12.86,8.49,28.11,13.47,44.52,13.47h0c17.99,0,34.61-5.93,48.16-15.97,16.29-11.58,28.88-28.54,34.48-47.75v50.26h-.11v11.08c0,21.84-5.71,38.27-17.34,49.36-11.61,11.08-31.04,16.63-58.25,16.63-11.12,0-28.79-.59-46.6-2.41-2.83-.29-5.46,1.5-6.27,4.22l-12.78,43.11c-1.02,3.46,1.27,7.02,4.83,7.53,21.52,3.08,42.52,4.68,54.65,4.68,48.91,0,85.16-10.75,108.89-32.21,21.48-19.41,33.15-48.89,35.2-88.52V110.63c0-3.26-2.64-5.9-5.9-5.9h-56.32Zm0,64.1s.65,139.13,0,143.36c-12.08,9.77-27.11,13.59-43.49,14.7-.16,.01-.33,.03-.49,.04-1.12,.07-2.24,.1-3.36,.1-1.32,0-2.63-.03-3.94-.1-40.41-2.11-74.52-37.26-74.52-79.38,0-10.25,1.96-20.01,5.42-28.98,11.22-29.12,38.77-49.74,71.06-49.74h49.33Z"}),r.createElement("path",{className:"cls-1",d:"M249.83,0C113.3,0,2,110.09,.03,246.16c-2,138.19,110.12,252.7,248.33,253.5,42.68,.25,83.79-10.19,120.3-30.03,3.56-1.93,4.11-6.83,1.08-9.51l-23.38-20.72c-4.75-4.21-11.51-5.4-17.36-2.92-25.48,10.84-53.17,16.38-81.71,16.03-111.68-1.37-201.91-94.29-200.13-205.96,1.76-110.26,92-199.41,202.67-199.41h202.69V407.41l-115-102.18c-3.72-3.31-9.42-2.66-12.42,1.31-18.46,24.44-48.53,39.64-81.93,37.34-46.33-3.2-83.87-40.5-87.34-86.81-4.15-55.24,39.63-101.52,94-101.52,49.18,0,89.68,37.85,93.91,85.95,.38,4.28,2.31,8.27,5.52,11.12l29.95,26.55c3.4,3.01,8.79,1.17,9.63-3.3,2.16-11.55,2.92-23.58,2.07-35.92-4.82-70.34-61.8-126.93-132.17-131.26-80.68-4.97-148.13,58.14-150.27,137.25-2.09,77.1,61.08,143.56,138.19,145.26,32.19,.71,62.03-9.41,86.14-26.95l150.26,133.2c6.44,5.71,16.61,1.14,16.61-7.47V9.48C499.66,4.25,495.42,0,490.18,0H249.83Z"})))}function Bt(e){return r.createElement("svg",{width:"15",height:"15","aria-label":e.ariaLabel,role:"img"},r.createElement("g",{fill:"none",stroke:"currentColor",strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:"1.2"},e.children))}function zt(e){var t=e.translations,n=void 0===t?{}:t,o=n.selectText,a=void 0===o?"to select":o,i=n.selectKeyAriaLabel,s=void 0===i?"Enter key":i,c=n.navigateText,l=void 0===c?"to navigate":c,u=n.navigateUpKeyAriaLabel,d=void 0===u?"Arrow up":u,p=n.navigateDownKeyAriaLabel,f=void 0===p?"Arrow down":p,m=n.closeText,g=void 0===m?"to close":m,h=n.closeKeyAriaLabel,b=void 0===h?"Escape key":h,y=n.searchByText,v=void 0===y?"Search by":y;return r.createElement(r.Fragment,null,r.createElement("div",{className:"DocSearch-Logo"},r.createElement(Ft,{translations:{searchByText:v}})),r.createElement("ul",{className:"DocSearch-Commands"},r.createElement("li",null,r.createElement("kbd",{className:"DocSearch-Commands-Key"},r.createElement(Bt,{ariaLabel:s},r.createElement("path",{d:"M12 3.53088v3c0 1-1 2-2 2H4M7 11.53088l-3-3 3-3"}))),r.createElement("span",{className:"DocSearch-Label"},a)),r.createElement("li",null,r.createElement("kbd",{className:"DocSearch-Commands-Key"},r.createElement(Bt,{ariaLabel:f},r.createElement("path",{d:"M7.5 3.5v8M10.5 8.5l-3 3-3-3"}))),r.createElement("kbd",{className:"DocSearch-Commands-Key"},r.createElement(Bt,{ariaLabel:d},r.createElement("path",{d:"M7.5 11.5v-8M10.5 6.5l-3-3-3 3"}))),r.createElement("span",{className:"DocSearch-Label"},l)),r.createElement("li",null,r.createElement("kbd",{className:"DocSearch-Commands-Key"},r.createElement(Bt,{ariaLabel:b},r.createElement("path",{d:"M13.6167 8.936c-.1065.3583-.6883.962-1.4875.962-.7993 0-1.653-.9165-1.653-2.1258v-.5678c0-1.2548.7896-2.1016 1.653-2.1016.8634 0 1.3601.4778 1.4875 1.0724M9 6c-.1352-.4735-.7506-.9219-1.46-.8972-.7092.0246-1.344.57-1.344 1.2166s.4198.8812 1.3445.9805C8.465 7.3992 8.968 7.9337 9 8.5c.032.5663-.454 1.398-1.4595 1.398C6.6593 9.898 6 9 5.963 8.4851m-1.4748.5368c-.2635.5941-.8099.876-1.5443.876s-1.7073-.6248-1.7073-2.204v-.4603c0-1.0416.721-2.131 1.7073-2.131.9864 0 1.6425 1.031 1.5443 2.2492h-2.956"}))),r.createElement("span",{className:"DocSearch-Label"},g))))}function $t(e){var t=e.hit,n=e.children;return r.createElement("a",{href:t.url},n)}function Ut(){return r.createElement("svg",{viewBox:"0 0 38 38",stroke:"currentColor",strokeOpacity:".5"},r.createElement("g",{fill:"none",fillRule:"evenodd"},r.createElement("g",{transform:"translate(1 1)",strokeWidth:"2"},r.createElement("circle",{strokeOpacity:".3",cx:"18",cy:"18",r:"18"}),r.createElement("path",{d:"M36 18c0-9.94-8.06-18-18-18"},r.createElement("animateTransform",{attributeName:"transform",type:"rotate",from:"0 18 18",to:"360 18 18",dur:"1s",repeatCount:"indefinite"})))))}function Ht(){return r.createElement("svg",{width:"20",height:"20",viewBox:"0 0 20 20"},r.createElement("g",{stroke:"currentColor",fill:"none",fillRule:"evenodd",strokeLinecap:"round",strokeLinejoin:"round"},r.createElement("path",{d:"M3.18 6.6a8.23 8.23 0 1112.93 9.94h0a8.23 8.23 0 01-11.63 0"}),r.createElement("path",{d:"M6.44 7.25H2.55V3.36M10.45 6v5.6M10.45 11.6L13 13"})))}function qt(){return r.createElement("svg",{width:"20",height:"20",viewBox:"0 0 20 20"},r.createElement("path",{d:"M10 10l5.09-5.09L10 10l5.09 5.09L10 10zm0 0L4.91 4.91 10 10l-5.09 5.09L10 10z",stroke:"currentColor",fill:"none",fillRule:"evenodd",strokeLinecap:"round",strokeLinejoin:"round"}))}function Vt(){return r.createElement("svg",{className:"DocSearch-Hit-Select-Icon",width:"20",height:"20",viewBox:"0 0 20 20"},r.createElement("g",{stroke:"currentColor",fill:"none",fillRule:"evenodd",strokeLinecap:"round",strokeLinejoin:"round"},r.createElement("path",{d:"M18 3v4c0 2-2 4-4 4H2"}),r.createElement("path",{d:"M8 17l-6-6 6-6"})))}var Wt=function(){return r.createElement("svg",{width:"20",height:"20",viewBox:"0 0 20 20"},r.createElement("path",{d:"M17 6v12c0 .52-.2 1-1 1H4c-.7 0-1-.33-1-1V2c0-.55.42-1 1-1h8l5 5zM14 8h-3.13c-.51 0-.87-.34-.87-.87V4",stroke:"currentColor",fill:"none",fillRule:"evenodd",strokeLinejoin:"round"}))};function Gt(e){switch(e.type){case"lvl1":return r.createElement(Wt,null);case"content":return r.createElement(Yt,null);default:return r.createElement(Kt,null)}}function Kt(){return r.createElement("svg",{width:"20",height:"20",viewBox:"0 0 20 20"},r.createElement("path",{d:"M13 13h4-4V8H7v5h6v4-4H7V8H3h4V3v5h6V3v5h4-4v5zm-6 0v4-4H3h4z",stroke:"currentColor",fill:"none",fillRule:"evenodd",strokeLinecap:"round",strokeLinejoin:"round"}))}function Yt(){return r.createElement("svg",{width:"20",height:"20",viewBox:"0 0 20 20"},r.createElement("path",{d:"M17 5H3h14zm0 5H3h14zm0 5H3h14z",stroke:"currentColor",fill:"none",fillRule:"evenodd",strokeLinejoin:"round"}))}function Qt(){return r.createElement("svg",{width:"20",height:"20",viewBox:"0 0 20 20"},r.createElement("path",{d:"M10 14.2L5 17l1-5.6-4-4 5.5-.7 2.5-5 2.5 5 5.6.8-4 4 .9 5.5z",stroke:"currentColor",fill:"none",fillRule:"evenodd",strokeLinejoin:"round"}))}function Zt(){return r.createElement("svg",{width:"40",height:"40",viewBox:"0 0 20 20",fill:"none",fillRule:"evenodd",stroke:"currentColor",strokeLinecap:"round",strokeLinejoin:"round"},r.createElement("path",{d:"M19 4.8a16 16 0 00-2-1.2m-3.3-1.2A16 16 0 001.1 4.7M16.7 8a12 12 0 00-2.8-1.4M10 6a12 12 0 00-6.7 2M12.3 14.7a4 4 0 00-4.5 0M14.5 11.4A8 8 0 0010 10M3 16L18 2M10 18h0"}))}function Xt(){return r.createElement("svg",{width:"40",height:"40",viewBox:"0 0 20 20",fill:"none",fillRule:"evenodd",stroke:"currentColor",strokeLinecap:"round",strokeLinejoin:"round"},r.createElement("path",{d:"M15.5 4.8c2 3 1.7 7-1 9.7h0l4.3 4.3-4.3-4.3a7.8 7.8 0 01-9.8 1m-2.2-2.2A7.8 7.8 0 0113.2 2.4M2 18L18 2"}))}function Jt(e){var t=e.translations,n=void 0===t?{}:t,o=n.titleText,a=void 0===o?"Unable to fetch results":o,i=n.helpText,s=void 0===i?"You might want to check your network connection.":i;return r.createElement("div",{className:"DocSearch-ErrorScreen"},r.createElement("div",{className:"DocSearch-Screen-Icon"},r.createElement(Zt,null)),r.createElement("p",{className:"DocSearch-Title"},a),r.createElement("p",{className:"DocSearch-Help"},s))}var en=["translations"];function tn(e){var t=e.translations,n=void 0===t?{}:t,o=b(e,en),a=n.noResultsText,i=void 0===a?"No results for":a,s=n.suggestedQueryText,c=void 0===s?"Try searching for":s,l=n.reportMissingResultsText,u=void 0===l?"Believe this query should return results?":l,d=n.reportMissingResultsLinkText,p=void 0===d?"Let us know.":d,f=o.state.context.searchSuggestions;return r.createElement("div",{className:"DocSearch-NoResults"},r.createElement("div",{className:"DocSearch-Screen-Icon"},r.createElement(Xt,null)),r.createElement("p",{className:"DocSearch-Title"},i,' "',r.createElement("strong",null,o.state.query),'"'),f&&f.length>0&&r.createElement("div",{className:"DocSearch-NoResults-Prefill-List"},r.createElement("p",{className:"DocSearch-Help"},c,":"),r.createElement("ul",null,f.slice(0,3).reduce((function(e,t){return[].concat(S(e),[r.createElement("li",{key:t},r.createElement("button",{className:"DocSearch-Prefill",key:t,type:"button",onClick:function(){o.setQuery(t.toLowerCase()+" "),o.refresh(),o.inputRef.current.focus()}},t))])}),[]))),o.getMissingResultsUrl&&r.createElement("p",{className:"DocSearch-Help"},"".concat(u," "),r.createElement("a",{href:o.getMissingResultsUrl({query:o.state.query}),target:"_blank",rel:"noopener noreferrer"},p)))}var nn=["hit","attribute","tagName"];function rn(e,t){return t.split(".").reduce((function(e,t){return null!=e&&e[t]?e[t]:null}),e)}function on(e){var t=e.hit,n=e.attribute,o=e.tagName,a=void 0===o?"span":o,i=b(e,nn);return(0,r.createElement)(a,h(h({},i),{},{dangerouslySetInnerHTML:{__html:rn(t,"_snippetResult.".concat(n,".value"))||rn(t,n)}}))}function an(e){return e.collection&&0!==e.collection.items.length?r.createElement("section",{className:"DocSearch-Hits"},r.createElement("div",{className:"DocSearch-Hit-source"},e.title),r.createElement("ul",e.getListProps(),e.collection.items.map((function(t,n){return r.createElement(sn,d({key:[e.title,t.objectID].join(":"),item:t,index:n},e))})))):null}function sn(e){var t=e.item,n=e.index,o=e.renderIcon,a=e.renderAction,i=e.getItemProps,s=e.onItemClick,c=e.collection,l=e.hitComponent,u=w(r.useState(!1),2),p=u[0],f=u[1],m=w(r.useState(!1),2),g=m[0],h=m[1],b=r.useRef(null),y=l;return r.createElement("li",d({className:["DocSearch-Hit",t.__docsearch_parent&&"DocSearch-Hit--Child",p&&"DocSearch-Hit--deleting",g&&"DocSearch-Hit--favoriting"].filter(Boolean).join(" "),onTransitionEnd:function(){b.current&&b.current()}},i({item:t,source:c.source,onClick:function(e){s(t,e)}})),r.createElement(y,{hit:t},r.createElement("div",{className:"DocSearch-Hit-Container"},o({item:t,index:n}),t.hierarchy[t.type]&&"lvl1"===t.type&&r.createElement("div",{className:"DocSearch-Hit-content-wrapper"},r.createElement(on,{className:"DocSearch-Hit-title",hit:t,attribute:"hierarchy.lvl1"}),t.content&&r.createElement(on,{className:"DocSearch-Hit-path",hit:t,attribute:"content"})),t.hierarchy[t.type]&&("lvl2"===t.type||"lvl3"===t.type||"lvl4"===t.type||"lvl5"===t.type||"lvl6"===t.type)&&r.createElement("div",{className:"DocSearch-Hit-content-wrapper"},r.createElement(on,{className:"DocSearch-Hit-title",hit:t,attribute:"hierarchy.".concat(t.type)}),r.createElement(on,{className:"DocSearch-Hit-path",hit:t,attribute:"hierarchy.lvl1"})),"content"===t.type&&r.createElement("div",{className:"DocSearch-Hit-content-wrapper"},r.createElement(on,{className:"DocSearch-Hit-title",hit:t,attribute:"content"}),r.createElement(on,{className:"DocSearch-Hit-path",hit:t,attribute:"hierarchy.lvl1"})),a({item:t,runDeleteTransition:function(e){f(!0),b.current=e},runFavoriteTransition:function(e){h(!0),b.current=e}}))))}function cn(e,t,n){return e.reduce((function(e,r){var o=t(r);return e.hasOwnProperty(o)||(e[o]=[]),e[o].length<(n||5)&&e[o].push(r),e}),{})}function ln(e){return e}function un(e){return 1===e.button||e.altKey||e.ctrlKey||e.metaKey||e.shiftKey}function dn(){}var pn=/(<mark>|<\/mark>)/g,fn=RegExp(pn.source);function mn(e){var t,n,r=e;if(!r.__docsearch_parent&&!e._highlightResult)return e.hierarchy.lvl0;var o=r.__docsearch_parent?null===(t=r.__docsearch_parent)||void 0===t||null===(t=t._highlightResult)||void 0===t||null===(t=t.hierarchy)||void 0===t?void 0:t.lvl0:null===(n=e._highlightResult)||void 0===n||null===(n=n.hierarchy)||void 0===n?void 0:n.lvl0;return o?o.value&&fn.test(o.value)?o.value.replace(pn,""):o.value:e.hierarchy.lvl0}function gn(e){return r.createElement("div",{className:"DocSearch-Dropdown-Container"},e.state.collections.map((function(t){if(0===t.items.length)return null;var n=mn(t.items[0]);return r.createElement(an,d({},e,{key:t.source.sourceId,title:n,collection:t,renderIcon:function(e){var n,o=e.item,a=e.index;return r.createElement(r.Fragment,null,o.__docsearch_parent&&r.createElement("svg",{className:"DocSearch-Hit-Tree",viewBox:"0 0 24 54"},r.createElement("g",{stroke:"currentColor",fill:"none",fillRule:"evenodd",strokeLinecap:"round",strokeLinejoin:"round"},o.__docsearch_parent!==(null===(n=t.items[a+1])||void 0===n?void 0:n.__docsearch_parent)?r.createElement("path",{d:"M8 6v21M20 27H8.3"}):r.createElement("path",{d:"M8 6v42M20 27H8.3"}))),r.createElement("div",{className:"DocSearch-Hit-icon"},r.createElement(Gt,{type:o.type})))},renderAction:function(){return r.createElement("div",{className:"DocSearch-Hit-action"},r.createElement(Vt,null))}}))})),e.resultsFooterComponent&&r.createElement("section",{className:"DocSearch-HitsFooter"},r.createElement(e.resultsFooterComponent,{state:e.state})))}var hn=["translations"];function bn(e){var t=e.translations,n=void 0===t?{}:t,o=b(e,hn),a=n.recentSearchesTitle,i=void 0===a?"Recent":a,s=n.noRecentSearchesText,c=void 0===s?"No recent searches":s,l=n.saveRecentSearchButtonTitle,u=void 0===l?"Save this search":l,p=n.removeRecentSearchButtonTitle,f=void 0===p?"Remove this search from history":p,m=n.favoriteSearchesTitle,g=void 0===m?"Favorite":m,h=n.removeFavoriteSearchButtonTitle,y=void 0===h?"Remove this search from favorites":h;return"idle"===o.state.status&&!1===o.hasCollections?o.disableUserPersonalization?null:r.createElement("div",{className:"DocSearch-StartScreen"},r.createElement("p",{className:"DocSearch-Help"},c)):!1===o.hasCollections?null:r.createElement("div",{className:"DocSearch-Dropdown-Container"},r.createElement(an,d({},o,{title:i,collection:o.state.collections[0],renderIcon:function(){return r.createElement("div",{className:"DocSearch-Hit-icon"},r.createElement(Ht,null))},renderAction:function(e){var t=e.item,n=e.runFavoriteTransition,a=e.runDeleteTransition;return r.createElement(r.Fragment,null,r.createElement("div",{className:"DocSearch-Hit-action"},r.createElement("button",{className:"DocSearch-Hit-action-button",title:u,type:"submit",onClick:function(e){e.preventDefault(),e.stopPropagation(),n((function(){o.favoriteSearches.add(t),o.recentSearches.remove(t),o.refresh()}))}},r.createElement(Qt,null))),r.createElement("div",{className:"DocSearch-Hit-action"},r.createElement("button",{className:"DocSearch-Hit-action-button",title:f,type:"submit",onClick:function(e){e.preventDefault(),e.stopPropagation(),a((function(){o.recentSearches.remove(t),o.refresh()}))}},r.createElement(qt,null))))}})),r.createElement(an,d({},o,{title:g,collection:o.state.collections[1],renderIcon:function(){return r.createElement("div",{className:"DocSearch-Hit-icon"},r.createElement(Qt,null))},renderAction:function(e){var t=e.item,n=e.runDeleteTransition;return r.createElement("div",{className:"DocSearch-Hit-action"},r.createElement("button",{className:"DocSearch-Hit-action-button",title:y,type:"submit",onClick:function(e){e.preventDefault(),e.stopPropagation(),n((function(){o.favoriteSearches.remove(t),o.refresh()}))}},r.createElement(qt,null)))}})))}var yn=["translations"],vn=r.memo((function(e){var t=e.translations,n=void 0===t?{}:t,o=b(e,yn);if("error"===o.state.status)return r.createElement(Jt,{translations:null==n?void 0:n.errorScreen});var a=o.state.collections.some((function(e){return e.items.length>0}));return o.state.query?!1===a?r.createElement(tn,d({},o,{translations:null==n?void 0:n.noResultsScreen})):r.createElement(gn,o):r.createElement(bn,d({},o,{hasCollections:a,translations:null==n?void 0:n.startScreen}))}),(function(e,t){return"loading"===t.state.status||"stalled"===t.state.status})),wn=["translations"];function Sn(e){var t=e.translations,n=void 0===t?{}:t,o=b(e,wn),a=n.resetButtonTitle,i=void 0===a?"Clear the query":a,s=n.resetButtonAriaLabel,c=void 0===s?"Clear the query":s,l=n.cancelButtonText,u=void 0===l?"Cancel":l,p=n.cancelButtonAriaLabel,f=void 0===p?"Cancel":p,m=n.searchInputLabel,g=void 0===m?"Search":m,h=o.getFormProps({inputElement:o.inputRef.current}).onReset;return r.useEffect((function(){o.autoFocus&&o.inputRef.current&&o.inputRef.current.focus()}),[o.autoFocus,o.inputRef]),r.useEffect((function(){o.isFromSelection&&o.inputRef.current&&o.inputRef.current.select()}),[o.isFromSelection,o.inputRef]),r.createElement(r.Fragment,null,r.createElement("form",{className:"DocSearch-Form",onSubmit:function(e){e.preventDefault()},onReset:h},r.createElement("label",d({className:"DocSearch-MagnifierLabel"},o.getLabelProps()),r.createElement(E,null),r.createElement("span",{className:"DocSearch-VisuallyHiddenForAccessibility"},g)),r.createElement("div",{className:"DocSearch-LoadingIndicator"},r.createElement(Ut,null)),r.createElement("input",d({className:"DocSearch-Input",ref:o.inputRef},o.getInputProps({inputElement:o.inputRef.current,autoFocus:o.autoFocus,maxLength:64}))),r.createElement("button",{type:"reset",title:i,className:"DocSearch-Reset","aria-label":c,hidden:!o.state.query},r.createElement(qt,null))),r.createElement("button",{className:"DocSearch-Cancel",type:"reset","aria-label":f,onClick:o.onClose},u))}var kn=["_highlightResult","_snippetResult"];function xn(e){var t=e.key,n=e.limit,r=void 0===n?5:n,o=function(e){return!1===function(){var e="__TEST_KEY__";try{return localStorage.setItem(e,""),localStorage.removeItem(e),!0}catch(e){return!1}}()?{setItem:function(){},getItem:function(){return[]}}:{setItem:function(t){return window.localStorage.setItem(e,JSON.stringify(t))},getItem:function(){var t=window.localStorage.getItem(e);return t?JSON.parse(t):[]}}}(t),a=o.getItem().slice(0,r);return{add:function(e){var t=e;t._highlightResult,t._snippetResult;var n=b(t,kn),i=a.findIndex((function(e){return e.objectID===n.objectID}));i>-1&&a.splice(i,1),a.unshift(n),a=a.slice(0,r),o.setItem(a)},remove:function(e){a=a.filter((function(t){return t.objectID!==e.objectID})),o.setItem(a)},getAll:function(){return a}}}function _n(e){var t,n="algolia-client-js-".concat(e.key);function r(){return void 0===t&&(t=e.localStorage||window.localStorage),t}function o(){return JSON.parse(r().getItem(n)||"{}")}function a(e){r().setItem(n,JSON.stringify(e))}return{get:function(t,n){var r=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{miss:function(){return Promise.resolve()}};return Promise.resolve().then((function(){var n,r,i;return n=e.timeToLive?1e3*e.timeToLive:null,r=o(),a(i=Object.fromEntries(Object.entries(r).filter((function(e){return void 0!==w(e,2)[1].timestamp})))),n&&a(Object.fromEntries(Object.entries(i).filter((function(e){var t=w(e,2)[1],r=(new Date).getTime();return!(t.timestamp+n<r)})))),o()[JSON.stringify(t)]})).then((function(e){return Promise.all([e?e.value:n(),void 0!==e])})).then((function(e){var t=w(e,2),n=t[0],o=t[1];return Promise.all([n,o||r.miss(n)])})).then((function(e){return w(e,1)[0]}))},set:function(e,t){return Promise.resolve().then((function(){var a=o();return a[JSON.stringify(e)]={timestamp:(new Date).getTime(),value:t},r().setItem(n,JSON.stringify(a)),t}))},delete:function(e){return Promise.resolve().then((function(){var t=o();delete t[JSON.stringify(e)],r().setItem(n,JSON.stringify(t))}))},clear:function(){return Promise.resolve().then((function(){r().removeItem(n)}))}}}function En(e){var t=S(e.caches),n=t.shift();return void 0===n?{get:function(e,t){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{miss:function(){return Promise.resolve()}};return t().then((function(e){return Promise.all([e,n.miss(e)])})).then((function(e){return w(e,1)[0]}))},set:function(e,t){return Promise.resolve(t)},delete:function(e){return Promise.resolve()},clear:function(){return Promise.resolve()}}:{get:function(e,r){var o=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{miss:function(){return Promise.resolve()}};return n.get(e,r,o).catch((function(){return En({caches:t}).get(e,r,o)}))},set:function(e,r){return n.set(e,r).catch((function(){return En({caches:t}).set(e,r)}))},delete:function(e){return n.delete(e).catch((function(){return En({caches:t}).delete(e)}))},clear:function(){return n.clear().catch((function(){return En({caches:t}).clear()}))}}}function jn(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{serializable:!0},t={};return{get:function(n,r){var o=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{miss:function(){return Promise.resolve()}},a=JSON.stringify(n);if(a in t)return Promise.resolve(e.serializable?JSON.parse(t[a]):t[a]);var i=r();return i.then((function(e){return o.miss(e)})).then((function(){return i}))},set:function(n,r){return t[JSON.stringify(n)]=e.serializable?JSON.stringify(r):r,Promise.resolve(r)},delete:function(e){return delete t[JSON.stringify(e)],Promise.resolve()},clear:function(){return t={},Promise.resolve()}}}function On(e){var t=e.algoliaAgents,n=e.client,r=e.version,o=function(e){var t={value:"Algolia for JavaScript (".concat(e,")"),add:function(e){var n="; ".concat(e.segment).concat(void 0!==e.version?" (".concat(e.version,")"):"");return-1===t.value.indexOf(n)&&(t.value="".concat(t.value).concat(n)),t}};return t}(r).add({segment:n,version:r});return t.forEach((function(e){return o.add(e)})),o}var An=12e4;function Cn(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"up",n=Date.now();return h(h({},e),{},{status:t,lastUpdate:n,isUp:function(){return"up"===t||Date.now()-n>An},isTimedOut:function(){return"timed out"===t&&Date.now()-n<=An}})}var Tn=function(){function e(t,n){var r;return c(this,e),u(r=s(this,e,[t]),"name","AlgoliaError"),n&&(r.name=n),r}return f(e,x(Error)),l(e)}(),Pn=function(){function e(t,n,r){var o;return c(this,e),u(o=s(this,e,[t,r]),"stackTrace",void 0),o.stackTrace=n,o}return f(e,Tn),l(e)}(),In=function(){function e(t){return c(this,e),s(this,e,["Unreachable hosts - your application id may be incorrect. If the error persists, please reach out to the Algolia Support team: https://alg.li/support.",t,"RetryError"])}return f(e,Pn),l(e)}(),Nn=function(){function e(t,n,r){var o,a=arguments.length>3&&void 0!==arguments[3]?arguments[3]:"ApiError";return c(this,e),u(o=s(this,e,[t,r,a]),"status",void 0),o.status=n,o}return f(e,Pn),l(e)}(),Rn=function(){function e(t,n){var r;return c(this,e),u(r=s(this,e,[t,"DeserializationError"]),"response",void 0),r.response=n,r}return f(e,Tn),l(e)}(),Ln=function(){function e(t,n,r,o){var a;return c(this,e),u(a=s(this,e,[t,n,o,"DetailedApiError"]),"error",void 0),a.error=r,a}return f(e,Nn),l(e)}();function Dn(e,t,n){var r,o=(r=n,Object.keys(r).filter((function(e){return void 0!==r[e]})).sort().map((function(e){return"".concat(e,"=").concat(encodeURIComponent("[object Array]"===Object.prototype.toString.call(r[e])?r[e].join(","):r[e]).replace(/\+/g,"%20"))})).join("&")),a="".concat(e.protocol,"://").concat(e.url).concat(e.port?":".concat(e.port):"","/").concat("/"===t.charAt(0)?t.substring(1):t);return o.length&&(a+="?".concat(o)),a}function Mn(e,t){if("GET"!==e.method&&(void 0!==e.data||void 0!==t.data)){var n=Array.isArray(e.data)?e.data:h(h({},e.data),t.data);return JSON.stringify(n)}}function Fn(e,t,n){var r=h(h(h({Accept:"application/json"},e),t),n),o={};return Object.keys(r).forEach((function(e){var t=r[e];o[e.toLowerCase()]=t})),o}function Bn(e){try{return JSON.parse(e.content)}catch(t){throw new Rn(t.message,e)}}function zn(e,t){var n=e.content,r=e.status;try{var o=JSON.parse(n);return"error"in o?new Ln(o.message,r,o.error,t):new Nn(o.message,r,t)}catch(e){}return new Nn(n,r,t)}function $n(e){return e.map((function(e){return Un(e)}))}function Un(e){var t=e.request.headers["x-algolia-api-key"]?{"x-algolia-api-key":"*****"}:{};return h(h({},e),{},{request:h(h({},e.request),{},{headers:h(h({},e.request.headers),t)})})}var Hn=["appId","apiKey","authMode","algoliaAgents"],qn=["params"],Vn="5.12.0";function Wn(e){return[{url:"".concat(e,"-dsn.algolia.net"),accept:"read",protocol:"https"},{url:"".concat(e,".algolia.net"),accept:"write",protocol:"https"}].concat(function(e){for(var t=e,n=e.length-1;n>0;n--){var r=Math.floor(Math.random()*(n+1)),o=e[n];t[n]=e[r],t[r]=o}return t}([{url:"".concat(e,"-1.algolianet.com"),accept:"readWrite",protocol:"https"},{url:"".concat(e,"-2.algolianet.com"),accept:"readWrite",protocol:"https"},{url:"".concat(e,"-3.algolianet.com"),accept:"readWrite",protocol:"https"}]))}var Gn="3.8.0";function Kn(e,t,n){return r.useMemo((function(){var r=function(e,t){if(!e||"string"!=typeof e)throw new Error("`appId` is missing.");if(!t||"string"!=typeof t)throw new Error("`apiKey` is missing.");return function(e){var t=e.appId,n=e.apiKey,r=e.authMode,o=e.algoliaAgents,a=b(e,Hn),s=function(e,t){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:"WithinHeaders",r={"x-algolia-api-key":t,"x-algolia-application-id":e};return{headers:function(){return"WithinHeaders"===n?r:{}},queryParameters:function(){return"WithinQueryParameters"===n?r:{}}}}(t,n,r),c=function(e){var t=e.hosts,n=e.hostsCache,r=e.baseHeaders,o=e.logger,a=e.baseQueryParameters,s=e.algoliaAgent,c=e.timeouts,l=e.requester,u=e.requestsCache,d=e.responsesCache;function p(e){return f.apply(this,arguments)}function f(){return(f=i(y().mark((function e(t){var r,o,a,i,s;return y().wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return e.next=2,Promise.all(t.map((function(e){return n.get(e,(function(){return Promise.resolve(Cn(e))}))})));case 2:return r=e.sent,o=r.filter((function(e){return e.isUp()})),a=r.filter((function(e){return e.isTimedOut()})),i=[].concat(S(o),S(a)),s=i.length>0?i:t,e.abrupt("return",{hosts:s,getTimeout:function(e,t){return(0===a.length&&0===e?1:a.length+3+e)*t}});case 8:case"end":return e.stop()}}),e)})))).apply(this,arguments)}function m(e,t){return g.apply(this,arguments)}function g(){return g=i(y().mark((function e(u,d){var f,m,g,b,v,w,k,x,_,E,j,O,A,C=arguments;return y().wrap((function(e){for(;;)switch(e.prev=e.next){case 0:if(f=!(C.length>2&&void 0!==C[2])||C[2],m=[],g=Mn(u,d),b=Fn(r,u.headers,d.headers),v="GET"===u.method?h(h({},u.data),d.data):{},w=h(h(h({},a),u.queryParameters),v),s.value&&(w["x-algolia-agent"]=s.value),d&&d.queryParameters)for(k=0,x=Object.keys(d.queryParameters);k<x.length;k++)_=x[k],d.queryParameters[_]&&"[object Object]"!==Object.prototype.toString.call(d.queryParameters[_])?w[_]=d.queryParameters[_].toString():w[_]=d.queryParameters[_];return E=0,j=function(){var e=i(y().mark((function e(t,r){var a,i,s,p,v,S;return y().wrap((function(e){for(;;)switch(e.prev=e.next){case 0:if(void 0!==(a=t.pop())){e.next=3;break}throw new In($n(m));case 3:return i=h(h({},c),d.timeouts),s={data:g,headers:b,method:u.method,url:Dn(a,u.path,w),connectTimeout:r(E,i.connect),responseTimeout:r(E,f?i.read:i.write)},p=function(e){var n={request:s,response:e,host:a,triesLeft:t.length};return m.push(n),n},e.next=8,l.send(s);case 8:if(k=(y=v=e.sent).isTimedOut,x=y.status,!(k||function(e){return!e.isTimedOut&&!~~e.status}({isTimedOut:k,status:x})||2!=~~(x/100)&&4!=~~(x/100))){e.next=16;break}return S=p(v),v.isTimedOut&&E++,o.info("Retryable failure",Un(S)),e.next=15,n.set(a,Cn(a,v.isTimedOut?"timed out":"down"));case 15:return e.abrupt("return",j(t,r));case 16:if(2!=~~(v.status/100)){e.next=18;break}return e.abrupt("return",Bn(v));case 18:throw p(v),zn(v,m);case 20:case"end":return e.stop()}var y,k,x}),e)})));return function(t,n){return e.apply(this,arguments)}}(),O=t.filter((function(e){return"readWrite"===e.accept||(f?"read"===e.accept:"write"===e.accept)})),e.next=13,p(O);case 13:return A=e.sent,e.abrupt("return",j(S(A.hosts).reverse(),A.getTimeout));case 15:case"end":return e.stop()}}),e)}))),g.apply(this,arguments)}return{hostsCache:n,requester:l,timeouts:c,logger:o,algoliaAgent:s,baseHeaders:r,baseQueryParameters:a,hosts:t,request:function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},n=e.useReadTransporter||"GET"===e.method;if(!n)return m(e,t,n);var o=function(){return m(e,t)};if(!0!==(t.cacheable||e.cacheable))return o();var i={request:e,requestOptions:t,transporter:{queryParameters:a,headers:r}};return d.get(i,(function(){return u.get(i,(function(){return u.set(i,o()).then((function(e){return Promise.all([u.delete(i),e])}),(function(e){return Promise.all([u.delete(i),Promise.reject(e)])})).then((function(e){var t=w(e,2);return t[0],t[1]}))}))}),{miss:function(e){return d.set(i,e)}})},requestsCache:u,responsesCache:d}}(h(h({hosts:Wn(t)},a),{},{algoliaAgent:On({algoliaAgents:o,client:"Lite",version:Vn}),baseHeaders:h(h({"content-type":"text/plain"},s.headers()),a.baseHeaders),baseQueryParameters:h(h({},s.queryParameters()),a.baseQueryParameters)}));return{transporter:c,appId:t,clearCache:function(){return Promise.all([c.requestsCache.clear(),c.responsesCache.clear()]).then((function(){}))},get _ua(){return c.algoliaAgent.value},addAlgoliaAgent:function(e,t){c.algoliaAgent.add({segment:e,version:t})},setClientApiKey:function(e){var t=e.apiKey;r&&"WithinHeaders"!==r?c.baseQueryParameters["x-algolia-api-key"]=t:c.baseHeaders["x-algolia-api-key"]=t},searchForHits:function(e,t){return this.search(e,t)},searchForFacets:function(e,t){return this.search(e,t)},customPost:function(e,t){var n=e.path,r=e.parameters,o=e.body;if(!n)throw new Error("Parameter `path` is required when calling `customPost`.");var a={method:"POST",path:"/{path}".replace("{path}",n),queryParameters:r||{},headers:{},data:o||{}};return c.request(a,t)},getRecommendations:function(e,t){if(e&&Array.isArray(e)&&(e={requests:e}),!e)throw new Error("Parameter `getRecommendationsParams` is required when calling `getRecommendations`.");if(!e.requests)throw new Error("Parameter `getRecommendationsParams.requests` is required when calling `getRecommendations`.");var n={method:"POST",path:"/1/indexes/*/recommendations",queryParameters:{},headers:{},data:e,useReadTransporter:!0,cacheable:!0};return c.request(n,t)},search:function(e,t){if(e&&Array.isArray(e)){var n={requests:e.map((function(e){var t=e.params,n=b(e,qn);return"facet"===n.type?h(h(h({},n),t),{},{type:"facet"}):h(h(h({},n),t),{},{facet:void 0,maxFacetHits:void 0,facetQuery:void 0})}))};e=n}if(!e)throw new Error("Parameter `searchMethodParams` is required when calling `search`.");if(!e.requests)throw new Error("Parameter `searchMethodParams.requests` is required when calling `search`.");var r={method:"POST",path:"/1/indexes/*/queries",queryParameters:{},headers:{},data:e,useReadTransporter:!0,cacheable:!0};return c.request(r,t)}}}(h({appId:e,apiKey:t,timeouts:{connect:1e3,read:2e3,write:3e4},logger:{debug:function(e,t){return Promise.resolve()},info:function(e,t){return Promise.resolve()},error:function(e,t){return Promise.resolve()}},requester:{send:function(e){return new Promise((function(t){var n=new XMLHttpRequest;n.open(e.method,e.url,!0),Object.keys(e.headers).forEach((function(t){return n.setRequestHeader(t,e.headers[t])}));var r,o=function(e,r){return setTimeout((function(){n.abort(),t({status:0,content:r,isTimedOut:!0})}),e)},a=o(e.connectTimeout,"Connection timeout");n.onreadystatechange=function(){n.readyState>n.OPENED&&void 0===r&&(clearTimeout(a),r=o(e.responseTimeout,"Socket timeout"))},n.onerror=function(){0===n.status&&(clearTimeout(a),clearTimeout(r),t({content:n.responseText||"Network request failed",status:n.status,isTimedOut:!1}))},n.onload=function(){clearTimeout(a),clearTimeout(r),t({content:n.responseText,status:n.status,isTimedOut:!1})},n.send(e.data)}))}},algoliaAgents:[{segment:"Browser"}],authMode:"WithinQueryParameters",responsesCache:jn(),requestsCache:jn({serializable:!1}),hostsCache:En({caches:[_n({key:"".concat(Vn,"-").concat(e)}),jn()]})},void 0))}(e,t);return r.addAlgoliaAgent("docsearch",Gn),!1===/docsearch.js \(.*\)/.test(r.transporter.algoliaAgent.value)&&r.addAlgoliaAgent("docsearch-react",Gn),n(r)}),[e,t,n])}var Yn=["footer","searchBox"];function Qn(e){var t=e.appId,n=e.apiKey,o=e.indexName,a=e.placeholder,i=void 0===a?"Search docs":a,s=e.searchParameters,c=e.maxResultsPerGroup,l=e.onClose,u=void 0===l?dn:l,p=e.transformItems,f=void 0===p?ln:p,m=e.hitComponent,g=void 0===m?$t:m,y=e.resultsFooterComponent,v=void 0===y?function(){return null}:y,S=e.navigator,k=e.initialScrollY,x=void 0===k?0:k,_=e.transformSearchClient,E=void 0===_?ln:_,j=e.disableUserPersonalization,O=void 0!==j&&j,A=e.initialQuery,C=void 0===A?"":A,T=e.translations,P=void 0===T?{}:T,I=e.getMissingResultsUrl,N=e.insights,R=void 0!==N&&N,L=P.footer,D=P.searchBox,M=b(P,Yn),F=w(r.useState({query:"",collections:[],completion:null,context:{},isOpen:!1,activeItemId:null,status:"idle"}),2),B=F[0],z=F[1],$=r.useRef(null),U=r.useRef(null),H=r.useRef(null),q=r.useRef(null),V=r.useRef(null),W=r.useRef(10),G=r.useRef("undefined"!=typeof window?window.getSelection().toString().slice(0,64):"").current,K=r.useRef(C||G).current,Y=Kn(t,n,E),Q=r.useRef(xn({key:"__DOCSEARCH_FAVORITE_SEARCHES__".concat(o),limit:10})).current,Z=r.useRef(xn({key:"__DOCSEARCH_RECENT_SEARCHES__".concat(o),limit:0===Q.getAll().length?7:4})).current,X=r.useCallback((function(e){if(!O){var t="content"===e.type?e.__docsearch_parent:e;t&&-1===Q.getAll().findIndex((function(e){return e.objectID===t.objectID}))&&Z.add(t)}}),[Q,Z,O]),J=r.useCallback((function(e){if(B.context.algoliaInsightsPlugin&&e.__autocomplete_id){var t=e,n={eventName:"Item Selected",index:t.__autocomplete_indexName,items:[t],positions:[e.__autocomplete_id],queryID:t.__autocomplete_queryID};B.context.algoliaInsightsPlugin.insights.clickedObjectIDsAfterSearch(n)}}),[B.context.algoliaInsightsPlugin]),ee=r.useMemo((function(){return Mt({id:"docsearch",defaultActiveItemId:0,placeholder:i,openOnFocus:!0,initialState:{query:K,context:{searchSuggestions:[]}},insights:R,navigator:S,onStateChange:function(e){z(e.state)},getSources:function(e){var r=e.query,a=e.state,i=e.setContext,l=e.setStatus;if(!r)return O?[]:[{sourceId:"recentSearches",onSelect:function(e){var t=e.item,n=e.event;X(t),un(n)||u()},getItemUrl:function(e){return e.item.url},getItems:function(){return Z.getAll()}},{sourceId:"favoriteSearches",onSelect:function(e){var t=e.item,n=e.event;X(t),un(n)||u()},getItemUrl:function(e){return e.item.url},getItems:function(){return Q.getAll()}}];var d=Boolean(R);return Y.search({requests:[h({query:r,indexName:o,attributesToRetrieve:["hierarchy.lvl0","hierarchy.lvl1","hierarchy.lvl2","hierarchy.lvl3","hierarchy.lvl4","hierarchy.lvl5","hierarchy.lvl6","content","type","url"],attributesToSnippet:["hierarchy.lvl1:".concat(W.current),"hierarchy.lvl2:".concat(W.current),"hierarchy.lvl3:".concat(W.current),"hierarchy.lvl4:".concat(W.current),"hierarchy.lvl5:".concat(W.current),"hierarchy.lvl6:".concat(W.current),"content:".concat(W.current)],snippetEllipsisText:"\u2026",highlightPreTag:"<mark>",highlightPostTag:"</mark>",hitsPerPage:20,clickAnalytics:d},s)]}).catch((function(e){throw"RetryError"===e.name&&l("error"),e})).then((function(e){var r=e.results[0],s=r.hits,l=r.nbHits,p=cn(s,(function(e){return mn(e)}),c);a.context.searchSuggestions.length<Object.keys(p).length&&i({searchSuggestions:Object.keys(p)}),i({nbHits:l});var m={};return d&&(m={__autocomplete_indexName:o,__autocomplete_queryID:r.queryID,__autocomplete_algoliaCredentials:{appId:t,apiKey:n}}),Object.values(p).map((function(e,t){return{sourceId:"hits".concat(t),onSelect:function(e){var t=e.item,n=e.event;X(t),un(n)||u()},getItemUrl:function(e){return e.item.url},getItems:function(){return Object.values(cn(e,(function(e){return e.hierarchy.lvl1}),c)).map(f).map((function(e){return e.map((function(t){var n=null,r=e.find((function(e){return"lvl1"===e.type&&e.hierarchy.lvl1===t.hierarchy.lvl1}));return"lvl1"!==t.type&&r&&(n=r),h(h({},t),{},{__docsearch_parent:n},m)}))})).flat()}}}))}))}})}),[o,s,c,Y,u,Z,Q,X,K,i,S,f,O,R,t,n]),te=ee.getEnvironmentProps,ne=ee.getRootProps,re=ee.refresh;return function(e){var t=e.getEnvironmentProps,n=e.panelElement,o=e.formElement,a=e.inputElement;r.useEffect((function(){if(n&&o&&a){var e=t({panelElement:n,formElement:o,inputElement:a}),r=e.onTouchStart,i=e.onTouchMove;return window.addEventListener("touchstart",r),window.addEventListener("touchmove",i),function(){window.removeEventListener("touchstart",r),window.removeEventListener("touchmove",i)}}}),[t,n,o,a])}({getEnvironmentProps:te,panelElement:q.current,formElement:H.current,inputElement:V.current}),function(e){var t=e.container;r.useEffect((function(){if(t){var e=t.querySelectorAll("a[href]:not([disabled]), button:not([disabled]), input:not([disabled])"),n=e[0],r=e[e.length-1];return t.addEventListener("keydown",o),function(){t.removeEventListener("keydown",o)}}function o(e){"Tab"===e.key&&(e.shiftKey?document.activeElement===n&&(e.preventDefault(),r.focus()):document.activeElement===r&&(e.preventDefault(),n.focus()))}}),[t])}({container:$.current}),r.useEffect((function(){return document.body.classList.add("DocSearch--active"),function(){var e,t;document.body.classList.remove("DocSearch--active"),null===(e=(t=window).scrollTo)||void 0===e||e.call(t,0,x)}}),[]),r.useEffect((function(){window.matchMedia("(max-width: 768px)").matches&&(W.current=5)}),[]),r.useEffect((function(){q.current&&(q.current.scrollTop=0)}),[B.query]),r.useEffect((function(){K.length>0&&(re(),V.current&&V.current.focus())}),[K,re]),r.useEffect((function(){function e(){if(U.current){var e=.01*window.innerHeight;U.current.style.setProperty("--docsearch-vh","".concat(e,"px"))}}return e(),window.addEventListener("resize",e),function(){window.removeEventListener("resize",e)}}),[]),r.createElement("div",d({ref:$},ne({"aria-expanded":!0}),{className:["DocSearch","DocSearch-Container","stalled"===B.status&&"DocSearch-Container--Stalled","error"===B.status&&"DocSearch-Container--Errored"].filter(Boolean).join(" "),role:"button",tabIndex:0,onMouseDown:function(e){e.target===e.currentTarget&&u()}}),r.createElement("div",{className:"DocSearch-Modal",ref:U},r.createElement("header",{className:"DocSearch-SearchBar",ref:H},r.createElement(Sn,d({},ee,{state:B,autoFocus:0===K.length,inputRef:V,isFromSelection:Boolean(K)&&K===G,translations:D,onClose:u}))),r.createElement("div",{className:"DocSearch-Dropdown",ref:q},r.createElement(vn,d({},ee,{indexName:o,state:B,hitComponent:g,resultsFooterComponent:v,disableUserPersonalization:O,recentSearches:Z,favoriteSearches:Q,inputRef:V,translations:M,getMissingResultsUrl:I,onItemClick:function(e,t){J(e),X(e),un(t)||u()}}))),r.createElement("footer",{className:"DocSearch-Footer"},r.createElement(zt,{translations:L}))))}function Zn(e){var t=e.isOpen,n=e.onOpen,o=e.onClose,a=e.onInput,i=e.searchButtonRef;r.useEffect((function(){function e(e){var r;if("Escape"===e.code&&t||"k"===(null===(r=e.key)||void 0===r?void 0:r.toLowerCase())&&(e.metaKey||e.ctrlKey)||!function(e){var t=e.target,n=t.tagName;return t.isContentEditable||"INPUT"===n||"SELECT"===n||"TEXTAREA"===n}(e)&&"/"===e.key&&!t)return e.preventDefault(),void(t?o():document.body.classList.contains("DocSearch--active")||n());i&&i.current===document.activeElement&&a&&/[a-zA-Z0-9]/.test(String.fromCharCode(e.keyCode))&&a(e)}return window.addEventListener("keydown",e),function(){window.removeEventListener("keydown",e)}}),[t,n,o,a,i])}},8328:(e,t,n)=>{"use strict";n.d(t,{A:()=>p});n(6540);var r=n(3259),o=n.n(r),a=n(4054);const i={"003b6e74":[()=>n.e(7562).then(n.bind(n,9430)),"@site/docs/05-go-client/16-distributed-cron.md",9430],"004bd3e7":[()=>n.e(1594).then(n.t.bind(n,2701,19)),"@generated/docusaurus-plugin-content-blog/default/p/blog-authors-taylanisikdemir-04f.json",2701],"0058b4c6":[()=>n.e(849).then(n.t.bind(n,6164,19)),"@generated/docusaurus-plugin-content-docs/default/p/docs-175.json",6164],"01a85c17":[()=>Promise.all([n.e(1869),n.e(8209)]).then(n.bind(n,9158)),"@theme/BlogTagsListPage",9158],"02fb669a":[()=>n.e(1839).then(n.bind(n,3839)),"@site/docs/03-concepts/01-workflows.md",3839],"04e595f1":[()=>n.e(908).then(n.t.bind(n,3420,19)),"@generated/docusaurus-plugin-content-blog/default/p/blog-tags-announcements-53f.json",3420],"05d44d04":[()=>n.e(3774).then(n.bind(n,79)),"@site/docs/04-java-client/07-versioning.md",79],"0826fbec":[()=>n.e(8067).then(n.bind(n,3952)),"@site/docs/05-go-client/17-tracing.md",3952],"0922f36e":[()=>n.e(1640).then(n.t.bind(n,7683,19)),"@generated/docusaurus-plugin-content-blog/default/p/blog-authors-ibarrajo-bb0.json",7683],"0b211f8a":[()=>n.e(6758).then(n.bind(n,8140)),"@site/docs/09-about/index.md",8140],"0bc129c0":[()=>n.e(5371).then(n.bind(n,4425)),"@site/blog/2023-06-28-components-of-cadence-application-setup.md",4425],"0cfc60d3":[()=>n.e(8396).then(n.t.bind(n,3215,19)),"@generated/docusaurus-plugin-content-blog/default/p/blog-authors-shaddoll-7a3.json",3215],"0ece390c":[()=>n.e(8125).then(n.bind(n,9561)),"@site/docs/04-java-client/01-client-overview.md",9561],"115ec24d":[()=>n.e(5332).then(n.bind(n,2960)),"@site/blog/2024-11-18-cadence-workflows-github-organization.md",2960],"144c3ace":[()=>n.e(8035).then(n.bind(n,2817)),"@site/blog/2022-02-28-community-spotlight-february-2022.md?truncated=true",2817],"1685be14":[()=>n.e(1919).then(n.bind(n,7747)),"@site/docs/04-java-client/02-workflow-interface.md",7747],"177ff540":[()=>n.e(647).then(n.bind(n,4329)),"@site/blog/2021-10-19-moving-to-grpc/2021-10-19-moving-to-grpc.md",4329],17896441:[()=>Promise.all([n.e(1869),n.e(8498),n.e(8401)]).then(n.bind(n,575)),"@theme/DocItem",575],17896883:[()=>n.e(1643).then(n.t.bind(n,9379,19)),"@generated/docusaurus-plugin-content-blog/default/p/blog-authors-kcorbett-netapp-1d2.json",9379],"18e1ae2c":[()=>n.e(3029).then(n.bind(n,3198)),"@site/blog/2023-07-05-implement-cadence-worker-from-scratch.md",3198],"18ffe98c":[()=>n.e(4269).then(n.t.bind(n,5363,19)),"@generated/docusaurus-plugin-content-blog/default/p/blog-page-3-7c8.json",5363],"1a4e3797":[()=>Promise.all([n.e(1869),n.e(2138)]).then(n.bind(n,4604)),"@theme/SearchPage",4604],"1c90ed0c":[()=>n.e(4860).then(n.bind(n,6553)),"@site/blog/2022-05-31-community-spotlight-update-may-2022.md?truncated=true",6553],"1dec29fa":[()=>n.e(9612).then(n.bind(n,3209)),"@site/docs/08-workflow-troubleshooting/01-timeouts.md",3209],"1df93b7f":[()=>Promise.all([n.e(1869),n.e(4583)]).then(n.bind(n,5579)),"@site/src/pages/index.tsx",5579],"1f391b9e":[()=>Promise.all([n.e(1869),n.e(8498),n.e(6061)]).then(n.bind(n,7973)),"@theme/MDXPage",7973],"20139c40":[()=>n.e(9369).then(n.bind(n,8281)),"@site/community/3-contributing.mdx",8281],"278bd730":[()=>n.e(1198).then(n.bind(n,9328)),"@site/blog/2021-09-30-long-term-commitment-and-support-for-the-cadence-project-and-its-community.md",9328],"27f46eca":[()=>n.e(447).then(n.bind(n,9303)),"@site/docs/09-about/01-license.md",9303],28839895:[()=>n.e(9171).then(n.bind(n,649)),"@site/docs/01-get-started/03-golang-hello-world.md",649],"28f6f2b5":[()=>n.e(4830).then(n.bind(n,3947)),"@site/blog/2021-10-19-moving-to-grpc/2021-10-19-moving-to-grpc.md?truncated=true",3947],"2955167d":[()=>n.e(8202).then(n.bind(n,5372)),"@site/blog/2023-08-28-nondeterministic-errors-replayers-shadowers.md",5372],"2a3fd662":[()=>n.e(2813).then(n.bind(n,9556)),"@site/docs/03-concepts/06-task-lists.md",9556],"2b58a6fe":[()=>n.e(3190).then(n.bind(n,5490)),"@site/docs/05-go-client/01-workers.md",5490],"2bc7f48b":[()=>n.e(5861).then(n.bind(n,6082)),"@site/docs/05-go-client/06-retries.md",6082],"31f8b8ae":[()=>n.e(4569).then(n.bind(n,9500)),"@site/blog/2024-11-18-cadence-workflows-github-organization.md?truncated=true",9500],"33348b0e":[()=>n.e(4739).then(n.bind(n,2399)),"@site/blog/2024-3-11-community-spotlight-update-march-2024.md?truncated=true",2399],"33cf8314":[()=>n.e(6806).then(n.bind(n,8644)),"@site/blog/2023-01-31-community-spotlight-january-2023.md?truncated=true",8644],"33fc5bb8":[()=>Promise.all([n.e(1869),n.e(8498),n.e(3347),n.e(867)]).then(n.bind(n,778)),"@theme/Blog/Pages/BlogAuthorsPostsPage",778],"3408eb41":[()=>n.e(9866).then(n.bind(n,7521)),"@site/docs/01-get-started/02-java-hello-world.md",7521],"3485e756":[()=>n.e(4378).then(n.t.bind(n,5263,19)),"@generated/docusaurus-plugin-content-blog/default/p/blog-authors-vytautas-karpavicius-86f.json",5263],"3525dd13":[()=>n.e(7240).then(n.bind(n,5477)),"@site/docs/03-concepts/03-events.md",5477],"36994c47":[()=>n.e(9858).then(n.t.bind(n,5516,19)),"@generated/docusaurus-plugin-content-blog/default/__plugin.json",5516],"36aefe7c":[()=>n.e(9379).then(n.bind(n,8047)),"@site/blog/2023-02-28-community-spotlight-february.md?truncated=true",8047],"393be207":[()=>n.e(4134).then(n.bind(n,591)),"@site/src/pages/markdown-page.md",591],"3a2db09e":[()=>n.e(8121).then(n.t.bind(n,8070,19)),"@generated/docusaurus-plugin-content-blog/default/p/blog-tags-df9.json",8070],"3ca3c927":[()=>n.e(4552).then(n.bind(n,3438)),"@site/blog/2022-01-31-community-spotlight-january-2022.md",3438],"3ce9624a":[()=>n.e(2450).then(n.bind(n,3284)),"@site/community/2-resources.mdx",3284],"3d5497b2":[()=>n.e(2529).then(n.bind(n,6742)),"@site/blog/2022-04-30-community-spotlight-update-april-2022.md",6742],"3e206144":[()=>n.e(1898).then(n.bind(n,5335)),"@site/community/0-support.mdx",5335],"3e30df86":[()=>n.e(2222).then(n.bind(n,725)),"@site/docs/05-go-client/02.5-starting-workflows.md",725],"3faec549":[()=>n.e(2559).then(n.bind(n,6885)),"@site/docs/07-operation-guide/05-migration.md",6885],"40011a75":[()=>n.e(492).then(n.t.bind(n,5443,19)),"@generated/docusaurus-plugin-content-blog/default/p/blog-page-4-4d1.json",5443],"41417ef6":[()=>n.e(6323).then(n.bind(n,3795)),"@site/docs/02-use-cases/08-deployment.md",3795],"43e9f1b6":[()=>n.e(8817).then(n.bind(n,4512)),"@site/docs/07-operation-guide/04-troubleshooting.md",4512],"44abbaf5":[()=>n.e(7682).then(n.bind(n,6513)),"@site/docs/04-java-client/04-starting-workflow-executions.md",6513],"44d6dde1":[()=>n.e(4471).then(n.bind(n,7739)),"@site/blog/2024-07-11-yearly-roadmap-update/2024-07-11-yearly-roadmap-update.md?truncated=true",7739],"47f0ea92":[()=>n.e(4669).then(n.bind(n,6981)),"@site/docs/04-java-client/15-continue-as-new.md",6981],"4b94b3ad":[()=>n.e(1816).then(n.bind(n,2088)),"@site/blog/2022-06-30-community-spotlight-update-june-2022.md",2088],"4c35ffca":[()=>n.e(2872).then(n.bind(n,8539)),"@site/docs/04-java-client/14-exception-handling.md",8539],"4c9d8eaa":[()=>n.e(3116).then(n.bind(n,9614)),"@site/community/1-team.mdx",9614],"4d332630":[()=>n.e(7748).then(n.bind(n,434)),"@site/blog/2022-08-31-community-spotlight-august-2022.md?truncated=true",434],"528620f0":[()=>n.e(7600).then(n.bind(n,5506)),"@site/blog/2022-11-30-community-spotlight-november-2022.md?truncated=true",5506],"534a6068":[()=>n.e(862).then(n.bind(n,3340)),"@site/blog/2023-07-10-cadence-bad-practices-part-1.md?truncated=true",3340],"5450051a":[()=>n.e(9528).then(n.bind(n,8781)),"@site/docs/07-operation-guide/02-maintain.md",8781],"55db2bea":[()=>n.e(573).then(n.bind(n,7919)),"@site/docs/07-operation-guide/01-setup.md",7919],"5806acc5":[()=>n.e(9306).then(n.bind(n,4639)),"@site/blog/2024-10-01-announcing-cadence-helm-charts-v0.md?truncated=true",4639],"580cfca3":[()=>n.e(7770).then(n.bind(n,3800)),"@site/blog/2023-11-30-community-spotlight-update-november-2023.md",3800],"5ab0d6d5":[()=>n.e(8848).then(n.t.bind(n,2266,19)),"@generated/docusaurus-plugin-content-blog/default/p/blog-tags-deep-dives-7b7.json",2266],"5b895f91":[()=>n.e(7180).then(n.bind(n,3112)),"@site/blog/2023-08-28-nondeterministic-errors-replayers-shadowers.md?truncated=true",3112],"5cd48241":[()=>n.e(3732).then(n.bind(n,5835)),"@site/docs/02-use-cases/07-provisioning.md",5835],"5cfaf3a2":[()=>n.e(4344).then(n.bind(n,5101)),"@site/blog/zonal-isolation-v1/zonal-isolation-v1.md",5101],"5d1ead22":[()=>n.e(4713).then(n.bind(n,6462)),"@site/docs/04-java-client/16-side-effect.md",6462],"5e95c892":[()=>n.e(9647).then(n.bind(n,7121)),"@theme/DocsRoot",7121],"5e9f5e1a":[()=>Promise.resolve().then(n.bind(n,4784)),"@generated/docusaurus.config",4784],"5f63c9de":[()=>n.e(8770).then(n.bind(n,9344)),"@site/blog/2023-07-10-cadence-bad-practices-part-1.md",9344],"6081a96a":[()=>n.e(8729).then(n.bind(n,2428)),"@site/blog/2022-09-30-community-spotlight-september-2022.md",2428],"61aeb84e":[()=>n.e(2641).then(n.bind(n,754)),"@site/docs/04-java-client/index.md",754],"621db11d":[()=>Promise.all([n.e(1869),n.e(3347),n.e(4212)]).then(n.bind(n,3250)),"@theme/Blog/Pages/BlogAuthorsListPage",3250],"643bf5c6":[()=>n.e(4950).then(n.bind(n,5770)),"@site/docs/05-go-client/02-create-workflows.md",5770],"647edc7e":[()=>n.e(7478).then(n.bind(n,3108)),"@site/blog/2023-07-31-community-spotlight-july-2023.md",3108],"6601f8a9":[()=>n.e(7998).then(n.bind(n,3276)),"@site/docs/04-java-client/13-child-workflows.md",3276],"667be76f":[()=>n.e(4120).then(n.bind(n,1515)),"@site/blog/2023-06-28-components-of-cadence-application-setup.md?truncated=true",1515],"67affde7":[()=>n.e(9609).then(n.bind(n,5519)),"@site/docs/04-java-client/12-retries.md",5519],"67d45d0f":[()=>n.e(207).then(n.bind(n,5212)),"@site/docs/08-workflow-troubleshooting/03-retries.md",5212],"6875c492":[()=>Promise.all([n.e(1869),n.e(8498),n.e(3347),n.e(4813)]).then(n.bind(n,3069)),"@theme/BlogTagsPostsPage",3069],"69a323c8":[()=>n.e(6156).then(n.bind(n,887)),"@site/docs/05-go-client/04-execute-activity.md",887],"6e9b4a66":[()=>n.e(3252).then(n.bind(n,5907)),"@site/docs/07-operation-guide/03-monitoring.md",5907],"7373c0c0":[()=>n.e(2779).then(n.bind(n,2123)),"@site/docs/03-concepts/04-queries.md",2123],"73759d73":[()=>n.e(3364).then(n.bind(n,2855)),"@site/docs/04-java-client/03-implementing-workflows.md",2855],"741d205a":[()=>n.e(8941).then(n.t.bind(n,7438,19)),"@generated/docusaurus-plugin-content-blog/default/p/blog-authors-sharanf-813.json",7438],"7613fcd7":[()=>n.e(2370).then(n.bind(n,1675)),"@site/blog/2023-06-08-survey-results/2023-06-08-survey-results.md?truncated=true",1675],"7684a5b2":[()=>n.e(4422).then(n.bind(n,4778)),"@site/docs/02-use-cases/05-partitioned-scan.md",4778],"76dc6352":[()=>n.e(1347).then(n.bind(n,120)),"@site/blog/2024-09-05-workflow-specific-rate-limits.md?truncated=true",120],"775920c1":[()=>n.e(7009).then(n.bind(n,1614)),"@site/blog/2022-12-23-community-spotlight-december-2022.md",1614],"77a860e9":[()=>n.e(5538).then(n.bind(n,6454)),"@site/docs/04-java-client/08-distributed-cron.md",6454],"79f715ea":[()=>n.e(3314).then(n.bind(n,4316)),"@site/docs/02-use-cases/12-big-ml.md",4316],"7a568d1f":[()=>n.e(9699).then(n.bind(n,3915)),"@site/docs/04-java-client/11-queries.md",3915],"7afb0752":[()=>n.e(8929).then(n.bind(n,861)),"@site/blog/2023-02-28-community-spotlight-february.md",861],"7d996443":[()=>n.e(3685).then(n.bind(n,6611)),"@site/docs/08-workflow-troubleshooting/02-activity-failures.md",6611],"7f8511d4":[()=>n.e(8363).then(n.bind(n,84)),"@site/docs/01-get-started/01-server-installation.md",84],"7fda255c":[()=>n.e(4978).then(n.bind(n,7786)),"@site/blog/2024-02-15-cadence-non-deterministic-common-qa.md",7786],"80db4ed1":[()=>n.e(3333).then(n.t.bind(n,1575,19)),"@generated/docusaurus-plugin-content-blog/default/p/blog-tags-community-spotlights-e98.json",1575],"80e02aec":[()=>n.e(1963).then(n.bind(n,2447)),"@site/blog/zonal-isolation-v1/zonal-isolation-v1.md?truncated=true",2447],"814003d2":[()=>n.e(751).then(n.bind(n,5092)),"@site/docs/03-concepts/07-archival.md",5092],"814f3328":[()=>n.e(7472).then(n.t.bind(n,5513,19)),"~blog/default/blog-post-list-prop-default.json",5513],"82c81335":[()=>n.e(1584).then(n.t.bind(n,8417,19)),"@generated/docusaurus-plugin-content-blog/default/p/blog-tags-testing-29d.json",8417],"848b9863":[()=>n.e(7207).then(n.bind(n,4738)),"@site/docs/04-java-client/09-workers.md",4738],"849b28af":[()=>n.e(9881).then(n.bind(n,7705)),"@site/blog/2024-09-05-workflow-specific-rate-limits.md",7705],"86c2314d":[()=>n.e(7262).then(n.bind(n,8251)),"@site/docs/05-go-client/index.md",8251],"87d83cd2":[()=>n.e(9928).then(n.bind(n,994)),"@site/blog/2022-12-23-community-spotlight-december-2022.md?truncated=true",994],"88d84d8e":[()=>n.e(1094).then(n.bind(n,9003)),"@site/blog/2022-03-31-community-spotlight-update-march-2022.md",9003],"8a72c69a":[()=>n.e(4196).then(n.bind(n,3475)),"@site/blog/2023-07-16-write-your-first-workflow-with-cadence/2023-07-16-write-your-first-workflow-with-cadence.md?truncated=true",3475],"8d2e039e":[()=>n.e(4505).then(n.bind(n,1316)),"@site/docs/08-workflow-troubleshooting/index.md",1316],"8ea09047":[()=>n.e(9385).then(n.t.bind(n,600,19)),"@generated/docusaurus-plugin-content-blog/default/p/blog-page-2-433.json",600],"8edf5fa8":[()=>n.e(5910).then(n.bind(n,7629)),"@site/blog/2024-3-11-community-spotlight-update-march-2024.md",7629],"90f276f1":[()=>n.e(4960).then(n.bind(n,8926)),"@site/docs/05-go-client/09-continue-as-new.md",8926],"9250e00d":[()=>n.e(3914).then(n.t.bind(n,121,19)),"@generated/docusaurus-plugin-content-blog/default/p/blog-authors-chopincode-b62.json",121],"92ce93dc":[()=>n.e(6941).then(n.bind(n,3273)),"@site/blog/2023-06-08-survey-results/2023-06-08-survey-results.md",3273],"92fb1dcd":[()=>n.e(9552).then(n.t.bind(n,6129,19)),"@generated/docusaurus-plugin-content-blog/default/p/blog-tags-roadmap-e35.json",6129],"9366521c":[()=>n.e(5086).then(n.bind(n,5365)),"@site/blog/2023-03-31-community-spotlight-march-2023.md",5365],"93e7684d":[()=>n.e(2761).then(n.t.bind(n,9001,19)),"@generated/docusaurus-plugin-content-blog/default/p/blog-tags-cadence-operations-f05.json",9001],"959827cd":[()=>n.e(150).then(n.bind(n,6392)),"@site/blog/2022-09-30-community-spotlight-september-2022.md?truncated=true",6392],"95cc356a":[()=>n.e(4324).then(n.bind(n,7669)),"@site/docs/05-go-client/18-workflow-replay-shadowing.md",7669],"95d054c5":[()=>n.e(9586).then(n.bind(n,7969)),"@site/docs/04-java-client/18-workflow-replay-shadowing.md",7969],"965c09ae":[()=>n.e(2469).then(n.bind(n,9382)),"@site/blog/2023-08-31-community-spotlight-august-2023.md?truncated=true",9382],"9674d0ef":[()=>n.e(1010).then(n.bind(n,6705)),"@site/docs/03-concepts/08-cross-dc-replication.md",6705],"97fa9516":[()=>n.e(3355).then(n.t.bind(n,771,19)),"@generated/docusaurus-plugin-content-blog/default/p/blog-tags-releases-519.json",771],"981d14b8":[()=>n.e(7970).then(n.bind(n,2724)),"@site/blog/2023-11-30-community-spotlight-update-november-2023.md?truncated=true",2724],"98f5ac88":[()=>n.e(2235).then(n.bind(n,6724)),"@site/blog/2023-06-30-community-spotlight-june-2023.md",6724],"98f77afb":[()=>n.e(1193).then(n.bind(n,1786)),"@site/blog/2022-04-30-community-spotlight-update-april-2022.md?truncated=true",1786],"99c90dae":[()=>n.e(9203).then(n.bind(n,2771)),"@site/docs/03-concepts/index.md",2771],"9e4087bc":[()=>n.e(2711).then(n.bind(n,9331)),"@theme/BlogArchivePage",9331],"9e9bbe09":[()=>n.e(3718).then(n.bind(n,9118)),"@site/blog/2024-02-15-cadence-non-deterministic-common-qa.md?truncated=true",9118],a197b989:[()=>n.e(6975).then(n.bind(n,5905)),"@site/blog/2023-07-16-write-your-first-workflow-with-cadence/2023-07-16-write-your-first-workflow-with-cadence.md",5905],a3886376:[()=>n.e(5349).then(n.t.bind(n,7159,19)),"@generated/docusaurus-plugin-content-blog/default/p/blog-authors-enderdemirkaya-1e7.json",7159],a3dd65a2:[()=>n.e(1485).then(n.bind(n,9983)),"@site/blog/2022-02-28-community-spotlight-february-2022.md",9983],a48fa53f:[()=>n.e(9387).then(n.t.bind(n,552,19)),"@generated/docusaurus-plugin-content-blog/default/p/blog-authors-sharanf-authors-2-8fb.json",552],a4f1f4dd:[()=>n.e(9961).then(n.bind(n,2496)),"@site/docs/05-go-client/19-workflow-non-deterministic-error.md",2496],a6aa9e1f:[()=>Promise.all([n.e(1869),n.e(8498),n.e(3347),n.e(7643)]).then(n.bind(n,5124)),"@theme/BlogListPage",5124],a7456010:[()=>n.e(1235).then(n.t.bind(n,8552,19)),"@generated/docusaurus-plugin-content-pages/default/__plugin.json",8552],a7552915:[()=>n.e(9520).then(n.bind(n,1735)),"@site/docs/04-java-client/06-implementing-activities.md",1735],a7bd4aaa:[()=>n.e(7098).then(n.bind(n,4532)),"@theme/DocVersionRoot",4532],a7de3fbd:[()=>n.e(783).then(n.bind(n,8515)),"@site/docs/02-use-cases/11-dsl.md",8515],a94703ab:[()=>Promise.all([n.e(1869),n.e(9048)]).then(n.bind(n,1377)),"@theme/DocRoot",1377],a94774ec:[()=>n.e(2887).then(n.bind(n,2318)),"@site/blog/2022-08-31-community-spotlight-august-2022.md",2318],aa55d0af:[()=>n.e(8330).then(n.t.bind(n,7867,19)),"@generated/docusaurus-plugin-content-blog/default/p/blog-authors-jakobht-8d3.json",7867],aac593d4:[()=>n.e(6269).then(n.bind(n,5492)),"@site/blog/2022-06-30-community-spotlight-update-june-2022.md?truncated=true",5492],aacb5a6b:[()=>n.e(5620).then(n.bind(n,8146)),"@site/docs/05-go-client/07-error-handling.md",8146],aba21aa0:[()=>n.e(5742).then(n.t.bind(n,7093,19)),"@generated/docusaurus-plugin-content-docs/default/__plugin.json",7093],acecf23e:[()=>n.e(1903).then(n.t.bind(n,1912,19)),"~blog/default/blogMetadata-default.json",1912],acfca6f1:[()=>n.e(5484).then(n.bind(n,4066)),"@site/blog/2022-01-31-community-spotlight-january-2022.md?truncated=true",4066],ad9e871f:[()=>n.e(3992).then(n.bind(n,8696)),"@site/docs/01-get-started/04-video-tutorials.md",8696],aeb329ea:[()=>n.e(2937).then(n.bind(n,3347)),"@site/docs/GLOSSARY.md",3347],b4266c8b:[()=>n.e(4962).then(n.bind(n,8060)),"@site/docs/03-concepts/02-activities.md",8060],b69803f5:[()=>n.e(5552).then(n.bind(n,4055)),"@site/blog/2022-05-31-community-spotlight-update-may-2022.md",4055],bc79ac75:[()=>n.e(1662).then(n.bind(n,1241)),"@site/docs/02-use-cases/01-periodic-execution.md",1241],bde620bf:[()=>n.e(3890).then(n.bind(n,4591)),"@site/docs/05-go-client/12-activity-async-completion.md",4591],c141421f:[()=>n.e(957).then(n.t.bind(n,936,19)),"@generated/docusaurus-theme-search-algolia/default/__plugin.json",936],c15d9823:[()=>n.e(8146).then(n.t.bind(n,6947,19)),"@generated/docusaurus-plugin-content-blog/default/p/blog-bd9.json",6947],c47f6b82:[()=>n.e(9855).then(n.bind(n,4281)),"@site/blog/2024-07-11-yearly-roadmap-update/2024-07-11-yearly-roadmap-update.md",4281],c4da92db:[()=>n.e(1700).then(n.bind(n,8863)),"@site/docs/02-use-cases/10-interactive.md",8863],c5abbc6d:[()=>n.e(1337).then(n.bind(n,9976)),"@site/docs/05-go-client/15-sessions.md",9976],ccc49370:[()=>Promise.all([n.e(1869),n.e(8498),n.e(3347),n.e(3249)]).then(n.bind(n,3858)),"@theme/BlogPostPage",3858],cccd73f1:[()=>n.e(9513).then(n.bind(n,5441)),"@site/docs/01-get-started/index.md",5441],cd7e9a8f:[()=>n.e(7338).then(n.bind(n,3907)),"@site/docs/03-concepts/10-http-api.md",3907],cdada9ee:[()=>n.e(1249).then(n.bind(n,1176)),"@site/docs/03-concepts/05-topology.md",1176],cdf6e634:[()=>n.e(3334).then(n.bind(n,8752)),"@site/blog/2023-06-30-community-spotlight-june-2023.md?truncated=true",8752],cfb807c8:[()=>n.e(9308).then(n.bind(n,8935)),"@site/blog/2022-07-31-community-spotlight-update-july-2022.md?truncated=true",8935],cfd61dd5:[()=>n.e(3044).then(n.bind(n,7237)),"@site/docs/02-use-cases/index.md",7237],d0ac2d40:[()=>n.e(6401).then(n.bind(n,9878)),"@site/docs/04-java-client/05-activity-interface.md",9878],d0bf664b:[()=>n.e(4177).then(n.t.bind(n,1285,19)),"@generated/docusaurus-plugin-content-blog/default/p/blog-tags-community-spotlights-page-2-dda.json",1285],d2436a2b:[()=>n.e(837).then(n.t.bind(n,9112,19)),"@generated/docusaurus-plugin-content-docs/community/p/community-038.json",9112],d27d92a2:[()=>n.e(3060).then(n.bind(n,3592)),"@site/blog/2022-07-31-community-spotlight-update-july-2022.md",3592],d280f29d:[()=>n.e(4881).then(n.bind(n,1892)),"@site/docs/05-go-client/08-signals.md",1892],d33895f8:[()=>n.e(7125).then(n.bind(n,4669)),"@site/blog/2024-10-01-announcing-cadence-helm-charts-v0.md",4669],d33bd0ff:[()=>n.e(1759).then(n.bind(n,605)),"@site/blog/2022-03-31-community-spotlight-update-march-2022.md?truncated=true",605],d67a7980:[()=>n.e(5733).then(n.bind(n,608)),"@site/docs/05-go-client/14-workflow-versioning.md",608],d6960a6f:[()=>n.e(5557).then(n.bind(n,5234)),"@site/blog/2023-07-05-implement-cadence-worker-from-scratch.md?truncated=true",5234],d70bd24b:[()=>n.e(1118).then(n.bind(n,5680)),"@site/blog/2023-07-31-community-spotlight-july-2023.md?truncated=true",5680],d7b037f3:[()=>n.e(5385).then(n.bind(n,3547)),"@site/docs/02-use-cases/02-orchestration.md",3547],d87fba2a:[()=>n.e(104).then(n.bind(n,2171)),"@site/docs/02-use-cases/09-operational-management.md",2171],de3708c6:[()=>n.e(4619).then(n.bind(n,988)),"@site/blog/2021-10-13-announcing-cadence-oss-office-hours-and-community-sync-up.md",988],dec4f520:[()=>n.e(4898).then(n.bind(n,190)),"@site/blog/2022-10-31-community-spotlight-october-2022.md?truncated=true",190],df4cf6e6:[()=>n.e(2379).then(n.bind(n,2652)),"@site/blog/2021-09-30-long-term-commitment-and-support-for-the-cadence-project-and-its-community.md?truncated=true",2652],e0719818:[()=>n.e(5220).then(n.t.bind(n,8669,19)),"@generated/docusaurus-plugin-content-docs/community/__plugin.json",8669],e1ea741a:[()=>n.e(2192).then(n.bind(n,1612)),"@site/docs/02-use-cases/03-polling.md",1612],e8c8106b:[()=>n.e(22).then(n.bind(n,2863)),"@site/docs/05-go-client/11-queries.md",2863],e9c26ae5:[()=>n.e(8631).then(n.bind(n,5726)),"@site/blog/2022-11-30-community-spotlight-november-2022.md",5726],ea1e4697:[()=>n.e(9617).then(n.bind(n,8442)),"@site/blog/2022-10-31-community-spotlight-october-2022.md",8442],eb57c500:[()=>n.e(7246).then(n.bind(n,266)),"@site/docs/05-go-client/10-side-effect.md",266],ec02fbe0:[()=>n.e(5438).then(n.bind(n,3231)),"@site/docs/05-go-client/03-activities.md",3231],ef69cbb3:[()=>n.e(6267).then(n.bind(n,5864)),"@site/blog/2023-01-31-community-spotlight-january-2023.md",5864],ef8b811a:[()=>n.e(8947).then(n.t.bind(n,6600,19)),"@generated/docusaurus-plugin-content-blog/default/p/blog-authors-790.json",6600],f09be712:[()=>n.e(3493).then(n.t.bind(n,3122,19)),"@generated/docusaurus-plugin-content-blog/default/p/blog-authors-meiliang-86-9a6.json",3122],f0ea030e:[()=>n.e(93).then(n.t.bind(n,1267,19)),"@generated/docusaurus-plugin-content-blog/default/p/blog-tags-introduction-to-cadence-397.json",1267],f0efcb43:[()=>n.e(4144).then(n.bind(n,71)),"@site/docs/05-go-client/05-child-workflows.md",71],f1de825c:[()=>n.e(9407).then(n.bind(n,4834)),"@site/blog/2023-08-31-community-spotlight-august-2023.md",4834],f2a162ea:[()=>n.e(3087).then(n.bind(n,1592)),"@site/docs/04-java-client/10-signals.md",1592],f5140c76:[()=>n.e(6763).then(n.bind(n,5658)),"@site/docs/04-java-client/17-testing.md",5658],f7be646d:[()=>n.e(5429).then(n.bind(n,455)),"@site/blog/2023-03-31-community-spotlight-march-2023.md?truncated=true",455],f81c1134:[()=>n.e(8130).then(n.t.bind(n,7735,19)),"@generated/docusaurus-plugin-content-blog/default/p/blog-archive-f05.json",7735],f81e7c5e:[()=>n.e(5351).then(n.bind(n,9540)),"@site/docs/05-go-client/13-workflow-testing.md",9540],f8f32361:[()=>n.e(734).then(n.bind(n,5913)),"@site/docs/06-cli/index.md",5913],f997f9c8:[()=>n.e(5138).then(n.bind(n,9691)),"@site/docs/07-operation-guide/index.md",9691],fa0e6b45:[()=>n.e(1328).then(n.bind(n,8094)),"@site/docs/02-use-cases/06-batch-job.md",8094],fcdcf093:[()=>n.e(9051).then(n.bind(n,4271)),"@site/docs/02-use-cases/04-event-driven.md",4271],fda2e45a:[()=>n.e(1653).then(n.bind(n,8856)),"@site/blog/2021-10-13-announcing-cadence-oss-office-hours-and-community-sync-up.md?truncated=true",8856],fde82b69:[()=>n.e(6185).then(n.bind(n,5410)),"@site/docs/03-concepts/09-search-workflows.md",5410]};var s=n(4848);function c(e){let{error:t,retry:n,pastDelay:r}=e;return t?(0,s.jsxs)("div",{style:{textAlign:"center",color:"#fff",backgroundColor:"#fa383e",borderColor:"#fa383e",borderStyle:"solid",borderRadius:"0.25rem",borderWidth:"1px",boxSizing:"border-box",display:"block",padding:"1rem",flex:"0 0 50%",marginLeft:"25%",marginRight:"25%",marginTop:"5rem",maxWidth:"50%",width:"100%"},children:[(0,s.jsx)("p",{children:String(t)}),(0,s.jsx)("div",{children:(0,s.jsx)("button",{type:"button",onClick:n,children:"Retry"})})]}):r?(0,s.jsx)("div",{style:{display:"flex",justifyContent:"center",alignItems:"center",height:"100vh"},children:(0,s.jsx)("svg",{id:"loader",style:{width:128,height:110,position:"absolute",top:"calc(100vh - 64%)"},viewBox:"0 0 45 45",xmlns:"http://www.w3.org/2000/svg",stroke:"#61dafb",children:(0,s.jsxs)("g",{fill:"none",fillRule:"evenodd",transform:"translate(1 1)",strokeWidth:"2",children:[(0,s.jsxs)("circle",{cx:"22",cy:"22",r:"6",strokeOpacity:"0",children:[(0,s.jsx)("animate",{attributeName:"r",begin:"1.5s",dur:"3s",values:"6;22",calcMode:"linear",repeatCount:"indefinite"}),(0,s.jsx)("animate",{attributeName:"stroke-opacity",begin:"1.5s",dur:"3s",values:"1;0",calcMode:"linear",repeatCount:"indefinite"}),(0,s.jsx)("animate",{attributeName:"stroke-width",begin:"1.5s",dur:"3s",values:"2;0",calcMode:"linear",repeatCount:"indefinite"})]}),(0,s.jsxs)("circle",{cx:"22",cy:"22",r:"6",strokeOpacity:"0",children:[(0,s.jsx)("animate",{attributeName:"r",begin:"3s",dur:"3s",values:"6;22",calcMode:"linear",repeatCount:"indefinite"}),(0,s.jsx)("animate",{attributeName:"stroke-opacity",begin:"3s",dur:"3s",values:"1;0",calcMode:"linear",repeatCount:"indefinite"}),(0,s.jsx)("animate",{attributeName:"stroke-width",begin:"3s",dur:"3s",values:"2;0",calcMode:"linear",repeatCount:"indefinite"})]}),(0,s.jsx)("circle",{cx:"22",cy:"22",r:"8",children:(0,s.jsx)("animate",{attributeName:"r",begin:"0s",dur:"1.5s",values:"6;1;2;3;4;5;6",calcMode:"linear",repeatCount:"indefinite"})})]})})}):null}var l=n(6921),u=n(3102);function d(e,t){if("*"===e)return o()({loading:c,loader:()=>n.e(2237).then(n.bind(n,2237)),modules:["@theme/NotFound"],webpack:()=>[2237],render(e,t){const n=e.default;return(0,s.jsx)(u.W,{value:{plugin:{name:"native",id:"default"}},children:(0,s.jsx)(n,{...t})})}});const r=a[`${e}-${t}`],d={},p=[],f=[],m=(0,l.A)(r);return Object.entries(m).forEach((e=>{let[t,n]=e;const r=i[n];r&&(d[t]=r[0],p.push(r[1]),f.push(r[2]))})),o().Map({loading:c,loader:d,modules:p,webpack:()=>f,render(t,n){const o=JSON.parse(JSON.stringify(r));Object.entries(t).forEach((t=>{let[n,r]=t;const a=r.default;if(!a)throw new Error(`The page component at ${e} doesn't have a default export. This makes it impossible to render anything. Consider default-exporting a React component.`);"object"!=typeof a&&"function"!=typeof a||Object.keys(r).filter((e=>"default"!==e)).forEach((e=>{a[e]=r[e]}));let i=o;const s=n.split(".");s.slice(0,-1).forEach((e=>{i=i[e]})),i[s[s.length-1]]=a}));const a=o.__comp;delete o.__comp;const i=o.__context;delete o.__context;const c=o.__props;return delete o.__props,(0,s.jsx)(u.W,{value:i,children:(0,s.jsx)(a,{...o,...c,...n})})}})}const p=[{path:"/blog",component:d("/blog","775"),exact:!0},{path:"/blog/2021/09/30/long-term-commitment-and-support-for-the-cadence-project-and-its-community",component:d("/blog/2021/09/30/long-term-commitment-and-support-for-the-cadence-project-and-its-community","bcb"),exact:!0},{path:"/blog/2021/10/13/announcing-cadence-oss-office-hours-and-community-sync-up",component:d("/blog/2021/10/13/announcing-cadence-oss-office-hours-and-community-sync-up","0d6"),exact:!0},{path:"/blog/2021/10/19/2021-10-19-moving-to-grpc/moving-to-grpc",component:d("/blog/2021/10/19/2021-10-19-moving-to-grpc/moving-to-grpc","7db"),exact:!0},{path:"/blog/2022/01/31/community-spotlight-january-2022",component:d("/blog/2022/01/31/community-spotlight-january-2022","511"),exact:!0},{path:"/blog/2022/02/28/community-spotlight-february-2022",component:d("/blog/2022/02/28/community-spotlight-february-2022","b9d"),exact:!0},{path:"/blog/2022/03/31/community-spotlight-update-march-2022",component:d("/blog/2022/03/31/community-spotlight-update-march-2022","fa6"),exact:!0},{path:"/blog/2022/04/30/community-spotlight-update-april-2022",component:d("/blog/2022/04/30/community-spotlight-update-april-2022","6c1"),exact:!0},{path:"/blog/2022/05/31/community-spotlight-update-may-2022",component:d("/blog/2022/05/31/community-spotlight-update-may-2022","7b3"),exact:!0},{path:"/blog/2022/06/30/community-spotlight-update-june-2022",component:d("/blog/2022/06/30/community-spotlight-update-june-2022","f54"),exact:!0},{path:"/blog/2022/07/31/community-spotlight-update-july-2022",component:d("/blog/2022/07/31/community-spotlight-update-july-2022","c4f"),exact:!0},{path:"/blog/2022/08/31/community-spotlight-august-2022",component:d("/blog/2022/08/31/community-spotlight-august-2022","697"),exact:!0},{path:"/blog/2022/09/30/community-spotlight-september-2022",component:d("/blog/2022/09/30/community-spotlight-september-2022","0e6"),exact:!0},{path:"/blog/2022/10/31/community-spotlight-october-2022",component:d("/blog/2022/10/31/community-spotlight-october-2022","829"),exact:!0},{path:"/blog/2022/11/30/community-spotlight-november-2022",component:d("/blog/2022/11/30/community-spotlight-november-2022","30a"),exact:!0},{path:"/blog/2022/12/23/community-spotlight-december-2022",component:d("/blog/2022/12/23/community-spotlight-december-2022","618"),exact:!0},{path:"/blog/2023/01/31/community-spotlight-january-2023",component:d("/blog/2023/01/31/community-spotlight-january-2023","47e"),exact:!0},{path:"/blog/2023/02/28/community-spotlight-february",component:d("/blog/2023/02/28/community-spotlight-february","943"),exact:!0},{path:"/blog/2023/03/31/community-spotlight-march-2023",component:d("/blog/2023/03/31/community-spotlight-march-2023","580"),exact:!0},{path:"/blog/2023/06/08/2023-06-08-survey-results/survey-results",component:d("/blog/2023/06/08/2023-06-08-survey-results/survey-results","ee6"),exact:!0},{path:"/blog/2023/06/28/components-of-cadence-application-setup",component:d("/blog/2023/06/28/components-of-cadence-application-setup","060"),exact:!0},{path:"/blog/2023/06/30/community-spotlight-june-2023",component:d("/blog/2023/06/30/community-spotlight-june-2023","3cc"),exact:!0},{path:"/blog/2023/07/05/implement-cadence-worker-from-scratch",component:d("/blog/2023/07/05/implement-cadence-worker-from-scratch","f2f"),exact:!0},{path:"/blog/2023/07/10/cadence-bad-practices-part-1",component:d("/blog/2023/07/10/cadence-bad-practices-part-1","4d6"),exact:!0},{path:"/blog/2023/07/16/2023-07-16-write-your-first-workflow-with-cadence/write-your-first-workflow-with-cadence",component:d("/blog/2023/07/16/2023-07-16-write-your-first-workflow-with-cadence/write-your-first-workflow-with-cadence","342"),exact:!0},{path:"/blog/2023/07/31/community-spotlight-july-2023",component:d("/blog/2023/07/31/community-spotlight-july-2023","c49"),exact:!0},{path:"/blog/2023/08/28/nondeterministic-errors-replayers-shadowers",component:d("/blog/2023/08/28/nondeterministic-errors-replayers-shadowers","0c6"),exact:!0},{path:"/blog/2023/08/31/community-spotlight-august-2023",component:d("/blog/2023/08/31/community-spotlight-august-2023","221"),exact:!0},{path:"/blog/2023/11/30/community-spotlight-update-november-2023",component:d("/blog/2023/11/30/community-spotlight-update-november-2023","174"),exact:!0},{path:"/blog/2024/02/15/cadence-non-deterministic-common-qa",component:d("/blog/2024/02/15/cadence-non-deterministic-common-qa","ed4"),exact:!0},{path:"/blog/2024/07/11/2024-07-11-yearly-roadmap-update/yearly-roadmap-update",component:d("/blog/2024/07/11/2024-07-11-yearly-roadmap-update/yearly-roadmap-update","cef"),exact:!0},{path:"/blog/2024/09/05/workflow-specific-rate-limits",component:d("/blog/2024/09/05/workflow-specific-rate-limits","778"),exact:!0},{path:"/blog/2024/10/01/announcing-cadence-helm-charts-v0",component:d("/blog/2024/10/01/announcing-cadence-helm-charts-v0","8fb"),exact:!0},{path:"/blog/2024/11/18/cadence-workflows-github-organization",component:d("/blog/2024/11/18/cadence-workflows-github-organization","6df"),exact:!0},{path:"/blog/2024/3/11/community-spotlight-update-march-2024",component:d("/blog/2024/3/11/community-spotlight-update-march-2024","7a7"),exact:!0},{path:"/blog/archive",component:d("/blog/archive","182"),exact:!0},{path:"/blog/authors",component:d("/blog/authors","0b7"),exact:!0},{path:"/blog/authors/chopincode",component:d("/blog/authors/chopincode","b0f"),exact:!0},{path:"/blog/authors/enderdemirkaya",component:d("/blog/authors/enderdemirkaya","5c6"),exact:!0},{path:"/blog/authors/ibarrajo",component:d("/blog/authors/ibarrajo","353"),exact:!0},{path:"/blog/authors/jakobht",component:d("/blog/authors/jakobht","e9a"),exact:!0},{path:"/blog/authors/kcorbett-netapp",component:d("/blog/authors/kcorbett-netapp","34e"),exact:!0},{path:"/blog/authors/meiliang-86",component:d("/blog/authors/meiliang-86","00a"),exact:!0},{path:"/blog/authors/shaddoll",component:d("/blog/authors/shaddoll","91b"),exact:!0},{path:"/blog/authors/sharanf",component:d("/blog/authors/sharanf","293"),exact:!0},{path:"/blog/authors/sharanf/authors/2",component:d("/blog/authors/sharanf/authors/2","e3a"),exact:!0},{path:"/blog/authors/taylanisikdemir",component:d("/blog/authors/taylanisikdemir","2ca"),exact:!0},{path:"/blog/authors/vytautas-karpavicius",component:d("/blog/authors/vytautas-karpavicius","e09"),exact:!0},{path:"/blog/page/2",component:d("/blog/page/2","10f"),exact:!0},{path:"/blog/page/3",component:d("/blog/page/3","b5e"),exact:!0},{path:"/blog/page/4",component:d("/blog/page/4","3a4"),exact:!0},{path:"/blog/tags",component:d("/blog/tags","287"),exact:!0},{path:"/blog/tags/announcements",component:d("/blog/tags/announcements","83f"),exact:!0},{path:"/blog/tags/cadence-operations",component:d("/blog/tags/cadence-operations","8cc"),exact:!0},{path:"/blog/tags/community-spotlights",component:d("/blog/tags/community-spotlights","d90"),exact:!0},{path:"/blog/tags/community-spotlights/page/2",component:d("/blog/tags/community-spotlights/page/2","62d"),exact:!0},{path:"/blog/tags/deep-dives",component:d("/blog/tags/deep-dives","cd9"),exact:!0},{path:"/blog/tags/introduction-to-cadence",component:d("/blog/tags/introduction-to-cadence","c8c"),exact:!0},{path:"/blog/tags/releases",component:d("/blog/tags/releases","194"),exact:!0},{path:"/blog/tags/roadmap",component:d("/blog/tags/roadmap","df5"),exact:!0},{path:"/blog/tags/testing",component:d("/blog/tags/testing","550"),exact:!0},{path:"/blog/zonal-isolation-v1/zonal-isolation-v1",component:d("/blog/zonal-isolation-v1/zonal-isolation-v1","093"),exact:!0},{path:"/markdown-page",component:d("/markdown-page","3d7"),exact:!0},{path:"/search",component:d("/search","5de"),exact:!0},{path:"/community",component:d("/community","c2a"),routes:[{path:"/community",component:d("/community","41a"),routes:[{path:"/community",component:d("/community","143"),routes:[{path:"/community/contributing",component:d("/community/contributing","5ca"),exact:!0},{path:"/community/resources",component:d("/community/resources","3cf"),exact:!0},{path:"/community/support",component:d("/community/support","35e"),exact:!0,sidebar:"community"},{path:"/community/team",component:d("/community/team","112"),exact:!0,sidebar:"community"}]}]}]},{path:"/docs",component:d("/docs","3eb"),routes:[{path:"/docs",component:d("/docs","75e"),routes:[{path:"/docs",component:d("/docs","14f"),routes:[{path:"/docs/about",component:d("/docs/about","280"),exact:!0,sidebar:"docsSidebar"},{path:"/docs/about/license",component:d("/docs/about/license","75f"),exact:!0,sidebar:"docsSidebar"},{path:"/docs/cli",component:d("/docs/cli","c8b"),exact:!0,sidebar:"docsSidebar"},{path:"/docs/concepts",component:d("/docs/concepts","c76"),exact:!0,sidebar:"docsSidebar"},{path:"/docs/concepts/activities",component:d("/docs/concepts/activities","6a3"),exact:!0,sidebar:"docsSidebar"},{path:"/docs/concepts/archival",component:d("/docs/concepts/archival","71e"),exact:!0,sidebar:"docsSidebar"},{path:"/docs/concepts/cross-dc-replication",component:d("/docs/concepts/cross-dc-replication","5b1"),exact:!0,sidebar:"docsSidebar"},{path:"/docs/concepts/events",component:d("/docs/concepts/events","7e7"),exact:!0,sidebar:"docsSidebar"},{path:"/docs/concepts/http-api",component:d("/docs/concepts/http-api","3fb"),exact:!0,sidebar:"docsSidebar"},{path:"/docs/concepts/queries",component:d("/docs/concepts/queries","9a8"),exact:!0,sidebar:"docsSidebar"},{path:"/docs/concepts/search-workflows",component:d("/docs/concepts/search-workflows","bdb"),exact:!0,sidebar:"docsSidebar"},{path:"/docs/concepts/task-lists",component:d("/docs/concepts/task-lists","805"),exact:!0,sidebar:"docsSidebar"},{path:"/docs/concepts/topology",component:d("/docs/concepts/topology","3fa"),exact:!0,sidebar:"docsSidebar"},{path:"/docs/concepts/workflows",component:d("/docs/concepts/workflows","280"),exact:!0},{path:"/docs/get-started",component:d("/docs/get-started","b10"),exact:!0,sidebar:"docsSidebar"},{path:"/docs/get-started/golang-hello-world",component:d("/docs/get-started/golang-hello-world","154"),exact:!0,sidebar:"docsSidebar"},{path:"/docs/get-started/java-hello-world",component:d("/docs/get-started/java-hello-world","94d"),exact:!0,sidebar:"docsSidebar"},{path:"/docs/get-started/server-installation",component:d("/docs/get-started/server-installation","223"),exact:!0,sidebar:"docsSidebar"},{path:"/docs/get-started/video-tutorials",component:d("/docs/get-started/video-tutorials","bef"),exact:!0,sidebar:"docsSidebar"},{path:"/docs/glossary",component:d("/docs/glossary","9c6"),exact:!0},{path:"/docs/go-client",component:d("/docs/go-client","9b9"),exact:!0,sidebar:"docsSidebar"},{path:"/docs/go-client/02.5-starting-workflows",component:d("/docs/go-client/02.5-starting-workflows","ea1"),exact:!0,sidebar:"docsSidebar"},{path:"/docs/go-client/activities",component:d("/docs/go-client/activities","c4d"),exact:!0,sidebar:"docsSidebar"},{path:"/docs/go-client/activity-async-completion",component:d("/docs/go-client/activity-async-completion","42b"),exact:!0,sidebar:"docsSidebar"},{path:"/docs/go-client/child-workflows",component:d("/docs/go-client/child-workflows","4fd"),exact:!0,sidebar:"docsSidebar"},{path:"/docs/go-client/continue-as-new",component:d("/docs/go-client/continue-as-new","2d0"),exact:!0,sidebar:"docsSidebar"},{path:"/docs/go-client/create-workflows",component:d("/docs/go-client/create-workflows","5de"),exact:!0,sidebar:"docsSidebar"},{path:"/docs/go-client/distributed-cron",component:d("/docs/go-client/distributed-cron","ae6"),exact:!0,sidebar:"docsSidebar"},{path:"/docs/go-client/error-handling",component:d("/docs/go-client/error-handling","d9a"),exact:!0,sidebar:"docsSidebar"},{path:"/docs/go-client/execute-activity",component:d("/docs/go-client/execute-activity","63f"),exact:!0,sidebar:"docsSidebar"},{path:"/docs/go-client/queries",component:d("/docs/go-client/queries","83a"),exact:!0,sidebar:"docsSidebar"},{path:"/docs/go-client/retries",component:d("/docs/go-client/retries","b66"),exact:!0,sidebar:"docsSidebar"},{path:"/docs/go-client/sessions",component:d("/docs/go-client/sessions","ef2"),exact:!0,sidebar:"docsSidebar"},{path:"/docs/go-client/side-effect",component:d("/docs/go-client/side-effect","807"),exact:!0,sidebar:"docsSidebar"},{path:"/docs/go-client/signals",component:d("/docs/go-client/signals","f35"),exact:!0,sidebar:"docsSidebar"},{path:"/docs/go-client/tracing",component:d("/docs/go-client/tracing","83a"),exact:!0,sidebar:"docsSidebar"},{path:"/docs/go-client/workers",component:d("/docs/go-client/workers","2e9"),exact:!0,sidebar:"docsSidebar"},{path:"/docs/go-client/workflow-non-deterministic-error",component:d("/docs/go-client/workflow-non-deterministic-error","08a"),exact:!0},{path:"/docs/go-client/workflow-replay-shadowing",component:d("/docs/go-client/workflow-replay-shadowing","398"),exact:!0,sidebar:"docsSidebar"},{path:"/docs/go-client/workflow-testing",component:d("/docs/go-client/workflow-testing","034"),exact:!0,sidebar:"docsSidebar"},{path:"/docs/go-client/workflow-versioning",component:d("/docs/go-client/workflow-versioning","764"),exact:!0,sidebar:"docsSidebar"},{path:"/docs/java-client",component:d("/docs/java-client","6d4"),exact:!0,sidebar:"docsSidebar"},{path:"/docs/java-client/activity-interface",component:d("/docs/java-client/activity-interface","fcd"),exact:!0,sidebar:"docsSidebar"},{path:"/docs/java-client/child-workflows",component:d("/docs/java-client/child-workflows","187"),exact:!0,sidebar:"docsSidebar"},{path:"/docs/java-client/client-overview",component:d("/docs/java-client/client-overview","94c"),exact:!0,sidebar:"docsSidebar"},{path:"/docs/java-client/continue-as-new",component:d("/docs/java-client/continue-as-new","def"),exact:!0,sidebar:"docsSidebar"},{path:"/docs/java-client/distributed-cron",component:d("/docs/java-client/distributed-cron","ac5"),exact:!0,sidebar:"docsSidebar"},{path:"/docs/java-client/exception-handling",component:d("/docs/java-client/exception-handling","d3e"),exact:!0,sidebar:"docsSidebar"},{path:"/docs/java-client/implementing-activities",component:d("/docs/java-client/implementing-activities","871"),exact:!0},{path:"/docs/java-client/implementing-workflows",component:d("/docs/java-client/implementing-workflows","007"),exact:!0,sidebar:"docsSidebar"},{path:"/docs/java-client/queries",component:d("/docs/java-client/queries","92f"),exact:!0,sidebar:"docsSidebar"},{path:"/docs/java-client/retries",component:d("/docs/java-client/retries","dcf"),exact:!0,sidebar:"docsSidebar"},{path:"/docs/java-client/side-effect",component:d("/docs/java-client/side-effect","f90"),exact:!0,sidebar:"docsSidebar"},{path:"/docs/java-client/signals",component:d("/docs/java-client/signals","a8e"),exact:!0,sidebar:"docsSidebar"},{path:"/docs/java-client/starting-workflow-executions",component:d("/docs/java-client/starting-workflow-executions","452"),exact:!0,sidebar:"docsSidebar"},{path:"/docs/java-client/testing",component:d("/docs/java-client/testing","28b"),exact:!0,sidebar:"docsSidebar"},{path:"/docs/java-client/versioning",component:d("/docs/java-client/versioning","36a"),exact:!0,sidebar:"docsSidebar"},{path:"/docs/java-client/workers",component:d("/docs/java-client/workers","132"),exact:!0,sidebar:"docsSidebar"},{path:"/docs/java-client/workflow-interface",component:d("/docs/java-client/workflow-interface","8b6"),exact:!0,sidebar:"docsSidebar"},{path:"/docs/java-client/workflow-replay-shadowing",component:d("/docs/java-client/workflow-replay-shadowing","dd8"),exact:!0,sidebar:"docsSidebar"},{path:"/docs/operation-guide",component:d("/docs/operation-guide","18d"),exact:!0,sidebar:"docsSidebar"},{path:"/docs/operation-guide/maintain",component:d("/docs/operation-guide/maintain","54d"),exact:!0,sidebar:"docsSidebar"},{path:"/docs/operation-guide/migration",component:d("/docs/operation-guide/migration","b5e"),exact:!0,sidebar:"docsSidebar"},{path:"/docs/operation-guide/monitoring",component:d("/docs/operation-guide/monitoring","b13"),exact:!0,sidebar:"docsSidebar"},{path:"/docs/operation-guide/setup",component:d("/docs/operation-guide/setup","3a6"),exact:!0,sidebar:"docsSidebar"},{path:"/docs/operation-guide/troubleshooting",component:d("/docs/operation-guide/troubleshooting","454"),exact:!0,sidebar:"docsSidebar"},{path:"/docs/use-cases",component:d("/docs/use-cases","236"),exact:!0,sidebar:"docsSidebar"},{path:"/docs/use-cases/batch-job",component:d("/docs/use-cases/batch-job","420"),exact:!0,sidebar:"docsSidebar"},{path:"/docs/use-cases/big-ml",component:d("/docs/use-cases/big-ml","a02"),exact:!0,sidebar:"docsSidebar"},{path:"/docs/use-cases/deployment",component:d("/docs/use-cases/deployment","5a6"),exact:!0,sidebar:"docsSidebar"},{path:"/docs/use-cases/dsl",component:d("/docs/use-cases/dsl","c7f"),exact:!0,sidebar:"docsSidebar"},{path:"/docs/use-cases/event-driven",component:d("/docs/use-cases/event-driven","bb0"),exact:!0,sidebar:"docsSidebar"},{path:"/docs/use-cases/interactive",component:d("/docs/use-cases/interactive","d9f"),exact:!0,sidebar:"docsSidebar"},{path:"/docs/use-cases/operational-management",component:d("/docs/use-cases/operational-management","ec1"),exact:!0,sidebar:"docsSidebar"},{path:"/docs/use-cases/orchestration",component:d("/docs/use-cases/orchestration","757"),exact:!0,sidebar:"docsSidebar"},{path:"/docs/use-cases/partitioned-scan",component:d("/docs/use-cases/partitioned-scan","95e"),exact:!0,sidebar:"docsSidebar"},{path:"/docs/use-cases/periodic-execution",component:d("/docs/use-cases/periodic-execution","77d"),exact:!0,sidebar:"docsSidebar"},{path:"/docs/use-cases/polling",component:d("/docs/use-cases/polling","ca2"),exact:!0,sidebar:"docsSidebar"},{path:"/docs/use-cases/provisioning",component:d("/docs/use-cases/provisioning","922"),exact:!0,sidebar:"docsSidebar"},{path:"/docs/workflow-troubleshooting",component:d("/docs/workflow-troubleshooting","58e"),exact:!0,sidebar:"docsSidebar"},{path:"/docs/workflow-troubleshooting/activity-failures",component:d("/docs/workflow-troubleshooting/activity-failures","d2f"),exact:!0,sidebar:"docsSidebar"},{path:"/docs/workflow-troubleshooting/retries",component:d("/docs/workflow-troubleshooting/retries","337"),exact:!0,sidebar:"docsSidebar"},{path:"/docs/workflow-troubleshooting/timeouts",component:d("/docs/workflow-troubleshooting/timeouts","d77"),exact:!0,sidebar:"docsSidebar"}]}]}]},{path:"/",component:d("/","e5f"),exact:!0},{path:"*",component:d("*")}]},6125:(e,t,n)=>{"use strict";n.d(t,{o:()=>a,x:()=>i});var r=n(6540),o=n(4848);const a=r.createContext(!1);function i(e){let{children:t}=e;const[n,i]=(0,r.useState)(!1);return(0,r.useEffect)((()=>{i(!0)}),[]),(0,o.jsx)(a.Provider,{value:n,children:t})}},8536:(e,t,n)=>{"use strict";var r=n(6540),o=n(5338),a=n(545),i=n(4625),s=n(4784),c=n(8193);const l=[n(1911),n(119),n(6491),n(6294),n(1043)];var u=n(8328),d=n(6347),p=n(2831),f=n(4848);function m(e){let{children:t}=e;return(0,f.jsx)(f.Fragment,{children:t})}var g=n(5260),h=n(4586),b=n(6025),y=n(6342),v=n(5500),w=n(2131),S=n(4090),k=n(2967),x=n(440),_=n(1463);function E(){const{i18n:{currentLocale:e,defaultLocale:t,localeConfigs:n}}=(0,h.A)(),r=(0,w.o)(),o=n[e].htmlLang,a=e=>e.replace("-","_");return(0,f.jsxs)(g.A,{children:[Object.entries(n).map((e=>{let[t,{htmlLang:n}]=e;return(0,f.jsx)("link",{rel:"alternate",href:r.createUrl({locale:t,fullyQualified:!0}),hrefLang:n},t)})),(0,f.jsx)("link",{rel:"alternate",href:r.createUrl({locale:t,fullyQualified:!0}),hrefLang:"x-default"}),(0,f.jsx)("meta",{property:"og:locale",content:a(o)}),Object.values(n).filter((e=>o!==e.htmlLang)).map((e=>(0,f.jsx)("meta",{property:"og:locale:alternate",content:a(e.htmlLang)},`meta-og-${e.htmlLang}`)))]})}function j(e){let{permalink:t}=e;const{siteConfig:{url:n}}=(0,h.A)(),r=function(){const{siteConfig:{url:e,baseUrl:t,trailingSlash:n}}=(0,h.A)(),{pathname:r}=(0,d.zy)();return e+(0,x.Ks)((0,b.Ay)(r),{trailingSlash:n,baseUrl:t})}(),o=t?`${n}${t}`:r;return(0,f.jsxs)(g.A,{children:[(0,f.jsx)("meta",{property:"og:url",content:o}),(0,f.jsx)("link",{rel:"canonical",href:o})]})}function O(){const{i18n:{currentLocale:e}}=(0,h.A)(),{metadata:t,image:n}=(0,y.p)();return(0,f.jsxs)(f.Fragment,{children:[(0,f.jsxs)(g.A,{children:[(0,f.jsx)("meta",{name:"twitter:card",content:"summary_large_image"}),(0,f.jsx)("body",{className:S.w})]}),n&&(0,f.jsx)(v.be,{image:n}),(0,f.jsx)(j,{}),(0,f.jsx)(E,{}),(0,f.jsx)(_.A,{tag:k.C,locale:e}),(0,f.jsx)(g.A,{children:t.map(((e,t)=>(0,f.jsx)("meta",{...e},t)))})]})}const A=new Map;var C=n(6125),T=n(6988),P=n(205);function I(e){for(var t=arguments.length,n=new Array(t>1?t-1:0),r=1;r<t;r++)n[r-1]=arguments[r];const o=l.map((t=>{const r=t.default?.[e]??t[e];return r?.(...n)}));return()=>o.forEach((e=>e?.()))}const N=function(e){let{children:t,location:n,previousLocation:r}=e;return(0,P.A)((()=>{r!==n&&(!function(e){let{location:t,previousLocation:n}=e;if(!n)return;const r=t.pathname===n.pathname,o=t.hash===n.hash,a=t.search===n.search;if(r&&o&&!a)return;const{hash:i}=t;if(i){const e=decodeURIComponent(i.substring(1)),t=document.getElementById(e);t?.scrollIntoView()}else window.scrollTo(0,0)}({location:n,previousLocation:r}),I("onRouteDidUpdate",{previousLocation:r,location:n}))}),[r,n]),t};function R(e){const t=Array.from(new Set([e,decodeURI(e)])).map((e=>(0,p.u)(u.A,e))).flat();return Promise.all(t.map((e=>e.route.component.preload?.())))}class L extends r.Component{previousLocation;routeUpdateCleanupCb;constructor(e){super(e),this.previousLocation=null,this.routeUpdateCleanupCb=c.A.canUseDOM?I("onRouteUpdate",{previousLocation:null,location:this.props.location}):()=>{},this.state={nextRouteHasLoaded:!0}}shouldComponentUpdate(e,t){if(e.location===this.props.location)return t.nextRouteHasLoaded;const n=e.location;return this.previousLocation=this.props.location,this.setState({nextRouteHasLoaded:!1}),this.routeUpdateCleanupCb=I("onRouteUpdate",{previousLocation:this.previousLocation,location:n}),R(n.pathname).then((()=>{this.routeUpdateCleanupCb(),this.setState({nextRouteHasLoaded:!0})})).catch((e=>{console.warn(e),window.location.reload()})),!1}render(){const{children:e,location:t}=this.props;return(0,f.jsx)(N,{previousLocation:this.previousLocation,location:t,children:(0,f.jsx)(d.qh,{location:t,render:()=>e})})}}const D=L,M="__docusaurus-base-url-issue-banner-suggestion-container";function F(e){return`\ndocument.addEventListener('DOMContentLoaded', function maybeInsertBanner() {\n var shouldInsert = typeof window['docusaurus'] === 'undefined';\n shouldInsert && insertBanner();\n});\n\nfunction insertBanner() {\n var bannerContainer = document.createElement('div');\n bannerContainer.id = '__docusaurus-base-url-issue-banner-container';\n var bannerHtml = ${JSON.stringify(function(e){return`\n<div id="__docusaurus-base-url-issue-banner" style="border: thick solid red; background-color: rgb(255, 230, 179); margin: 20px; padding: 20px; font-size: 20px;">\n <p style="font-weight: bold; font-size: 30px;">Your Docusaurus site did not load properly.</p>\n <p>A very common reason is a wrong site <a href="https://docusaurus.io/docs/docusaurus.config.js/#baseUrl" style="font-weight: bold;">baseUrl configuration</a>.</p>\n <p>Current configured baseUrl = <span style="font-weight: bold; color: red;">${e}</span> ${"/"===e?" (default value)":""}</p>\n <p>We suggest trying baseUrl = <span id="${M}" style="font-weight: bold; color: green;"></span></p>\n</div>\n`}(e)).replace(/</g,"\\<")};\n bannerContainer.innerHTML = bannerHtml;\n document.body.prepend(bannerContainer);\n var suggestionContainer = document.getElementById('${M}');\n var actualHomePagePath = window.location.pathname;\n var suggestedBaseUrl = actualHomePagePath.substr(-1) === '/'\n ? actualHomePagePath\n : actualHomePagePath + '/';\n suggestionContainer.innerHTML = suggestedBaseUrl;\n}\n`}function B(){const{siteConfig:{baseUrl:e}}=(0,h.A)();return(0,f.jsx)(f.Fragment,{children:!c.A.canUseDOM&&(0,f.jsx)(g.A,{children:(0,f.jsx)("script",{children:F(e)})})})}function z(){const{siteConfig:{baseUrl:e,baseUrlIssueBanner:t}}=(0,h.A)(),{pathname:n}=(0,d.zy)();return t&&n===e?(0,f.jsx)(B,{}):null}function $(){const{siteConfig:{favicon:e,title:t,noIndex:n},i18n:{currentLocale:r,localeConfigs:o}}=(0,h.A)(),a=(0,b.Ay)(e),{htmlLang:i,direction:s}=o[r];return(0,f.jsxs)(g.A,{children:[(0,f.jsx)("html",{lang:i,dir:s}),(0,f.jsx)("title",{children:t}),(0,f.jsx)("meta",{property:"og:title",content:t}),(0,f.jsx)("meta",{name:"viewport",content:"width=device-width, initial-scale=1.0"}),n&&(0,f.jsx)("meta",{name:"robots",content:"noindex, nofollow"}),e&&(0,f.jsx)("link",{rel:"icon",href:a})]})}var U=n(7489),H=n(2303);function q(){const e=(0,H.A)();return(0,f.jsx)(g.A,{children:(0,f.jsx)("html",{"data-has-hydrated":e})})}const V=(0,p.v)(u.A);function W(){const e=function(e){if(A.has(e.pathname))return{...e,pathname:A.get(e.pathname)};if((0,p.u)(u.A,e.pathname).some((e=>{let{route:t}=e;return!0===t.exact})))return A.set(e.pathname,e.pathname),e;const t=e.pathname.trim().replace(/(?:\/index)?\.html$/,"")||"/";return A.set(e.pathname,t),{...e,pathname:t}}((0,d.zy)());return(0,f.jsx)(D,{location:e,children:V})}function G(){return(0,f.jsx)(U.A,{children:(0,f.jsx)(T.l,{children:(0,f.jsxs)(C.x,{children:[(0,f.jsxs)(m,{children:[(0,f.jsx)($,{}),(0,f.jsx)(O,{}),(0,f.jsx)(z,{}),(0,f.jsx)(W,{})]}),(0,f.jsx)(q,{})]})})})}var K=n(4054);const Y=function(e){try{return document.createElement("link").relList.supports(e)}catch{return!1}}("prefetch")?function(e){return new Promise(((t,n)=>{if("undefined"==typeof document)return void n();const r=document.createElement("link");r.setAttribute("rel","prefetch"),r.setAttribute("href",e),r.onload=()=>t(),r.onerror=()=>n();const o=document.getElementsByTagName("head")[0]??document.getElementsByName("script")[0]?.parentNode;o?.appendChild(r)}))}:function(e){return new Promise(((t,n)=>{const r=new XMLHttpRequest;r.open("GET",e,!0),r.withCredentials=!0,r.onload=()=>{200===r.status?t():n()},r.send(null)}))};var Q=n(6921);const Z=new Set,X=new Set,J=()=>navigator.connection?.effectiveType.includes("2g")||navigator.connection?.saveData,ee={prefetch:e=>{if(!(e=>!J()&&!X.has(e)&&!Z.has(e))(e))return!1;Z.add(e);const t=(0,p.u)(u.A,e).flatMap((e=>{return t=e.route.path,Object.entries(K).filter((e=>{let[n]=e;return n.replace(/-[^-]+$/,"")===t})).flatMap((e=>{let[,t]=e;return Object.values((0,Q.A)(t))}));var t}));return Promise.all(t.map((e=>{const t=n.gca(e);return t&&!t.includes("undefined")?Y(t).catch((()=>{})):Promise.resolve()})))},preload:e=>!!(e=>!J()&&!X.has(e))(e)&&(X.add(e),R(e))},te=Object.freeze(ee);function ne(e){let{children:t}=e;return"hash"===s.default.future.experimental_router?(0,f.jsx)(i.I9,{children:t}):(0,f.jsx)(i.Kd,{children:t})}const re=Boolean(!0);if(c.A.canUseDOM){window.docusaurus=te;const e=document.getElementById("__docusaurus"),t=(0,f.jsx)(a.vd,{children:(0,f.jsx)(ne,{children:(0,f.jsx)(G,{})})}),n=(e,t)=>{console.error("Docusaurus React Root onRecoverableError:",e,t)},i=()=>{if(window.docusaurusRoot)window.docusaurusRoot.render(t);else if(re)window.docusaurusRoot=o.hydrateRoot(e,t,{onRecoverableError:n});else{const r=o.createRoot(e,{onRecoverableError:n});r.render(t),window.docusaurusRoot=r}};R(window.location.pathname).then((()=>{(0,r.startTransition)(i)}))}},6988:(e,t,n)=>{"use strict";n.d(t,{o:()=>d,l:()=>p});var r=n(6540),o=n(4784);const a=JSON.parse('{"docusaurus-plugin-content-docs":{"default":{"path":"/docs","versions":[{"name":"current","label":"Next","isLast":true,"path":"/docs","mainDocId":"get-started/index","docs":[{"id":"about/index","path":"/docs/about/","sidebar":"docsSidebar"},{"id":"about/license","path":"/docs/about/license","sidebar":"docsSidebar"},{"id":"cli/index","path":"/docs/cli/","sidebar":"docsSidebar"},{"id":"concepts/activities","path":"/docs/concepts/activities","sidebar":"docsSidebar"},{"id":"concepts/archival","path":"/docs/concepts/archival","sidebar":"docsSidebar"},{"id":"concepts/cross-dc-replication","path":"/docs/concepts/cross-dc-replication","sidebar":"docsSidebar"},{"id":"concepts/events","path":"/docs/concepts/events","sidebar":"docsSidebar"},{"id":"concepts/http-api","path":"/docs/concepts/http-api","sidebar":"docsSidebar"},{"id":"concepts/index","path":"/docs/concepts/","sidebar":"docsSidebar"},{"id":"concepts/queries","path":"/docs/concepts/queries","sidebar":"docsSidebar"},{"id":"concepts/search-workflows","path":"/docs/concepts/search-workflows","sidebar":"docsSidebar"},{"id":"concepts/task-lists","path":"/docs/concepts/task-lists","sidebar":"docsSidebar"},{"id":"concepts/topology","path":"/docs/concepts/topology","sidebar":"docsSidebar"},{"id":"concepts/workflows","path":"/docs/concepts/workflows"},{"id":"get-started/golang-hello-world","path":"/docs/get-started/golang-hello-world","sidebar":"docsSidebar"},{"id":"get-started/index","path":"/docs/get-started/","sidebar":"docsSidebar"},{"id":"get-started/java-hello-world","path":"/docs/get-started/java-hello-world","sidebar":"docsSidebar"},{"id":"get-started/server-installation","path":"/docs/get-started/server-installation","sidebar":"docsSidebar"},{"id":"get-started/video-tutorials","path":"/docs/get-started/video-tutorials","sidebar":"docsSidebar"},{"id":"glossary","path":"/docs/glossary"},{"id":"go-client/02.5-starting-workflows","path":"/docs/go-client/02.5-starting-workflows","sidebar":"docsSidebar"},{"id":"go-client/activities","path":"/docs/go-client/activities","sidebar":"docsSidebar"},{"id":"go-client/activity-async-completion","path":"/docs/go-client/activity-async-completion","sidebar":"docsSidebar"},{"id":"go-client/child-workflows","path":"/docs/go-client/child-workflows","sidebar":"docsSidebar"},{"id":"go-client/continue-as-new","path":"/docs/go-client/continue-as-new","sidebar":"docsSidebar"},{"id":"go-client/create-workflows","path":"/docs/go-client/create-workflows","sidebar":"docsSidebar"},{"id":"go-client/distributed-cron","path":"/docs/go-client/distributed-cron","sidebar":"docsSidebar"},{"id":"go-client/error-handling","path":"/docs/go-client/error-handling","sidebar":"docsSidebar"},{"id":"go-client/execute-activity","path":"/docs/go-client/execute-activity","sidebar":"docsSidebar"},{"id":"go-client/index","path":"/docs/go-client/","sidebar":"docsSidebar"},{"id":"go-client/queries","path":"/docs/go-client/queries","sidebar":"docsSidebar"},{"id":"go-client/retries","path":"/docs/go-client/retries","sidebar":"docsSidebar"},{"id":"go-client/sessions","path":"/docs/go-client/sessions","sidebar":"docsSidebar"},{"id":"go-client/side-effect","path":"/docs/go-client/side-effect","sidebar":"docsSidebar"},{"id":"go-client/signals","path":"/docs/go-client/signals","sidebar":"docsSidebar"},{"id":"go-client/tracing","path":"/docs/go-client/tracing","sidebar":"docsSidebar"},{"id":"go-client/workers","path":"/docs/go-client/workers","sidebar":"docsSidebar"},{"id":"go-client/workflow-non-deterministic-error","path":"/docs/go-client/workflow-non-deterministic-error"},{"id":"go-client/workflow-replay-shadowing","path":"/docs/go-client/workflow-replay-shadowing","sidebar":"docsSidebar"},{"id":"go-client/workflow-testing","path":"/docs/go-client/workflow-testing","sidebar":"docsSidebar"},{"id":"go-client/workflow-versioning","path":"/docs/go-client/workflow-versioning","sidebar":"docsSidebar"},{"id":"java-client/activity-interface","path":"/docs/java-client/activity-interface","sidebar":"docsSidebar"},{"id":"java-client/child-workflows","path":"/docs/java-client/child-workflows","sidebar":"docsSidebar"},{"id":"java-client/client-overview","path":"/docs/java-client/client-overview","sidebar":"docsSidebar"},{"id":"java-client/continue-as-new","path":"/docs/java-client/continue-as-new","sidebar":"docsSidebar"},{"id":"java-client/distributed-cron","path":"/docs/java-client/distributed-cron","sidebar":"docsSidebar"},{"id":"java-client/exception-handling","path":"/docs/java-client/exception-handling","sidebar":"docsSidebar"},{"id":"java-client/implementing-activities","path":"/docs/java-client/implementing-activities"},{"id":"java-client/implementing-workflows","path":"/docs/java-client/implementing-workflows","sidebar":"docsSidebar"},{"id":"java-client/index","path":"/docs/java-client/","sidebar":"docsSidebar"},{"id":"java-client/queries","path":"/docs/java-client/queries","sidebar":"docsSidebar"},{"id":"java-client/retries","path":"/docs/java-client/retries","sidebar":"docsSidebar"},{"id":"java-client/side-effect","path":"/docs/java-client/side-effect","sidebar":"docsSidebar"},{"id":"java-client/signals","path":"/docs/java-client/signals","sidebar":"docsSidebar"},{"id":"java-client/starting-workflow-executions","path":"/docs/java-client/starting-workflow-executions","sidebar":"docsSidebar"},{"id":"java-client/testing","path":"/docs/java-client/testing","sidebar":"docsSidebar"},{"id":"java-client/versioning","path":"/docs/java-client/versioning","sidebar":"docsSidebar"},{"id":"java-client/workers","path":"/docs/java-client/workers","sidebar":"docsSidebar"},{"id":"java-client/workflow-interface","path":"/docs/java-client/workflow-interface","sidebar":"docsSidebar"},{"id":"java-client/workflow-replay-shadowing","path":"/docs/java-client/workflow-replay-shadowing","sidebar":"docsSidebar"},{"id":"operation-guide/index","path":"/docs/operation-guide/","sidebar":"docsSidebar"},{"id":"operation-guide/maintain","path":"/docs/operation-guide/maintain","sidebar":"docsSidebar"},{"id":"operation-guide/migration","path":"/docs/operation-guide/migration","sidebar":"docsSidebar"},{"id":"operation-guide/monitoring","path":"/docs/operation-guide/monitoring","sidebar":"docsSidebar"},{"id":"operation-guide/setup","path":"/docs/operation-guide/setup","sidebar":"docsSidebar"},{"id":"operation-guide/troubleshooting","path":"/docs/operation-guide/troubleshooting","sidebar":"docsSidebar"},{"id":"use-cases/batch-job","path":"/docs/use-cases/batch-job","sidebar":"docsSidebar"},{"id":"use-cases/big-ml","path":"/docs/use-cases/big-ml","sidebar":"docsSidebar"},{"id":"use-cases/deployment","path":"/docs/use-cases/deployment","sidebar":"docsSidebar"},{"id":"use-cases/dsl","path":"/docs/use-cases/dsl","sidebar":"docsSidebar"},{"id":"use-cases/event-driven","path":"/docs/use-cases/event-driven","sidebar":"docsSidebar"},{"id":"use-cases/index","path":"/docs/use-cases/","sidebar":"docsSidebar"},{"id":"use-cases/interactive","path":"/docs/use-cases/interactive","sidebar":"docsSidebar"},{"id":"use-cases/operational-management","path":"/docs/use-cases/operational-management","sidebar":"docsSidebar"},{"id":"use-cases/orchestration","path":"/docs/use-cases/orchestration","sidebar":"docsSidebar"},{"id":"use-cases/partitioned-scan","path":"/docs/use-cases/partitioned-scan","sidebar":"docsSidebar"},{"id":"use-cases/periodic-execution","path":"/docs/use-cases/periodic-execution","sidebar":"docsSidebar"},{"id":"use-cases/polling","path":"/docs/use-cases/polling","sidebar":"docsSidebar"},{"id":"use-cases/provisioning","path":"/docs/use-cases/provisioning","sidebar":"docsSidebar"},{"id":"workflow-troubleshooting/activity-failures","path":"/docs/workflow-troubleshooting/activity-failures","sidebar":"docsSidebar"},{"id":"workflow-troubleshooting/index","path":"/docs/workflow-troubleshooting/","sidebar":"docsSidebar"},{"id":"workflow-troubleshooting/retries","path":"/docs/workflow-troubleshooting/retries","sidebar":"docsSidebar"},{"id":"workflow-troubleshooting/timeouts","path":"/docs/workflow-troubleshooting/timeouts","sidebar":"docsSidebar"}],"draftIds":[],"sidebars":{"docsSidebar":{"link":{"path":"/docs/get-started/","label":"get-started/index"}}}}],"breadcrumbs":true},"community":{"path":"/community","versions":[{"name":"current","label":"Next","isLast":true,"path":"/community","mainDocId":"support","docs":[{"id":"contributing","path":"/community/contributing"},{"id":"resources","path":"/community/resources"},{"id":"support","path":"/community/support","sidebar":"community"},{"id":"team","path":"/community/team","sidebar":"community"}],"draftIds":[],"sidebars":{"community":{"link":{"path":"/community/support","label":"support"}}}}],"breadcrumbs":true}},"docusaurus-plugin-google-gtag":{"default":{"trackingID":["G-W63QD8QE6E"],"anonymizeIP":true,"id":"default"}},"docusaurus-plugin-google-tag-manager":{"default":{"containerId":"G-W63QD8QE6E","id":"default"}}}'),i=JSON.parse('{"defaultLocale":"en","locales":["en"],"path":"i18n","currentLocale":"en","localeConfigs":{"en":{"label":"English","direction":"ltr","htmlLang":"en","calendar":"gregory","path":"en"}}}');var s=n(2654);const c=JSON.parse('{"docusaurusVersion":"3.6.3","siteVersion":"1.0.0","pluginVersions":{"docusaurus-plugin-content-docs":{"type":"package","name":"@docusaurus/plugin-content-docs","version":"3.6.3"},"docusaurus-plugin-content-blog":{"type":"package","name":"@docusaurus/plugin-content-blog","version":"3.6.3"},"docusaurus-plugin-content-pages":{"type":"package","name":"@docusaurus/plugin-content-pages","version":"3.6.3"},"docusaurus-plugin-google-gtag":{"type":"package","name":"@docusaurus/plugin-google-gtag","version":"3.6.3"},"docusaurus-plugin-google-tag-manager":{"type":"package","name":"@docusaurus/plugin-google-tag-manager","version":"3.6.3"},"docusaurus-plugin-sitemap":{"type":"package","name":"@docusaurus/plugin-sitemap","version":"3.6.3"},"docusaurus-theme-classic":{"type":"package","name":"@docusaurus/theme-classic","version":"3.6.3"},"docusaurus-theme-search-algolia":{"type":"package","name":"@docusaurus/theme-search-algolia","version":"3.6.3"},"changelog-plugin":{"type":"project"},"docusaurus-plugin-client-redirects":{"type":"package","name":"@docusaurus/plugin-client-redirects","version":"3.6.3"}}}');var l=n(4848);const u={siteConfig:o.default,siteMetadata:c,globalData:a,i18n:i,codeTranslations:s},d=r.createContext(u);function p(e){let{children:t}=e;return(0,l.jsx)(d.Provider,{value:u,children:t})}},7489:(e,t,n)=>{"use strict";n.d(t,{A:()=>g});var r=n(6540),o=n(8193),a=n(5260),i=n(440),s=n(1957),c=n(3102),l=n(4848);function u(e){let{error:t,tryAgain:n}=e;return(0,l.jsxs)("div",{style:{display:"flex",flexDirection:"column",justifyContent:"center",alignItems:"flex-start",minHeight:"100vh",width:"100%",maxWidth:"80ch",fontSize:"20px",margin:"0 auto",padding:"1rem"},children:[(0,l.jsx)("h1",{style:{fontSize:"3rem"},children:"This page crashed"}),(0,l.jsx)("button",{type:"button",onClick:n,style:{margin:"1rem 0",fontSize:"2rem",cursor:"pointer",borderRadius:20,padding:"1rem"},children:"Try again"}),(0,l.jsx)(d,{error:t})]})}function d(e){let{error:t}=e;const n=(0,i.rA)(t).map((e=>e.message)).join("\n\nCause:\n");return(0,l.jsx)("p",{style:{whiteSpace:"pre-wrap"},children:n})}function p(e){let{children:t}=e;return(0,l.jsx)(c.W,{value:{plugin:{name:"docusaurus-core-error-boundary",id:"default"}},children:t})}function f(e){let{error:t,tryAgain:n}=e;return(0,l.jsx)(p,{children:(0,l.jsxs)(g,{fallback:()=>(0,l.jsx)(u,{error:t,tryAgain:n}),children:[(0,l.jsx)(a.A,{children:(0,l.jsx)("title",{children:"Page Error"})}),(0,l.jsx)(s.A,{children:(0,l.jsx)(u,{error:t,tryAgain:n})})]})})}const m=e=>(0,l.jsx)(f,{...e});class g extends r.Component{constructor(e){super(e),this.state={error:null}}componentDidCatch(e){o.A.canUseDOM&&this.setState({error:e})}render(){const{children:e}=this.props,{error:t}=this.state;if(t){const e={error:t,tryAgain:()=>this.setState({error:null})};return(this.props.fallback??m)(e)}return e??null}}},8193:(e,t,n)=>{"use strict";n.d(t,{A:()=>o});const r="undefined"!=typeof window&&"document"in window&&"createElement"in window.document,o={canUseDOM:r,canUseEventListeners:r&&("addEventListener"in window||"attachEvent"in window),canUseIntersectionObserver:r&&"IntersectionObserver"in window,canUseViewport:r&&"screen"in window}},5260:(e,t,n)=>{"use strict";n.d(t,{A:()=>a});n(6540);var r=n(545),o=n(4848);function a(e){return(0,o.jsx)(r.mg,{...e})}},8774:(e,t,n)=>{"use strict";n.d(t,{A:()=>f});var r=n(6540),o=n(4625),a=n(440),i=n(4586),s=n(6654),c=n(8193),l=n(3427),u=n(6025),d=n(4848);function p(e,t){let{isNavLink:n,to:p,href:f,activeClassName:m,isActive:g,"data-noBrokenLinkCheck":h,autoAddBaseUrl:b=!0,...y}=e;const{siteConfig:v}=(0,i.A)(),{trailingSlash:w,baseUrl:S}=v,k=v.future.experimental_router,{withBaseUrl:x}=(0,u.hH)(),_=(0,l.A)(),E=(0,r.useRef)(null);(0,r.useImperativeHandle)(t,(()=>E.current));const j=p||f;const O=(0,s.A)(j),A=j?.replace("pathname://","");let C=void 0!==A?(T=A,b&&(e=>e.startsWith("/"))(T)?x(T):T):void 0;var T;"hash"===k&&C?.startsWith("./")&&(C=C?.slice(1)),C&&O&&(C=(0,a.Ks)(C,{trailingSlash:w,baseUrl:S}));const P=(0,r.useRef)(!1),I=n?o.k2:o.N_,N=c.A.canUseIntersectionObserver,R=(0,r.useRef)(),L=()=>{P.current||null==C||(window.docusaurus.preload(C),P.current=!0)};(0,r.useEffect)((()=>(!N&&O&&c.A.canUseDOM&&null!=C&&window.docusaurus.prefetch(C),()=>{N&&R.current&&R.current.disconnect()})),[R,C,N,O]);const D=C?.startsWith("#")??!1,M=!y.target||"_self"===y.target,F=!C||!O||!M||D&&"hash"!==k;h||!D&&F||_.collectLink(C),y.id&&_.collectAnchor(y.id);const B={};return F?(0,d.jsx)("a",{ref:E,href:C,...j&&!O&&{target:"_blank",rel:"noopener noreferrer"},...y,...B}):(0,d.jsx)(I,{...y,onMouseEnter:L,onTouchStart:L,innerRef:e=>{E.current=e,N&&e&&O&&(R.current=new window.IntersectionObserver((t=>{t.forEach((t=>{e===t.target&&(t.isIntersecting||t.intersectionRatio>0)&&(R.current.unobserve(e),R.current.disconnect(),null!=C&&window.docusaurus.prefetch(C))}))})),R.current.observe(e))},to:C,...n&&{isActive:g,activeClassName:m},...B})}const f=r.forwardRef(p)},1312:(e,t,n)=>{"use strict";n.d(t,{A:()=>l,T:()=>c});var r=n(6540),o=n(4848);function a(e,t){const n=e.split(/(\{\w+\})/).map(((e,n)=>{if(n%2==1){const n=t?.[e.slice(1,-1)];if(void 0!==n)return n}return e}));return n.some((e=>(0,r.isValidElement)(e)))?n.map(((e,t)=>(0,r.isValidElement)(e)?r.cloneElement(e,{key:t}):e)).filter((e=>""!==e)):n.join("")}var i=n(2654);function s(e){let{id:t,message:n}=e;if(void 0===t&&void 0===n)throw new Error("Docusaurus translation declarations must have at least a translation id or a default translation message");return i[t??n]??n??t}function c(e,t){let{message:n,id:r}=e;return a(s({message:n,id:r}),t)}function l(e){let{children:t,id:n,values:r}=e;if(t&&"string"!=typeof t)throw console.warn("Illegal <Translate> children",t),new Error("The Docusaurus <Translate> component only accept simple string values");const i=s({message:t,id:n});return(0,o.jsx)(o.Fragment,{children:a(i,r)})}},7065:(e,t,n)=>{"use strict";n.d(t,{W:()=>r});const r="default"},6654:(e,t,n)=>{"use strict";function r(e){return/^(?:\w*:|\/\/)/.test(e)}function o(e){return void 0!==e&&!r(e)}n.d(t,{A:()=>o,z:()=>r})},6025:(e,t,n)=>{"use strict";n.d(t,{Ay:()=>s,hH:()=>i});var r=n(6540),o=n(4586),a=n(6654);function i(){const{siteConfig:e}=(0,o.A)(),{baseUrl:t,url:n}=e,i=e.future.experimental_router,s=(0,r.useCallback)(((e,r)=>function(e){let{siteUrl:t,baseUrl:n,url:r,options:{forcePrependBaseUrl:o=!1,absolute:i=!1}={},router:s}=e;if(!r||r.startsWith("#")||(0,a.z)(r))return r;if("hash"===s)return r.startsWith("/")?`.${r}`:`./${r}`;if(o)return n+r.replace(/^\//,"");if(r===n.replace(/\/$/,""))return n;const c=r.startsWith(n)?r:n+r.replace(/^\//,"");return i?t+c:c}({siteUrl:n,baseUrl:t,url:e,options:r,router:i})),[n,t,i]);return{withBaseUrl:s}}function s(e,t){void 0===t&&(t={});const{withBaseUrl:n}=i();return n(e,t)}},3427:(e,t,n)=>{"use strict";n.d(t,{A:()=>i});var r=n(6540);n(4848);const o=r.createContext({collectAnchor:()=>{},collectLink:()=>{}}),a=()=>(0,r.useContext)(o);function i(){return a()}},4586:(e,t,n)=>{"use strict";n.d(t,{A:()=>a});var r=n(6540),o=n(6988);function a(){return(0,r.useContext)(o.o)}},2303:(e,t,n)=>{"use strict";n.d(t,{A:()=>a});var r=n(6540),o=n(6125);function a(){return(0,r.useContext)(o.o)}},205:(e,t,n)=>{"use strict";n.d(t,{A:()=>o});var r=n(6540);const o=n(8193).A.canUseDOM?r.useLayoutEffect:r.useEffect},6803:(e,t,n)=>{"use strict";n.d(t,{A:()=>a});var r=n(6540),o=n(3102);function a(){const e=r.useContext(o.o);if(!e)throw new Error("Unexpected: no Docusaurus route context found");return e}},6921:(e,t,n)=>{"use strict";n.d(t,{A:()=>o});const r=e=>"object"==typeof e&&!!e&&Object.keys(e).length>0;function o(e){const t={};return function e(n,o){Object.entries(n).forEach((n=>{let[a,i]=n;const s=o?`${o}.${a}`:a;r(i)?e(i,s):t[s]=i}))}(e),t}},3102:(e,t,n)=>{"use strict";n.d(t,{W:()=>i,o:()=>a});var r=n(6540),o=n(4848);const a=r.createContext(null);function i(e){let{children:t,value:n}=e;const i=r.useContext(a),s=(0,r.useMemo)((()=>function(e){let{parent:t,value:n}=e;if(!t){if(!n)throw new Error("Unexpected: no Docusaurus route context found");if(!("plugin"in n))throw new Error("Unexpected: Docusaurus topmost route context has no `plugin` attribute");return n}const r={...t.data,...n?.data};return{plugin:t.plugin,data:r}}({parent:i,value:n})),[i,n]);return(0,o.jsx)(a.Provider,{value:s,children:t})}},3886:(e,t,n)=>{"use strict";n.d(t,{VQ:()=>h,XK:()=>v,g1:()=>y});var r=n(6540),o=n(4070),a=n(7065),i=n(6342),s=n(679),c=n(9532),l=n(4848);const u=e=>`docs-preferred-version-${e}`,d={save:(e,t,n)=>{(0,s.Wf)(u(e),{persistence:t}).set(n)},read:(e,t)=>(0,s.Wf)(u(e),{persistence:t}).get(),clear:(e,t)=>{(0,s.Wf)(u(e),{persistence:t}).del()}},p=e=>Object.fromEntries(e.map((e=>[e,{preferredVersionName:null}])));const f=r.createContext(null);function m(){const e=(0,o.Gy)(),t=(0,i.p)().docs.versionPersistence,n=(0,r.useMemo)((()=>Object.keys(e)),[e]),[a,s]=(0,r.useState)((()=>p(n)));(0,r.useEffect)((()=>{s(function(e){let{pluginIds:t,versionPersistence:n,allDocsData:r}=e;function o(e){const t=d.read(e,n);return r[e].versions.some((e=>e.name===t))?{preferredVersionName:t}:(d.clear(e,n),{preferredVersionName:null})}return Object.fromEntries(t.map((e=>[e,o(e)])))}({allDocsData:e,versionPersistence:t,pluginIds:n}))}),[e,t,n]);return[a,(0,r.useMemo)((()=>({savePreferredVersion:function(e,n){d.save(e,t,n),s((t=>({...t,[e]:{preferredVersionName:n}})))}})),[t])]}function g(e){let{children:t}=e;const n=m();return(0,l.jsx)(f.Provider,{value:n,children:t})}function h(e){let{children:t}=e;return(0,l.jsx)(g,{children:t})}function b(){const e=(0,r.useContext)(f);if(!e)throw new c.dV("DocsPreferredVersionContextProvider");return e}function y(e){void 0===e&&(e=a.W);const t=(0,o.ht)(e),[n,i]=b(),{preferredVersionName:s}=n[e];return{preferredVersion:t.versions.find((e=>e.name===s))??null,savePreferredVersionName:(0,r.useCallback)((t=>{i.savePreferredVersion(e,t)}),[i,e])}}function v(){const e=(0,o.Gy)(),[t]=b();function n(n){const r=e[n],{preferredVersionName:o}=t[n];return r.versions.find((e=>e.name===o))??null}const r=Object.keys(e);return Object.fromEntries(r.map((e=>[e,n(e)])))}},2565:(e,t,n)=>{"use strict";n.d(t,{k:()=>a,v:()=>i});var r=n(4070),o=n(3886);function a(e,t){return`docs-${e}-${t}`}function i(){const e=(0,r.Gy)(),t=(0,r.gk)(),n=(0,o.XK)();return[...Object.keys(e).map((function(r){const o=t?.activePlugin.pluginId===r?t.activeVersion:void 0,i=n[r],s=e[r].versions.find((e=>e.isLast));return a(r,(o??i??s).name)}))]}},609:(e,t,n)=>{"use strict";n.d(t,{V:()=>c,t:()=>l});var r=n(6540),o=n(9532),a=n(4848);const i=Symbol("EmptyContext"),s=r.createContext(i);function c(e){let{children:t,name:n,items:o}=e;const i=(0,r.useMemo)((()=>n&&o?{name:n,items:o}:null),[n,o]);return(0,a.jsx)(s.Provider,{value:i,children:t})}function l(){const e=(0,r.useContext)(s);if(e===i)throw new o.dV("DocsSidebarProvider");return e}},6972:(e,t,n)=>{"use strict";n.d(t,{B5:()=>x,Nr:()=>p,OF:()=>v,QB:()=>k,Vd:()=>w,Y:()=>b,fW:()=>S,w8:()=>g});var r=n(6540),o=n(6347),a=n(2831),i=n(4070),s=n(9169),c=n(1682),l=n(3886),u=n(3025),d=n(609);function p(e){return"link"!==e.type||e.unlisted?"category"===e.type?function(e){if(e.href&&!e.linkUnlisted)return e.href;for(const t of e.items){const e=p(t);if(e)return e}}(e):void 0:e.href}const f=(e,t)=>void 0!==e&&(0,s.ys)(e,t),m=(e,t)=>e.some((e=>g(e,t)));function g(e,t){return"link"===e.type?f(e.href,t):"category"===e.type&&(f(e.href,t)||m(e.items,t))}function h(e,t){switch(e.type){case"category":return g(e,t)||e.items.some((e=>h(e,t)));case"link":return!e.unlisted||g(e,t);default:return!0}}function b(e,t){return(0,r.useMemo)((()=>e.filter((e=>h(e,t)))),[e,t])}function y(e){let{sidebarItems:t,pathname:n,onlyCategories:r=!1}=e;const o=[];return function e(t){for(const a of t)if("category"===a.type&&((0,s.ys)(a.href,n)||e(a.items))||"link"===a.type&&(0,s.ys)(a.href,n)){return r&&"category"!==a.type||o.unshift(a),!0}return!1}(t),o}function v(){const e=(0,d.t)(),{pathname:t}=(0,o.zy)(),n=(0,i.vT)()?.pluginData.breadcrumbs;return!1!==n&&e?y({sidebarItems:e.items,pathname:t}):null}function w(e){const{activeVersion:t}=(0,i.zK)(e),{preferredVersion:n}=(0,l.g1)(e),o=(0,i.r7)(e);return(0,r.useMemo)((()=>(0,c.sb)([t,n,o].filter(Boolean))),[t,n,o])}function S(e,t){const n=w(t);return(0,r.useMemo)((()=>{const t=n.flatMap((e=>e.sidebars?Object.entries(e.sidebars):[])),r=t.find((t=>t[0]===e));if(!r)throw new Error(`Can't find any sidebar with id "${e}" in version${n.length>1?"s":""} ${n.map((e=>e.name)).join(", ")}".\nAvailable sidebar ids are:\n- ${t.map((e=>e[0])).join("\n- ")}`);return r[1]}),[e,n])}function k(e,t){const n=w(t);return(0,r.useMemo)((()=>{const t=n.flatMap((e=>e.docs)),r=t.find((t=>t.id===e));if(!r){if(n.flatMap((e=>e.draftIds)).includes(e))return null;throw new Error(`Couldn't find any doc with id "${e}" in version${n.length>1?"s":""} "${n.map((e=>e.name)).join(", ")}".\nAvailable doc ids are:\n- ${(0,c.sb)(t.map((e=>e.id))).join("\n- ")}`)}return r}),[e,n])}function x(e){let{route:t}=e;const n=(0,o.zy)(),r=(0,u.r)(),i=t.routes,s=i.find((e=>(0,o.B6)(n.pathname,e)));if(!s)return null;const c=s.sidebar,l=c?r.docsSidebars[c]:void 0;return{docElement:(0,a.v)(i),sidebarName:c,sidebarItems:l}}},3025:(e,t,n)=>{"use strict";n.d(t,{n:()=>s,r:()=>c});var r=n(6540),o=n(9532),a=n(4848);const i=r.createContext(null);function s(e){let{children:t,version:n}=e;return(0,a.jsx)(i.Provider,{value:n,children:t})}function c(){const e=(0,r.useContext)(i);if(null===e)throw new o.dV("DocsVersionProvider");return e}},4070:(e,t,n)=>{"use strict";n.d(t,{zK:()=>b,vT:()=>f,gk:()=>m,Gy:()=>d,HW:()=>y,ht:()=>p,r7:()=>h,jh:()=>g});var r=n(6347),o=n(4586),a=n(7065);function i(e,t){void 0===t&&(t={});const n=function(){const{globalData:e}=(0,o.A)();return e}()[e];if(!n&&t.failfast)throw new Error(`Docusaurus plugin global data not found for "${e}" plugin.`);return n}const s=e=>e.versions.find((e=>e.isLast));function c(e,t){return[...e.versions].sort(((e,t)=>e.path===t.path?0:e.path.includes(t.path)?-1:t.path.includes(e.path)?1:0)).find((e=>!!(0,r.B6)(t,{path:e.path,exact:!1,strict:!1})))}function l(e,t){const n=c(e,t),o=n?.docs.find((e=>!!(0,r.B6)(t,{path:e.path,exact:!0,strict:!1})));return{activeVersion:n,activeDoc:o,alternateDocVersions:o?function(t){const n={};return e.versions.forEach((e=>{e.docs.forEach((r=>{r.id===t&&(n[e.name]=r)}))})),n}(o.id):{}}}const u={},d=()=>i("docusaurus-plugin-content-docs")??u,p=e=>{try{return function(e,t,n){void 0===t&&(t=a.W),void 0===n&&(n={});const r=i(e),o=r?.[t];if(!o&&n.failfast)throw new Error(`Docusaurus plugin global data not found for "${e}" plugin with id "${t}".`);return o}("docusaurus-plugin-content-docs",e,{failfast:!0})}catch(t){throw new Error("You are using a feature of the Docusaurus docs plugin, but this plugin does not seem to be enabled"+("Default"===e?"":` (pluginId=${e}`),{cause:t})}};function f(e){void 0===e&&(e={});const t=d(),{pathname:n}=(0,r.zy)();return function(e,t,n){void 0===n&&(n={});const o=Object.entries(e).sort(((e,t)=>t[1].path.localeCompare(e[1].path))).find((e=>{let[,n]=e;return!!(0,r.B6)(t,{path:n.path,exact:!1,strict:!1})})),a=o?{pluginId:o[0],pluginData:o[1]}:void 0;if(!a&&n.failfast)throw new Error(`Can't find active docs plugin for "${t}" pathname, while it was expected to be found. Maybe you tried to use a docs feature that can only be used on a docs-related page? Existing docs plugin paths are: ${Object.values(e).map((e=>e.path)).join(", ")}`);return a}(t,n,e)}function m(e){void 0===e&&(e={});const t=f(e),{pathname:n}=(0,r.zy)();if(!t)return;return{activePlugin:t,activeVersion:c(t.pluginData,n)}}function g(e){return p(e).versions}function h(e){const t=p(e);return s(t)}function b(e){const t=p(e),{pathname:n}=(0,r.zy)();return l(t,n)}function y(e){const t=p(e),{pathname:n}=(0,r.zy)();return function(e,t){const n=s(e);return{latestDocSuggestion:l(e,t).alternateDocVersions[n.name],latestVersionSuggestion:n}}(t,n)}},1911:(e,t,n)=>{"use strict";n.r(t),n.d(t,{default:()=>r});const r={onRouteDidUpdate(e){let{location:t,previousLocation:n}=e;!n||t.pathname===n.pathname&&t.search===n.search&&t.hash===n.hash||setTimeout((()=>{window.gtag("set","page_path",t.pathname+t.search+t.hash),window.gtag("event","page_view")}))}}},6294:(e,t,n)=>{"use strict";n.r(t),n.d(t,{default:()=>a});var r=n(5947),o=n.n(r);o().configure({showSpinner:!1});const a={onRouteUpdate(e){let{location:t,previousLocation:n}=e;if(n&&t.pathname!==n.pathname){const e=window.setTimeout((()=>{o().start()}),200);return()=>window.clearTimeout(e)}},onRouteDidUpdate(){o().done()}}},6491:(e,t,n)=>{"use strict";var r=n(1765),o=n(4784);!function(e){const{themeConfig:{prism:t}}=o.default,{additionalLanguages:r}=t,a=globalThis.Prism;globalThis.Prism=e,r.forEach((e=>{"php"===e&&n(9700),n(803)(`./prism-${e}`)})),n(7712),delete globalThis.Prism,void 0!==a&&(globalThis.Prism=e)}(r.My)},1107:(e,t,n)=>{"use strict";n.d(t,{A:()=>u});n(6540);var r=n(4164),o=n(1312),a=n(6342),i=n(8774),s=n(3427);const c={anchorWithStickyNavbar:"anchorWithStickyNavbar_LWe7",anchorWithHideOnScrollNavbar:"anchorWithHideOnScrollNavbar_WYt5"};var l=n(4848);function u(e){let{as:t,id:n,...u}=e;const d=(0,s.A)(),{navbar:{hideOnScroll:p}}=(0,a.p)();if("h1"===t||!n)return(0,l.jsx)(t,{...u,id:void 0});d.collectAnchor(n);const f=(0,o.T)({id:"theme.common.headingLinkTitle",message:"Direct link to {heading}",description:"Title for link to heading"},{heading:"string"==typeof u.children?u.children:n});return(0,l.jsxs)(t,{...u,className:(0,r.A)("anchor",p?c.anchorWithHideOnScrollNavbar:c.anchorWithStickyNavbar,u.className),id:n,children:[u.children,(0,l.jsx)(i.A,{className:"hash-link",to:`#${n}`,"aria-label":f,title:f,children:"\u200b"})]})}},3186:(e,t,n)=>{"use strict";n.d(t,{A:()=>a});n(6540);const r={iconExternalLink:"iconExternalLink_nPIU"};var o=n(4848);function a(e){let{width:t=13.5,height:n=13.5}=e;return(0,o.jsx)("svg",{width:t,height:n,"aria-hidden":"true",viewBox:"0 0 24 24",className:r.iconExternalLink,children:(0,o.jsx)("path",{fill:"currentColor",d:"M21 13v10h-21v-19h12v2h-10v15h17v-8h2zm3-12h-10.988l4.035 4-6.977 7.07 2.828 2.828 6.977-7.07 4.125 4.172v-11z"})})}},1957:(e,t,n)=>{"use strict";n.d(t,{A:()=>jt});var r=n(6540),o=n(4164),a=n(7489),i=n(5500),s=n(6347),c=n(1312),l=n(5062),u=n(4848);const d="__docusaurus_skipToContent_fallback";function p(e){e.setAttribute("tabindex","-1"),e.focus(),e.removeAttribute("tabindex")}function f(){const e=(0,r.useRef)(null),{action:t}=(0,s.W6)(),n=(0,r.useCallback)((e=>{e.preventDefault();const t=document.querySelector("main:first-of-type")??document.getElementById(d);t&&p(t)}),[]);return(0,l.$)((n=>{let{location:r}=n;e.current&&!r.hash&&"PUSH"===t&&p(e.current)})),{containerRef:e,onClick:n}}const m=(0,c.T)({id:"theme.common.skipToMainContent",description:"The skip to content label used for accessibility, allowing to rapidly navigate to main content with keyboard tab/enter navigation",message:"Skip to main content"});function g(e){const t=e.children??m,{containerRef:n,onClick:r}=f();return(0,u.jsx)("div",{ref:n,role:"region","aria-label":m,children:(0,u.jsx)("a",{...e,href:`#${d}`,onClick:r,children:t})})}var h=n(7559),b=n(4090);const y={skipToContent:"skipToContent_fXgn"};function v(){return(0,u.jsx)(g,{className:y.skipToContent})}var w=n(6342),S=n(5041);function k(e){let{width:t=21,height:n=21,color:r="currentColor",strokeWidth:o=1.2,className:a,...i}=e;return(0,u.jsx)("svg",{viewBox:"0 0 15 15",width:t,height:n,...i,children:(0,u.jsx)("g",{stroke:r,strokeWidth:o,children:(0,u.jsx)("path",{d:"M.75.75l13.5 13.5M14.25.75L.75 14.25"})})})}const x={closeButton:"closeButton_CVFx"};function _(e){return(0,u.jsx)("button",{type:"button","aria-label":(0,c.T)({id:"theme.AnnouncementBar.closeButtonAriaLabel",message:"Close",description:"The ARIA label for close button of announcement bar"}),...e,className:(0,o.A)("clean-btn close",x.closeButton,e.className),children:(0,u.jsx)(k,{width:14,height:14,strokeWidth:3.1})})}const E={content:"content_knG7"};function j(e){const{announcementBar:t}=(0,w.p)(),{content:n}=t;return(0,u.jsx)("div",{...e,className:(0,o.A)(E.content,e.className),dangerouslySetInnerHTML:{__html:n}})}const O={announcementBar:"announcementBar_mb4j",announcementBarPlaceholder:"announcementBarPlaceholder_vyr4",announcementBarClose:"announcementBarClose_gvF7",announcementBarContent:"announcementBarContent_xLdY"};function A(){const{announcementBar:e}=(0,w.p)(),{isActive:t,close:n}=(0,S.M)();if(!t)return null;const{backgroundColor:r,textColor:o,isCloseable:a}=e;return(0,u.jsxs)("div",{className:O.announcementBar,style:{backgroundColor:r,color:o},role:"banner",children:[a&&(0,u.jsx)("div",{className:O.announcementBarPlaceholder}),(0,u.jsx)(j,{className:O.announcementBarContent}),a&&(0,u.jsx)(_,{onClick:n,className:O.announcementBarClose})]})}var C=n(2069),T=n(3104);var P=n(9532),I=n(5600);const N=r.createContext(null);function R(e){let{children:t}=e;const n=function(){const e=(0,C.M)(),t=(0,I.YL)(),[n,o]=(0,r.useState)(!1),a=null!==t.component,i=(0,P.ZC)(a);return(0,r.useEffect)((()=>{a&&!i&&o(!0)}),[a,i]),(0,r.useEffect)((()=>{a?e.shown||o(!0):o(!1)}),[e.shown,a]),(0,r.useMemo)((()=>[n,o]),[n])}();return(0,u.jsx)(N.Provider,{value:n,children:t})}function L(e){if(e.component){const t=e.component;return(0,u.jsx)(t,{...e.props})}}function D(){const e=(0,r.useContext)(N);if(!e)throw new P.dV("NavbarSecondaryMenuDisplayProvider");const[t,n]=e,o=(0,r.useCallback)((()=>n(!1)),[n]),a=(0,I.YL)();return(0,r.useMemo)((()=>({shown:t,hide:o,content:L(a)})),[o,a,t])}function M(e){let{header:t,primaryMenu:n,secondaryMenu:r}=e;const{shown:a}=D();return(0,u.jsxs)("div",{className:"navbar-sidebar",children:[t,(0,u.jsxs)("div",{className:(0,o.A)("navbar-sidebar__items",{"navbar-sidebar__items--show-secondary":a}),children:[(0,u.jsx)("div",{className:"navbar-sidebar__item menu",children:n}),(0,u.jsx)("div",{className:"navbar-sidebar__item menu",children:r})]})]})}var F=n(5293),B=n(2303);function z(e){return(0,u.jsx)("svg",{viewBox:"0 0 24 24",width:24,height:24,...e,children:(0,u.jsx)("path",{fill:"currentColor",d:"M12,9c1.65,0,3,1.35,3,3s-1.35,3-3,3s-3-1.35-3-3S10.35,9,12,9 M12,7c-2.76,0-5,2.24-5,5s2.24,5,5,5s5-2.24,5-5 S14.76,7,12,7L12,7z M2,13l2,0c0.55,0,1-0.45,1-1s-0.45-1-1-1l-2,0c-0.55,0-1,0.45-1,1S1.45,13,2,13z M20,13l2,0c0.55,0,1-0.45,1-1 s-0.45-1-1-1l-2,0c-0.55,0-1,0.45-1,1S19.45,13,20,13z M11,2v2c0,0.55,0.45,1,1,1s1-0.45,1-1V2c0-0.55-0.45-1-1-1S11,1.45,11,2z M11,20v2c0,0.55,0.45,1,1,1s1-0.45,1-1v-2c0-0.55-0.45-1-1-1C11.45,19,11,19.45,11,20z M5.99,4.58c-0.39-0.39-1.03-0.39-1.41,0 c-0.39,0.39-0.39,1.03,0,1.41l1.06,1.06c0.39,0.39,1.03,0.39,1.41,0s0.39-1.03,0-1.41L5.99,4.58z M18.36,16.95 c-0.39-0.39-1.03-0.39-1.41,0c-0.39,0.39-0.39,1.03,0,1.41l1.06,1.06c0.39,0.39,1.03,0.39,1.41,0c0.39-0.39,0.39-1.03,0-1.41 L18.36,16.95z M19.42,5.99c0.39-0.39,0.39-1.03,0-1.41c-0.39-0.39-1.03-0.39-1.41,0l-1.06,1.06c-0.39,0.39-0.39,1.03,0,1.41 s1.03,0.39,1.41,0L19.42,5.99z M7.05,18.36c0.39-0.39,0.39-1.03,0-1.41c-0.39-0.39-1.03-0.39-1.41,0l-1.06,1.06 c-0.39,0.39-0.39,1.03,0,1.41s1.03,0.39,1.41,0L7.05,18.36z"})})}function $(e){return(0,u.jsx)("svg",{viewBox:"0 0 24 24",width:24,height:24,...e,children:(0,u.jsx)("path",{fill:"currentColor",d:"M9.37,5.51C9.19,6.15,9.1,6.82,9.1,7.5c0,4.08,3.32,7.4,7.4,7.4c0.68,0,1.35-0.09,1.99-0.27C17.45,17.19,14.93,19,12,19 c-3.86,0-7-3.14-7-7C5,9.07,6.81,6.55,9.37,5.51z M12,3c-4.97,0-9,4.03-9,9s4.03,9,9,9s9-4.03,9-9c0-0.46-0.04-0.92-0.1-1.36 c-0.98,1.37-2.58,2.26-4.4,2.26c-2.98,0-5.4-2.42-5.4-5.4c0-1.81,0.89-3.42,2.26-4.4C12.92,3.04,12.46,3,12,3L12,3z"})})}const U={toggle:"toggle_vylO",toggleButton:"toggleButton_gllP",darkToggleIcon:"darkToggleIcon_wfgR",lightToggleIcon:"lightToggleIcon_pyhR",toggleButtonDisabled:"toggleButtonDisabled_aARS"};function H(e){let{className:t,buttonClassName:n,value:r,onChange:a}=e;const i=(0,B.A)(),s=(0,c.T)({message:"Switch between dark and light mode (currently {mode})",id:"theme.colorToggle.ariaLabel",description:"The ARIA label for the navbar color mode toggle"},{mode:"dark"===r?(0,c.T)({message:"dark mode",id:"theme.colorToggle.ariaLabel.mode.dark",description:"The name for the dark color mode"}):(0,c.T)({message:"light mode",id:"theme.colorToggle.ariaLabel.mode.light",description:"The name for the light color mode"})});return(0,u.jsx)("div",{className:(0,o.A)(U.toggle,t),children:(0,u.jsxs)("button",{className:(0,o.A)("clean-btn",U.toggleButton,!i&&U.toggleButtonDisabled,n),type:"button",onClick:()=>a("dark"===r?"light":"dark"),disabled:!i,title:s,"aria-label":s,"aria-live":"polite","aria-pressed":"dark"===r?"true":"false",children:[(0,u.jsx)(z,{className:(0,o.A)(U.toggleIcon,U.lightToggleIcon)}),(0,u.jsx)($,{className:(0,o.A)(U.toggleIcon,U.darkToggleIcon)})]})})}const q=r.memo(H),V={darkNavbarColorModeToggle:"darkNavbarColorModeToggle_X3D1"};function W(e){let{className:t}=e;const n=(0,w.p)().navbar.style,r=(0,w.p)().colorMode.disableSwitch,{colorMode:o,setColorMode:a}=(0,F.G)();return r?null:(0,u.jsx)(q,{className:t,buttonClassName:"dark"===n?V.darkNavbarColorModeToggle:void 0,value:o,onChange:a})}var G=n(3465);function K(){return(0,u.jsx)(G.A,{className:"navbar__brand",imageClassName:"navbar__logo",titleClassName:"navbar__title text--truncate"})}function Y(){const e=(0,C.M)();return(0,u.jsx)("button",{type:"button","aria-label":(0,c.T)({id:"theme.docs.sidebar.closeSidebarButtonAriaLabel",message:"Close navigation bar",description:"The ARIA label for close button of mobile sidebar"}),className:"clean-btn navbar-sidebar__close",onClick:()=>e.toggle(),children:(0,u.jsx)(k,{color:"var(--ifm-color-emphasis-600)"})})}function Q(){return(0,u.jsxs)("div",{className:"navbar-sidebar__brand",children:[(0,u.jsx)(K,{}),(0,u.jsx)(W,{className:"margin-right--md"}),(0,u.jsx)(Y,{})]})}var Z=n(8774),X=n(6025),J=n(6654),ee=n(1252),te=n(3186);function ne(e){let{activeBasePath:t,activeBaseRegex:n,to:r,href:o,label:a,html:i,isDropdownLink:s,prependBaseUrlToHref:c,...l}=e;const d=(0,X.Ay)(r),p=(0,X.Ay)(t),f=(0,X.Ay)(o,{forcePrependBaseUrl:!0}),m=a&&o&&!(0,J.A)(o),g=i?{dangerouslySetInnerHTML:{__html:i}}:{children:(0,u.jsxs)(u.Fragment,{children:[a,m&&(0,u.jsx)(te.A,{...s&&{width:12,height:12}})]})};return o?(0,u.jsx)(Z.A,{href:c?f:o,...l,...g}):(0,u.jsx)(Z.A,{to:d,isNavLink:!0,...(t||n)&&{isActive:(e,t)=>n?(0,ee.G)(n,t.pathname):t.pathname.startsWith(p)},...l,...g})}function re(e){let{className:t,isDropdownItem:n=!1,...r}=e;const a=(0,u.jsx)(ne,{className:(0,o.A)(n?"dropdown__link":"navbar__item navbar__link",t),isDropdownLink:n,...r});return n?(0,u.jsx)("li",{children:a}):a}function oe(e){let{className:t,isDropdownItem:n,...r}=e;return(0,u.jsx)("li",{className:"menu__list-item",children:(0,u.jsx)(ne,{className:(0,o.A)("menu__link",t),...r})})}function ae(e){let{mobile:t=!1,position:n,...r}=e;const o=t?oe:re;return(0,u.jsx)(o,{...r,activeClassName:r.activeClassName??(t?"menu__link--active":"navbar__link--active")})}var ie=n(1422),se=n(9169),ce=n(4586);const le="dropdownNavbarItemMobile_S0Fm";function ue(e,t){return e.some((e=>function(e,t){return!!(0,se.ys)(e.to,t)||!!(0,ee.G)(e.activeBaseRegex,t)||!(!e.activeBasePath||!t.startsWith(e.activeBasePath))}(e,t)))}function de(e){let{items:t,position:n,className:a,onClick:i,...s}=e;const c=(0,r.useRef)(null),[l,d]=(0,r.useState)(!1);return(0,r.useEffect)((()=>{const e=e=>{c.current&&!c.current.contains(e.target)&&d(!1)};return document.addEventListener("mousedown",e),document.addEventListener("touchstart",e),document.addEventListener("focusin",e),()=>{document.removeEventListener("mousedown",e),document.removeEventListener("touchstart",e),document.removeEventListener("focusin",e)}}),[c]),(0,u.jsxs)("div",{ref:c,className:(0,o.A)("navbar__item","dropdown","dropdown--hoverable",{"dropdown--right":"right"===n,"dropdown--show":l}),children:[(0,u.jsx)(ne,{"aria-haspopup":"true","aria-expanded":l,role:"button",href:s.to?void 0:"#",className:(0,o.A)("navbar__link",a),...s,onClick:s.to?void 0:e=>e.preventDefault(),onKeyDown:e=>{"Enter"===e.key&&(e.preventDefault(),d(!l))},children:s.children??s.label}),(0,u.jsx)("ul",{className:"dropdown__menu",children:t.map(((e,t)=>(0,r.createElement)(Fe,{isDropdownItem:!0,activeClassName:"dropdown__link--active",...e,key:t})))})]})}function pe(e){let{items:t,className:n,position:a,onClick:i,...c}=e;const l=function(){const{siteConfig:{baseUrl:e}}=(0,ce.A)(),{pathname:t}=(0,s.zy)();return t.replace(e,"/")}(),d=ue(t,l),{collapsed:p,toggleCollapsed:f,setCollapsed:m}=(0,ie.u)({initialState:()=>!d});return(0,r.useEffect)((()=>{d&&m(!d)}),[l,d,m]),(0,u.jsxs)("li",{className:(0,o.A)("menu__list-item",{"menu__list-item--collapsed":p}),children:[(0,u.jsx)(ne,{role:"button",className:(0,o.A)(le,"menu__link menu__link--sublist menu__link--sublist-caret",n),...c,onClick:e=>{e.preventDefault(),f()},children:c.children??c.label}),(0,u.jsx)(ie.N,{lazy:!0,as:"ul",className:"menu__list",collapsed:p,children:t.map(((e,t)=>(0,r.createElement)(Fe,{mobile:!0,isDropdownItem:!0,onClick:i,activeClassName:"menu__link--active",...e,key:t})))})]})}function fe(e){let{mobile:t=!1,...n}=e;const r=t?pe:de;return(0,u.jsx)(r,{...n})}var me=n(2131);function ge(e){let{width:t=20,height:n=20,...r}=e;return(0,u.jsx)("svg",{viewBox:"0 0 24 24",width:t,height:n,"aria-hidden":!0,...r,children:(0,u.jsx)("path",{fill:"currentColor",d:"M12.87 15.07l-2.54-2.51.03-.03c1.74-1.94 2.98-4.17 3.71-6.53H17V4h-7V2H8v2H1v1.99h11.17C11.5 7.92 10.44 9.75 9 11.35 8.07 10.32 7.3 9.19 6.69 8h-2c.73 1.63 1.73 3.17 2.98 4.56l-5.09 5.02L4 19l5-5 3.11 3.11.76-2.04zM18.5 10h-2L12 22h2l1.12-3h4.75L21 22h2l-4.5-12zm-2.62 7l1.62-4.33L19.12 17h-3.24z"})})}const he="iconLanguage_nlXk";var be=n(961),ye=n(3219),ve=n(5260),we=n(4255),Se=n(1062),ke=n(2967),xe=n(2565);function _e(){return[`language:${(0,ce.A)().i18n.currentLocale}`,function(){const e=(0,xe.v)();return[ke.C,...e]}().map((e=>`docusaurus_tag:${e}`))]}const Ee={button:{buttonText:(0,c.T)({id:"theme.SearchBar.label",message:"Search",description:"The ARIA label and placeholder for search button"}),buttonAriaLabel:(0,c.T)({id:"theme.SearchBar.label",message:"Search",description:"The ARIA label and placeholder for search button"})},modal:{searchBox:{resetButtonTitle:(0,c.T)({id:"theme.SearchModal.searchBox.resetButtonTitle",message:"Clear the query",description:"The label and ARIA label for search box reset button"}),resetButtonAriaLabel:(0,c.T)({id:"theme.SearchModal.searchBox.resetButtonTitle",message:"Clear the query",description:"The label and ARIA label for search box reset button"}),cancelButtonText:(0,c.T)({id:"theme.SearchModal.searchBox.cancelButtonText",message:"Cancel",description:"The label and ARIA label for search box cancel button"}),cancelButtonAriaLabel:(0,c.T)({id:"theme.SearchModal.searchBox.cancelButtonText",message:"Cancel",description:"The label and ARIA label for search box cancel button"})},startScreen:{recentSearchesTitle:(0,c.T)({id:"theme.SearchModal.startScreen.recentSearchesTitle",message:"Recent",description:"The title for recent searches"}),noRecentSearchesText:(0,c.T)({id:"theme.SearchModal.startScreen.noRecentSearchesText",message:"No recent searches",description:"The text when no recent searches"}),saveRecentSearchButtonTitle:(0,c.T)({id:"theme.SearchModal.startScreen.saveRecentSearchButtonTitle",message:"Save this search",description:"The label for save recent search button"}),removeRecentSearchButtonTitle:(0,c.T)({id:"theme.SearchModal.startScreen.removeRecentSearchButtonTitle",message:"Remove this search from history",description:"The label for remove recent search button"}),favoriteSearchesTitle:(0,c.T)({id:"theme.SearchModal.startScreen.favoriteSearchesTitle",message:"Favorite",description:"The title for favorite searches"}),removeFavoriteSearchButtonTitle:(0,c.T)({id:"theme.SearchModal.startScreen.removeFavoriteSearchButtonTitle",message:"Remove this search from favorites",description:"The label for remove favorite search button"})},errorScreen:{titleText:(0,c.T)({id:"theme.SearchModal.errorScreen.titleText",message:"Unable to fetch results",description:"The title for error screen of search modal"}),helpText:(0,c.T)({id:"theme.SearchModal.errorScreen.helpText",message:"You might want to check your network connection.",description:"The help text for error screen of search modal"})},footer:{selectText:(0,c.T)({id:"theme.SearchModal.footer.selectText",message:"to select",description:"The explanatory text of the action for the enter key"}),selectKeyAriaLabel:(0,c.T)({id:"theme.SearchModal.footer.selectKeyAriaLabel",message:"Enter key",description:"The ARIA label for the Enter key button that makes the selection"}),navigateText:(0,c.T)({id:"theme.SearchModal.footer.navigateText",message:"to navigate",description:"The explanatory text of the action for the Arrow up and Arrow down key"}),navigateUpKeyAriaLabel:(0,c.T)({id:"theme.SearchModal.footer.navigateUpKeyAriaLabel",message:"Arrow up",description:"The ARIA label for the Arrow up key button that makes the navigation"}),navigateDownKeyAriaLabel:(0,c.T)({id:"theme.SearchModal.footer.navigateDownKeyAriaLabel",message:"Arrow down",description:"The ARIA label for the Arrow down key button that makes the navigation"}),closeText:(0,c.T)({id:"theme.SearchModal.footer.closeText",message:"to close",description:"The explanatory text of the action for Escape key"}),closeKeyAriaLabel:(0,c.T)({id:"theme.SearchModal.footer.closeKeyAriaLabel",message:"Escape key",description:"The ARIA label for the Escape key button that close the modal"}),searchByText:(0,c.T)({id:"theme.SearchModal.footer.searchByText",message:"Search by",description:"The text explain that the search is making by Algolia"})},noResultsScreen:{noResultsText:(0,c.T)({id:"theme.SearchModal.noResultsScreen.noResultsText",message:"No results for",description:"The text explains that there are no results for the following search"}),suggestedQueryText:(0,c.T)({id:"theme.SearchModal.noResultsScreen.suggestedQueryText",message:"Try searching for",description:"The text for the suggested query when no results are found for the following search"}),reportMissingResultsText:(0,c.T)({id:"theme.SearchModal.noResultsScreen.reportMissingResultsText",message:"Believe this query should return results?",description:"The text for the question where the user thinks there are missing results"}),reportMissingResultsLinkText:(0,c.T)({id:"theme.SearchModal.noResultsScreen.reportMissingResultsLinkText",message:"Let us know.",description:"The text for the link to report missing results"})}},placeholder:(0,c.T)({id:"theme.SearchModal.placeholder",message:"Search docs",description:"The placeholder of the input of the DocSearch pop-up modal"})};let je=null;function Oe(e){let{hit:t,children:n}=e;return(0,u.jsx)(Z.A,{to:t.url,children:n})}function Ae(e){let{state:t,onClose:n}=e;const r=(0,we.w)();return(0,u.jsx)(Z.A,{to:r(t.query),onClick:n,children:(0,u.jsx)(c.A,{id:"theme.SearchBar.seeAll",values:{count:t.context.nbHits},children:"See all {count} results"})})}function Ce(e){let{contextualSearch:t,externalUrlRegex:o,...a}=e;const{siteMetadata:i}=(0,ce.A)(),c=(0,Se.C)(),l=_e(),d=a.searchParameters?.facetFilters??[],p=t?function(e,t){const n=e=>"string"==typeof e?[e]:e;return[...n(e),...n(t)]}(l,d):d,f={...a.searchParameters,facetFilters:p},m=(0,s.W6)(),g=(0,r.useRef)(null),h=(0,r.useRef)(null),[b,y]=(0,r.useState)(!1),[v,w]=(0,r.useState)(void 0),S=(0,r.useCallback)((()=>je?Promise.resolve():Promise.all([n.e(8158).then(n.bind(n,8158)),Promise.all([n.e(1869),n.e(8913)]).then(n.bind(n,8913)),Promise.all([n.e(1869),n.e(416)]).then(n.bind(n,416))]).then((e=>{let[{DocSearchModal:t}]=e;je=t}))),[]),k=(0,r.useCallback)((()=>{if(!g.current){const e=document.createElement("div");g.current=e,document.body.insertBefore(e,document.body.firstChild)}}),[]),x=(0,r.useCallback)((()=>{k(),S().then((()=>y(!0)))}),[S,k]),_=(0,r.useCallback)((()=>{y(!1),h.current?.focus()}),[]),E=(0,r.useCallback)((e=>{"f"===e.key&&(e.metaKey||e.ctrlKey)||(e.preventDefault(),w(e.key),x())}),[x]),j=(0,r.useRef)({navigate(e){let{itemUrl:t}=e;(0,ee.G)(o,t)?window.location.href=t:m.push(t)}}).current,O=(0,r.useRef)((e=>a.transformItems?a.transformItems(e):e.map((e=>({...e,url:c(e.url)}))))).current,A=(0,r.useMemo)((()=>e=>(0,u.jsx)(Ae,{...e,onClose:_})),[_]),C=(0,r.useCallback)((e=>(e.addAlgoliaAgent("docusaurus",i.docusaurusVersion),e)),[i.docusaurusVersion]);return(0,ye.E8)({isOpen:b,onOpen:x,onClose:_,onInput:E,searchButtonRef:h}),(0,u.jsxs)(u.Fragment,{children:[(0,u.jsx)(ve.A,{children:(0,u.jsx)("link",{rel:"preconnect",href:`https://${a.appId}-dsn.algolia.net`,crossOrigin:"anonymous"})}),(0,u.jsx)(ye.Bc,{onTouchStart:S,onFocus:S,onMouseOver:S,onClick:x,ref:h,translations:Ee.button}),b&&je&&g.current&&(0,be.createPortal)((0,u.jsx)(je,{onClose:_,initialScrollY:window.scrollY,initialQuery:v,navigator:j,transformItems:O,hitComponent:Oe,transformSearchClient:C,...a.searchPagePath&&{resultsFooterComponent:A},...a,searchParameters:f,placeholder:Ee.placeholder,translations:Ee.modal}),g.current)]})}function Te(){const{siteConfig:e}=(0,ce.A)();return(0,u.jsx)(Ce,{...e.themeConfig.algolia})}const Pe={navbarSearchContainer:"navbarSearchContainer_Bca1"};function Ie(e){let{children:t,className:n}=e;return(0,u.jsx)("div",{className:(0,o.A)(n,Pe.navbarSearchContainer),children:t})}var Ne=n(4070),Re=n(6972);var Le=n(3886);function De(e,t){return t.alternateDocVersions[e.name]??function(e){return e.docs.find((t=>t.id===e.mainDocId))}(e)}const Me={default:ae,localeDropdown:function(e){let{mobile:t,dropdownItemsBefore:n,dropdownItemsAfter:r,queryString:o="",...a}=e;const{i18n:{currentLocale:i,locales:l,localeConfigs:d}}=(0,ce.A)(),p=(0,me.o)(),{search:f,hash:m}=(0,s.zy)(),g=[...n,...l.map((e=>{const n=`${`pathname://${p.createUrl({locale:e,fullyQualified:!1})}`}${f}${m}${o}`;return{label:d[e].label,lang:d[e].htmlLang,to:n,target:"_self",autoAddBaseUrl:!1,className:e===i?t?"menu__link--active":"dropdown__link--active":""}})),...r],h=t?(0,c.T)({message:"Languages",id:"theme.navbar.mobileLanguageDropdown.label",description:"The label for the mobile language switcher dropdown"}):d[i].label;return(0,u.jsx)(fe,{...a,mobile:t,label:(0,u.jsxs)(u.Fragment,{children:[(0,u.jsx)(ge,{className:he}),h]}),items:g})},search:function(e){let{mobile:t,className:n}=e;return t?null:(0,u.jsx)(Ie,{className:n,children:(0,u.jsx)(Te,{})})},dropdown:fe,html:function(e){let{value:t,className:n,mobile:r=!1,isDropdownItem:a=!1}=e;const i=a?"li":"div";return(0,u.jsx)(i,{className:(0,o.A)({navbar__item:!r&&!a,"menu__list-item":r},n),dangerouslySetInnerHTML:{__html:t}})},doc:function(e){let{docId:t,label:n,docsPluginId:r,...o}=e;const{activeDoc:a}=(0,Ne.zK)(r),i=(0,Re.QB)(t,r),s=a?.path===i?.path;return null===i||i.unlisted&&!s?null:(0,u.jsx)(ae,{exact:!0,...o,isActive:()=>s||!!a?.sidebar&&a.sidebar===i.sidebar,label:n??i.id,to:i.path})},docSidebar:function(e){let{sidebarId:t,label:n,docsPluginId:r,...o}=e;const{activeDoc:a}=(0,Ne.zK)(r),i=(0,Re.fW)(t,r).link;if(!i)throw new Error(`DocSidebarNavbarItem: Sidebar with ID "${t}" doesn't have anything to be linked to.`);return(0,u.jsx)(ae,{exact:!0,...o,isActive:()=>a?.sidebar===t,label:n??i.label,to:i.path})},docsVersion:function(e){let{label:t,to:n,docsPluginId:r,...o}=e;const a=(0,Re.Vd)(r)[0],i=t??a.label,s=n??(e=>e.docs.find((t=>t.id===e.mainDocId)))(a).path;return(0,u.jsx)(ae,{...o,label:i,to:s})},docsVersionDropdown:function(e){let{mobile:t,docsPluginId:n,dropdownActiveClassDisabled:r,dropdownItemsBefore:o,dropdownItemsAfter:a,...i}=e;const{search:l,hash:d}=(0,s.zy)(),p=(0,Ne.zK)(n),f=(0,Ne.jh)(n),{savePreferredVersionName:m}=(0,Le.g1)(n),g=[...o,...f.map((function(e){const t=De(e,p);return{label:e.label,to:`${t.path}${l}${d}`,isActive:()=>e===p.activeVersion,onClick:()=>m(e.name)}})),...a],h=(0,Re.Vd)(n)[0],b=t&&g.length>1?(0,c.T)({id:"theme.navbar.mobileVersionsDropdown.label",message:"Versions",description:"The label for the navbar versions dropdown on mobile view"}):h.label,y=t&&g.length>1?void 0:De(h,p).path;return g.length<=1?(0,u.jsx)(ae,{...i,mobile:t,label:b,to:y,isActive:r?()=>!1:void 0}):(0,u.jsx)(fe,{...i,mobile:t,label:b,to:y,items:g,isActive:r?()=>!1:void 0})}};function Fe(e){let{type:t,...n}=e;const r=function(e,t){return e&&"default"!==e?e:"items"in t?"dropdown":"default"}(t,n),o=Me[r];if(!o)throw new Error(`No NavbarItem component found for type "${t}".`);return(0,u.jsx)(o,{...n})}function Be(){const e=(0,C.M)(),t=(0,w.p)().navbar.items;return(0,u.jsx)("ul",{className:"menu__list",children:t.map(((t,n)=>(0,r.createElement)(Fe,{mobile:!0,...t,onClick:()=>e.toggle(),key:n})))})}function ze(e){return(0,u.jsx)("button",{...e,type:"button",className:"clean-btn navbar-sidebar__back",children:(0,u.jsx)(c.A,{id:"theme.navbar.mobileSidebarSecondaryMenu.backButtonLabel",description:"The label of the back button to return to main menu, inside the mobile navbar sidebar secondary menu (notably used to display the docs sidebar)",children:"\u2190 Back to main menu"})})}function $e(){const e=0===(0,w.p)().navbar.items.length,t=D();return(0,u.jsxs)(u.Fragment,{children:[!e&&(0,u.jsx)(ze,{onClick:()=>t.hide()}),t.content]})}function Ue(){const e=(0,C.M)();var t;return void 0===(t=e.shown)&&(t=!0),(0,r.useEffect)((()=>(document.body.style.overflow=t?"hidden":"visible",()=>{document.body.style.overflow="visible"})),[t]),e.shouldRender?(0,u.jsx)(M,{header:(0,u.jsx)(Q,{}),primaryMenu:(0,u.jsx)(Be,{}),secondaryMenu:(0,u.jsx)($e,{})}):null}const He={navbarHideable:"navbarHideable_m1mJ",navbarHidden:"navbarHidden_jGov"};function qe(e){return(0,u.jsx)("div",{role:"presentation",...e,className:(0,o.A)("navbar-sidebar__backdrop",e.className)})}function Ve(e){let{children:t}=e;const{navbar:{hideOnScroll:n,style:a}}=(0,w.p)(),i=(0,C.M)(),{navbarRef:s,isNavbarVisible:d}=function(e){const[t,n]=(0,r.useState)(e),o=(0,r.useRef)(!1),a=(0,r.useRef)(0),i=(0,r.useCallback)((e=>{null!==e&&(a.current=e.getBoundingClientRect().height)}),[]);return(0,T.Mq)(((t,r)=>{let{scrollY:i}=t;if(!e)return;if(i<a.current)return void n(!0);if(o.current)return void(o.current=!1);const s=r?.scrollY,c=document.documentElement.scrollHeight-a.current,l=window.innerHeight;s&&i>=s?n(!1):i+l<c&&n(!0)})),(0,l.$)((t=>{if(!e)return;const r=t.location.hash;if(r?document.getElementById(r.substring(1)):void 0)return o.current=!0,void n(!1);n(!0)})),{navbarRef:i,isNavbarVisible:t}}(n);return(0,u.jsxs)("nav",{ref:s,"aria-label":(0,c.T)({id:"theme.NavBar.navAriaLabel",message:"Main",description:"The ARIA label for the main navigation"}),className:(0,o.A)("navbar","navbar--fixed-top",n&&[He.navbarHideable,!d&&He.navbarHidden],{"navbar--dark":"dark"===a,"navbar--primary":"primary"===a,"navbar-sidebar--show":i.shown}),children:[t,(0,u.jsx)(qe,{onClick:i.toggle}),(0,u.jsx)(Ue,{})]})}var We=n(440);const Ge={errorBoundaryError:"errorBoundaryError_a6uf",errorBoundaryFallback:"errorBoundaryFallback_VBag"};function Ke(e){return(0,u.jsx)("button",{type:"button",...e,children:(0,u.jsx)(c.A,{id:"theme.ErrorPageContent.tryAgain",description:"The label of the button to try again rendering when the React error boundary captures an error",children:"Try again"})})}function Ye(e){let{error:t}=e;const n=(0,We.rA)(t).map((e=>e.message)).join("\n\nCause:\n");return(0,u.jsx)("p",{className:Ge.errorBoundaryError,children:n})}class Qe extends r.Component{componentDidCatch(e,t){throw this.props.onError(e,t)}render(){return this.props.children}}const Ze="right";function Xe(e){let{width:t=30,height:n=30,className:r,...o}=e;return(0,u.jsx)("svg",{className:r,width:t,height:n,viewBox:"0 0 30 30","aria-hidden":"true",...o,children:(0,u.jsx)("path",{stroke:"currentColor",strokeLinecap:"round",strokeMiterlimit:"10",strokeWidth:"2",d:"M4 7h22M4 15h22M4 23h22"})})}function Je(){const{toggle:e,shown:t}=(0,C.M)();return(0,u.jsx)("button",{onClick:e,"aria-label":(0,c.T)({id:"theme.docs.sidebar.toggleSidebarButtonAriaLabel",message:"Toggle navigation bar",description:"The ARIA label for hamburger menu button of mobile navigation"}),"aria-expanded":t,className:"navbar__toggle clean-btn",type:"button",children:(0,u.jsx)(Xe,{})})}const et={colorModeToggle:"colorModeToggle_DEke"};function tt(e){let{items:t}=e;return(0,u.jsx)(u.Fragment,{children:t.map(((e,t)=>(0,u.jsx)(Qe,{onError:t=>new Error(`A theme navbar item failed to render.\nPlease double-check the following navbar item (themeConfig.navbar.items) of your Docusaurus config:\n${JSON.stringify(e,null,2)}`,{cause:t}),children:(0,u.jsx)(Fe,{...e})},t)))})}function nt(e){let{left:t,right:n}=e;return(0,u.jsxs)("div",{className:"navbar__inner",children:[(0,u.jsx)("div",{className:"navbar__items",children:t}),(0,u.jsx)("div",{className:"navbar__items navbar__items--right",children:n})]})}function rt(){const e=(0,C.M)(),t=(0,w.p)().navbar.items,[n,r]=function(e){function t(e){return"left"===(e.position??Ze)}return[e.filter(t),e.filter((e=>!t(e)))]}(t),o=t.find((e=>"search"===e.type));return(0,u.jsx)(nt,{left:(0,u.jsxs)(u.Fragment,{children:[!e.disabled&&(0,u.jsx)(Je,{}),(0,u.jsx)(K,{}),(0,u.jsx)(tt,{items:n})]}),right:(0,u.jsxs)(u.Fragment,{children:[(0,u.jsx)(tt,{items:r}),(0,u.jsx)(W,{className:et.colorModeToggle}),!o&&(0,u.jsx)(Ie,{children:(0,u.jsx)(Te,{})})]})})}function ot(){return(0,u.jsx)(Ve,{children:(0,u.jsx)(rt,{})})}function at(e){let{item:t}=e;const{to:n,href:r,label:o,prependBaseUrlToHref:a,...i}=t,s=(0,X.Ay)(n),c=(0,X.Ay)(r,{forcePrependBaseUrl:!0});return(0,u.jsxs)(Z.A,{className:"footer__link-item",...r?{href:a?c:r}:{to:s},...i,children:[o,r&&!(0,J.A)(r)&&(0,u.jsx)(te.A,{})]})}function it(e){let{item:t}=e;return t.html?(0,u.jsx)("li",{className:"footer__item",dangerouslySetInnerHTML:{__html:t.html}}):(0,u.jsx)("li",{className:"footer__item",children:(0,u.jsx)(at,{item:t})},t.href??t.to)}function st(e){let{column:t}=e;return(0,u.jsxs)("div",{className:"col footer__col",children:[(0,u.jsx)("div",{className:"footer__title",children:t.title}),(0,u.jsx)("ul",{className:"footer__items clean-list",children:t.items.map(((e,t)=>(0,u.jsx)(it,{item:e},t)))})]})}function ct(e){let{columns:t}=e;return(0,u.jsx)("div",{className:"row footer__links",children:t.map(((e,t)=>(0,u.jsx)(st,{column:e},t)))})}function lt(){return(0,u.jsx)("span",{className:"footer__link-separator",children:"\xb7"})}function ut(e){let{item:t}=e;return t.html?(0,u.jsx)("span",{className:"footer__link-item",dangerouslySetInnerHTML:{__html:t.html}}):(0,u.jsx)(at,{item:t})}function dt(e){let{links:t}=e;return(0,u.jsx)("div",{className:"footer__links text--center",children:(0,u.jsx)("div",{className:"footer__links",children:t.map(((e,n)=>(0,u.jsxs)(r.Fragment,{children:[(0,u.jsx)(ut,{item:e}),t.length!==n+1&&(0,u.jsx)(lt,{})]},n)))})})}function pt(e){let{links:t}=e;return function(e){return"title"in e[0]}(t)?(0,u.jsx)(ct,{columns:t}):(0,u.jsx)(dt,{links:t})}var ft=n(1122);const mt="footerLogoLink_BH7S";function gt(e){let{logo:t}=e;const{withBaseUrl:n}=(0,X.hH)(),r={light:n(t.src),dark:n(t.srcDark??t.src)};return(0,u.jsx)(ft.A,{className:(0,o.A)("footer__logo",t.className),alt:t.alt,sources:r,width:t.width,height:t.height,style:t.style})}function ht(e){let{logo:t}=e;return t.href?(0,u.jsx)(Z.A,{href:t.href,className:mt,target:t.target,children:(0,u.jsx)(gt,{logo:t})}):(0,u.jsx)(gt,{logo:t})}function bt(e){let{copyright:t}=e;return(0,u.jsx)("div",{className:"footer__copyright",dangerouslySetInnerHTML:{__html:t}})}function yt(e){let{style:t,links:n,logo:r,copyright:a}=e;return(0,u.jsx)("footer",{className:(0,o.A)("footer",{"footer--dark":"dark"===t}),children:(0,u.jsxs)("div",{className:"container container-fluid",children:[n,(r||a)&&(0,u.jsxs)("div",{className:"footer__bottom text--center",children:[r&&(0,u.jsx)("div",{className:"margin-bottom--sm",children:r}),a]})]})})}function vt(){const{footer:e}=(0,w.p)();if(!e)return null;const{copyright:t,links:n,logo:r,style:o}=e;return(0,u.jsx)(yt,{style:o,links:n&&n.length>0&&(0,u.jsx)(pt,{links:n}),logo:r&&(0,u.jsx)(ht,{logo:r}),copyright:t&&(0,u.jsx)(bt,{copyright:t})})}const wt=r.memo(vt),St=(0,P.fM)([F.a,S.o,T.Tv,Le.VQ,i.Jx,function(e){let{children:t}=e;return(0,u.jsx)(I.y_,{children:(0,u.jsx)(C.e,{children:(0,u.jsx)(R,{children:t})})})}]);function kt(e){let{children:t}=e;return(0,u.jsx)(St,{children:t})}var xt=n(1107);function _t(e){let{error:t,tryAgain:n}=e;return(0,u.jsx)("main",{className:"container margin-vert--xl",children:(0,u.jsx)("div",{className:"row",children:(0,u.jsxs)("div",{className:"col col--6 col--offset-3",children:[(0,u.jsx)(xt.A,{as:"h1",className:"hero__title",children:(0,u.jsx)(c.A,{id:"theme.ErrorPageContent.title",description:"The title of the fallback page when the page crashed",children:"This page crashed."})}),(0,u.jsx)("div",{className:"margin-vert--lg",children:(0,u.jsx)(Ke,{onClick:n,className:"button button--primary shadow--lw"})}),(0,u.jsx)("hr",{}),(0,u.jsx)("div",{className:"margin-vert--md",children:(0,u.jsx)(Ye,{error:t})})]})})})}const Et={mainWrapper:"mainWrapper_z2l0"};function jt(e){const{children:t,noFooter:n,wrapperClassName:r,title:s,description:c}=e;return(0,b.J)(),(0,u.jsxs)(kt,{children:[(0,u.jsx)(i.be,{title:s,description:c}),(0,u.jsx)(v,{}),(0,u.jsx)(A,{}),(0,u.jsx)(ot,{}),(0,u.jsx)("div",{id:d,className:(0,o.A)(h.G.wrapper.main,Et.mainWrapper,r),children:(0,u.jsx)(a.A,{fallback:e=>(0,u.jsx)(_t,{...e}),children:t})}),!n&&(0,u.jsx)(wt,{})]})}},3465:(e,t,n)=>{"use strict";n.d(t,{A:()=>u});n(6540);var r=n(8774),o=n(6025),a=n(4586),i=n(6342),s=n(1122),c=n(4848);function l(e){let{logo:t,alt:n,imageClassName:r}=e;const a={light:(0,o.Ay)(t.src),dark:(0,o.Ay)(t.srcDark||t.src)},i=(0,c.jsx)(s.A,{className:t.className,sources:a,height:t.height,width:t.width,alt:n,style:t.style});return r?(0,c.jsx)("div",{className:r,children:i}):i}function u(e){const{siteConfig:{title:t}}=(0,a.A)(),{navbar:{title:n,logo:s}}=(0,i.p)(),{imageClassName:u,titleClassName:d,...p}=e,f=(0,o.Ay)(s?.href||"/"),m=n?"":t,g=s?.alt??m;return(0,c.jsxs)(r.A,{to:f,...p,...s?.target&&{target:s.target},children:[s&&(0,c.jsx)(l,{logo:s,alt:g,imageClassName:u}),null!=n&&(0,c.jsx)("b",{className:d,children:n})]})}},1463:(e,t,n)=>{"use strict";n.d(t,{A:()=>a});n(6540);var r=n(5260),o=n(4848);function a(e){let{locale:t,version:n,tag:a}=e;const i=t;return(0,o.jsxs)(r.A,{children:[t&&(0,o.jsx)("meta",{name:"docusaurus_locale",content:t}),n&&(0,o.jsx)("meta",{name:"docusaurus_version",content:n}),a&&(0,o.jsx)("meta",{name:"docusaurus_tag",content:a}),i&&(0,o.jsx)("meta",{name:"docsearch:language",content:i}),n&&(0,o.jsx)("meta",{name:"docsearch:version",content:n}),a&&(0,o.jsx)("meta",{name:"docsearch:docusaurus_tag",content:a})]})}},1122:(e,t,n)=>{"use strict";n.d(t,{A:()=>u});var r=n(6540),o=n(4164),a=n(2303),i=n(5293);const s={themedComponent:"themedComponent_mlkZ","themedComponent--light":"themedComponent--light_NVdE","themedComponent--dark":"themedComponent--dark_xIcU"};var c=n(4848);function l(e){let{className:t,children:n}=e;const l=(0,a.A)(),{colorMode:u}=(0,i.G)();return(0,c.jsx)(c.Fragment,{children:(l?"dark"===u?["dark"]:["light"]:["light","dark"]).map((e=>{const a=n({theme:e,className:(0,o.A)(t,s.themedComponent,s[`themedComponent--${e}`])});return(0,c.jsx)(r.Fragment,{children:a},e)}))})}function u(e){const{sources:t,className:n,alt:r,...o}=e;return(0,c.jsx)(l,{className:n,children:e=>{let{theme:n,className:a}=e;return(0,c.jsx)("img",{src:t[n],alt:r,className:a,...o})}})}},1422:(e,t,n)=>{"use strict";n.d(t,{N:()=>b,u:()=>l});var r=n(6540),o=n(8193),a=n(205),i=n(3109),s=n(4848);const c="ease-in-out";function l(e){let{initialState:t}=e;const[n,o]=(0,r.useState)(t??!1),a=(0,r.useCallback)((()=>{o((e=>!e))}),[]);return{collapsed:n,setCollapsed:o,toggleCollapsed:a}}const u={display:"none",overflow:"hidden",height:"0px"},d={display:"block",overflow:"visible",height:"auto"};function p(e,t){const n=t?u:d;e.style.display=n.display,e.style.overflow=n.overflow,e.style.height=n.height}function f(e){let{collapsibleRef:t,collapsed:n,animation:o}=e;const a=(0,r.useRef)(!1);(0,r.useEffect)((()=>{const e=t.current;function r(){const t=e.scrollHeight,n=o?.duration??function(e){if((0,i.O)())return 1;const t=e/36;return Math.round(10*(4+15*t**.25+t/5))}(t);return{transition:`height ${n}ms ${o?.easing??c}`,height:`${t}px`}}function s(){const t=r();e.style.transition=t.transition,e.style.height=t.height}if(!a.current)return p(e,n),void(a.current=!0);return e.style.willChange="height",function(){const t=requestAnimationFrame((()=>{n?(s(),requestAnimationFrame((()=>{e.style.height=u.height,e.style.overflow=u.overflow}))):(e.style.display="block",requestAnimationFrame((()=>{s()})))}));return()=>cancelAnimationFrame(t)}()}),[t,n,o])}function m(e){if(!o.A.canUseDOM)return e?u:d}function g(e){let{as:t="div",collapsed:n,children:o,animation:a,onCollapseTransitionEnd:i,className:c,disableSSRStyle:l}=e;const u=(0,r.useRef)(null);return f({collapsibleRef:u,collapsed:n,animation:a}),(0,s.jsx)(t,{ref:u,style:l?void 0:m(n),onTransitionEnd:e=>{"height"===e.propertyName&&(p(u.current,n),i?.(n))},className:c,children:o})}function h(e){let{collapsed:t,...n}=e;const[o,i]=(0,r.useState)(!t),[c,l]=(0,r.useState)(t);return(0,a.A)((()=>{t||i(!0)}),[t]),(0,a.A)((()=>{o&&l(t)}),[o,t]),o?(0,s.jsx)(g,{...n,collapsed:c}):null}function b(e){let{lazy:t,...n}=e;const r=t?h:g;return(0,s.jsx)(r,{...n})}},5041:(e,t,n)=>{"use strict";n.d(t,{M:()=>g,o:()=>m});var r=n(6540),o=n(2303),a=n(679),i=n(9532),s=n(6342),c=n(4848);const l=(0,a.Wf)("docusaurus.announcement.dismiss"),u=(0,a.Wf)("docusaurus.announcement.id"),d=()=>"true"===l.get(),p=e=>l.set(String(e)),f=r.createContext(null);function m(e){let{children:t}=e;const n=function(){const{announcementBar:e}=(0,s.p)(),t=(0,o.A)(),[n,a]=(0,r.useState)((()=>!!t&&d()));(0,r.useEffect)((()=>{a(d())}),[]);const i=(0,r.useCallback)((()=>{p(!0),a(!0)}),[]);return(0,r.useEffect)((()=>{if(!e)return;const{id:t}=e;let n=u.get();"annoucement-bar"===n&&(n="announcement-bar");const r=t!==n;u.set(t),r&&p(!1),!r&&d()||a(!1)}),[e]),(0,r.useMemo)((()=>({isActive:!!e&&!n,close:i})),[e,n,i])}();return(0,c.jsx)(f.Provider,{value:n,children:t})}function g(){const e=(0,r.useContext)(f);if(!e)throw new i.dV("AnnouncementBarProvider");return e}},5293:(e,t,n)=>{"use strict";n.d(t,{G:()=>b,a:()=>h});var r=n(6540),o=n(8193),a=n(9532),i=n(679),s=n(6342),c=n(4848);const l=r.createContext(void 0),u="theme",d=(0,i.Wf)(u),p={light:"light",dark:"dark"},f=e=>e===p.dark?p.dark:p.light,m=e=>o.A.canUseDOM?f(document.documentElement.getAttribute("data-theme")):f(e),g=e=>{d.set(f(e))};function h(e){let{children:t}=e;const n=function(){const{colorMode:{defaultMode:e,disableSwitch:t,respectPrefersColorScheme:n}}=(0,s.p)(),[o,a]=(0,r.useState)(m(e));(0,r.useEffect)((()=>{t&&d.del()}),[t]);const i=(0,r.useCallback)((function(t,r){void 0===r&&(r={});const{persist:o=!0}=r;t?(a(t),o&&g(t)):(a(n?window.matchMedia("(prefers-color-scheme: dark)").matches?p.dark:p.light:e),d.del())}),[n,e]);(0,r.useEffect)((()=>{document.documentElement.setAttribute("data-theme",f(o))}),[o]),(0,r.useEffect)((()=>{if(t)return;const e=e=>{if(e.key!==u)return;const t=d.get();null!==t&&i(f(t))};return window.addEventListener("storage",e),()=>window.removeEventListener("storage",e)}),[t,i]);const c=(0,r.useRef)(!1);return(0,r.useEffect)((()=>{if(t&&!n)return;const e=window.matchMedia("(prefers-color-scheme: dark)"),r=()=>{window.matchMedia("print").matches||c.current?c.current=window.matchMedia("print").matches:i(null)};return e.addListener(r),()=>e.removeListener(r)}),[i,t,n]),(0,r.useMemo)((()=>({colorMode:o,setColorMode:i,get isDarkTheme(){return o===p.dark},setLightTheme(){i(p.light)},setDarkTheme(){i(p.dark)}})),[o,i])}();return(0,c.jsx)(l.Provider,{value:n,children:t})}function b(){const e=(0,r.useContext)(l);if(null==e)throw new a.dV("ColorModeProvider","Please see https://docusaurus.io/docs/api/themes/configuration#use-color-mode.");return e}},2069:(e,t,n)=>{"use strict";n.d(t,{M:()=>f,e:()=>p});var r=n(6540),o=n(5600),a=n(4581),i=n(7485),s=n(6342),c=n(9532),l=n(4848);const u=r.createContext(void 0);function d(){const e=function(){const e=(0,o.YL)(),{items:t}=(0,s.p)().navbar;return 0===t.length&&!e.component}(),t=(0,a.l)(),n=!e&&"mobile"===t,[c,l]=(0,r.useState)(!1);(0,i.$Z)((()=>{if(c)return l(!1),!1}));const u=(0,r.useCallback)((()=>{l((e=>!e))}),[]);return(0,r.useEffect)((()=>{"desktop"===t&&l(!1)}),[t]),(0,r.useMemo)((()=>({disabled:e,shouldRender:n,toggle:u,shown:c})),[e,n,u,c])}function p(e){let{children:t}=e;const n=d();return(0,l.jsx)(u.Provider,{value:n,children:t})}function f(){const e=r.useContext(u);if(void 0===e)throw new c.dV("NavbarMobileSidebarProvider");return e}},5600:(e,t,n)=>{"use strict";n.d(t,{GX:()=>l,YL:()=>c,y_:()=>s});var r=n(6540),o=n(9532),a=n(4848);const i=r.createContext(null);function s(e){let{children:t}=e;const n=(0,r.useState)({component:null,props:null});return(0,a.jsx)(i.Provider,{value:n,children:t})}function c(){const e=(0,r.useContext)(i);if(!e)throw new o.dV("NavbarSecondaryMenuContentProvider");return e[0]}function l(e){let{component:t,props:n}=e;const a=(0,r.useContext)(i);if(!a)throw new o.dV("NavbarSecondaryMenuContentProvider");const[,s]=a,c=(0,o.Be)(n);return(0,r.useEffect)((()=>{s({component:t,props:c})}),[s,t,c]),(0,r.useEffect)((()=>()=>s({component:null,props:null})),[s]),null}},4090:(e,t,n)=>{"use strict";n.d(t,{w:()=>o,J:()=>a});var r=n(6540);const o="navigation-with-keyboard";function a(){(0,r.useEffect)((()=>{function e(e){"keydown"===e.type&&"Tab"===e.key&&document.body.classList.add(o),"mousedown"===e.type&&document.body.classList.remove(o)}return document.addEventListener("keydown",e),document.addEventListener("mousedown",e),()=>{document.body.classList.remove(o),document.removeEventListener("keydown",e),document.removeEventListener("mousedown",e)}}),[])}},4255:(e,t,n)=>{"use strict";n.d(t,{b:()=>s,w:()=>c});var r=n(6540),o=n(4586),a=n(7485);const i="q";function s(){return(0,a.l)(i)}function c(){const{siteConfig:{baseUrl:e,themeConfig:t}}=(0,o.A)(),{algolia:{searchPagePath:n}}=t;return(0,r.useCallback)((t=>`${e}${n}?${i}=${encodeURIComponent(t)}`),[e,n])}},4581:(e,t,n)=>{"use strict";n.d(t,{l:()=>s});var r=n(6540),o=n(8193);const a={desktop:"desktop",mobile:"mobile",ssr:"ssr"},i=996;function s(e){let{desktopBreakpoint:t=i}=void 0===e?{}:e;const[n,s]=(0,r.useState)((()=>"ssr"));return(0,r.useEffect)((()=>{function e(){s(function(e){if(!o.A.canUseDOM)throw new Error("getWindowSize() should only be called after React hydration");return window.innerWidth>e?a.desktop:a.mobile}(t))}return e(),window.addEventListener("resize",e),()=>{window.removeEventListener("resize",e)}}),[t]),n}},7559:(e,t,n)=>{"use strict";n.d(t,{G:()=>r});const r={page:{blogListPage:"blog-list-page",blogPostPage:"blog-post-page",blogTagsListPage:"blog-tags-list-page",blogTagPostListPage:"blog-tags-post-list-page",blogAuthorsListPage:"blog-authors-list-page",blogAuthorsPostsPage:"blog-authors-posts-page",docsDocPage:"docs-doc-page",docsTagsListPage:"docs-tags-list-page",docsTagDocListPage:"docs-tags-doc-list-page",mdxPage:"mdx-page"},wrapper:{main:"main-wrapper",blogPages:"blog-wrapper",docsPages:"docs-wrapper",mdxPages:"mdx-wrapper"},common:{editThisPage:"theme-edit-this-page",lastUpdated:"theme-last-updated",backToTopButton:"theme-back-to-top-button",codeBlock:"theme-code-block",admonition:"theme-admonition",unlistedBanner:"theme-unlisted-banner",draftBanner:"theme-draft-banner",admonitionType:e=>`theme-admonition-${e}`},layout:{},docs:{docVersionBanner:"theme-doc-version-banner",docVersionBadge:"theme-doc-version-badge",docBreadcrumbs:"theme-doc-breadcrumbs",docMarkdown:"theme-doc-markdown",docTocMobile:"theme-doc-toc-mobile",docTocDesktop:"theme-doc-toc-desktop",docFooter:"theme-doc-footer",docFooterTagsRow:"theme-doc-footer-tags-row",docFooterEditMetaRow:"theme-doc-footer-edit-meta-row",docSidebarContainer:"theme-doc-sidebar-container",docSidebarMenu:"theme-doc-sidebar-menu",docSidebarItemCategory:"theme-doc-sidebar-item-category",docSidebarItemLink:"theme-doc-sidebar-item-link",docSidebarItemCategoryLevel:e=>`theme-doc-sidebar-item-category-level-${e}`,docSidebarItemLinkLevel:e=>`theme-doc-sidebar-item-link-level-${e}`},blog:{blogFooterTagsRow:"theme-blog-footer-tags-row",blogFooterEditMetaRow:"theme-blog-footer-edit-meta-row"},pages:{pageFooterEditMetaRow:"theme-pages-footer-edit-meta-row"}}},3109:(e,t,n)=>{"use strict";function r(){return window.matchMedia("(prefers-reduced-motion: reduce)").matches}n.d(t,{O:()=>r})},481:(e,t,n)=>{"use strict";n.d(t,{s:()=>o});var r=n(4586);function o(e){const{siteConfig:t}=(0,r.A)(),{title:n,titleDelimiter:o}=t;return e?.trim().length?`${e.trim()} ${o} ${n}`:n}},7485:(e,t,n)=>{"use strict";n.d(t,{$Z:()=>i,l:()=>c});var r=n(6540),o=n(6347),a=n(9532);function i(e){!function(e){const t=(0,o.W6)(),n=(0,a._q)(e);(0,r.useEffect)((()=>t.block(((e,t)=>n(e,t)))),[t,n])}(((t,n)=>{if("POP"===n)return e(t,n)}))}function s(e){const t=(0,o.W6)();return(0,r.useSyncExternalStore)(t.listen,(()=>e(t)),(()=>e(t)))}function c(e){const t=function(e){return s((t=>null===e?null:new URLSearchParams(t.location.search).get(e)))}(e)??"",n=function(e){const t=(0,o.W6)();return(0,r.useCallback)(((n,r)=>{const o=new URLSearchParams(t.location.search);n?o.set(e,n):o.delete(e),(r?.push?t.push:t.replace)({search:o.toString()})}),[e,t])}(e);return[t,n]}},1682:(e,t,n)=>{"use strict";function r(e){return Array.from(new Set(e))}function o(e,t){const n={};let r=0;for(const o of e){const e=t(o,r);n[e]??=[],n[e].push(o),r+=1}return n}n.d(t,{$z:()=>o,sb:()=>r})},5500:(e,t,n)=>{"use strict";n.d(t,{Jx:()=>f,be:()=>u,e3:()=>p});var r=n(6540),o=n(4164),a=n(5260),i=n(6803),s=n(6025),c=n(481),l=n(4848);function u(e){let{title:t,description:n,keywords:r,image:o,children:i}=e;const u=(0,c.s)(t),{withBaseUrl:d}=(0,s.hH)(),p=o?d(o,{absolute:!0}):void 0;return(0,l.jsxs)(a.A,{children:[t&&(0,l.jsx)("title",{children:u}),t&&(0,l.jsx)("meta",{property:"og:title",content:u}),n&&(0,l.jsx)("meta",{name:"description",content:n}),n&&(0,l.jsx)("meta",{property:"og:description",content:n}),r&&(0,l.jsx)("meta",{name:"keywords",content:Array.isArray(r)?r.join(","):r}),p&&(0,l.jsx)("meta",{property:"og:image",content:p}),p&&(0,l.jsx)("meta",{name:"twitter:image",content:p}),i]})}const d=r.createContext(void 0);function p(e){let{className:t,children:n}=e;const i=r.useContext(d),s=(0,o.A)(i,t);return(0,l.jsxs)(d.Provider,{value:s,children:[(0,l.jsx)(a.A,{children:(0,l.jsx)("html",{className:s})}),n]})}function f(e){let{children:t}=e;const n=(0,i.A)(),r=`plugin-${n.plugin.name.replace(/docusaurus-(?:plugin|theme)-(?:content-)?/gi,"")}`;const a=`plugin-id-${n.plugin.id}`;return(0,l.jsx)(p,{className:(0,o.A)(r,a),children:t})}},9532:(e,t,n)=>{"use strict";n.d(t,{Be:()=>l,ZC:()=>s,_q:()=>i,dV:()=>c,fM:()=>u});var r=n(6540),o=n(205),a=n(4848);function i(e){const t=(0,r.useRef)(e);return(0,o.A)((()=>{t.current=e}),[e]),(0,r.useCallback)((function(){return t.current(...arguments)}),[])}function s(e){const t=(0,r.useRef)();return(0,o.A)((()=>{t.current=e})),t.current}class c extends Error{constructor(e,t){super(),this.name="ReactContextError",this.message=`Hook ${this.stack?.split("\n")[1]?.match(/at (?:\w+\.)?(?<name>\w+)/)?.groups.name??""} is called outside the <${e}>. ${t??""}`}}function l(e){const t=Object.entries(e);return t.sort(((e,t)=>e[0].localeCompare(t[0]))),(0,r.useMemo)((()=>e),t.flat())}function u(e){return t=>{let{children:n}=t;return(0,a.jsx)(a.Fragment,{children:e.reduceRight(((e,t)=>(0,a.jsx)(t,{children:e})),n)})}}},1252:(e,t,n)=>{"use strict";function r(e,t){return void 0!==e&&void 0!==t&&new RegExp(e,"gi").test(t)}n.d(t,{G:()=>r})},9169:(e,t,n)=>{"use strict";n.d(t,{Dt:()=>s,ys:()=>i});var r=n(6540),o=n(8328),a=n(4586);function i(e,t){const n=e=>(!e||e.endsWith("/")?e:`${e}/`)?.toLowerCase();return n(e)===n(t)}function s(){const{baseUrl:e}=(0,a.A)().siteConfig;return(0,r.useMemo)((()=>function(e){let{baseUrl:t,routes:n}=e;function r(e){return e.path===t&&!0===e.exact}function o(e){return e.path===t&&!e.exact}return function e(t){if(0===t.length)return;return t.find(r)||e(t.filter(o).flatMap((e=>e.routes??[])))}(n)}({routes:o.A,baseUrl:e})),[e])}},3104:(e,t,n)=>{"use strict";n.d(t,{Mq:()=>p,Tv:()=>l,gk:()=>f});var r=n(6540),o=n(8193),a=n(2303),i=(n(205),n(9532)),s=n(4848);const c=r.createContext(void 0);function l(e){let{children:t}=e;const n=function(){const e=(0,r.useRef)(!0);return(0,r.useMemo)((()=>({scrollEventsEnabledRef:e,enableScrollEvents:()=>{e.current=!0},disableScrollEvents:()=>{e.current=!1}})),[])}();return(0,s.jsx)(c.Provider,{value:n,children:t})}function u(){const e=(0,r.useContext)(c);if(null==e)throw new i.dV("ScrollControllerProvider");return e}const d=()=>o.A.canUseDOM?{scrollX:window.pageXOffset,scrollY:window.pageYOffset}:null;function p(e,t){void 0===t&&(t=[]);const{scrollEventsEnabledRef:n}=u(),o=(0,r.useRef)(d()),a=(0,i._q)(e);(0,r.useEffect)((()=>{const e=()=>{if(!n.current)return;const e=d();a(e,o.current),o.current=e},t={passive:!0};return e(),window.addEventListener("scroll",e,t),()=>window.removeEventListener("scroll",e,t)}),[a,n,...t])}function f(){const e=(0,r.useRef)(null),t=(0,a.A)()&&"smooth"===getComputedStyle(document.documentElement).scrollBehavior;return{startScroll:n=>{e.current=t?function(e){return window.scrollTo({top:e,behavior:"smooth"}),()=>{}}(n):function(e){let t=null;const n=document.documentElement.scrollTop>e;return function r(){const o=document.documentElement.scrollTop;(n&&o>e||!n&&o<e)&&(t=requestAnimationFrame(r),window.scrollTo(0,Math.floor(.85*(o-e))+e))}(),()=>t&&cancelAnimationFrame(t)}(n)},cancelScroll:()=>e.current?.()}}},2967:(e,t,n)=>{"use strict";n.d(t,{C:()=>r});const r="default"},679:(e,t,n)=>{"use strict";n.d(t,{Wf:()=>l});n(6540);const r=JSON.parse('{"N":"localStorage","M":""}'),o=r.N;function a(e){let{key:t,oldValue:n,newValue:r,storage:o}=e;if(n===r)return;const a=document.createEvent("StorageEvent");a.initStorageEvent("storage",!1,!1,t,n,r,window.location.href,o),window.dispatchEvent(a)}function i(e){if(void 0===e&&(e=o),"undefined"==typeof window)throw new Error("Browser storage is not available on Node.js/Docusaurus SSR process.");if("none"===e)return null;try{return window[e]}catch(n){return t=n,s||(console.warn("Docusaurus browser storage is not available.\nPossible reasons: running Docusaurus in an iframe, in an incognito browser session, or using too strict browser privacy settings.",t),s=!0),null}var t}let s=!1;const c={get:()=>null,set:()=>{},del:()=>{},listen:()=>()=>{}};function l(e,t){const n=`${e}${r.M}`;if("undefined"==typeof window)return function(e){function t(){throw new Error(`Illegal storage API usage for storage key "${e}".\nDocusaurus storage APIs are not supposed to be called on the server-rendering process.\nPlease only call storage APIs in effects and event handlers.`)}return{get:t,set:t,del:t,listen:t}}(n);const o=i(t?.persistence);return null===o?c:{get:()=>{try{return o.getItem(n)}catch(e){return console.error(`Docusaurus storage error, can't get key=${n}`,e),null}},set:e=>{try{const t=o.getItem(n);o.setItem(n,e),a({key:n,oldValue:t,newValue:e,storage:o})}catch(t){console.error(`Docusaurus storage error, can't set ${n}=${e}`,t)}},del:()=>{try{const e=o.getItem(n);o.removeItem(n),a({key:n,oldValue:e,newValue:null,storage:o})}catch(e){console.error(`Docusaurus storage error, can't delete key=${n}`,e)}},listen:e=>{try{const t=t=>{t.storageArea===o&&t.key===n&&e(t)};return window.addEventListener("storage",t),()=>window.removeEventListener("storage",t)}catch(t){return console.error(`Docusaurus storage error, can't listen for changes of key=${n}`,t),()=>{}}}}}},2131:(e,t,n)=>{"use strict";n.d(t,{o:()=>i});var r=n(4586),o=n(6347),a=n(440);function i(){const{siteConfig:{baseUrl:e,url:t,trailingSlash:n},i18n:{defaultLocale:i,currentLocale:s}}=(0,r.A)(),{pathname:c}=(0,o.zy)(),l=(0,a.Ks)(c,{trailingSlash:n,baseUrl:e}),u=s===i?e:e.replace(`/${s}/`,"/"),d=l.replace(e,"");return{createUrl:function(e){let{locale:n,fullyQualified:r}=e;return`${r?t:""}${function(e){return e===i?`${u}`:`${u}${e}/`}(n)}${d}`}}}},5062:(e,t,n)=>{"use strict";n.d(t,{$:()=>i});var r=n(6540),o=n(6347),a=n(9532);function i(e){const t=(0,o.zy)(),n=(0,a.ZC)(t),i=(0,a._q)(e);(0,r.useEffect)((()=>{n&&t!==n&&i({location:t,previousLocation:n})}),[i,t,n])}},6342:(e,t,n)=>{"use strict";n.d(t,{p:()=>o});var r=n(4586);function o(){return(0,r.A)().siteConfig.themeConfig}},8126:(e,t,n)=>{"use strict";n.d(t,{c:()=>o});var r=n(4586);function o(){const{siteConfig:{themeConfig:e}}=(0,r.A)();return e}},1062:(e,t,n)=>{"use strict";n.d(t,{C:()=>s});var r=n(6540),o=n(1252),a=n(6025),i=n(8126);function s(){const{withBaseUrl:e}=(0,a.hH)(),{algolia:{externalUrlRegex:t,replaceSearchResultPathname:n}}=(0,i.c)();return(0,r.useCallback)((r=>{const a=new URL(r);if((0,o.G)(t,a.href))return r;const i=`${a.pathname+a.hash}`;return e(function(e,t){return t?e.replaceAll(new RegExp(t.from,"g"),t.to):e}(i,n))}),[e,t,n])}},2983:(e,t,n)=>{"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.addTrailingSlash=o,t.default=function(e,t){const{trailingSlash:n,baseUrl:r}=t;if(e.startsWith("#"))return e;if(void 0===n)return e;const[i]=e.split(/[#?]/),s="/"===i||i===r?i:(c=i,l=n,l?o(c):a(c));var c,l;return e.replace(i,s)},t.addLeadingSlash=function(e){return(0,r.addPrefix)(e,"/")},t.removeTrailingSlash=a;const r=n(2566);function o(e){return e.endsWith("/")?e:`${e}/`}function a(e){return(0,r.removeSuffix)(e,"/")}},253:(e,t)=>{"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.getErrorCausalChain=function e(t){if(t.cause)return[t,...e(t.cause)];return[t]}},440:(e,t,n)=>{"use strict";t.rA=t.Ks=t.LU=void 0;const r=n(1635);t.LU="__blog-post-container";var o=n(2983);Object.defineProperty(t,"Ks",{enumerable:!0,get:function(){return r.__importDefault(o).default}});var a=n(2566);var i=n(253);Object.defineProperty(t,"rA",{enumerable:!0,get:function(){return i.getErrorCausalChain}})},2566:(e,t)=>{"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.addPrefix=function(e,t){return e.startsWith(t)?e:`${t}${e}`},t.removeSuffix=function(e,t){if(""===t)return e;return e.endsWith(t)?e.slice(0,-t.length):e},t.addSuffix=function(e,t){return e.endsWith(t)?e:`${e}${t}`},t.removePrefix=function(e,t){return e.startsWith(t)?e.slice(t.length):e}},7712:()=>{Prism.languages.dql={comment:[{pattern:/(^|[^\\])\/\*[\s\S]*?(?:\*\/|$)/,lookbehind:!0,greedy:!0},{pattern:/(^|[^\\:])\/\/.*/,lookbehind:!0,greedy:!0}],string:{pattern:/(["'])(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,greedy:!0},"class-name":{pattern:/(\b(?:env|service|operation_name|resource_name|status|ingestion_reason|trace_id)\s+|\bcatch\s+\()[\w.\\]+/i,lookbehind:!0,inside:{punctuation:/[.\\]/}},entity:/\b(?:env|service|operation_name|resource_name|status|ingestion_reason|trace_id)\b/,keyword:/\b(?:by|in|and|not|count|count\sby|stddev|p\d\d)\b/i,boolean:/\b(?:false|true)\b/i,function:/(\b\w+(?=\())|(\w+(?=:))/,number:/\b0x[\da-f]+\b|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?!\d*percentile)(?:e[+-]?\d+)?/i,operator:/[<>]=?|[!=]=?=?|--?|\+\+?|&&?|\|\|?|[?*/~^%]|->|=>/i,punctuation:/[{}[\];(),.:]/,builtin:{pattern:/\b(\d{2}percentile)\b|\b(avg|max|min|sum|set|median|count|is_greater|is_less|is_between|quantile)\b/i},variable:/\$+(?:\w+\b|(?=\{))/},Prism.languages.insertBefore("dql","operator",{"literal-property":{pattern:/((?:^|[,{])[ \t]*)(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*:)/m,lookbehind:!0,alias:"property"}})},1513:(e,t,n)=>{"use strict";n.d(t,{zR:()=>w,TM:()=>j,yJ:()=>f,sC:()=>A,AO:()=>p});var r=n(8168);function o(e){return"/"===e.charAt(0)}function a(e,t){for(var n=t,r=n+1,o=e.length;r<o;n+=1,r+=1)e[n]=e[r];e.pop()}const i=function(e,t){void 0===t&&(t="");var n,r=e&&e.split("/")||[],i=t&&t.split("/")||[],s=e&&o(e),c=t&&o(t),l=s||c;if(e&&o(e)?i=r:r.length&&(i.pop(),i=i.concat(r)),!i.length)return"/";if(i.length){var u=i[i.length-1];n="."===u||".."===u||""===u}else n=!1;for(var d=0,p=i.length;p>=0;p--){var f=i[p];"."===f?a(i,p):".."===f?(a(i,p),d++):d&&(a(i,p),d--)}if(!l)for(;d--;d)i.unshift("..");!l||""===i[0]||i[0]&&o(i[0])||i.unshift("");var m=i.join("/");return n&&"/"!==m.substr(-1)&&(m+="/"),m};var s=n(1561);function c(e){return"/"===e.charAt(0)?e:"/"+e}function l(e){return"/"===e.charAt(0)?e.substr(1):e}function u(e,t){return function(e,t){return 0===e.toLowerCase().indexOf(t.toLowerCase())&&-1!=="/?#".indexOf(e.charAt(t.length))}(e,t)?e.substr(t.length):e}function d(e){return"/"===e.charAt(e.length-1)?e.slice(0,-1):e}function p(e){var t=e.pathname,n=e.search,r=e.hash,o=t||"/";return n&&"?"!==n&&(o+="?"===n.charAt(0)?n:"?"+n),r&&"#"!==r&&(o+="#"===r.charAt(0)?r:"#"+r),o}function f(e,t,n,o){var a;"string"==typeof e?(a=function(e){var t=e||"/",n="",r="",o=t.indexOf("#");-1!==o&&(r=t.substr(o),t=t.substr(0,o));var a=t.indexOf("?");return-1!==a&&(n=t.substr(a),t=t.substr(0,a)),{pathname:t,search:"?"===n?"":n,hash:"#"===r?"":r}}(e),a.state=t):(void 0===(a=(0,r.A)({},e)).pathname&&(a.pathname=""),a.search?"?"!==a.search.charAt(0)&&(a.search="?"+a.search):a.search="",a.hash?"#"!==a.hash.charAt(0)&&(a.hash="#"+a.hash):a.hash="",void 0!==t&&void 0===a.state&&(a.state=t));try{a.pathname=decodeURI(a.pathname)}catch(s){throw s instanceof URIError?new URIError('Pathname "'+a.pathname+'" could not be decoded. This is likely caused by an invalid percent-encoding.'):s}return n&&(a.key=n),o?a.pathname?"/"!==a.pathname.charAt(0)&&(a.pathname=i(a.pathname,o.pathname)):a.pathname=o.pathname:a.pathname||(a.pathname="/"),a}function m(){var e=null;var t=[];return{setPrompt:function(t){return e=t,function(){e===t&&(e=null)}},confirmTransitionTo:function(t,n,r,o){if(null!=e){var a="function"==typeof e?e(t,n):e;"string"==typeof a?"function"==typeof r?r(a,o):o(!0):o(!1!==a)}else o(!0)},appendListener:function(e){var n=!0;function r(){n&&e.apply(void 0,arguments)}return t.push(r),function(){n=!1,t=t.filter((function(e){return e!==r}))}},notifyListeners:function(){for(var e=arguments.length,n=new Array(e),r=0;r<e;r++)n[r]=arguments[r];t.forEach((function(e){return e.apply(void 0,n)}))}}}var g=!("undefined"==typeof window||!window.document||!window.document.createElement);function h(e,t){t(window.confirm(e))}var b="popstate",y="hashchange";function v(){try{return window.history.state||{}}catch(e){return{}}}function w(e){void 0===e&&(e={}),g||(0,s.A)(!1);var t,n=window.history,o=(-1===(t=window.navigator.userAgent).indexOf("Android 2.")&&-1===t.indexOf("Android 4.0")||-1===t.indexOf("Mobile Safari")||-1!==t.indexOf("Chrome")||-1!==t.indexOf("Windows Phone"))&&window.history&&"pushState"in window.history,a=!(-1===window.navigator.userAgent.indexOf("Trident")),i=e,l=i.forceRefresh,w=void 0!==l&&l,S=i.getUserConfirmation,k=void 0===S?h:S,x=i.keyLength,_=void 0===x?6:x,E=e.basename?d(c(e.basename)):"";function j(e){var t=e||{},n=t.key,r=t.state,o=window.location,a=o.pathname+o.search+o.hash;return E&&(a=u(a,E)),f(a,r,n)}function O(){return Math.random().toString(36).substr(2,_)}var A=m();function C(e){(0,r.A)($,e),$.length=n.length,A.notifyListeners($.location,$.action)}function T(e){(function(e){return void 0===e.state&&-1===navigator.userAgent.indexOf("CriOS")})(e)||N(j(e.state))}function P(){N(j(v()))}var I=!1;function N(e){if(I)I=!1,C();else{A.confirmTransitionTo(e,"POP",k,(function(t){t?C({action:"POP",location:e}):function(e){var t=$.location,n=L.indexOf(t.key);-1===n&&(n=0);var r=L.indexOf(e.key);-1===r&&(r=0);var o=n-r;o&&(I=!0,M(o))}(e)}))}}var R=j(v()),L=[R.key];function D(e){return E+p(e)}function M(e){n.go(e)}var F=0;function B(e){1===(F+=e)&&1===e?(window.addEventListener(b,T),a&&window.addEventListener(y,P)):0===F&&(window.removeEventListener(b,T),a&&window.removeEventListener(y,P))}var z=!1;var $={length:n.length,action:"POP",location:R,createHref:D,push:function(e,t){var r="PUSH",a=f(e,t,O(),$.location);A.confirmTransitionTo(a,r,k,(function(e){if(e){var t=D(a),i=a.key,s=a.state;if(o)if(n.pushState({key:i,state:s},null,t),w)window.location.href=t;else{var c=L.indexOf($.location.key),l=L.slice(0,c+1);l.push(a.key),L=l,C({action:r,location:a})}else window.location.href=t}}))},replace:function(e,t){var r="REPLACE",a=f(e,t,O(),$.location);A.confirmTransitionTo(a,r,k,(function(e){if(e){var t=D(a),i=a.key,s=a.state;if(o)if(n.replaceState({key:i,state:s},null,t),w)window.location.replace(t);else{var c=L.indexOf($.location.key);-1!==c&&(L[c]=a.key),C({action:r,location:a})}else window.location.replace(t)}}))},go:M,goBack:function(){M(-1)},goForward:function(){M(1)},block:function(e){void 0===e&&(e=!1);var t=A.setPrompt(e);return z||(B(1),z=!0),function(){return z&&(z=!1,B(-1)),t()}},listen:function(e){var t=A.appendListener(e);return B(1),function(){B(-1),t()}}};return $}var S="hashchange",k={hashbang:{encodePath:function(e){return"!"===e.charAt(0)?e:"!/"+l(e)},decodePath:function(e){return"!"===e.charAt(0)?e.substr(1):e}},noslash:{encodePath:l,decodePath:c},slash:{encodePath:c,decodePath:c}};function x(e){var t=e.indexOf("#");return-1===t?e:e.slice(0,t)}function _(){var e=window.location.href,t=e.indexOf("#");return-1===t?"":e.substring(t+1)}function E(e){window.location.replace(x(window.location.href)+"#"+e)}function j(e){void 0===e&&(e={}),g||(0,s.A)(!1);var t=window.history,n=(window.navigator.userAgent.indexOf("Firefox"),e),o=n.getUserConfirmation,a=void 0===o?h:o,i=n.hashType,l=void 0===i?"slash":i,b=e.basename?d(c(e.basename)):"",y=k[l],v=y.encodePath,w=y.decodePath;function j(){var e=w(_());return b&&(e=u(e,b)),f(e)}var O=m();function A(e){(0,r.A)(z,e),z.length=t.length,O.notifyListeners(z.location,z.action)}var C=!1,T=null;function P(){var e,t,n=_(),r=v(n);if(n!==r)E(r);else{var o=j(),i=z.location;if(!C&&(t=o,(e=i).pathname===t.pathname&&e.search===t.search&&e.hash===t.hash))return;if(T===p(o))return;T=null,function(e){if(C)C=!1,A();else{var t="POP";O.confirmTransitionTo(e,t,a,(function(n){n?A({action:t,location:e}):function(e){var t=z.location,n=L.lastIndexOf(p(t));-1===n&&(n=0);var r=L.lastIndexOf(p(e));-1===r&&(r=0);var o=n-r;o&&(C=!0,D(o))}(e)}))}}(o)}}var I=_(),N=v(I);I!==N&&E(N);var R=j(),L=[p(R)];function D(e){t.go(e)}var M=0;function F(e){1===(M+=e)&&1===e?window.addEventListener(S,P):0===M&&window.removeEventListener(S,P)}var B=!1;var z={length:t.length,action:"POP",location:R,createHref:function(e){var t=document.querySelector("base"),n="";return t&&t.getAttribute("href")&&(n=x(window.location.href)),n+"#"+v(b+p(e))},push:function(e,t){var n="PUSH",r=f(e,void 0,void 0,z.location);O.confirmTransitionTo(r,n,a,(function(e){if(e){var t=p(r),o=v(b+t);if(_()!==o){T=t,function(e){window.location.hash=e}(o);var a=L.lastIndexOf(p(z.location)),i=L.slice(0,a+1);i.push(t),L=i,A({action:n,location:r})}else A()}}))},replace:function(e,t){var n="REPLACE",r=f(e,void 0,void 0,z.location);O.confirmTransitionTo(r,n,a,(function(e){if(e){var t=p(r),o=v(b+t);_()!==o&&(T=t,E(o));var a=L.indexOf(p(z.location));-1!==a&&(L[a]=t),A({action:n,location:r})}}))},go:D,goBack:function(){D(-1)},goForward:function(){D(1)},block:function(e){void 0===e&&(e=!1);var t=O.setPrompt(e);return B||(F(1),B=!0),function(){return B&&(B=!1,F(-1)),t()}},listen:function(e){var t=O.appendListener(e);return F(1),function(){F(-1),t()}}};return z}function O(e,t,n){return Math.min(Math.max(e,t),n)}function A(e){void 0===e&&(e={});var t=e,n=t.getUserConfirmation,o=t.initialEntries,a=void 0===o?["/"]:o,i=t.initialIndex,s=void 0===i?0:i,c=t.keyLength,l=void 0===c?6:c,u=m();function d(e){(0,r.A)(w,e),w.length=w.entries.length,u.notifyListeners(w.location,w.action)}function g(){return Math.random().toString(36).substr(2,l)}var h=O(s,0,a.length-1),b=a.map((function(e){return f(e,void 0,"string"==typeof e?g():e.key||g())})),y=p;function v(e){var t=O(w.index+e,0,w.entries.length-1),r=w.entries[t];u.confirmTransitionTo(r,"POP",n,(function(e){e?d({action:"POP",location:r,index:t}):d()}))}var w={length:b.length,action:"POP",location:b[h],index:h,entries:b,createHref:y,push:function(e,t){var r="PUSH",o=f(e,t,g(),w.location);u.confirmTransitionTo(o,r,n,(function(e){if(e){var t=w.index+1,n=w.entries.slice(0);n.length>t?n.splice(t,n.length-t,o):n.push(o),d({action:r,location:o,index:t,entries:n})}}))},replace:function(e,t){var r="REPLACE",o=f(e,t,g(),w.location);u.confirmTransitionTo(o,r,n,(function(e){e&&(w.entries[w.index]=o,d({action:r,location:o}))}))},go:v,goBack:function(){v(-1)},goForward:function(){v(1)},canGo:function(e){var t=w.index+e;return t>=0&&t<w.entries.length},block:function(e){return void 0===e&&(e=!1),u.setPrompt(e)},listen:function(e){return u.appendListener(e)}};return w}},4146:(e,t,n)=>{"use strict";var r=n(4363),o={childContextTypes:!0,contextType:!0,contextTypes:!0,defaultProps:!0,displayName:!0,getDefaultProps:!0,getDerivedStateFromError:!0,getDerivedStateFromProps:!0,mixins:!0,propTypes:!0,type:!0},a={name:!0,length:!0,prototype:!0,caller:!0,callee:!0,arguments:!0,arity:!0},i={$$typeof:!0,compare:!0,defaultProps:!0,displayName:!0,propTypes:!0,type:!0},s={};function c(e){return r.isMemo(e)?i:s[e.$$typeof]||o}s[r.ForwardRef]={$$typeof:!0,render:!0,defaultProps:!0,displayName:!0,propTypes:!0},s[r.Memo]=i;var l=Object.defineProperty,u=Object.getOwnPropertyNames,d=Object.getOwnPropertySymbols,p=Object.getOwnPropertyDescriptor,f=Object.getPrototypeOf,m=Object.prototype;e.exports=function e(t,n,r){if("string"!=typeof n){if(m){var o=f(n);o&&o!==m&&e(t,o,r)}var i=u(n);d&&(i=i.concat(d(n)));for(var s=c(t),g=c(n),h=0;h<i.length;++h){var b=i[h];if(!(a[b]||r&&r[b]||g&&g[b]||s&&s[b])){var y=p(n,b);try{l(t,b,y)}catch(v){}}}}return t}},311:e=>{"use strict";e.exports=function(e,t,n,r,o,a,i,s){if(!e){var c;if(void 0===t)c=new Error("Minified exception occurred; use the non-minified dev environment for the full error message and additional helpful warnings.");else{var l=[n,r,o,a,i,s],u=0;(c=new Error(t.replace(/%s/g,(function(){return l[u++]})))).name="Invariant Violation"}throw c.framesToPop=1,c}}},4634:e=>{e.exports=Array.isArray||function(e){return"[object Array]"==Object.prototype.toString.call(e)}},119:(e,t,n)=>{"use strict";n.r(t)},1043:(e,t,n)=>{"use strict";n.r(t)},5947:function(e,t,n){var r,o;r=function(){var e,t,n={version:"0.2.0"},r=n.settings={minimum:.08,easing:"ease",positionUsing:"",speed:200,trickle:!0,trickleRate:.02,trickleSpeed:800,showSpinner:!0,barSelector:'[role="bar"]',spinnerSelector:'[role="spinner"]',parent:"body",template:'<div class="bar" role="bar"><div class="peg"></div></div><div class="spinner" role="spinner"><div class="spinner-icon"></div></div>'};function o(e,t,n){return e<t?t:e>n?n:e}function a(e){return 100*(-1+e)}function i(e,t,n){var o;return(o="translate3d"===r.positionUsing?{transform:"translate3d("+a(e)+"%,0,0)"}:"translate"===r.positionUsing?{transform:"translate("+a(e)+"%,0)"}:{"margin-left":a(e)+"%"}).transition="all "+t+"ms "+n,o}n.configure=function(e){var t,n;for(t in e)void 0!==(n=e[t])&&e.hasOwnProperty(t)&&(r[t]=n);return this},n.status=null,n.set=function(e){var t=n.isStarted();e=o(e,r.minimum,1),n.status=1===e?null:e;var a=n.render(!t),l=a.querySelector(r.barSelector),u=r.speed,d=r.easing;return a.offsetWidth,s((function(t){""===r.positionUsing&&(r.positionUsing=n.getPositioningCSS()),c(l,i(e,u,d)),1===e?(c(a,{transition:"none",opacity:1}),a.offsetWidth,setTimeout((function(){c(a,{transition:"all "+u+"ms linear",opacity:0}),setTimeout((function(){n.remove(),t()}),u)}),u)):setTimeout(t,u)})),this},n.isStarted=function(){return"number"==typeof n.status},n.start=function(){n.status||n.set(0);var e=function(){setTimeout((function(){n.status&&(n.trickle(),e())}),r.trickleSpeed)};return r.trickle&&e(),this},n.done=function(e){return e||n.status?n.inc(.3+.5*Math.random()).set(1):this},n.inc=function(e){var t=n.status;return t?("number"!=typeof e&&(e=(1-t)*o(Math.random()*t,.1,.95)),t=o(t+e,0,.994),n.set(t)):n.start()},n.trickle=function(){return n.inc(Math.random()*r.trickleRate)},e=0,t=0,n.promise=function(r){return r&&"resolved"!==r.state()?(0===t&&n.start(),e++,t++,r.always((function(){0==--t?(e=0,n.done()):n.set((e-t)/e)})),this):this},n.render=function(e){if(n.isRendered())return document.getElementById("nprogress");u(document.documentElement,"nprogress-busy");var t=document.createElement("div");t.id="nprogress",t.innerHTML=r.template;var o,i=t.querySelector(r.barSelector),s=e?"-100":a(n.status||0),l=document.querySelector(r.parent);return c(i,{transition:"all 0 linear",transform:"translate3d("+s+"%,0,0)"}),r.showSpinner||(o=t.querySelector(r.spinnerSelector))&&f(o),l!=document.body&&u(l,"nprogress-custom-parent"),l.appendChild(t),t},n.remove=function(){d(document.documentElement,"nprogress-busy"),d(document.querySelector(r.parent),"nprogress-custom-parent");var e=document.getElementById("nprogress");e&&f(e)},n.isRendered=function(){return!!document.getElementById("nprogress")},n.getPositioningCSS=function(){var e=document.body.style,t="WebkitTransform"in e?"Webkit":"MozTransform"in e?"Moz":"msTransform"in e?"ms":"OTransform"in e?"O":"";return t+"Perspective"in e?"translate3d":t+"Transform"in e?"translate":"margin"};var s=function(){var e=[];function t(){var n=e.shift();n&&n(t)}return function(n){e.push(n),1==e.length&&t()}}(),c=function(){var e=["Webkit","O","Moz","ms"],t={};function n(e){return e.replace(/^-ms-/,"ms-").replace(/-([\da-z])/gi,(function(e,t){return t.toUpperCase()}))}function r(t){var n=document.body.style;if(t in n)return t;for(var r,o=e.length,a=t.charAt(0).toUpperCase()+t.slice(1);o--;)if((r=e[o]+a)in n)return r;return t}function o(e){return e=n(e),t[e]||(t[e]=r(e))}function a(e,t,n){t=o(t),e.style[t]=n}return function(e,t){var n,r,o=arguments;if(2==o.length)for(n in t)void 0!==(r=t[n])&&t.hasOwnProperty(n)&&a(e,n,r);else a(e,o[1],o[2])}}();function l(e,t){return("string"==typeof e?e:p(e)).indexOf(" "+t+" ")>=0}function u(e,t){var n=p(e),r=n+t;l(n,t)||(e.className=r.substring(1))}function d(e,t){var n,r=p(e);l(e,t)&&(n=r.replace(" "+t+" "," "),e.className=n.substring(1,n.length-1))}function p(e){return(" "+(e.className||"")+" ").replace(/\s+/gi," ")}function f(e){e&&e.parentNode&&e.parentNode.removeChild(e)}return n},void 0===(o="function"==typeof r?r.call(t,n,t,e):r)||(e.exports=o)},5302:(e,t,n)=>{var r=n(4634);e.exports=m,e.exports.parse=a,e.exports.compile=function(e,t){return c(a(e,t),t)},e.exports.tokensToFunction=c,e.exports.tokensToRegExp=f;var o=new RegExp(["(\\\\.)","([\\/.])?(?:(?:\\:(\\w+)(?:\\(((?:\\\\.|[^\\\\()])+)\\))?|\\(((?:\\\\.|[^\\\\()])+)\\))([+*?])?|(\\*))"].join("|"),"g");function a(e,t){for(var n,r=[],a=0,s=0,c="",l=t&&t.delimiter||"/";null!=(n=o.exec(e));){var d=n[0],p=n[1],f=n.index;if(c+=e.slice(s,f),s=f+d.length,p)c+=p[1];else{var m=e[s],g=n[2],h=n[3],b=n[4],y=n[5],v=n[6],w=n[7];c&&(r.push(c),c="");var S=null!=g&&null!=m&&m!==g,k="+"===v||"*"===v,x="?"===v||"*"===v,_=g||l,E=b||y,j=g||("string"==typeof r[r.length-1]?r[r.length-1]:"");r.push({name:h||a++,prefix:g||"",delimiter:_,optional:x,repeat:k,partial:S,asterisk:!!w,pattern:E?u(E):w?".*":i(_,j)})}}return s<e.length&&(c+=e.substr(s)),c&&r.push(c),r}function i(e,t){return!t||t.indexOf(e)>-1?"[^"+l(e)+"]+?":l(t)+"|(?:(?!"+l(t)+")[^"+l(e)+"])+?"}function s(e){return encodeURI(e).replace(/[\/?#]/g,(function(e){return"%"+e.charCodeAt(0).toString(16).toUpperCase()}))}function c(e,t){for(var n=new Array(e.length),o=0;o<e.length;o++)"object"==typeof e[o]&&(n[o]=new RegExp("^(?:"+e[o].pattern+")$",p(t)));return function(t,o){for(var a="",i=t||{},c=(o||{}).pretty?s:encodeURIComponent,l=0;l<e.length;l++){var u=e[l];if("string"!=typeof u){var d,p=i[u.name];if(null==p){if(u.optional){u.partial&&(a+=u.prefix);continue}throw new TypeError('Expected "'+u.name+'" to be defined')}if(r(p)){if(!u.repeat)throw new TypeError('Expected "'+u.name+'" to not repeat, but received `'+JSON.stringify(p)+"`");if(0===p.length){if(u.optional)continue;throw new TypeError('Expected "'+u.name+'" to not be empty')}for(var f=0;f<p.length;f++){if(d=c(p[f]),!n[l].test(d))throw new TypeError('Expected all "'+u.name+'" to match "'+u.pattern+'", but received `'+JSON.stringify(d)+"`");a+=(0===f?u.prefix:u.delimiter)+d}}else{if(d=u.asterisk?encodeURI(p).replace(/[?#]/g,(function(e){return"%"+e.charCodeAt(0).toString(16).toUpperCase()})):c(p),!n[l].test(d))throw new TypeError('Expected "'+u.name+'" to match "'+u.pattern+'", but received "'+d+'"');a+=u.prefix+d}}else a+=u}return a}}function l(e){return e.replace(/([.+*?=^!:${}()[\]|\/\\])/g,"\\$1")}function u(e){return e.replace(/([=!:$\/()])/g,"\\$1")}function d(e,t){return e.keys=t,e}function p(e){return e&&e.sensitive?"":"i"}function f(e,t,n){r(t)||(n=t||n,t=[]);for(var o=(n=n||{}).strict,a=!1!==n.end,i="",s=0;s<e.length;s++){var c=e[s];if("string"==typeof c)i+=l(c);else{var u=l(c.prefix),f="(?:"+c.pattern+")";t.push(c),c.repeat&&(f+="(?:"+u+f+")*"),i+=f=c.optional?c.partial?u+"("+f+")?":"(?:"+u+"("+f+"))?":u+"("+f+")"}}var m=l(n.delimiter||"/"),g=i.slice(-m.length)===m;return o||(i=(g?i.slice(0,-m.length):i)+"(?:"+m+"(?=$))?"),i+=a?"$":o&&g?"":"(?="+m+"|$)",d(new RegExp("^"+i,p(n)),t)}function m(e,t,n){return r(t)||(n=t||n,t=[]),n=n||{},e instanceof RegExp?function(e,t){var n=e.source.match(/\((?!\?)/g);if(n)for(var r=0;r<n.length;r++)t.push({name:r,prefix:null,delimiter:null,optional:!1,repeat:!1,partial:!1,asterisk:!1,pattern:null});return d(e,t)}(e,t):r(e)?function(e,t,n){for(var r=[],o=0;o<e.length;o++)r.push(m(e[o],t,n).source);return d(new RegExp("(?:"+r.join("|")+")",p(n)),t)}(e,t,n):function(e,t,n){return f(a(e,n),t,n)}(e,t,n)}},7022:()=>{!function(e){var t="\\b(?:BASH|BASHOPTS|BASH_ALIASES|BASH_ARGC|BASH_ARGV|BASH_CMDS|BASH_COMPLETION_COMPAT_DIR|BASH_LINENO|BASH_REMATCH|BASH_SOURCE|BASH_VERSINFO|BASH_VERSION|COLORTERM|COLUMNS|COMP_WORDBREAKS|DBUS_SESSION_BUS_ADDRESS|DEFAULTS_PATH|DESKTOP_SESSION|DIRSTACK|DISPLAY|EUID|GDMSESSION|GDM_LANG|GNOME_KEYRING_CONTROL|GNOME_KEYRING_PID|GPG_AGENT_INFO|GROUPS|HISTCONTROL|HISTFILE|HISTFILESIZE|HISTSIZE|HOME|HOSTNAME|HOSTTYPE|IFS|INSTANCE|JOB|LANG|LANGUAGE|LC_ADDRESS|LC_ALL|LC_IDENTIFICATION|LC_MEASUREMENT|LC_MONETARY|LC_NAME|LC_NUMERIC|LC_PAPER|LC_TELEPHONE|LC_TIME|LESSCLOSE|LESSOPEN|LINES|LOGNAME|LS_COLORS|MACHTYPE|MAILCHECK|MANDATORY_PATH|NO_AT_BRIDGE|OLDPWD|OPTERR|OPTIND|ORBIT_SOCKETDIR|OSTYPE|PAPERSIZE|PATH|PIPESTATUS|PPID|PS1|PS2|PS3|PS4|PWD|RANDOM|REPLY|SECONDS|SELINUX_INIT|SESSION|SESSIONTYPE|SESSION_MANAGER|SHELL|SHELLOPTS|SHLVL|SSH_AUTH_SOCK|TERM|UID|UPSTART_EVENTS|UPSTART_INSTANCE|UPSTART_JOB|UPSTART_SESSION|USER|WINDOWID|XAUTHORITY|XDG_CONFIG_DIRS|XDG_CURRENT_DESKTOP|XDG_DATA_DIRS|XDG_GREETER_DATA_DIR|XDG_MENU_PREFIX|XDG_RUNTIME_DIR|XDG_SEAT|XDG_SEAT_PATH|XDG_SESSION_DESKTOP|XDG_SESSION_ID|XDG_SESSION_PATH|XDG_SESSION_TYPE|XDG_VTNR|XMODIFIERS)\\b",n={pattern:/(^(["']?)\w+\2)[ \t]+\S.*/,lookbehind:!0,alias:"punctuation",inside:null},r={bash:n,environment:{pattern:RegExp("\\$"+t),alias:"constant"},variable:[{pattern:/\$?\(\([\s\S]+?\)\)/,greedy:!0,inside:{variable:[{pattern:/(^\$\(\([\s\S]+)\)\)/,lookbehind:!0},/^\$\(\(/],number:/\b0x[\dA-Fa-f]+\b|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:[Ee]-?\d+)?/,operator:/--|\+\+|\*\*=?|<<=?|>>=?|&&|\|\||[=!+\-*/%<>^&|]=?|[?~:]/,punctuation:/\(\(?|\)\)?|,|;/}},{pattern:/\$\((?:\([^)]+\)|[^()])+\)|`[^`]+`/,greedy:!0,inside:{variable:/^\$\(|^`|\)$|`$/}},{pattern:/\$\{[^}]+\}/,greedy:!0,inside:{operator:/:[-=?+]?|[!\/]|##?|%%?|\^\^?|,,?/,punctuation:/[\[\]]/,environment:{pattern:RegExp("(\\{)"+t),lookbehind:!0,alias:"constant"}}},/\$(?:\w+|[#?*!@$])/],entity:/\\(?:[abceEfnrtv\\"]|O?[0-7]{1,3}|U[0-9a-fA-F]{8}|u[0-9a-fA-F]{4}|x[0-9a-fA-F]{1,2})/};e.languages.bash={shebang:{pattern:/^#!\s*\/.*/,alias:"important"},comment:{pattern:/(^|[^"{\\$])#.*/,lookbehind:!0},"function-name":[{pattern:/(\bfunction\s+)[\w-]+(?=(?:\s*\(?:\s*\))?\s*\{)/,lookbehind:!0,alias:"function"},{pattern:/\b[\w-]+(?=\s*\(\s*\)\s*\{)/,alias:"function"}],"for-or-select":{pattern:/(\b(?:for|select)\s+)\w+(?=\s+in\s)/,alias:"variable",lookbehind:!0},"assign-left":{pattern:/(^|[\s;|&]|[<>]\()\w+(?:\.\w+)*(?=\+?=)/,inside:{environment:{pattern:RegExp("(^|[\\s;|&]|[<>]\\()"+t),lookbehind:!0,alias:"constant"}},alias:"variable",lookbehind:!0},parameter:{pattern:/(^|\s)-{1,2}(?:\w+:[+-]?)?\w+(?:\.\w+)*(?=[=\s]|$)/,alias:"variable",lookbehind:!0},string:[{pattern:/((?:^|[^<])<<-?\s*)(\w+)\s[\s\S]*?(?:\r?\n|\r)\2/,lookbehind:!0,greedy:!0,inside:r},{pattern:/((?:^|[^<])<<-?\s*)(["'])(\w+)\2\s[\s\S]*?(?:\r?\n|\r)\3/,lookbehind:!0,greedy:!0,inside:{bash:n}},{pattern:/(^|[^\\](?:\\\\)*)"(?:\\[\s\S]|\$\([^)]+\)|\$(?!\()|`[^`]+`|[^"\\`$])*"/,lookbehind:!0,greedy:!0,inside:r},{pattern:/(^|[^$\\])'[^']*'/,lookbehind:!0,greedy:!0},{pattern:/\$'(?:[^'\\]|\\[\s\S])*'/,greedy:!0,inside:{entity:r.entity}}],environment:{pattern:RegExp("\\$?"+t),alias:"constant"},variable:r.variable,function:{pattern:/(^|[\s;|&]|[<>]\()(?:add|apropos|apt|apt-cache|apt-get|aptitude|aspell|automysqlbackup|awk|basename|bash|bc|bconsole|bg|bzip2|cal|cargo|cat|cfdisk|chgrp|chkconfig|chmod|chown|chroot|cksum|clear|cmp|column|comm|composer|cp|cron|crontab|csplit|curl|cut|date|dc|dd|ddrescue|debootstrap|df|diff|diff3|dig|dir|dircolors|dirname|dirs|dmesg|docker|docker-compose|du|egrep|eject|env|ethtool|expand|expect|expr|fdformat|fdisk|fg|fgrep|file|find|fmt|fold|format|free|fsck|ftp|fuser|gawk|git|gparted|grep|groupadd|groupdel|groupmod|groups|grub-mkconfig|gzip|halt|head|hg|history|host|hostname|htop|iconv|id|ifconfig|ifdown|ifup|import|install|ip|java|jobs|join|kill|killall|less|link|ln|locate|logname|logrotate|look|lpc|lpr|lprint|lprintd|lprintq|lprm|ls|lsof|lynx|make|man|mc|mdadm|mkconfig|mkdir|mke2fs|mkfifo|mkfs|mkisofs|mknod|mkswap|mmv|more|most|mount|mtools|mtr|mutt|mv|nano|nc|netstat|nice|nl|node|nohup|notify-send|npm|nslookup|op|open|parted|passwd|paste|pathchk|ping|pkill|pnpm|podman|podman-compose|popd|pr|printcap|printenv|ps|pushd|pv|quota|quotacheck|quotactl|ram|rar|rcp|reboot|remsync|rename|renice|rev|rm|rmdir|rpm|rsync|scp|screen|sdiff|sed|sendmail|seq|service|sftp|sh|shellcheck|shuf|shutdown|sleep|slocate|sort|split|ssh|stat|strace|su|sudo|sum|suspend|swapon|sync|sysctl|tac|tail|tar|tee|time|timeout|top|touch|tr|traceroute|tsort|tty|umount|uname|unexpand|uniq|units|unrar|unshar|unzip|update-grub|uptime|useradd|userdel|usermod|users|uudecode|uuencode|v|vcpkg|vdir|vi|vim|virsh|vmstat|wait|watch|wc|wget|whereis|which|who|whoami|write|xargs|xdg-open|yarn|yes|zenity|zip|zsh|zypper)(?=$|[)\s;|&])/,lookbehind:!0},keyword:{pattern:/(^|[\s;|&]|[<>]\()(?:case|do|done|elif|else|esac|fi|for|function|if|in|select|then|until|while)(?=$|[)\s;|&])/,lookbehind:!0},builtin:{pattern:/(^|[\s;|&]|[<>]\()(?:\.|:|alias|bind|break|builtin|caller|cd|command|continue|declare|echo|enable|eval|exec|exit|export|getopts|hash|help|let|local|logout|mapfile|printf|pwd|read|readarray|readonly|return|set|shift|shopt|source|test|times|trap|type|typeset|ulimit|umask|unalias|unset)(?=$|[)\s;|&])/,lookbehind:!0,alias:"class-name"},boolean:{pattern:/(^|[\s;|&]|[<>]\()(?:false|true)(?=$|[)\s;|&])/,lookbehind:!0},"file-descriptor":{pattern:/\B&\d\b/,alias:"important"},operator:{pattern:/\d?<>|>\||\+=|=[=~]?|!=?|<<[<-]?|[&\d]?>>|\d[<>]&?|[<>][&=]?|&[>&]?|\|[&|]?/,inside:{"file-descriptor":{pattern:/^\d/,alias:"important"}}},punctuation:/\$?\(\(?|\)\)?|\.\.|[{}[\];\\]/,number:{pattern:/(^|\s)(?:[1-9]\d*|0)(?:[.,]\d+)?\b/,lookbehind:!0}},n.inside=e.languages.bash;for(var o=["comment","function-name","for-or-select","assign-left","parameter","string","environment","function","keyword","builtin","boolean","file-descriptor","operator","punctuation","number"],a=r.variable[1].inside,i=0;i<o.length;i++)a[o[i]]=e.languages.bash[o[i]];e.languages.sh=e.languages.bash,e.languages.shell=e.languages.bash}(Prism)},6378:()=>{Prism.languages.go=Prism.languages.extend("clike",{string:{pattern:/(^|[^\\])"(?:\\.|[^"\\\r\n])*"|`[^`]*`/,lookbehind:!0,greedy:!0},keyword:/\b(?:break|case|chan|const|continue|default|defer|else|fallthrough|for|func|go(?:to)?|if|import|interface|map|package|range|return|select|struct|switch|type|var)\b/,boolean:/\b(?:_|false|iota|nil|true)\b/,number:[/\b0(?:b[01_]+|o[0-7_]+)i?\b/i,/\b0x(?:[a-f\d_]+(?:\.[a-f\d_]*)?|\.[a-f\d_]+)(?:p[+-]?\d+(?:_\d+)*)?i?(?!\w)/i,/(?:\b\d[\d_]*(?:\.[\d_]*)?|\B\.\d[\d_]*)(?:e[+-]?[\d_]+)?i?(?!\w)/i],operator:/[*\/%^!=]=?|\+[=+]?|-[=-]?|\|[=|]?|&(?:=|&|\^=?)?|>(?:>=?|=)?|<(?:<=?|=|-)?|:=|\.\.\./,builtin:/\b(?:append|bool|byte|cap|close|complex|complex(?:64|128)|copy|delete|error|float(?:32|64)|u?int(?:8|16|32|64)?|imag|len|make|new|panic|print(?:ln)?|real|recover|rune|string|uintptr)\b/}),Prism.languages.insertBefore("go","string",{char:{pattern:/'(?:\\.|[^'\\\r\n]){0,10}'/,greedy:!0}}),delete Prism.languages.go["class-name"]},3523:()=>{!function(e){var t={pattern:/((?:^|[^\\$])(?:\\{2})*)\$(?:\w+|\{[^{}]*\})/,lookbehind:!0,inside:{"interpolation-punctuation":{pattern:/^\$\{?|\}$/,alias:"punctuation"},expression:{pattern:/[\s\S]+/,inside:null}}};e.languages.gradle=e.languages.extend("clike",{string:{pattern:/'''(?:[^\\]|\\[\s\S])*?'''|'(?:\\.|[^\\'\r\n])*'/,greedy:!0},keyword:/\b(?:apply|def|dependencies|else|if|implementation|import|plugin|plugins|project|repositories|repository|sourceSets|tasks|val)\b/,number:/\b(?:0b[01_]+|0x[\da-f_]+(?:\.[\da-f_p\-]+)?|[\d_]+(?:\.[\d_]+)?(?:e[+-]?\d+)?)[glidf]?\b/i,operator:{pattern:/(^|[^.])(?:~|==?~?|\?[.:]?|\*(?:[.=]|\*=?)?|\.[@&]|\.\.<|\.\.(?!\.)|-[-=>]?|\+[+=]?|!=?|<(?:<=?|=>?)?|>(?:>>?=?|=)?|&[&=]?|\|[|=]?|\/=?|\^=?|%=?)/,lookbehind:!0},punctuation:/\.+|[{}[\];(),:$]/}),e.languages.insertBefore("gradle","string",{shebang:{pattern:/#!.+/,alias:"comment",greedy:!0},"interpolation-string":{pattern:/"""(?:[^\\]|\\[\s\S])*?"""|(["/])(?:\\.|(?!\1)[^\\\r\n])*\1|\$\/(?:[^/$]|\$(?:[/$]|(?![/$]))|\/(?!\$))*\/\$/,greedy:!0,inside:{interpolation:t,string:/[\s\S]+/}}}),e.languages.insertBefore("gradle","punctuation",{"spock-block":/\b(?:and|cleanup|expect|given|setup|then|when|where):/}),e.languages.insertBefore("gradle","function",{annotation:{pattern:/(^|[^.])@\w+/,lookbehind:!0,alias:"punctuation"}}),t.inside.expression.inside=e.languages.gradle}(Prism)},6976:()=>{!function(e){var t=/\b(?:abstract|assert|boolean|break|byte|case|catch|char|class|const|continue|default|do|double|else|enum|exports|extends|final|finally|float|for|goto|if|implements|import|instanceof|int|interface|long|module|native|new|non-sealed|null|open|opens|package|permits|private|protected|provides|public|record(?!\s*[(){}[\]<>=%~.:,;?+\-*/&|^])|requires|return|sealed|short|static|strictfp|super|switch|synchronized|this|throw|throws|to|transient|transitive|try|uses|var|void|volatile|while|with|yield)\b/,n=/(?:[a-z]\w*\s*\.\s*)*(?:[A-Z]\w*\s*\.\s*)*/.source,r={pattern:RegExp(/(^|[^\w.])/.source+n+/[A-Z](?:[\d_A-Z]*[a-z]\w*)?\b/.source),lookbehind:!0,inside:{namespace:{pattern:/^[a-z]\w*(?:\s*\.\s*[a-z]\w*)*(?:\s*\.)?/,inside:{punctuation:/\./}},punctuation:/\./}};e.languages.java=e.languages.extend("clike",{string:{pattern:/(^|[^\\])"(?:\\.|[^"\\\r\n])*"/,lookbehind:!0,greedy:!0},"class-name":[r,{pattern:RegExp(/(^|[^\w.])/.source+n+/[A-Z]\w*(?=\s+\w+\s*[;,=()]|\s*(?:\[[\s,]*\]\s*)?::\s*new\b)/.source),lookbehind:!0,inside:r.inside},{pattern:RegExp(/(\b(?:class|enum|extends|implements|instanceof|interface|new|record|throws)\s+)/.source+n+/[A-Z]\w*\b/.source),lookbehind:!0,inside:r.inside}],keyword:t,function:[e.languages.clike.function,{pattern:/(::\s*)[a-z_]\w*/,lookbehind:!0}],number:/\b0b[01][01_]*L?\b|\b0x(?:\.[\da-f_p+-]+|[\da-f_]+(?:\.[\da-f_p+-]+)?)\b|(?:\b\d[\d_]*(?:\.[\d_]*)?|\B\.\d[\d_]*)(?:e[+-]?\d[\d_]*)?[dfl]?/i,operator:{pattern:/(^|[^.])(?:<<=?|>>>?=?|->|--|\+\+|&&|\|\||::|[?:~]|[-+*/%&|^!=<>]=?)/m,lookbehind:!0},constant:/\b[A-Z][A-Z_\d]+\b/}),e.languages.insertBefore("java","string",{"triple-quoted-string":{pattern:/"""[ \t]*[\r\n](?:(?:"|"")?(?:\\.|[^"\\]))*"""/,greedy:!0,alias:"string"},char:{pattern:/'(?:\\.|[^'\\\r\n]){1,6}'/,greedy:!0}}),e.languages.insertBefore("java","class-name",{annotation:{pattern:/(^|[^.])@\w+(?:\s*\.\s*\w+)*/,lookbehind:!0,alias:"punctuation"},generics:{pattern:/<(?:[\w\s,.?]|&(?!&)|<(?:[\w\s,.?]|&(?!&)|<(?:[\w\s,.?]|&(?!&)|<(?:[\w\s,.?]|&(?!&))*>)*>)*>)*>/,inside:{"class-name":r,keyword:t,punctuation:/[<>(),.:]/,operator:/[?&|]/}},import:[{pattern:RegExp(/(\bimport\s+)/.source+n+/(?:[A-Z]\w*|\*)(?=\s*;)/.source),lookbehind:!0,inside:{namespace:r.inside.namespace,punctuation:/\./,operator:/\*/,"class-name":/\w+/}},{pattern:RegExp(/(\bimport\s+static\s+)/.source+n+/(?:\w+|\*)(?=\s*;)/.source),lookbehind:!0,alias:"static",inside:{namespace:r.inside.namespace,static:/\b\w+$/,punctuation:/\./,operator:/\*/,"class-name":/\w+/}}],namespace:{pattern:RegExp(/(\b(?:exports|import(?:\s+static)?|module|open|opens|package|provides|requires|to|transitive|uses|with)\s+)(?!<keyword>)[a-z]\w*(?:\.[a-z]\w*)*\.?/.source.replace(/<keyword>/g,(function(){return t.source}))),lookbehind:!0,inside:{punctuation:/\./}}})}(Prism)},2514:()=>{Prism.languages.json={property:{pattern:/(^|[^\\])"(?:\\.|[^\\"\r\n])*"(?=\s*:)/,lookbehind:!0,greedy:!0},string:{pattern:/(^|[^\\])"(?:\\.|[^\\"\r\n])*"(?!\s*:)/,lookbehind:!0,greedy:!0},comment:{pattern:/\/\/.*|\/\*[\s\S]*?(?:\*\/|$)/,greedy:!0},number:/-?\b\d+(?:\.\d+)?(?:e[+-]?\d+)?\b/i,punctuation:/[{}[\],]/,operator:/:/,boolean:/\b(?:false|true)\b/,null:{pattern:/\bnull\b/,alias:"keyword"}},Prism.languages.webmanifest=Prism.languages.json},8160:()=>{Prism.languages.log={string:{pattern:/"(?:[^"\\\r\n]|\\.)*"|'(?![st] | \w)(?:[^'\\\r\n]|\\.)*'/,greedy:!0},exception:{pattern:/(^|[^\w.])[a-z][\w.]*(?:Error|Exception):.*(?:(?:\r\n?|\n)[ \t]*(?:at[ \t].+|\.{3}.*|Caused by:.*))+(?:(?:\r\n?|\n)[ \t]*\.\.\. .*)?/,lookbehind:!0,greedy:!0,alias:["javastacktrace","language-javastacktrace"],inside:Prism.languages.javastacktrace||{keyword:/\bat\b/,function:/[a-z_][\w$]*(?=\()/,punctuation:/[.:()]/}},level:[{pattern:/\b(?:ALERT|CRIT|CRITICAL|EMERG|EMERGENCY|ERR|ERROR|FAILURE|FATAL|SEVERE)\b/,alias:["error","important"]},{pattern:/\b(?:WARN|WARNING|WRN)\b/,alias:["warning","important"]},{pattern:/\b(?:DISPLAY|INF|INFO|NOTICE|STATUS)\b/,alias:["info","keyword"]},{pattern:/\b(?:DBG|DEBUG|FINE)\b/,alias:["debug","keyword"]},{pattern:/\b(?:FINER|FINEST|TRACE|TRC|VERBOSE|VRB)\b/,alias:["trace","comment"]}],property:{pattern:/((?:^|[\]|])[ \t]*)[a-z_](?:[\w-]|\b\/\b)*(?:[. ]\(?\w(?:[\w-]|\b\/\b)*\)?)*:(?=\s)/im,lookbehind:!0},separator:{pattern:/(^|[^-+])-{3,}|={3,}|\*{3,}|- - /m,lookbehind:!0,alias:"comment"},url:/\b(?:file|ftp|https?):\/\/[^\s|,;'"]*[^\s|,;'">.]/,email:{pattern:/(^|\s)[-\w+.]+@[a-z][a-z0-9-]*(?:\.[a-z][a-z0-9-]*)+(?=\s)/,lookbehind:!0,alias:"url"},"ip-address":{pattern:/\b(?:\d{1,3}(?:\.\d{1,3}){3})\b/,alias:"constant"},"mac-address":{pattern:/\b[a-f0-9]{2}(?::[a-f0-9]{2}){5}\b/i,alias:"constant"},domain:{pattern:/(^|\s)[a-z][a-z0-9-]*(?:\.[a-z][a-z0-9-]*)*\.[a-z][a-z0-9-]+(?=\s)/,lookbehind:!0,alias:"constant"},uuid:{pattern:/\b[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\b/i,alias:"constant"},hash:{pattern:/\b(?:[a-f0-9]{32}){1,2}\b/i,alias:"constant"},"file-path":{pattern:/\b[a-z]:[\\/][^\s|,;:(){}\[\]"']+|(^|[\s:\[\](>|])\.{0,2}\/\w[^\s|,;:(){}\[\]"']*/i,lookbehind:!0,greedy:!0,alias:"string"},date:{pattern:RegExp(/\b\d{4}[-/]\d{2}[-/]\d{2}(?:T(?=\d{1,2}:)|(?=\s\d{1,2}:))/.source+"|"+/\b\d{1,4}[-/ ](?:\d{1,2}|Apr|Aug|Dec|Feb|Jan|Jul|Jun|Mar|May|Nov|Oct|Sep)[-/ ]\d{2,4}T?\b/.source+"|"+/\b(?:(?:Fri|Mon|Sat|Sun|Thu|Tue|Wed)(?:\s{1,2}(?:Apr|Aug|Dec|Feb|Jan|Jul|Jun|Mar|May|Nov|Oct|Sep))?|Apr|Aug|Dec|Feb|Jan|Jul|Jun|Mar|May|Nov|Oct|Sep)\s{1,2}\d{1,2}\b/.source,"i"),alias:"number"},time:{pattern:/\b\d{1,2}:\d{1,2}:\d{1,2}(?:[.,:]\d+)?(?:\s?[+-]\d{2}:?\d{2}|Z)?\b/,alias:"number"},boolean:/\b(?:false|null|true)\b/i,number:{pattern:/(^|[^.\w])(?:0x[a-f0-9]+|0o[0-7]+|0b[01]+|v?\d[\da-f]*(?:\.\d+)*(?:e[+-]?\d+)?[a-z]{0,3}\b)\b(?!\.\w)/i,lookbehind:!0},operator:/[;:?<=>~/@!$%&+\-|^(){}*#]/,punctuation:/[\[\].,]/}},9700:()=>{!function(e){function t(e,t){return"___"+e.toUpperCase()+t+"___"}Object.defineProperties(e.languages["markup-templating"]={},{buildPlaceholders:{value:function(n,r,o,a){if(n.language===r){var i=n.tokenStack=[];n.code=n.code.replace(o,(function(e){if("function"==typeof a&&!a(e))return e;for(var o,s=i.length;-1!==n.code.indexOf(o=t(r,s));)++s;return i[s]=e,o})),n.grammar=e.languages.markup}}},tokenizePlaceholders:{value:function(n,r){if(n.language===r&&n.tokenStack){n.grammar=e.languages[r];var o=0,a=Object.keys(n.tokenStack);!function i(s){for(var c=0;c<s.length&&!(o>=a.length);c++){var l=s[c];if("string"==typeof l||l.content&&"string"==typeof l.content){var u=a[o],d=n.tokenStack[u],p="string"==typeof l?l:l.content,f=t(r,u),m=p.indexOf(f);if(m>-1){++o;var g=p.substring(0,m),h=new e.Token(r,e.tokenize(d,n.grammar),"language-"+r,d),b=p.substring(m+f.length),y=[];g&&y.push.apply(y,i([g])),y.push(h),b&&y.push.apply(y,i([b])),"string"==typeof l?s.splice.apply(s,[c,1].concat(y)):l.content=y}}else l.content&&i(l.content)}return s}(n.tokens)}}}})}(Prism)},4312:()=>{Prism.languages.markup={comment:{pattern:/<!--(?:(?!<!--)[\s\S])*?-->/,greedy:!0},prolog:{pattern:/<\?[\s\S]+?\?>/,greedy:!0},doctype:{pattern:/<!DOCTYPE(?:[^>"'[\]]|"[^"]*"|'[^']*')+(?:\[(?:[^<"'\]]|"[^"]*"|'[^']*'|<(?!!--)|<!--(?:[^-]|-(?!->))*-->)*\]\s*)?>/i,greedy:!0,inside:{"internal-subset":{pattern:/(^[^\[]*\[)[\s\S]+(?=\]>$)/,lookbehind:!0,greedy:!0,inside:null},string:{pattern:/"[^"]*"|'[^']*'/,greedy:!0},punctuation:/^<!|>$|[[\]]/,"doctype-tag":/^DOCTYPE/i,name:/[^\s<>'"]+/}},cdata:{pattern:/<!\[CDATA\[[\s\S]*?\]\]>/i,greedy:!0},tag:{pattern:/<\/?(?!\d)[^\s>\/=$<%]+(?:\s(?:\s*[^\s>\/=]+(?:\s*=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+(?=[\s>]))|(?=[\s/>])))+)?\s*\/?>/,greedy:!0,inside:{tag:{pattern:/^<\/?[^\s>\/]+/,inside:{punctuation:/^<\/?/,namespace:/^[^\s>\/:]+:/}},"special-attr":[],"attr-value":{pattern:/=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+)/,inside:{punctuation:[{pattern:/^=/,alias:"attr-equals"},{pattern:/^(\s*)["']|["']$/,lookbehind:!0}]}},punctuation:/\/?>/,"attr-name":{pattern:/[^\s>\/]+/,inside:{namespace:/^[^\s>\/:]+:/}}}},entity:[{pattern:/&[\da-z]{1,8};/i,alias:"named-entity"},/&#x?[\da-f]{1,8};/i]},Prism.languages.markup.tag.inside["attr-value"].inside.entity=Prism.languages.markup.entity,Prism.languages.markup.doctype.inside["internal-subset"].inside=Prism.languages.markup,Prism.hooks.add("wrap",(function(e){"entity"===e.type&&(e.attributes.title=e.content.replace(/&/,"&"))})),Object.defineProperty(Prism.languages.markup.tag,"addInlined",{value:function(e,t){var n={};n["language-"+t]={pattern:/(^<!\[CDATA\[)[\s\S]+?(?=\]\]>$)/i,lookbehind:!0,inside:Prism.languages[t]},n.cdata=/^<!\[CDATA\[|\]\]>$/i;var r={"included-cdata":{pattern:/<!\[CDATA\[[\s\S]*?\]\]>/i,inside:n}};r["language-"+t]={pattern:/[\s\S]+/,inside:Prism.languages[t]};var o={};o[e]={pattern:RegExp(/(<__[^>]*>)(?:<!\[CDATA\[(?:[^\]]|\](?!\]>))*\]\]>|(?!<!\[CDATA\[)[\s\S])*?(?=<\/__>)/.source.replace(/__/g,(function(){return e})),"i"),lookbehind:!0,greedy:!0,inside:r},Prism.languages.insertBefore("markup","cdata",o)}}),Object.defineProperty(Prism.languages.markup.tag,"addAttribute",{value:function(e,t){Prism.languages.markup.tag.inside["special-attr"].push({pattern:RegExp(/(^|["'\s])/.source+"(?:"+e+")"+/\s*=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+(?=[\s>]))/.source,"i"),lookbehind:!0,inside:{"attr-name":/^[^\s=]+/,"attr-value":{pattern:/=[\s\S]+/,inside:{value:{pattern:/(^=\s*(["']|(?!["'])))\S[\s\S]*(?=\2$)/,lookbehind:!0,alias:[t,"language-"+t],inside:Prism.languages[t]},punctuation:[{pattern:/^=/,alias:"attr-equals"},/"|'/]}}}})}}),Prism.languages.html=Prism.languages.markup,Prism.languages.mathml=Prism.languages.markup,Prism.languages.svg=Prism.languages.markup,Prism.languages.xml=Prism.languages.extend("markup",{}),Prism.languages.ssml=Prism.languages.xml,Prism.languages.atom=Prism.languages.xml,Prism.languages.rss=Prism.languages.xml},61:()=>{!function(e){var t=[/"(?:\\[\s\S]|\$\([^)]+\)|\$(?!\()|`[^`]+`|[^"\\`$])*"/.source,/'[^']*'/.source,/\$'(?:[^'\\]|\\[\s\S])*'/.source,/<<-?\s*(["']?)(\w+)\1\s[\s\S]*?[\r\n]\2/.source].join("|");e.languages["shell-session"]={command:{pattern:RegExp(/^/.source+"(?:"+/[^\s@:$#%*!/\\]+@[^\r\n@:$#%*!/\\]+(?::[^\0-\x1F$#%*?"<>:;|]+)?/.source+"|"+/[/~.][^\0-\x1F$#%*?"<>@:;|]*/.source+")?"+/[$#%](?=\s)/.source+/(?:[^\\\r\n \t'"<$]|[ \t](?:(?!#)|#.*$)|\\(?:[^\r]|\r\n?)|\$(?!')|<(?!<)|<<str>>)+/.source.replace(/<<str>>/g,(function(){return t})),"m"),greedy:!0,inside:{info:{pattern:/^[^#$%]+/,alias:"punctuation",inside:{user:/^[^\s@:$#%*!/\\]+@[^\r\n@:$#%*!/\\]+/,punctuation:/:/,path:/[\s\S]+/}},bash:{pattern:/(^[$#%]\s*)\S[\s\S]*/,lookbehind:!0,alias:"language-bash",inside:e.languages.bash},"shell-symbol":{pattern:/^[$#%]/,alias:"important"}}},output:/.(?:.*(?:[\r\n]|.$))*/},e.languages["sh-session"]=e.languages.shellsession=e.languages["shell-session"]}(Prism)},83:()=>{!function(e){var t=/[*&][^\s[\]{},]+/,n=/!(?:<[\w\-%#;/?:@&=+$,.!~*'()[\]]+>|(?:[a-zA-Z\d-]*!)?[\w\-%#;/?:@&=+$.~*'()]+)?/,r="(?:"+n.source+"(?:[ \t]+"+t.source+")?|"+t.source+"(?:[ \t]+"+n.source+")?)",o=/(?:[^\s\x00-\x08\x0e-\x1f!"#%&'*,\-:>?@[\]`{|}\x7f-\x84\x86-\x9f\ud800-\udfff\ufffe\uffff]|[?:-]<PLAIN>)(?:[ \t]*(?:(?![#:])<PLAIN>|:<PLAIN>))*/.source.replace(/<PLAIN>/g,(function(){return/[^\s\x00-\x08\x0e-\x1f,[\]{}\x7f-\x84\x86-\x9f\ud800-\udfff\ufffe\uffff]/.source})),a=/"(?:[^"\\\r\n]|\\.)*"|'(?:[^'\\\r\n]|\\.)*'/.source;function i(e,t){t=(t||"").replace(/m/g,"")+"m";var n=/([:\-,[{]\s*(?:\s<<prop>>[ \t]+)?)(?:<<value>>)(?=[ \t]*(?:$|,|\]|\}|(?:[\r\n]\s*)?#))/.source.replace(/<<prop>>/g,(function(){return r})).replace(/<<value>>/g,(function(){return e}));return RegExp(n,t)}e.languages.yaml={scalar:{pattern:RegExp(/([\-:]\s*(?:\s<<prop>>[ \t]+)?[|>])[ \t]*(?:((?:\r?\n|\r)[ \t]+)\S[^\r\n]*(?:\2[^\r\n]+)*)/.source.replace(/<<prop>>/g,(function(){return r}))),lookbehind:!0,alias:"string"},comment:/#.*/,key:{pattern:RegExp(/((?:^|[:\-,[{\r\n?])[ \t]*(?:<<prop>>[ \t]+)?)<<key>>(?=\s*:\s)/.source.replace(/<<prop>>/g,(function(){return r})).replace(/<<key>>/g,(function(){return"(?:"+o+"|"+a+")"}))),lookbehind:!0,greedy:!0,alias:"atrule"},directive:{pattern:/(^[ \t]*)%.+/m,lookbehind:!0,alias:"important"},datetime:{pattern:i(/\d{4}-\d\d?-\d\d?(?:[tT]|[ \t]+)\d\d?:\d{2}:\d{2}(?:\.\d*)?(?:[ \t]*(?:Z|[-+]\d\d?(?::\d{2})?))?|\d{4}-\d{2}-\d{2}|\d\d?:\d{2}(?::\d{2}(?:\.\d*)?)?/.source),lookbehind:!0,alias:"number"},boolean:{pattern:i(/false|true/.source,"i"),lookbehind:!0,alias:"important"},null:{pattern:i(/null|~/.source,"i"),lookbehind:!0,alias:"important"},string:{pattern:i(a),lookbehind:!0,greedy:!0},number:{pattern:i(/[+-]?(?:0x[\da-f]+|0o[0-7]+|(?:\d+(?:\.\d*)?|\.\d+)(?:e[+-]?\d+)?|\.inf|\.nan)/.source,"i"),lookbehind:!0},tag:n,important:t,punctuation:/---|[:[\]{}\-,|>?]|\.\.\./},e.languages.yml=e.languages.yaml}(Prism)},803:(e,t,n)=>{var r={"./prism-bash":7022,"./prism-go":6378,"./prism-gradle":3523,"./prism-java":6976,"./prism-json":2514,"./prism-log":8160,"./prism-markup":4312,"./prism-shell-session":61,"./prism-yaml":83};function o(e){var t=a(e);return n(t)}function a(e){if(!n.o(r,e)){var t=new Error("Cannot find module '"+e+"'");throw t.code="MODULE_NOT_FOUND",t}return r[e]}o.keys=function(){return Object.keys(r)},o.resolve=a,e.exports=o,o.id=803},2694:(e,t,n)=>{"use strict";var r=n(6925);function o(){}function a(){}a.resetWarningCache=o,e.exports=function(){function e(e,t,n,o,a,i){if(i!==r){var s=new Error("Calling PropTypes validators directly is not supported by the `prop-types` package. Use PropTypes.checkPropTypes() to call them. Read more at http://fb.me/use-check-prop-types");throw s.name="Invariant Violation",s}}function t(){return e}e.isRequired=e;var n={array:e,bigint:e,bool:e,func:e,number:e,object:e,string:e,symbol:e,any:e,arrayOf:t,element:e,elementType:e,instanceOf:t,node:e,objectOf:t,oneOf:t,oneOfType:t,shape:t,exact:t,checkPropTypes:a,resetWarningCache:o};return n.PropTypes=n,n}},5556:(e,t,n)=>{e.exports=n(2694)()},6925:e=>{"use strict";e.exports="SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED"},2551:(e,t,n)=>{"use strict";var r=n(6540),o=n(9982);function a(e){for(var t="https://reactjs.org/docs/error-decoder.html?invariant="+e,n=1;n<arguments.length;n++)t+="&args[]="+encodeURIComponent(arguments[n]);return"Minified React error #"+e+"; visit "+t+" for the full message or use the non-minified dev environment for full errors and additional helpful warnings."}var i=new Set,s={};function c(e,t){l(e,t),l(e+"Capture",t)}function l(e,t){for(s[e]=t,e=0;e<t.length;e++)i.add(t[e])}var u=!("undefined"==typeof window||void 0===window.document||void 0===window.document.createElement),d=Object.prototype.hasOwnProperty,p=/^[:A-Z_a-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD][:A-Z_a-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD\-.0-9\u00B7\u0300-\u036F\u203F-\u2040]*$/,f={},m={};function g(e,t,n,r,o,a,i){this.acceptsBooleans=2===t||3===t||4===t,this.attributeName=r,this.attributeNamespace=o,this.mustUseProperty=n,this.propertyName=e,this.type=t,this.sanitizeURL=a,this.removeEmptyString=i}var h={};"children dangerouslySetInnerHTML defaultValue defaultChecked innerHTML suppressContentEditableWarning suppressHydrationWarning style".split(" ").forEach((function(e){h[e]=new g(e,0,!1,e,null,!1,!1)})),[["acceptCharset","accept-charset"],["className","class"],["htmlFor","for"],["httpEquiv","http-equiv"]].forEach((function(e){var t=e[0];h[t]=new g(t,1,!1,e[1],null,!1,!1)})),["contentEditable","draggable","spellCheck","value"].forEach((function(e){h[e]=new g(e,2,!1,e.toLowerCase(),null,!1,!1)})),["autoReverse","externalResourcesRequired","focusable","preserveAlpha"].forEach((function(e){h[e]=new g(e,2,!1,e,null,!1,!1)})),"allowFullScreen async autoFocus autoPlay controls default defer disabled disablePictureInPicture disableRemotePlayback formNoValidate hidden loop noModule noValidate open playsInline readOnly required reversed scoped seamless itemScope".split(" ").forEach((function(e){h[e]=new g(e,3,!1,e.toLowerCase(),null,!1,!1)})),["checked","multiple","muted","selected"].forEach((function(e){h[e]=new g(e,3,!0,e,null,!1,!1)})),["capture","download"].forEach((function(e){h[e]=new g(e,4,!1,e,null,!1,!1)})),["cols","rows","size","span"].forEach((function(e){h[e]=new g(e,6,!1,e,null,!1,!1)})),["rowSpan","start"].forEach((function(e){h[e]=new g(e,5,!1,e.toLowerCase(),null,!1,!1)}));var b=/[\-:]([a-z])/g;function y(e){return e[1].toUpperCase()}function v(e,t,n,r){var o=h.hasOwnProperty(t)?h[t]:null;(null!==o?0!==o.type:r||!(2<t.length)||"o"!==t[0]&&"O"!==t[0]||"n"!==t[1]&&"N"!==t[1])&&(function(e,t,n,r){if(null==t||function(e,t,n,r){if(null!==n&&0===n.type)return!1;switch(typeof t){case"function":case"symbol":return!0;case"boolean":return!r&&(null!==n?!n.acceptsBooleans:"data-"!==(e=e.toLowerCase().slice(0,5))&&"aria-"!==e);default:return!1}}(e,t,n,r))return!0;if(r)return!1;if(null!==n)switch(n.type){case 3:return!t;case 4:return!1===t;case 5:return isNaN(t);case 6:return isNaN(t)||1>t}return!1}(t,n,o,r)&&(n=null),r||null===o?function(e){return!!d.call(m,e)||!d.call(f,e)&&(p.test(e)?m[e]=!0:(f[e]=!0,!1))}(t)&&(null===n?e.removeAttribute(t):e.setAttribute(t,""+n)):o.mustUseProperty?e[o.propertyName]=null===n?3!==o.type&&"":n:(t=o.attributeName,r=o.attributeNamespace,null===n?e.removeAttribute(t):(n=3===(o=o.type)||4===o&&!0===n?"":""+n,r?e.setAttributeNS(r,t,n):e.setAttribute(t,n))))}"accent-height alignment-baseline arabic-form baseline-shift cap-height clip-path clip-rule color-interpolation color-interpolation-filters color-profile color-rendering dominant-baseline enable-background fill-opacity fill-rule flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-name glyph-orientation-horizontal glyph-orientation-vertical horiz-adv-x horiz-origin-x image-rendering letter-spacing lighting-color marker-end marker-mid marker-start overline-position overline-thickness paint-order panose-1 pointer-events rendering-intent shape-rendering stop-color stop-opacity strikethrough-position strikethrough-thickness stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width text-anchor text-decoration text-rendering underline-position underline-thickness unicode-bidi unicode-range units-per-em v-alphabetic v-hanging v-ideographic v-mathematical vector-effect vert-adv-y vert-origin-x vert-origin-y word-spacing writing-mode xmlns:xlink x-height".split(" ").forEach((function(e){var t=e.replace(b,y);h[t]=new g(t,1,!1,e,null,!1,!1)})),"xlink:actuate xlink:arcrole xlink:role xlink:show xlink:title xlink:type".split(" ").forEach((function(e){var t=e.replace(b,y);h[t]=new g(t,1,!1,e,"http://www.w3.org/1999/xlink",!1,!1)})),["xml:base","xml:lang","xml:space"].forEach((function(e){var t=e.replace(b,y);h[t]=new g(t,1,!1,e,"http://www.w3.org/XML/1998/namespace",!1,!1)})),["tabIndex","crossOrigin"].forEach((function(e){h[e]=new g(e,1,!1,e.toLowerCase(),null,!1,!1)})),h.xlinkHref=new g("xlinkHref",1,!1,"xlink:href","http://www.w3.org/1999/xlink",!0,!1),["src","href","action","formAction"].forEach((function(e){h[e]=new g(e,1,!1,e.toLowerCase(),null,!0,!0)}));var w=r.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED,S=Symbol.for("react.element"),k=Symbol.for("react.portal"),x=Symbol.for("react.fragment"),_=Symbol.for("react.strict_mode"),E=Symbol.for("react.profiler"),j=Symbol.for("react.provider"),O=Symbol.for("react.context"),A=Symbol.for("react.forward_ref"),C=Symbol.for("react.suspense"),T=Symbol.for("react.suspense_list"),P=Symbol.for("react.memo"),I=Symbol.for("react.lazy");Symbol.for("react.scope"),Symbol.for("react.debug_trace_mode");var N=Symbol.for("react.offscreen");Symbol.for("react.legacy_hidden"),Symbol.for("react.cache"),Symbol.for("react.tracing_marker");var R=Symbol.iterator;function L(e){return null===e||"object"!=typeof e?null:"function"==typeof(e=R&&e[R]||e["@@iterator"])?e:null}var D,M=Object.assign;function F(e){if(void 0===D)try{throw Error()}catch(n){var t=n.stack.trim().match(/\n( *(at )?)/);D=t&&t[1]||""}return"\n"+D+e}var B=!1;function z(e,t){if(!e||B)return"";B=!0;var n=Error.prepareStackTrace;Error.prepareStackTrace=void 0;try{if(t)if(t=function(){throw Error()},Object.defineProperty(t.prototype,"props",{set:function(){throw Error()}}),"object"==typeof Reflect&&Reflect.construct){try{Reflect.construct(t,[])}catch(l){var r=l}Reflect.construct(e,[],t)}else{try{t.call()}catch(l){r=l}e.call(t.prototype)}else{try{throw Error()}catch(l){r=l}e()}}catch(l){if(l&&r&&"string"==typeof l.stack){for(var o=l.stack.split("\n"),a=r.stack.split("\n"),i=o.length-1,s=a.length-1;1<=i&&0<=s&&o[i]!==a[s];)s--;for(;1<=i&&0<=s;i--,s--)if(o[i]!==a[s]){if(1!==i||1!==s)do{if(i--,0>--s||o[i]!==a[s]){var c="\n"+o[i].replace(" at new "," at ");return e.displayName&&c.includes("<anonymous>")&&(c=c.replace("<anonymous>",e.displayName)),c}}while(1<=i&&0<=s);break}}}finally{B=!1,Error.prepareStackTrace=n}return(e=e?e.displayName||e.name:"")?F(e):""}function $(e){switch(e.tag){case 5:return F(e.type);case 16:return F("Lazy");case 13:return F("Suspense");case 19:return F("SuspenseList");case 0:case 2:case 15:return e=z(e.type,!1);case 11:return e=z(e.type.render,!1);case 1:return e=z(e.type,!0);default:return""}}function U(e){if(null==e)return null;if("function"==typeof e)return e.displayName||e.name||null;if("string"==typeof e)return e;switch(e){case x:return"Fragment";case k:return"Portal";case E:return"Profiler";case _:return"StrictMode";case C:return"Suspense";case T:return"SuspenseList"}if("object"==typeof e)switch(e.$$typeof){case O:return(e.displayName||"Context")+".Consumer";case j:return(e._context.displayName||"Context")+".Provider";case A:var t=e.render;return(e=e.displayName)||(e=""!==(e=t.displayName||t.name||"")?"ForwardRef("+e+")":"ForwardRef"),e;case P:return null!==(t=e.displayName||null)?t:U(e.type)||"Memo";case I:t=e._payload,e=e._init;try{return U(e(t))}catch(n){}}return null}function H(e){var t=e.type;switch(e.tag){case 24:return"Cache";case 9:return(t.displayName||"Context")+".Consumer";case 10:return(t._context.displayName||"Context")+".Provider";case 18:return"DehydratedFragment";case 11:return e=(e=t.render).displayName||e.name||"",t.displayName||(""!==e?"ForwardRef("+e+")":"ForwardRef");case 7:return"Fragment";case 5:return t;case 4:return"Portal";case 3:return"Root";case 6:return"Text";case 16:return U(t);case 8:return t===_?"StrictMode":"Mode";case 22:return"Offscreen";case 12:return"Profiler";case 21:return"Scope";case 13:return"Suspense";case 19:return"SuspenseList";case 25:return"TracingMarker";case 1:case 0:case 17:case 2:case 14:case 15:if("function"==typeof t)return t.displayName||t.name||null;if("string"==typeof t)return t}return null}function q(e){switch(typeof e){case"boolean":case"number":case"string":case"undefined":case"object":return e;default:return""}}function V(e){var t=e.type;return(e=e.nodeName)&&"input"===e.toLowerCase()&&("checkbox"===t||"radio"===t)}function W(e){e._valueTracker||(e._valueTracker=function(e){var t=V(e)?"checked":"value",n=Object.getOwnPropertyDescriptor(e.constructor.prototype,t),r=""+e[t];if(!e.hasOwnProperty(t)&&void 0!==n&&"function"==typeof n.get&&"function"==typeof n.set){var o=n.get,a=n.set;return Object.defineProperty(e,t,{configurable:!0,get:function(){return o.call(this)},set:function(e){r=""+e,a.call(this,e)}}),Object.defineProperty(e,t,{enumerable:n.enumerable}),{getValue:function(){return r},setValue:function(e){r=""+e},stopTracking:function(){e._valueTracker=null,delete e[t]}}}}(e))}function G(e){if(!e)return!1;var t=e._valueTracker;if(!t)return!0;var n=t.getValue(),r="";return e&&(r=V(e)?e.checked?"true":"false":e.value),(e=r)!==n&&(t.setValue(e),!0)}function K(e){if(void 0===(e=e||("undefined"!=typeof document?document:void 0)))return null;try{return e.activeElement||e.body}catch(t){return e.body}}function Y(e,t){var n=t.checked;return M({},t,{defaultChecked:void 0,defaultValue:void 0,value:void 0,checked:null!=n?n:e._wrapperState.initialChecked})}function Q(e,t){var n=null==t.defaultValue?"":t.defaultValue,r=null!=t.checked?t.checked:t.defaultChecked;n=q(null!=t.value?t.value:n),e._wrapperState={initialChecked:r,initialValue:n,controlled:"checkbox"===t.type||"radio"===t.type?null!=t.checked:null!=t.value}}function Z(e,t){null!=(t=t.checked)&&v(e,"checked",t,!1)}function X(e,t){Z(e,t);var n=q(t.value),r=t.type;if(null!=n)"number"===r?(0===n&&""===e.value||e.value!=n)&&(e.value=""+n):e.value!==""+n&&(e.value=""+n);else if("submit"===r||"reset"===r)return void e.removeAttribute("value");t.hasOwnProperty("value")?ee(e,t.type,n):t.hasOwnProperty("defaultValue")&&ee(e,t.type,q(t.defaultValue)),null==t.checked&&null!=t.defaultChecked&&(e.defaultChecked=!!t.defaultChecked)}function J(e,t,n){if(t.hasOwnProperty("value")||t.hasOwnProperty("defaultValue")){var r=t.type;if(!("submit"!==r&&"reset"!==r||void 0!==t.value&&null!==t.value))return;t=""+e._wrapperState.initialValue,n||t===e.value||(e.value=t),e.defaultValue=t}""!==(n=e.name)&&(e.name=""),e.defaultChecked=!!e._wrapperState.initialChecked,""!==n&&(e.name=n)}function ee(e,t,n){"number"===t&&K(e.ownerDocument)===e||(null==n?e.defaultValue=""+e._wrapperState.initialValue:e.defaultValue!==""+n&&(e.defaultValue=""+n))}var te=Array.isArray;function ne(e,t,n,r){if(e=e.options,t){t={};for(var o=0;o<n.length;o++)t["$"+n[o]]=!0;for(n=0;n<e.length;n++)o=t.hasOwnProperty("$"+e[n].value),e[n].selected!==o&&(e[n].selected=o),o&&r&&(e[n].defaultSelected=!0)}else{for(n=""+q(n),t=null,o=0;o<e.length;o++){if(e[o].value===n)return e[o].selected=!0,void(r&&(e[o].defaultSelected=!0));null!==t||e[o].disabled||(t=e[o])}null!==t&&(t.selected=!0)}}function re(e,t){if(null!=t.dangerouslySetInnerHTML)throw Error(a(91));return M({},t,{value:void 0,defaultValue:void 0,children:""+e._wrapperState.initialValue})}function oe(e,t){var n=t.value;if(null==n){if(n=t.children,t=t.defaultValue,null!=n){if(null!=t)throw Error(a(92));if(te(n)){if(1<n.length)throw Error(a(93));n=n[0]}t=n}null==t&&(t=""),n=t}e._wrapperState={initialValue:q(n)}}function ae(e,t){var n=q(t.value),r=q(t.defaultValue);null!=n&&((n=""+n)!==e.value&&(e.value=n),null==t.defaultValue&&e.defaultValue!==n&&(e.defaultValue=n)),null!=r&&(e.defaultValue=""+r)}function ie(e){var t=e.textContent;t===e._wrapperState.initialValue&&""!==t&&null!==t&&(e.value=t)}function se(e){switch(e){case"svg":return"http://www.w3.org/2000/svg";case"math":return"http://www.w3.org/1998/Math/MathML";default:return"http://www.w3.org/1999/xhtml"}}function ce(e,t){return null==e||"http://www.w3.org/1999/xhtml"===e?se(t):"http://www.w3.org/2000/svg"===e&&"foreignObject"===t?"http://www.w3.org/1999/xhtml":e}var le,ue,de=(ue=function(e,t){if("http://www.w3.org/2000/svg"!==e.namespaceURI||"innerHTML"in e)e.innerHTML=t;else{for((le=le||document.createElement("div")).innerHTML="<svg>"+t.valueOf().toString()+"</svg>",t=le.firstChild;e.firstChild;)e.removeChild(e.firstChild);for(;t.firstChild;)e.appendChild(t.firstChild)}},"undefined"!=typeof MSApp&&MSApp.execUnsafeLocalFunction?function(e,t,n,r){MSApp.execUnsafeLocalFunction((function(){return ue(e,t)}))}:ue);function pe(e,t){if(t){var n=e.firstChild;if(n&&n===e.lastChild&&3===n.nodeType)return void(n.nodeValue=t)}e.textContent=t}var fe={animationIterationCount:!0,aspectRatio:!0,borderImageOutset:!0,borderImageSlice:!0,borderImageWidth:!0,boxFlex:!0,boxFlexGroup:!0,boxOrdinalGroup:!0,columnCount:!0,columns:!0,flex:!0,flexGrow:!0,flexPositive:!0,flexShrink:!0,flexNegative:!0,flexOrder:!0,gridArea:!0,gridRow:!0,gridRowEnd:!0,gridRowSpan:!0,gridRowStart:!0,gridColumn:!0,gridColumnEnd:!0,gridColumnSpan:!0,gridColumnStart:!0,fontWeight:!0,lineClamp:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,tabSize:!0,widows:!0,zIndex:!0,zoom:!0,fillOpacity:!0,floodOpacity:!0,stopOpacity:!0,strokeDasharray:!0,strokeDashoffset:!0,strokeMiterlimit:!0,strokeOpacity:!0,strokeWidth:!0},me=["Webkit","ms","Moz","O"];function ge(e,t,n){return null==t||"boolean"==typeof t||""===t?"":n||"number"!=typeof t||0===t||fe.hasOwnProperty(e)&&fe[e]?(""+t).trim():t+"px"}function he(e,t){for(var n in e=e.style,t)if(t.hasOwnProperty(n)){var r=0===n.indexOf("--"),o=ge(n,t[n],r);"float"===n&&(n="cssFloat"),r?e.setProperty(n,o):e[n]=o}}Object.keys(fe).forEach((function(e){me.forEach((function(t){t=t+e.charAt(0).toUpperCase()+e.substring(1),fe[t]=fe[e]}))}));var be=M({menuitem:!0},{area:!0,base:!0,br:!0,col:!0,embed:!0,hr:!0,img:!0,input:!0,keygen:!0,link:!0,meta:!0,param:!0,source:!0,track:!0,wbr:!0});function ye(e,t){if(t){if(be[e]&&(null!=t.children||null!=t.dangerouslySetInnerHTML))throw Error(a(137,e));if(null!=t.dangerouslySetInnerHTML){if(null!=t.children)throw Error(a(60));if("object"!=typeof t.dangerouslySetInnerHTML||!("__html"in t.dangerouslySetInnerHTML))throw Error(a(61))}if(null!=t.style&&"object"!=typeof t.style)throw Error(a(62))}}function ve(e,t){if(-1===e.indexOf("-"))return"string"==typeof t.is;switch(e){case"annotation-xml":case"color-profile":case"font-face":case"font-face-src":case"font-face-uri":case"font-face-format":case"font-face-name":case"missing-glyph":return!1;default:return!0}}var we=null;function Se(e){return(e=e.target||e.srcElement||window).correspondingUseElement&&(e=e.correspondingUseElement),3===e.nodeType?e.parentNode:e}var ke=null,xe=null,_e=null;function Ee(e){if(e=wo(e)){if("function"!=typeof ke)throw Error(a(280));var t=e.stateNode;t&&(t=ko(t),ke(e.stateNode,e.type,t))}}function je(e){xe?_e?_e.push(e):_e=[e]:xe=e}function Oe(){if(xe){var e=xe,t=_e;if(_e=xe=null,Ee(e),t)for(e=0;e<t.length;e++)Ee(t[e])}}function Ae(e,t){return e(t)}function Ce(){}var Te=!1;function Pe(e,t,n){if(Te)return e(t,n);Te=!0;try{return Ae(e,t,n)}finally{Te=!1,(null!==xe||null!==_e)&&(Ce(),Oe())}}function Ie(e,t){var n=e.stateNode;if(null===n)return null;var r=ko(n);if(null===r)return null;n=r[t];e:switch(t){case"onClick":case"onClickCapture":case"onDoubleClick":case"onDoubleClickCapture":case"onMouseDown":case"onMouseDownCapture":case"onMouseMove":case"onMouseMoveCapture":case"onMouseUp":case"onMouseUpCapture":case"onMouseEnter":(r=!r.disabled)||(r=!("button"===(e=e.type)||"input"===e||"select"===e||"textarea"===e)),e=!r;break e;default:e=!1}if(e)return null;if(n&&"function"!=typeof n)throw Error(a(231,t,typeof n));return n}var Ne=!1;if(u)try{var Re={};Object.defineProperty(Re,"passive",{get:function(){Ne=!0}}),window.addEventListener("test",Re,Re),window.removeEventListener("test",Re,Re)}catch(ue){Ne=!1}function Le(e,t,n,r,o,a,i,s,c){var l=Array.prototype.slice.call(arguments,3);try{t.apply(n,l)}catch(u){this.onError(u)}}var De=!1,Me=null,Fe=!1,Be=null,ze={onError:function(e){De=!0,Me=e}};function $e(e,t,n,r,o,a,i,s,c){De=!1,Me=null,Le.apply(ze,arguments)}function Ue(e){var t=e,n=e;if(e.alternate)for(;t.return;)t=t.return;else{e=t;do{!!(4098&(t=e).flags)&&(n=t.return),e=t.return}while(e)}return 3===t.tag?n:null}function He(e){if(13===e.tag){var t=e.memoizedState;if(null===t&&(null!==(e=e.alternate)&&(t=e.memoizedState)),null!==t)return t.dehydrated}return null}function qe(e){if(Ue(e)!==e)throw Error(a(188))}function Ve(e){return null!==(e=function(e){var t=e.alternate;if(!t){if(null===(t=Ue(e)))throw Error(a(188));return t!==e?null:e}for(var n=e,r=t;;){var o=n.return;if(null===o)break;var i=o.alternate;if(null===i){if(null!==(r=o.return)){n=r;continue}break}if(o.child===i.child){for(i=o.child;i;){if(i===n)return qe(o),e;if(i===r)return qe(o),t;i=i.sibling}throw Error(a(188))}if(n.return!==r.return)n=o,r=i;else{for(var s=!1,c=o.child;c;){if(c===n){s=!0,n=o,r=i;break}if(c===r){s=!0,r=o,n=i;break}c=c.sibling}if(!s){for(c=i.child;c;){if(c===n){s=!0,n=i,r=o;break}if(c===r){s=!0,r=i,n=o;break}c=c.sibling}if(!s)throw Error(a(189))}}if(n.alternate!==r)throw Error(a(190))}if(3!==n.tag)throw Error(a(188));return n.stateNode.current===n?e:t}(e))?We(e):null}function We(e){if(5===e.tag||6===e.tag)return e;for(e=e.child;null!==e;){var t=We(e);if(null!==t)return t;e=e.sibling}return null}var Ge=o.unstable_scheduleCallback,Ke=o.unstable_cancelCallback,Ye=o.unstable_shouldYield,Qe=o.unstable_requestPaint,Ze=o.unstable_now,Xe=o.unstable_getCurrentPriorityLevel,Je=o.unstable_ImmediatePriority,et=o.unstable_UserBlockingPriority,tt=o.unstable_NormalPriority,nt=o.unstable_LowPriority,rt=o.unstable_IdlePriority,ot=null,at=null;var it=Math.clz32?Math.clz32:function(e){return e>>>=0,0===e?32:31-(st(e)/ct|0)|0},st=Math.log,ct=Math.LN2;var lt=64,ut=4194304;function dt(e){switch(e&-e){case 1:return 1;case 2:return 2;case 4:return 4;case 8:return 8;case 16:return 16;case 32:return 32;case 64:case 128:case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:case 262144:case 524288:case 1048576:case 2097152:return 4194240&e;case 4194304:case 8388608:case 16777216:case 33554432:case 67108864:return 130023424&e;case 134217728:return 134217728;case 268435456:return 268435456;case 536870912:return 536870912;case 1073741824:return 1073741824;default:return e}}function pt(e,t){var n=e.pendingLanes;if(0===n)return 0;var r=0,o=e.suspendedLanes,a=e.pingedLanes,i=268435455&n;if(0!==i){var s=i&~o;0!==s?r=dt(s):0!==(a&=i)&&(r=dt(a))}else 0!==(i=n&~o)?r=dt(i):0!==a&&(r=dt(a));if(0===r)return 0;if(0!==t&&t!==r&&!(t&o)&&((o=r&-r)>=(a=t&-t)||16===o&&4194240&a))return t;if(4&r&&(r|=16&n),0!==(t=e.entangledLanes))for(e=e.entanglements,t&=r;0<t;)o=1<<(n=31-it(t)),r|=e[n],t&=~o;return r}function ft(e,t){switch(e){case 1:case 2:case 4:return t+250;case 8:case 16:case 32:case 64:case 128:case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:case 262144:case 524288:case 1048576:case 2097152:return t+5e3;default:return-1}}function mt(e){return 0!==(e=-1073741825&e.pendingLanes)?e:1073741824&e?1073741824:0}function gt(){var e=lt;return!(4194240&(lt<<=1))&&(lt=64),e}function ht(e){for(var t=[],n=0;31>n;n++)t.push(e);return t}function bt(e,t,n){e.pendingLanes|=t,536870912!==t&&(e.suspendedLanes=0,e.pingedLanes=0),(e=e.eventTimes)[t=31-it(t)]=n}function yt(e,t){var n=e.entangledLanes|=t;for(e=e.entanglements;n;){var r=31-it(n),o=1<<r;o&t|e[r]&t&&(e[r]|=t),n&=~o}}var vt=0;function wt(e){return 1<(e&=-e)?4<e?268435455&e?16:536870912:4:1}var St,kt,xt,_t,Et,jt=!1,Ot=[],At=null,Ct=null,Tt=null,Pt=new Map,It=new Map,Nt=[],Rt="mousedown mouseup touchcancel touchend touchstart auxclick dblclick pointercancel pointerdown pointerup dragend dragstart drop compositionend compositionstart keydown keypress keyup input textInput copy cut paste click change contextmenu reset submit".split(" ");function Lt(e,t){switch(e){case"focusin":case"focusout":At=null;break;case"dragenter":case"dragleave":Ct=null;break;case"mouseover":case"mouseout":Tt=null;break;case"pointerover":case"pointerout":Pt.delete(t.pointerId);break;case"gotpointercapture":case"lostpointercapture":It.delete(t.pointerId)}}function Dt(e,t,n,r,o,a){return null===e||e.nativeEvent!==a?(e={blockedOn:t,domEventName:n,eventSystemFlags:r,nativeEvent:a,targetContainers:[o]},null!==t&&(null!==(t=wo(t))&&kt(t)),e):(e.eventSystemFlags|=r,t=e.targetContainers,null!==o&&-1===t.indexOf(o)&&t.push(o),e)}function Mt(e){var t=vo(e.target);if(null!==t){var n=Ue(t);if(null!==n)if(13===(t=n.tag)){if(null!==(t=He(n)))return e.blockedOn=t,void Et(e.priority,(function(){xt(n)}))}else if(3===t&&n.stateNode.current.memoizedState.isDehydrated)return void(e.blockedOn=3===n.tag?n.stateNode.containerInfo:null)}e.blockedOn=null}function Ft(e){if(null!==e.blockedOn)return!1;for(var t=e.targetContainers;0<t.length;){var n=Yt(e.domEventName,e.eventSystemFlags,t[0],e.nativeEvent);if(null!==n)return null!==(t=wo(n))&&kt(t),e.blockedOn=n,!1;var r=new(n=e.nativeEvent).constructor(n.type,n);we=r,n.target.dispatchEvent(r),we=null,t.shift()}return!0}function Bt(e,t,n){Ft(e)&&n.delete(t)}function zt(){jt=!1,null!==At&&Ft(At)&&(At=null),null!==Ct&&Ft(Ct)&&(Ct=null),null!==Tt&&Ft(Tt)&&(Tt=null),Pt.forEach(Bt),It.forEach(Bt)}function $t(e,t){e.blockedOn===t&&(e.blockedOn=null,jt||(jt=!0,o.unstable_scheduleCallback(o.unstable_NormalPriority,zt)))}function Ut(e){function t(t){return $t(t,e)}if(0<Ot.length){$t(Ot[0],e);for(var n=1;n<Ot.length;n++){var r=Ot[n];r.blockedOn===e&&(r.blockedOn=null)}}for(null!==At&&$t(At,e),null!==Ct&&$t(Ct,e),null!==Tt&&$t(Tt,e),Pt.forEach(t),It.forEach(t),n=0;n<Nt.length;n++)(r=Nt[n]).blockedOn===e&&(r.blockedOn=null);for(;0<Nt.length&&null===(n=Nt[0]).blockedOn;)Mt(n),null===n.blockedOn&&Nt.shift()}var Ht=w.ReactCurrentBatchConfig,qt=!0;function Vt(e,t,n,r){var o=vt,a=Ht.transition;Ht.transition=null;try{vt=1,Gt(e,t,n,r)}finally{vt=o,Ht.transition=a}}function Wt(e,t,n,r){var o=vt,a=Ht.transition;Ht.transition=null;try{vt=4,Gt(e,t,n,r)}finally{vt=o,Ht.transition=a}}function Gt(e,t,n,r){if(qt){var o=Yt(e,t,n,r);if(null===o)qr(e,t,r,Kt,n),Lt(e,r);else if(function(e,t,n,r,o){switch(t){case"focusin":return At=Dt(At,e,t,n,r,o),!0;case"dragenter":return Ct=Dt(Ct,e,t,n,r,o),!0;case"mouseover":return Tt=Dt(Tt,e,t,n,r,o),!0;case"pointerover":var a=o.pointerId;return Pt.set(a,Dt(Pt.get(a)||null,e,t,n,r,o)),!0;case"gotpointercapture":return a=o.pointerId,It.set(a,Dt(It.get(a)||null,e,t,n,r,o)),!0}return!1}(o,e,t,n,r))r.stopPropagation();else if(Lt(e,r),4&t&&-1<Rt.indexOf(e)){for(;null!==o;){var a=wo(o);if(null!==a&&St(a),null===(a=Yt(e,t,n,r))&&qr(e,t,r,Kt,n),a===o)break;o=a}null!==o&&r.stopPropagation()}else qr(e,t,r,null,n)}}var Kt=null;function Yt(e,t,n,r){if(Kt=null,null!==(e=vo(e=Se(r))))if(null===(t=Ue(e)))e=null;else if(13===(n=t.tag)){if(null!==(e=He(t)))return e;e=null}else if(3===n){if(t.stateNode.current.memoizedState.isDehydrated)return 3===t.tag?t.stateNode.containerInfo:null;e=null}else t!==e&&(e=null);return Kt=e,null}function Qt(e){switch(e){case"cancel":case"click":case"close":case"contextmenu":case"copy":case"cut":case"auxclick":case"dblclick":case"dragend":case"dragstart":case"drop":case"focusin":case"focusout":case"input":case"invalid":case"keydown":case"keypress":case"keyup":case"mousedown":case"mouseup":case"paste":case"pause":case"play":case"pointercancel":case"pointerdown":case"pointerup":case"ratechange":case"reset":case"resize":case"seeked":case"submit":case"touchcancel":case"touchend":case"touchstart":case"volumechange":case"change":case"selectionchange":case"textInput":case"compositionstart":case"compositionend":case"compositionupdate":case"beforeblur":case"afterblur":case"beforeinput":case"blur":case"fullscreenchange":case"focus":case"hashchange":case"popstate":case"select":case"selectstart":return 1;case"drag":case"dragenter":case"dragexit":case"dragleave":case"dragover":case"mousemove":case"mouseout":case"mouseover":case"pointermove":case"pointerout":case"pointerover":case"scroll":case"toggle":case"touchmove":case"wheel":case"mouseenter":case"mouseleave":case"pointerenter":case"pointerleave":return 4;case"message":switch(Xe()){case Je:return 1;case et:return 4;case tt:case nt:return 16;case rt:return 536870912;default:return 16}default:return 16}}var Zt=null,Xt=null,Jt=null;function en(){if(Jt)return Jt;var e,t,n=Xt,r=n.length,o="value"in Zt?Zt.value:Zt.textContent,a=o.length;for(e=0;e<r&&n[e]===o[e];e++);var i=r-e;for(t=1;t<=i&&n[r-t]===o[a-t];t++);return Jt=o.slice(e,1<t?1-t:void 0)}function tn(e){var t=e.keyCode;return"charCode"in e?0===(e=e.charCode)&&13===t&&(e=13):e=t,10===e&&(e=13),32<=e||13===e?e:0}function nn(){return!0}function rn(){return!1}function on(e){function t(t,n,r,o,a){for(var i in this._reactName=t,this._targetInst=r,this.type=n,this.nativeEvent=o,this.target=a,this.currentTarget=null,e)e.hasOwnProperty(i)&&(t=e[i],this[i]=t?t(o):o[i]);return this.isDefaultPrevented=(null!=o.defaultPrevented?o.defaultPrevented:!1===o.returnValue)?nn:rn,this.isPropagationStopped=rn,this}return M(t.prototype,{preventDefault:function(){this.defaultPrevented=!0;var e=this.nativeEvent;e&&(e.preventDefault?e.preventDefault():"unknown"!=typeof e.returnValue&&(e.returnValue=!1),this.isDefaultPrevented=nn)},stopPropagation:function(){var e=this.nativeEvent;e&&(e.stopPropagation?e.stopPropagation():"unknown"!=typeof e.cancelBubble&&(e.cancelBubble=!0),this.isPropagationStopped=nn)},persist:function(){},isPersistent:nn}),t}var an,sn,cn,ln={eventPhase:0,bubbles:0,cancelable:0,timeStamp:function(e){return e.timeStamp||Date.now()},defaultPrevented:0,isTrusted:0},un=on(ln),dn=M({},ln,{view:0,detail:0}),pn=on(dn),fn=M({},dn,{screenX:0,screenY:0,clientX:0,clientY:0,pageX:0,pageY:0,ctrlKey:0,shiftKey:0,altKey:0,metaKey:0,getModifierState:En,button:0,buttons:0,relatedTarget:function(e){return void 0===e.relatedTarget?e.fromElement===e.srcElement?e.toElement:e.fromElement:e.relatedTarget},movementX:function(e){return"movementX"in e?e.movementX:(e!==cn&&(cn&&"mousemove"===e.type?(an=e.screenX-cn.screenX,sn=e.screenY-cn.screenY):sn=an=0,cn=e),an)},movementY:function(e){return"movementY"in e?e.movementY:sn}}),mn=on(fn),gn=on(M({},fn,{dataTransfer:0})),hn=on(M({},dn,{relatedTarget:0})),bn=on(M({},ln,{animationName:0,elapsedTime:0,pseudoElement:0})),yn=M({},ln,{clipboardData:function(e){return"clipboardData"in e?e.clipboardData:window.clipboardData}}),vn=on(yn),wn=on(M({},ln,{data:0})),Sn={Esc:"Escape",Spacebar:" ",Left:"ArrowLeft",Up:"ArrowUp",Right:"ArrowRight",Down:"ArrowDown",Del:"Delete",Win:"OS",Menu:"ContextMenu",Apps:"ContextMenu",Scroll:"ScrollLock",MozPrintableKey:"Unidentified"},kn={8:"Backspace",9:"Tab",12:"Clear",13:"Enter",16:"Shift",17:"Control",18:"Alt",19:"Pause",20:"CapsLock",27:"Escape",32:" ",33:"PageUp",34:"PageDown",35:"End",36:"Home",37:"ArrowLeft",38:"ArrowUp",39:"ArrowRight",40:"ArrowDown",45:"Insert",46:"Delete",112:"F1",113:"F2",114:"F3",115:"F4",116:"F5",117:"F6",118:"F7",119:"F8",120:"F9",121:"F10",122:"F11",123:"F12",144:"NumLock",145:"ScrollLock",224:"Meta"},xn={Alt:"altKey",Control:"ctrlKey",Meta:"metaKey",Shift:"shiftKey"};function _n(e){var t=this.nativeEvent;return t.getModifierState?t.getModifierState(e):!!(e=xn[e])&&!!t[e]}function En(){return _n}var jn=M({},dn,{key:function(e){if(e.key){var t=Sn[e.key]||e.key;if("Unidentified"!==t)return t}return"keypress"===e.type?13===(e=tn(e))?"Enter":String.fromCharCode(e):"keydown"===e.type||"keyup"===e.type?kn[e.keyCode]||"Unidentified":""},code:0,location:0,ctrlKey:0,shiftKey:0,altKey:0,metaKey:0,repeat:0,locale:0,getModifierState:En,charCode:function(e){return"keypress"===e.type?tn(e):0},keyCode:function(e){return"keydown"===e.type||"keyup"===e.type?e.keyCode:0},which:function(e){return"keypress"===e.type?tn(e):"keydown"===e.type||"keyup"===e.type?e.keyCode:0}}),On=on(jn),An=on(M({},fn,{pointerId:0,width:0,height:0,pressure:0,tangentialPressure:0,tiltX:0,tiltY:0,twist:0,pointerType:0,isPrimary:0})),Cn=on(M({},dn,{touches:0,targetTouches:0,changedTouches:0,altKey:0,metaKey:0,ctrlKey:0,shiftKey:0,getModifierState:En})),Tn=on(M({},ln,{propertyName:0,elapsedTime:0,pseudoElement:0})),Pn=M({},fn,{deltaX:function(e){return"deltaX"in e?e.deltaX:"wheelDeltaX"in e?-e.wheelDeltaX:0},deltaY:function(e){return"deltaY"in e?e.deltaY:"wheelDeltaY"in e?-e.wheelDeltaY:"wheelDelta"in e?-e.wheelDelta:0},deltaZ:0,deltaMode:0}),In=on(Pn),Nn=[9,13,27,32],Rn=u&&"CompositionEvent"in window,Ln=null;u&&"documentMode"in document&&(Ln=document.documentMode);var Dn=u&&"TextEvent"in window&&!Ln,Mn=u&&(!Rn||Ln&&8<Ln&&11>=Ln),Fn=String.fromCharCode(32),Bn=!1;function zn(e,t){switch(e){case"keyup":return-1!==Nn.indexOf(t.keyCode);case"keydown":return 229!==t.keyCode;case"keypress":case"mousedown":case"focusout":return!0;default:return!1}}function $n(e){return"object"==typeof(e=e.detail)&&"data"in e?e.data:null}var Un=!1;var Hn={color:!0,date:!0,datetime:!0,"datetime-local":!0,email:!0,month:!0,number:!0,password:!0,range:!0,search:!0,tel:!0,text:!0,time:!0,url:!0,week:!0};function qn(e){var t=e&&e.nodeName&&e.nodeName.toLowerCase();return"input"===t?!!Hn[e.type]:"textarea"===t}function Vn(e,t,n,r){je(r),0<(t=Wr(t,"onChange")).length&&(n=new un("onChange","change",null,n,r),e.push({event:n,listeners:t}))}var Wn=null,Gn=null;function Kn(e){Fr(e,0)}function Yn(e){if(G(So(e)))return e}function Qn(e,t){if("change"===e)return t}var Zn=!1;if(u){var Xn;if(u){var Jn="oninput"in document;if(!Jn){var er=document.createElement("div");er.setAttribute("oninput","return;"),Jn="function"==typeof er.oninput}Xn=Jn}else Xn=!1;Zn=Xn&&(!document.documentMode||9<document.documentMode)}function tr(){Wn&&(Wn.detachEvent("onpropertychange",nr),Gn=Wn=null)}function nr(e){if("value"===e.propertyName&&Yn(Gn)){var t=[];Vn(t,Gn,e,Se(e)),Pe(Kn,t)}}function rr(e,t,n){"focusin"===e?(tr(),Gn=n,(Wn=t).attachEvent("onpropertychange",nr)):"focusout"===e&&tr()}function or(e){if("selectionchange"===e||"keyup"===e||"keydown"===e)return Yn(Gn)}function ar(e,t){if("click"===e)return Yn(t)}function ir(e,t){if("input"===e||"change"===e)return Yn(t)}var sr="function"==typeof Object.is?Object.is:function(e,t){return e===t&&(0!==e||1/e==1/t)||e!=e&&t!=t};function cr(e,t){if(sr(e,t))return!0;if("object"!=typeof e||null===e||"object"!=typeof t||null===t)return!1;var n=Object.keys(e),r=Object.keys(t);if(n.length!==r.length)return!1;for(r=0;r<n.length;r++){var o=n[r];if(!d.call(t,o)||!sr(e[o],t[o]))return!1}return!0}function lr(e){for(;e&&e.firstChild;)e=e.firstChild;return e}function ur(e,t){var n,r=lr(e);for(e=0;r;){if(3===r.nodeType){if(n=e+r.textContent.length,e<=t&&n>=t)return{node:r,offset:t-e};e=n}e:{for(;r;){if(r.nextSibling){r=r.nextSibling;break e}r=r.parentNode}r=void 0}r=lr(r)}}function dr(e,t){return!(!e||!t)&&(e===t||(!e||3!==e.nodeType)&&(t&&3===t.nodeType?dr(e,t.parentNode):"contains"in e?e.contains(t):!!e.compareDocumentPosition&&!!(16&e.compareDocumentPosition(t))))}function pr(){for(var e=window,t=K();t instanceof e.HTMLIFrameElement;){try{var n="string"==typeof t.contentWindow.location.href}catch(r){n=!1}if(!n)break;t=K((e=t.contentWindow).document)}return t}function fr(e){var t=e&&e.nodeName&&e.nodeName.toLowerCase();return t&&("input"===t&&("text"===e.type||"search"===e.type||"tel"===e.type||"url"===e.type||"password"===e.type)||"textarea"===t||"true"===e.contentEditable)}function mr(e){var t=pr(),n=e.focusedElem,r=e.selectionRange;if(t!==n&&n&&n.ownerDocument&&dr(n.ownerDocument.documentElement,n)){if(null!==r&&fr(n))if(t=r.start,void 0===(e=r.end)&&(e=t),"selectionStart"in n)n.selectionStart=t,n.selectionEnd=Math.min(e,n.value.length);else if((e=(t=n.ownerDocument||document)&&t.defaultView||window).getSelection){e=e.getSelection();var o=n.textContent.length,a=Math.min(r.start,o);r=void 0===r.end?a:Math.min(r.end,o),!e.extend&&a>r&&(o=r,r=a,a=o),o=ur(n,a);var i=ur(n,r);o&&i&&(1!==e.rangeCount||e.anchorNode!==o.node||e.anchorOffset!==o.offset||e.focusNode!==i.node||e.focusOffset!==i.offset)&&((t=t.createRange()).setStart(o.node,o.offset),e.removeAllRanges(),a>r?(e.addRange(t),e.extend(i.node,i.offset)):(t.setEnd(i.node,i.offset),e.addRange(t)))}for(t=[],e=n;e=e.parentNode;)1===e.nodeType&&t.push({element:e,left:e.scrollLeft,top:e.scrollTop});for("function"==typeof n.focus&&n.focus(),n=0;n<t.length;n++)(e=t[n]).element.scrollLeft=e.left,e.element.scrollTop=e.top}}var gr=u&&"documentMode"in document&&11>=document.documentMode,hr=null,br=null,yr=null,vr=!1;function wr(e,t,n){var r=n.window===n?n.document:9===n.nodeType?n:n.ownerDocument;vr||null==hr||hr!==K(r)||("selectionStart"in(r=hr)&&fr(r)?r={start:r.selectionStart,end:r.selectionEnd}:r={anchorNode:(r=(r.ownerDocument&&r.ownerDocument.defaultView||window).getSelection()).anchorNode,anchorOffset:r.anchorOffset,focusNode:r.focusNode,focusOffset:r.focusOffset},yr&&cr(yr,r)||(yr=r,0<(r=Wr(br,"onSelect")).length&&(t=new un("onSelect","select",null,t,n),e.push({event:t,listeners:r}),t.target=hr)))}function Sr(e,t){var n={};return n[e.toLowerCase()]=t.toLowerCase(),n["Webkit"+e]="webkit"+t,n["Moz"+e]="moz"+t,n}var kr={animationend:Sr("Animation","AnimationEnd"),animationiteration:Sr("Animation","AnimationIteration"),animationstart:Sr("Animation","AnimationStart"),transitionend:Sr("Transition","TransitionEnd")},xr={},_r={};function Er(e){if(xr[e])return xr[e];if(!kr[e])return e;var t,n=kr[e];for(t in n)if(n.hasOwnProperty(t)&&t in _r)return xr[e]=n[t];return e}u&&(_r=document.createElement("div").style,"AnimationEvent"in window||(delete kr.animationend.animation,delete kr.animationiteration.animation,delete kr.animationstart.animation),"TransitionEvent"in window||delete kr.transitionend.transition);var jr=Er("animationend"),Or=Er("animationiteration"),Ar=Er("animationstart"),Cr=Er("transitionend"),Tr=new Map,Pr="abort auxClick cancel canPlay canPlayThrough click close contextMenu copy cut drag dragEnd dragEnter dragExit dragLeave dragOver dragStart drop durationChange emptied encrypted ended error gotPointerCapture input invalid keyDown keyPress keyUp load loadedData loadedMetadata loadStart lostPointerCapture mouseDown mouseMove mouseOut mouseOver mouseUp paste pause play playing pointerCancel pointerDown pointerMove pointerOut pointerOver pointerUp progress rateChange reset resize seeked seeking stalled submit suspend timeUpdate touchCancel touchEnd touchStart volumeChange scroll toggle touchMove waiting wheel".split(" ");function Ir(e,t){Tr.set(e,t),c(t,[e])}for(var Nr=0;Nr<Pr.length;Nr++){var Rr=Pr[Nr];Ir(Rr.toLowerCase(),"on"+(Rr[0].toUpperCase()+Rr.slice(1)))}Ir(jr,"onAnimationEnd"),Ir(Or,"onAnimationIteration"),Ir(Ar,"onAnimationStart"),Ir("dblclick","onDoubleClick"),Ir("focusin","onFocus"),Ir("focusout","onBlur"),Ir(Cr,"onTransitionEnd"),l("onMouseEnter",["mouseout","mouseover"]),l("onMouseLeave",["mouseout","mouseover"]),l("onPointerEnter",["pointerout","pointerover"]),l("onPointerLeave",["pointerout","pointerover"]),c("onChange","change click focusin focusout input keydown keyup selectionchange".split(" ")),c("onSelect","focusout contextmenu dragend focusin keydown keyup mousedown mouseup selectionchange".split(" ")),c("onBeforeInput",["compositionend","keypress","textInput","paste"]),c("onCompositionEnd","compositionend focusout keydown keypress keyup mousedown".split(" ")),c("onCompositionStart","compositionstart focusout keydown keypress keyup mousedown".split(" ")),c("onCompositionUpdate","compositionupdate focusout keydown keypress keyup mousedown".split(" "));var Lr="abort canplay canplaythrough durationchange emptied encrypted ended error loadeddata loadedmetadata loadstart pause play playing progress ratechange resize seeked seeking stalled suspend timeupdate volumechange waiting".split(" "),Dr=new Set("cancel close invalid load scroll toggle".split(" ").concat(Lr));function Mr(e,t,n){var r=e.type||"unknown-event";e.currentTarget=n,function(e,t,n,r,o,i,s,c,l){if($e.apply(this,arguments),De){if(!De)throw Error(a(198));var u=Me;De=!1,Me=null,Fe||(Fe=!0,Be=u)}}(r,t,void 0,e),e.currentTarget=null}function Fr(e,t){t=!!(4&t);for(var n=0;n<e.length;n++){var r=e[n],o=r.event;r=r.listeners;e:{var a=void 0;if(t)for(var i=r.length-1;0<=i;i--){var s=r[i],c=s.instance,l=s.currentTarget;if(s=s.listener,c!==a&&o.isPropagationStopped())break e;Mr(o,s,l),a=c}else for(i=0;i<r.length;i++){if(c=(s=r[i]).instance,l=s.currentTarget,s=s.listener,c!==a&&o.isPropagationStopped())break e;Mr(o,s,l),a=c}}}if(Fe)throw e=Be,Fe=!1,Be=null,e}function Br(e,t){var n=t[ho];void 0===n&&(n=t[ho]=new Set);var r=e+"__bubble";n.has(r)||(Hr(t,e,2,!1),n.add(r))}function zr(e,t,n){var r=0;t&&(r|=4),Hr(n,e,r,t)}var $r="_reactListening"+Math.random().toString(36).slice(2);function Ur(e){if(!e[$r]){e[$r]=!0,i.forEach((function(t){"selectionchange"!==t&&(Dr.has(t)||zr(t,!1,e),zr(t,!0,e))}));var t=9===e.nodeType?e:e.ownerDocument;null===t||t[$r]||(t[$r]=!0,zr("selectionchange",!1,t))}}function Hr(e,t,n,r){switch(Qt(t)){case 1:var o=Vt;break;case 4:o=Wt;break;default:o=Gt}n=o.bind(null,t,n,e),o=void 0,!Ne||"touchstart"!==t&&"touchmove"!==t&&"wheel"!==t||(o=!0),r?void 0!==o?e.addEventListener(t,n,{capture:!0,passive:o}):e.addEventListener(t,n,!0):void 0!==o?e.addEventListener(t,n,{passive:o}):e.addEventListener(t,n,!1)}function qr(e,t,n,r,o){var a=r;if(!(1&t||2&t||null===r))e:for(;;){if(null===r)return;var i=r.tag;if(3===i||4===i){var s=r.stateNode.containerInfo;if(s===o||8===s.nodeType&&s.parentNode===o)break;if(4===i)for(i=r.return;null!==i;){var c=i.tag;if((3===c||4===c)&&((c=i.stateNode.containerInfo)===o||8===c.nodeType&&c.parentNode===o))return;i=i.return}for(;null!==s;){if(null===(i=vo(s)))return;if(5===(c=i.tag)||6===c){r=a=i;continue e}s=s.parentNode}}r=r.return}Pe((function(){var r=a,o=Se(n),i=[];e:{var s=Tr.get(e);if(void 0!==s){var c=un,l=e;switch(e){case"keypress":if(0===tn(n))break e;case"keydown":case"keyup":c=On;break;case"focusin":l="focus",c=hn;break;case"focusout":l="blur",c=hn;break;case"beforeblur":case"afterblur":c=hn;break;case"click":if(2===n.button)break e;case"auxclick":case"dblclick":case"mousedown":case"mousemove":case"mouseup":case"mouseout":case"mouseover":case"contextmenu":c=mn;break;case"drag":case"dragend":case"dragenter":case"dragexit":case"dragleave":case"dragover":case"dragstart":case"drop":c=gn;break;case"touchcancel":case"touchend":case"touchmove":case"touchstart":c=Cn;break;case jr:case Or:case Ar:c=bn;break;case Cr:c=Tn;break;case"scroll":c=pn;break;case"wheel":c=In;break;case"copy":case"cut":case"paste":c=vn;break;case"gotpointercapture":case"lostpointercapture":case"pointercancel":case"pointerdown":case"pointermove":case"pointerout":case"pointerover":case"pointerup":c=An}var u=!!(4&t),d=!u&&"scroll"===e,p=u?null!==s?s+"Capture":null:s;u=[];for(var f,m=r;null!==m;){var g=(f=m).stateNode;if(5===f.tag&&null!==g&&(f=g,null!==p&&(null!=(g=Ie(m,p))&&u.push(Vr(m,g,f)))),d)break;m=m.return}0<u.length&&(s=new c(s,l,null,n,o),i.push({event:s,listeners:u}))}}if(!(7&t)){if(c="mouseout"===e||"pointerout"===e,(!(s="mouseover"===e||"pointerover"===e)||n===we||!(l=n.relatedTarget||n.fromElement)||!vo(l)&&!l[go])&&(c||s)&&(s=o.window===o?o:(s=o.ownerDocument)?s.defaultView||s.parentWindow:window,c?(c=r,null!==(l=(l=n.relatedTarget||n.toElement)?vo(l):null)&&(l!==(d=Ue(l))||5!==l.tag&&6!==l.tag)&&(l=null)):(c=null,l=r),c!==l)){if(u=mn,g="onMouseLeave",p="onMouseEnter",m="mouse","pointerout"!==e&&"pointerover"!==e||(u=An,g="onPointerLeave",p="onPointerEnter",m="pointer"),d=null==c?s:So(c),f=null==l?s:So(l),(s=new u(g,m+"leave",c,n,o)).target=d,s.relatedTarget=f,g=null,vo(o)===r&&((u=new u(p,m+"enter",l,n,o)).target=f,u.relatedTarget=d,g=u),d=g,c&&l)e:{for(p=l,m=0,f=u=c;f;f=Gr(f))m++;for(f=0,g=p;g;g=Gr(g))f++;for(;0<m-f;)u=Gr(u),m--;for(;0<f-m;)p=Gr(p),f--;for(;m--;){if(u===p||null!==p&&u===p.alternate)break e;u=Gr(u),p=Gr(p)}u=null}else u=null;null!==c&&Kr(i,s,c,u,!1),null!==l&&null!==d&&Kr(i,d,l,u,!0)}if("select"===(c=(s=r?So(r):window).nodeName&&s.nodeName.toLowerCase())||"input"===c&&"file"===s.type)var h=Qn;else if(qn(s))if(Zn)h=ir;else{h=or;var b=rr}else(c=s.nodeName)&&"input"===c.toLowerCase()&&("checkbox"===s.type||"radio"===s.type)&&(h=ar);switch(h&&(h=h(e,r))?Vn(i,h,n,o):(b&&b(e,s,r),"focusout"===e&&(b=s._wrapperState)&&b.controlled&&"number"===s.type&&ee(s,"number",s.value)),b=r?So(r):window,e){case"focusin":(qn(b)||"true"===b.contentEditable)&&(hr=b,br=r,yr=null);break;case"focusout":yr=br=hr=null;break;case"mousedown":vr=!0;break;case"contextmenu":case"mouseup":case"dragend":vr=!1,wr(i,n,o);break;case"selectionchange":if(gr)break;case"keydown":case"keyup":wr(i,n,o)}var y;if(Rn)e:{switch(e){case"compositionstart":var v="onCompositionStart";break e;case"compositionend":v="onCompositionEnd";break e;case"compositionupdate":v="onCompositionUpdate";break e}v=void 0}else Un?zn(e,n)&&(v="onCompositionEnd"):"keydown"===e&&229===n.keyCode&&(v="onCompositionStart");v&&(Mn&&"ko"!==n.locale&&(Un||"onCompositionStart"!==v?"onCompositionEnd"===v&&Un&&(y=en()):(Xt="value"in(Zt=o)?Zt.value:Zt.textContent,Un=!0)),0<(b=Wr(r,v)).length&&(v=new wn(v,e,null,n,o),i.push({event:v,listeners:b}),y?v.data=y:null!==(y=$n(n))&&(v.data=y))),(y=Dn?function(e,t){switch(e){case"compositionend":return $n(t);case"keypress":return 32!==t.which?null:(Bn=!0,Fn);case"textInput":return(e=t.data)===Fn&&Bn?null:e;default:return null}}(e,n):function(e,t){if(Un)return"compositionend"===e||!Rn&&zn(e,t)?(e=en(),Jt=Xt=Zt=null,Un=!1,e):null;switch(e){case"paste":default:return null;case"keypress":if(!(t.ctrlKey||t.altKey||t.metaKey)||t.ctrlKey&&t.altKey){if(t.char&&1<t.char.length)return t.char;if(t.which)return String.fromCharCode(t.which)}return null;case"compositionend":return Mn&&"ko"!==t.locale?null:t.data}}(e,n))&&(0<(r=Wr(r,"onBeforeInput")).length&&(o=new wn("onBeforeInput","beforeinput",null,n,o),i.push({event:o,listeners:r}),o.data=y))}Fr(i,t)}))}function Vr(e,t,n){return{instance:e,listener:t,currentTarget:n}}function Wr(e,t){for(var n=t+"Capture",r=[];null!==e;){var o=e,a=o.stateNode;5===o.tag&&null!==a&&(o=a,null!=(a=Ie(e,n))&&r.unshift(Vr(e,a,o)),null!=(a=Ie(e,t))&&r.push(Vr(e,a,o))),e=e.return}return r}function Gr(e){if(null===e)return null;do{e=e.return}while(e&&5!==e.tag);return e||null}function Kr(e,t,n,r,o){for(var a=t._reactName,i=[];null!==n&&n!==r;){var s=n,c=s.alternate,l=s.stateNode;if(null!==c&&c===r)break;5===s.tag&&null!==l&&(s=l,o?null!=(c=Ie(n,a))&&i.unshift(Vr(n,c,s)):o||null!=(c=Ie(n,a))&&i.push(Vr(n,c,s))),n=n.return}0!==i.length&&e.push({event:t,listeners:i})}var Yr=/\r\n?/g,Qr=/\u0000|\uFFFD/g;function Zr(e){return("string"==typeof e?e:""+e).replace(Yr,"\n").replace(Qr,"")}function Xr(e,t,n){if(t=Zr(t),Zr(e)!==t&&n)throw Error(a(425))}function Jr(){}var eo=null,to=null;function no(e,t){return"textarea"===e||"noscript"===e||"string"==typeof t.children||"number"==typeof t.children||"object"==typeof t.dangerouslySetInnerHTML&&null!==t.dangerouslySetInnerHTML&&null!=t.dangerouslySetInnerHTML.__html}var ro="function"==typeof setTimeout?setTimeout:void 0,oo="function"==typeof clearTimeout?clearTimeout:void 0,ao="function"==typeof Promise?Promise:void 0,io="function"==typeof queueMicrotask?queueMicrotask:void 0!==ao?function(e){return ao.resolve(null).then(e).catch(so)}:ro;function so(e){setTimeout((function(){throw e}))}function co(e,t){var n=t,r=0;do{var o=n.nextSibling;if(e.removeChild(n),o&&8===o.nodeType)if("/$"===(n=o.data)){if(0===r)return e.removeChild(o),void Ut(t);r--}else"$"!==n&&"$?"!==n&&"$!"!==n||r++;n=o}while(n);Ut(t)}function lo(e){for(;null!=e;e=e.nextSibling){var t=e.nodeType;if(1===t||3===t)break;if(8===t){if("$"===(t=e.data)||"$!"===t||"$?"===t)break;if("/$"===t)return null}}return e}function uo(e){e=e.previousSibling;for(var t=0;e;){if(8===e.nodeType){var n=e.data;if("$"===n||"$!"===n||"$?"===n){if(0===t)return e;t--}else"/$"===n&&t++}e=e.previousSibling}return null}var po=Math.random().toString(36).slice(2),fo="__reactFiber$"+po,mo="__reactProps$"+po,go="__reactContainer$"+po,ho="__reactEvents$"+po,bo="__reactListeners$"+po,yo="__reactHandles$"+po;function vo(e){var t=e[fo];if(t)return t;for(var n=e.parentNode;n;){if(t=n[go]||n[fo]){if(n=t.alternate,null!==t.child||null!==n&&null!==n.child)for(e=uo(e);null!==e;){if(n=e[fo])return n;e=uo(e)}return t}n=(e=n).parentNode}return null}function wo(e){return!(e=e[fo]||e[go])||5!==e.tag&&6!==e.tag&&13!==e.tag&&3!==e.tag?null:e}function So(e){if(5===e.tag||6===e.tag)return e.stateNode;throw Error(a(33))}function ko(e){return e[mo]||null}var xo=[],_o=-1;function Eo(e){return{current:e}}function jo(e){0>_o||(e.current=xo[_o],xo[_o]=null,_o--)}function Oo(e,t){_o++,xo[_o]=e.current,e.current=t}var Ao={},Co=Eo(Ao),To=Eo(!1),Po=Ao;function Io(e,t){var n=e.type.contextTypes;if(!n)return Ao;var r=e.stateNode;if(r&&r.__reactInternalMemoizedUnmaskedChildContext===t)return r.__reactInternalMemoizedMaskedChildContext;var o,a={};for(o in n)a[o]=t[o];return r&&((e=e.stateNode).__reactInternalMemoizedUnmaskedChildContext=t,e.__reactInternalMemoizedMaskedChildContext=a),a}function No(e){return null!=(e=e.childContextTypes)}function Ro(){jo(To),jo(Co)}function Lo(e,t,n){if(Co.current!==Ao)throw Error(a(168));Oo(Co,t),Oo(To,n)}function Do(e,t,n){var r=e.stateNode;if(t=t.childContextTypes,"function"!=typeof r.getChildContext)return n;for(var o in r=r.getChildContext())if(!(o in t))throw Error(a(108,H(e)||"Unknown",o));return M({},n,r)}function Mo(e){return e=(e=e.stateNode)&&e.__reactInternalMemoizedMergedChildContext||Ao,Po=Co.current,Oo(Co,e),Oo(To,To.current),!0}function Fo(e,t,n){var r=e.stateNode;if(!r)throw Error(a(169));n?(e=Do(e,t,Po),r.__reactInternalMemoizedMergedChildContext=e,jo(To),jo(Co),Oo(Co,e)):jo(To),Oo(To,n)}var Bo=null,zo=!1,$o=!1;function Uo(e){null===Bo?Bo=[e]:Bo.push(e)}function Ho(){if(!$o&&null!==Bo){$o=!0;var e=0,t=vt;try{var n=Bo;for(vt=1;e<n.length;e++){var r=n[e];do{r=r(!0)}while(null!==r)}Bo=null,zo=!1}catch(o){throw null!==Bo&&(Bo=Bo.slice(e+1)),Ge(Je,Ho),o}finally{vt=t,$o=!1}}return null}var qo=[],Vo=0,Wo=null,Go=0,Ko=[],Yo=0,Qo=null,Zo=1,Xo="";function Jo(e,t){qo[Vo++]=Go,qo[Vo++]=Wo,Wo=e,Go=t}function ea(e,t,n){Ko[Yo++]=Zo,Ko[Yo++]=Xo,Ko[Yo++]=Qo,Qo=e;var r=Zo;e=Xo;var o=32-it(r)-1;r&=~(1<<o),n+=1;var a=32-it(t)+o;if(30<a){var i=o-o%5;a=(r&(1<<i)-1).toString(32),r>>=i,o-=i,Zo=1<<32-it(t)+o|n<<o|r,Xo=a+e}else Zo=1<<a|n<<o|r,Xo=e}function ta(e){null!==e.return&&(Jo(e,1),ea(e,1,0))}function na(e){for(;e===Wo;)Wo=qo[--Vo],qo[Vo]=null,Go=qo[--Vo],qo[Vo]=null;for(;e===Qo;)Qo=Ko[--Yo],Ko[Yo]=null,Xo=Ko[--Yo],Ko[Yo]=null,Zo=Ko[--Yo],Ko[Yo]=null}var ra=null,oa=null,aa=!1,ia=null;function sa(e,t){var n=Pl(5,null,null,0);n.elementType="DELETED",n.stateNode=t,n.return=e,null===(t=e.deletions)?(e.deletions=[n],e.flags|=16):t.push(n)}function ca(e,t){switch(e.tag){case 5:var n=e.type;return null!==(t=1!==t.nodeType||n.toLowerCase()!==t.nodeName.toLowerCase()?null:t)&&(e.stateNode=t,ra=e,oa=lo(t.firstChild),!0);case 6:return null!==(t=""===e.pendingProps||3!==t.nodeType?null:t)&&(e.stateNode=t,ra=e,oa=null,!0);case 13:return null!==(t=8!==t.nodeType?null:t)&&(n=null!==Qo?{id:Zo,overflow:Xo}:null,e.memoizedState={dehydrated:t,treeContext:n,retryLane:1073741824},(n=Pl(18,null,null,0)).stateNode=t,n.return=e,e.child=n,ra=e,oa=null,!0);default:return!1}}function la(e){return!(!(1&e.mode)||128&e.flags)}function ua(e){if(aa){var t=oa;if(t){var n=t;if(!ca(e,t)){if(la(e))throw Error(a(418));t=lo(n.nextSibling);var r=ra;t&&ca(e,t)?sa(r,n):(e.flags=-4097&e.flags|2,aa=!1,ra=e)}}else{if(la(e))throw Error(a(418));e.flags=-4097&e.flags|2,aa=!1,ra=e}}}function da(e){for(e=e.return;null!==e&&5!==e.tag&&3!==e.tag&&13!==e.tag;)e=e.return;ra=e}function pa(e){if(e!==ra)return!1;if(!aa)return da(e),aa=!0,!1;var t;if((t=3!==e.tag)&&!(t=5!==e.tag)&&(t="head"!==(t=e.type)&&"body"!==t&&!no(e.type,e.memoizedProps)),t&&(t=oa)){if(la(e))throw fa(),Error(a(418));for(;t;)sa(e,t),t=lo(t.nextSibling)}if(da(e),13===e.tag){if(!(e=null!==(e=e.memoizedState)?e.dehydrated:null))throw Error(a(317));e:{for(e=e.nextSibling,t=0;e;){if(8===e.nodeType){var n=e.data;if("/$"===n){if(0===t){oa=lo(e.nextSibling);break e}t--}else"$"!==n&&"$!"!==n&&"$?"!==n||t++}e=e.nextSibling}oa=null}}else oa=ra?lo(e.stateNode.nextSibling):null;return!0}function fa(){for(var e=oa;e;)e=lo(e.nextSibling)}function ma(){oa=ra=null,aa=!1}function ga(e){null===ia?ia=[e]:ia.push(e)}var ha=w.ReactCurrentBatchConfig;function ba(e,t,n){if(null!==(e=n.ref)&&"function"!=typeof e&&"object"!=typeof e){if(n._owner){if(n=n._owner){if(1!==n.tag)throw Error(a(309));var r=n.stateNode}if(!r)throw Error(a(147,e));var o=r,i=""+e;return null!==t&&null!==t.ref&&"function"==typeof t.ref&&t.ref._stringRef===i?t.ref:(t=function(e){var t=o.refs;null===e?delete t[i]:t[i]=e},t._stringRef=i,t)}if("string"!=typeof e)throw Error(a(284));if(!n._owner)throw Error(a(290,e))}return e}function ya(e,t){throw e=Object.prototype.toString.call(t),Error(a(31,"[object Object]"===e?"object with keys {"+Object.keys(t).join(", ")+"}":e))}function va(e){return(0,e._init)(e._payload)}function wa(e){function t(t,n){if(e){var r=t.deletions;null===r?(t.deletions=[n],t.flags|=16):r.push(n)}}function n(n,r){if(!e)return null;for(;null!==r;)t(n,r),r=r.sibling;return null}function r(e,t){for(e=new Map;null!==t;)null!==t.key?e.set(t.key,t):e.set(t.index,t),t=t.sibling;return e}function o(e,t){return(e=Nl(e,t)).index=0,e.sibling=null,e}function i(t,n,r){return t.index=r,e?null!==(r=t.alternate)?(r=r.index)<n?(t.flags|=2,n):r:(t.flags|=2,n):(t.flags|=1048576,n)}function s(t){return e&&null===t.alternate&&(t.flags|=2),t}function c(e,t,n,r){return null===t||6!==t.tag?((t=Ml(n,e.mode,r)).return=e,t):((t=o(t,n)).return=e,t)}function l(e,t,n,r){var a=n.type;return a===x?d(e,t,n.props.children,r,n.key):null!==t&&(t.elementType===a||"object"==typeof a&&null!==a&&a.$$typeof===I&&va(a)===t.type)?((r=o(t,n.props)).ref=ba(e,t,n),r.return=e,r):((r=Rl(n.type,n.key,n.props,null,e.mode,r)).ref=ba(e,t,n),r.return=e,r)}function u(e,t,n,r){return null===t||4!==t.tag||t.stateNode.containerInfo!==n.containerInfo||t.stateNode.implementation!==n.implementation?((t=Fl(n,e.mode,r)).return=e,t):((t=o(t,n.children||[])).return=e,t)}function d(e,t,n,r,a){return null===t||7!==t.tag?((t=Ll(n,e.mode,r,a)).return=e,t):((t=o(t,n)).return=e,t)}function p(e,t,n){if("string"==typeof t&&""!==t||"number"==typeof t)return(t=Ml(""+t,e.mode,n)).return=e,t;if("object"==typeof t&&null!==t){switch(t.$$typeof){case S:return(n=Rl(t.type,t.key,t.props,null,e.mode,n)).ref=ba(e,null,t),n.return=e,n;case k:return(t=Fl(t,e.mode,n)).return=e,t;case I:return p(e,(0,t._init)(t._payload),n)}if(te(t)||L(t))return(t=Ll(t,e.mode,n,null)).return=e,t;ya(e,t)}return null}function f(e,t,n,r){var o=null!==t?t.key:null;if("string"==typeof n&&""!==n||"number"==typeof n)return null!==o?null:c(e,t,""+n,r);if("object"==typeof n&&null!==n){switch(n.$$typeof){case S:return n.key===o?l(e,t,n,r):null;case k:return n.key===o?u(e,t,n,r):null;case I:return f(e,t,(o=n._init)(n._payload),r)}if(te(n)||L(n))return null!==o?null:d(e,t,n,r,null);ya(e,n)}return null}function m(e,t,n,r,o){if("string"==typeof r&&""!==r||"number"==typeof r)return c(t,e=e.get(n)||null,""+r,o);if("object"==typeof r&&null!==r){switch(r.$$typeof){case S:return l(t,e=e.get(null===r.key?n:r.key)||null,r,o);case k:return u(t,e=e.get(null===r.key?n:r.key)||null,r,o);case I:return m(e,t,n,(0,r._init)(r._payload),o)}if(te(r)||L(r))return d(t,e=e.get(n)||null,r,o,null);ya(t,r)}return null}function g(o,a,s,c){for(var l=null,u=null,d=a,g=a=0,h=null;null!==d&&g<s.length;g++){d.index>g?(h=d,d=null):h=d.sibling;var b=f(o,d,s[g],c);if(null===b){null===d&&(d=h);break}e&&d&&null===b.alternate&&t(o,d),a=i(b,a,g),null===u?l=b:u.sibling=b,u=b,d=h}if(g===s.length)return n(o,d),aa&&Jo(o,g),l;if(null===d){for(;g<s.length;g++)null!==(d=p(o,s[g],c))&&(a=i(d,a,g),null===u?l=d:u.sibling=d,u=d);return aa&&Jo(o,g),l}for(d=r(o,d);g<s.length;g++)null!==(h=m(d,o,g,s[g],c))&&(e&&null!==h.alternate&&d.delete(null===h.key?g:h.key),a=i(h,a,g),null===u?l=h:u.sibling=h,u=h);return e&&d.forEach((function(e){return t(o,e)})),aa&&Jo(o,g),l}function h(o,s,c,l){var u=L(c);if("function"!=typeof u)throw Error(a(150));if(null==(c=u.call(c)))throw Error(a(151));for(var d=u=null,g=s,h=s=0,b=null,y=c.next();null!==g&&!y.done;h++,y=c.next()){g.index>h?(b=g,g=null):b=g.sibling;var v=f(o,g,y.value,l);if(null===v){null===g&&(g=b);break}e&&g&&null===v.alternate&&t(o,g),s=i(v,s,h),null===d?u=v:d.sibling=v,d=v,g=b}if(y.done)return n(o,g),aa&&Jo(o,h),u;if(null===g){for(;!y.done;h++,y=c.next())null!==(y=p(o,y.value,l))&&(s=i(y,s,h),null===d?u=y:d.sibling=y,d=y);return aa&&Jo(o,h),u}for(g=r(o,g);!y.done;h++,y=c.next())null!==(y=m(g,o,h,y.value,l))&&(e&&null!==y.alternate&&g.delete(null===y.key?h:y.key),s=i(y,s,h),null===d?u=y:d.sibling=y,d=y);return e&&g.forEach((function(e){return t(o,e)})),aa&&Jo(o,h),u}return function e(r,a,i,c){if("object"==typeof i&&null!==i&&i.type===x&&null===i.key&&(i=i.props.children),"object"==typeof i&&null!==i){switch(i.$$typeof){case S:e:{for(var l=i.key,u=a;null!==u;){if(u.key===l){if((l=i.type)===x){if(7===u.tag){n(r,u.sibling),(a=o(u,i.props.children)).return=r,r=a;break e}}else if(u.elementType===l||"object"==typeof l&&null!==l&&l.$$typeof===I&&va(l)===u.type){n(r,u.sibling),(a=o(u,i.props)).ref=ba(r,u,i),a.return=r,r=a;break e}n(r,u);break}t(r,u),u=u.sibling}i.type===x?((a=Ll(i.props.children,r.mode,c,i.key)).return=r,r=a):((c=Rl(i.type,i.key,i.props,null,r.mode,c)).ref=ba(r,a,i),c.return=r,r=c)}return s(r);case k:e:{for(u=i.key;null!==a;){if(a.key===u){if(4===a.tag&&a.stateNode.containerInfo===i.containerInfo&&a.stateNode.implementation===i.implementation){n(r,a.sibling),(a=o(a,i.children||[])).return=r,r=a;break e}n(r,a);break}t(r,a),a=a.sibling}(a=Fl(i,r.mode,c)).return=r,r=a}return s(r);case I:return e(r,a,(u=i._init)(i._payload),c)}if(te(i))return g(r,a,i,c);if(L(i))return h(r,a,i,c);ya(r,i)}return"string"==typeof i&&""!==i||"number"==typeof i?(i=""+i,null!==a&&6===a.tag?(n(r,a.sibling),(a=o(a,i)).return=r,r=a):(n(r,a),(a=Ml(i,r.mode,c)).return=r,r=a),s(r)):n(r,a)}}var Sa=wa(!0),ka=wa(!1),xa=Eo(null),_a=null,Ea=null,ja=null;function Oa(){ja=Ea=_a=null}function Aa(e){var t=xa.current;jo(xa),e._currentValue=t}function Ca(e,t,n){for(;null!==e;){var r=e.alternate;if((e.childLanes&t)!==t?(e.childLanes|=t,null!==r&&(r.childLanes|=t)):null!==r&&(r.childLanes&t)!==t&&(r.childLanes|=t),e===n)break;e=e.return}}function Ta(e,t){_a=e,ja=Ea=null,null!==(e=e.dependencies)&&null!==e.firstContext&&(!!(e.lanes&t)&&(vs=!0),e.firstContext=null)}function Pa(e){var t=e._currentValue;if(ja!==e)if(e={context:e,memoizedValue:t,next:null},null===Ea){if(null===_a)throw Error(a(308));Ea=e,_a.dependencies={lanes:0,firstContext:e}}else Ea=Ea.next=e;return t}var Ia=null;function Na(e){null===Ia?Ia=[e]:Ia.push(e)}function Ra(e,t,n,r){var o=t.interleaved;return null===o?(n.next=n,Na(t)):(n.next=o.next,o.next=n),t.interleaved=n,La(e,r)}function La(e,t){e.lanes|=t;var n=e.alternate;for(null!==n&&(n.lanes|=t),n=e,e=e.return;null!==e;)e.childLanes|=t,null!==(n=e.alternate)&&(n.childLanes|=t),n=e,e=e.return;return 3===n.tag?n.stateNode:null}var Da=!1;function Ma(e){e.updateQueue={baseState:e.memoizedState,firstBaseUpdate:null,lastBaseUpdate:null,shared:{pending:null,interleaved:null,lanes:0},effects:null}}function Fa(e,t){e=e.updateQueue,t.updateQueue===e&&(t.updateQueue={baseState:e.baseState,firstBaseUpdate:e.firstBaseUpdate,lastBaseUpdate:e.lastBaseUpdate,shared:e.shared,effects:e.effects})}function Ba(e,t){return{eventTime:e,lane:t,tag:0,payload:null,callback:null,next:null}}function za(e,t,n){var r=e.updateQueue;if(null===r)return null;if(r=r.shared,2&Ac){var o=r.pending;return null===o?t.next=t:(t.next=o.next,o.next=t),r.pending=t,La(e,n)}return null===(o=r.interleaved)?(t.next=t,Na(r)):(t.next=o.next,o.next=t),r.interleaved=t,La(e,n)}function $a(e,t,n){if(null!==(t=t.updateQueue)&&(t=t.shared,4194240&n)){var r=t.lanes;n|=r&=e.pendingLanes,t.lanes=n,yt(e,n)}}function Ua(e,t){var n=e.updateQueue,r=e.alternate;if(null!==r&&n===(r=r.updateQueue)){var o=null,a=null;if(null!==(n=n.firstBaseUpdate)){do{var i={eventTime:n.eventTime,lane:n.lane,tag:n.tag,payload:n.payload,callback:n.callback,next:null};null===a?o=a=i:a=a.next=i,n=n.next}while(null!==n);null===a?o=a=t:a=a.next=t}else o=a=t;return n={baseState:r.baseState,firstBaseUpdate:o,lastBaseUpdate:a,shared:r.shared,effects:r.effects},void(e.updateQueue=n)}null===(e=n.lastBaseUpdate)?n.firstBaseUpdate=t:e.next=t,n.lastBaseUpdate=t}function Ha(e,t,n,r){var o=e.updateQueue;Da=!1;var a=o.firstBaseUpdate,i=o.lastBaseUpdate,s=o.shared.pending;if(null!==s){o.shared.pending=null;var c=s,l=c.next;c.next=null,null===i?a=l:i.next=l,i=c;var u=e.alternate;null!==u&&((s=(u=u.updateQueue).lastBaseUpdate)!==i&&(null===s?u.firstBaseUpdate=l:s.next=l,u.lastBaseUpdate=c))}if(null!==a){var d=o.baseState;for(i=0,u=l=c=null,s=a;;){var p=s.lane,f=s.eventTime;if((r&p)===p){null!==u&&(u=u.next={eventTime:f,lane:0,tag:s.tag,payload:s.payload,callback:s.callback,next:null});e:{var m=e,g=s;switch(p=t,f=n,g.tag){case 1:if("function"==typeof(m=g.payload)){d=m.call(f,d,p);break e}d=m;break e;case 3:m.flags=-65537&m.flags|128;case 0:if(null==(p="function"==typeof(m=g.payload)?m.call(f,d,p):m))break e;d=M({},d,p);break e;case 2:Da=!0}}null!==s.callback&&0!==s.lane&&(e.flags|=64,null===(p=o.effects)?o.effects=[s]:p.push(s))}else f={eventTime:f,lane:p,tag:s.tag,payload:s.payload,callback:s.callback,next:null},null===u?(l=u=f,c=d):u=u.next=f,i|=p;if(null===(s=s.next)){if(null===(s=o.shared.pending))break;s=(p=s).next,p.next=null,o.lastBaseUpdate=p,o.shared.pending=null}}if(null===u&&(c=d),o.baseState=c,o.firstBaseUpdate=l,o.lastBaseUpdate=u,null!==(t=o.shared.interleaved)){o=t;do{i|=o.lane,o=o.next}while(o!==t)}else null===a&&(o.shared.lanes=0);Dc|=i,e.lanes=i,e.memoizedState=d}}function qa(e,t,n){if(e=t.effects,t.effects=null,null!==e)for(t=0;t<e.length;t++){var r=e[t],o=r.callback;if(null!==o){if(r.callback=null,r=n,"function"!=typeof o)throw Error(a(191,o));o.call(r)}}}var Va={},Wa=Eo(Va),Ga=Eo(Va),Ka=Eo(Va);function Ya(e){if(e===Va)throw Error(a(174));return e}function Qa(e,t){switch(Oo(Ka,t),Oo(Ga,e),Oo(Wa,Va),e=t.nodeType){case 9:case 11:t=(t=t.documentElement)?t.namespaceURI:ce(null,"");break;default:t=ce(t=(e=8===e?t.parentNode:t).namespaceURI||null,e=e.tagName)}jo(Wa),Oo(Wa,t)}function Za(){jo(Wa),jo(Ga),jo(Ka)}function Xa(e){Ya(Ka.current);var t=Ya(Wa.current),n=ce(t,e.type);t!==n&&(Oo(Ga,e),Oo(Wa,n))}function Ja(e){Ga.current===e&&(jo(Wa),jo(Ga))}var ei=Eo(0);function ti(e){for(var t=e;null!==t;){if(13===t.tag){var n=t.memoizedState;if(null!==n&&(null===(n=n.dehydrated)||"$?"===n.data||"$!"===n.data))return t}else if(19===t.tag&&void 0!==t.memoizedProps.revealOrder){if(128&t.flags)return t}else if(null!==t.child){t.child.return=t,t=t.child;continue}if(t===e)break;for(;null===t.sibling;){if(null===t.return||t.return===e)return null;t=t.return}t.sibling.return=t.return,t=t.sibling}return null}var ni=[];function ri(){for(var e=0;e<ni.length;e++)ni[e]._workInProgressVersionPrimary=null;ni.length=0}var oi=w.ReactCurrentDispatcher,ai=w.ReactCurrentBatchConfig,ii=0,si=null,ci=null,li=null,ui=!1,di=!1,pi=0,fi=0;function mi(){throw Error(a(321))}function gi(e,t){if(null===t)return!1;for(var n=0;n<t.length&&n<e.length;n++)if(!sr(e[n],t[n]))return!1;return!0}function hi(e,t,n,r,o,i){if(ii=i,si=t,t.memoizedState=null,t.updateQueue=null,t.lanes=0,oi.current=null===e||null===e.memoizedState?Ji:es,e=n(r,o),di){i=0;do{if(di=!1,pi=0,25<=i)throw Error(a(301));i+=1,li=ci=null,t.updateQueue=null,oi.current=ts,e=n(r,o)}while(di)}if(oi.current=Xi,t=null!==ci&&null!==ci.next,ii=0,li=ci=si=null,ui=!1,t)throw Error(a(300));return e}function bi(){var e=0!==pi;return pi=0,e}function yi(){var e={memoizedState:null,baseState:null,baseQueue:null,queue:null,next:null};return null===li?si.memoizedState=li=e:li=li.next=e,li}function vi(){if(null===ci){var e=si.alternate;e=null!==e?e.memoizedState:null}else e=ci.next;var t=null===li?si.memoizedState:li.next;if(null!==t)li=t,ci=e;else{if(null===e)throw Error(a(310));e={memoizedState:(ci=e).memoizedState,baseState:ci.baseState,baseQueue:ci.baseQueue,queue:ci.queue,next:null},null===li?si.memoizedState=li=e:li=li.next=e}return li}function wi(e,t){return"function"==typeof t?t(e):t}function Si(e){var t=vi(),n=t.queue;if(null===n)throw Error(a(311));n.lastRenderedReducer=e;var r=ci,o=r.baseQueue,i=n.pending;if(null!==i){if(null!==o){var s=o.next;o.next=i.next,i.next=s}r.baseQueue=o=i,n.pending=null}if(null!==o){i=o.next,r=r.baseState;var c=s=null,l=null,u=i;do{var d=u.lane;if((ii&d)===d)null!==l&&(l=l.next={lane:0,action:u.action,hasEagerState:u.hasEagerState,eagerState:u.eagerState,next:null}),r=u.hasEagerState?u.eagerState:e(r,u.action);else{var p={lane:d,action:u.action,hasEagerState:u.hasEagerState,eagerState:u.eagerState,next:null};null===l?(c=l=p,s=r):l=l.next=p,si.lanes|=d,Dc|=d}u=u.next}while(null!==u&&u!==i);null===l?s=r:l.next=c,sr(r,t.memoizedState)||(vs=!0),t.memoizedState=r,t.baseState=s,t.baseQueue=l,n.lastRenderedState=r}if(null!==(e=n.interleaved)){o=e;do{i=o.lane,si.lanes|=i,Dc|=i,o=o.next}while(o!==e)}else null===o&&(n.lanes=0);return[t.memoizedState,n.dispatch]}function ki(e){var t=vi(),n=t.queue;if(null===n)throw Error(a(311));n.lastRenderedReducer=e;var r=n.dispatch,o=n.pending,i=t.memoizedState;if(null!==o){n.pending=null;var s=o=o.next;do{i=e(i,s.action),s=s.next}while(s!==o);sr(i,t.memoizedState)||(vs=!0),t.memoizedState=i,null===t.baseQueue&&(t.baseState=i),n.lastRenderedState=i}return[i,r]}function xi(){}function _i(e,t){var n=si,r=vi(),o=t(),i=!sr(r.memoizedState,o);if(i&&(r.memoizedState=o,vs=!0),r=r.queue,Di(Oi.bind(null,n,r,e),[e]),r.getSnapshot!==t||i||null!==li&&1&li.memoizedState.tag){if(n.flags|=2048,Pi(9,ji.bind(null,n,r,o,t),void 0,null),null===Cc)throw Error(a(349));30&ii||Ei(n,t,o)}return o}function Ei(e,t,n){e.flags|=16384,e={getSnapshot:t,value:n},null===(t=si.updateQueue)?(t={lastEffect:null,stores:null},si.updateQueue=t,t.stores=[e]):null===(n=t.stores)?t.stores=[e]:n.push(e)}function ji(e,t,n,r){t.value=n,t.getSnapshot=r,Ai(t)&&Ci(e)}function Oi(e,t,n){return n((function(){Ai(t)&&Ci(e)}))}function Ai(e){var t=e.getSnapshot;e=e.value;try{var n=t();return!sr(e,n)}catch(r){return!0}}function Ci(e){var t=La(e,1);null!==t&&nl(t,e,1,-1)}function Ti(e){var t=yi();return"function"==typeof e&&(e=e()),t.memoizedState=t.baseState=e,e={pending:null,interleaved:null,lanes:0,dispatch:null,lastRenderedReducer:wi,lastRenderedState:e},t.queue=e,e=e.dispatch=Ki.bind(null,si,e),[t.memoizedState,e]}function Pi(e,t,n,r){return e={tag:e,create:t,destroy:n,deps:r,next:null},null===(t=si.updateQueue)?(t={lastEffect:null,stores:null},si.updateQueue=t,t.lastEffect=e.next=e):null===(n=t.lastEffect)?t.lastEffect=e.next=e:(r=n.next,n.next=e,e.next=r,t.lastEffect=e),e}function Ii(){return vi().memoizedState}function Ni(e,t,n,r){var o=yi();si.flags|=e,o.memoizedState=Pi(1|t,n,void 0,void 0===r?null:r)}function Ri(e,t,n,r){var o=vi();r=void 0===r?null:r;var a=void 0;if(null!==ci){var i=ci.memoizedState;if(a=i.destroy,null!==r&&gi(r,i.deps))return void(o.memoizedState=Pi(t,n,a,r))}si.flags|=e,o.memoizedState=Pi(1|t,n,a,r)}function Li(e,t){return Ni(8390656,8,e,t)}function Di(e,t){return Ri(2048,8,e,t)}function Mi(e,t){return Ri(4,2,e,t)}function Fi(e,t){return Ri(4,4,e,t)}function Bi(e,t){return"function"==typeof t?(e=e(),t(e),function(){t(null)}):null!=t?(e=e(),t.current=e,function(){t.current=null}):void 0}function zi(e,t,n){return n=null!=n?n.concat([e]):null,Ri(4,4,Bi.bind(null,t,e),n)}function $i(){}function Ui(e,t){var n=vi();t=void 0===t?null:t;var r=n.memoizedState;return null!==r&&null!==t&&gi(t,r[1])?r[0]:(n.memoizedState=[e,t],e)}function Hi(e,t){var n=vi();t=void 0===t?null:t;var r=n.memoizedState;return null!==r&&null!==t&&gi(t,r[1])?r[0]:(e=e(),n.memoizedState=[e,t],e)}function qi(e,t,n){return 21&ii?(sr(n,t)||(n=gt(),si.lanes|=n,Dc|=n,e.baseState=!0),t):(e.baseState&&(e.baseState=!1,vs=!0),e.memoizedState=n)}function Vi(e,t){var n=vt;vt=0!==n&&4>n?n:4,e(!0);var r=ai.transition;ai.transition={};try{e(!1),t()}finally{vt=n,ai.transition=r}}function Wi(){return vi().memoizedState}function Gi(e,t,n){var r=tl(e);if(n={lane:r,action:n,hasEagerState:!1,eagerState:null,next:null},Yi(e))Qi(t,n);else if(null!==(n=Ra(e,t,n,r))){nl(n,e,r,el()),Zi(n,t,r)}}function Ki(e,t,n){var r=tl(e),o={lane:r,action:n,hasEagerState:!1,eagerState:null,next:null};if(Yi(e))Qi(t,o);else{var a=e.alternate;if(0===e.lanes&&(null===a||0===a.lanes)&&null!==(a=t.lastRenderedReducer))try{var i=t.lastRenderedState,s=a(i,n);if(o.hasEagerState=!0,o.eagerState=s,sr(s,i)){var c=t.interleaved;return null===c?(o.next=o,Na(t)):(o.next=c.next,c.next=o),void(t.interleaved=o)}}catch(l){}null!==(n=Ra(e,t,o,r))&&(nl(n,e,r,o=el()),Zi(n,t,r))}}function Yi(e){var t=e.alternate;return e===si||null!==t&&t===si}function Qi(e,t){di=ui=!0;var n=e.pending;null===n?t.next=t:(t.next=n.next,n.next=t),e.pending=t}function Zi(e,t,n){if(4194240&n){var r=t.lanes;n|=r&=e.pendingLanes,t.lanes=n,yt(e,n)}}var Xi={readContext:Pa,useCallback:mi,useContext:mi,useEffect:mi,useImperativeHandle:mi,useInsertionEffect:mi,useLayoutEffect:mi,useMemo:mi,useReducer:mi,useRef:mi,useState:mi,useDebugValue:mi,useDeferredValue:mi,useTransition:mi,useMutableSource:mi,useSyncExternalStore:mi,useId:mi,unstable_isNewReconciler:!1},Ji={readContext:Pa,useCallback:function(e,t){return yi().memoizedState=[e,void 0===t?null:t],e},useContext:Pa,useEffect:Li,useImperativeHandle:function(e,t,n){return n=null!=n?n.concat([e]):null,Ni(4194308,4,Bi.bind(null,t,e),n)},useLayoutEffect:function(e,t){return Ni(4194308,4,e,t)},useInsertionEffect:function(e,t){return Ni(4,2,e,t)},useMemo:function(e,t){var n=yi();return t=void 0===t?null:t,e=e(),n.memoizedState=[e,t],e},useReducer:function(e,t,n){var r=yi();return t=void 0!==n?n(t):t,r.memoizedState=r.baseState=t,e={pending:null,interleaved:null,lanes:0,dispatch:null,lastRenderedReducer:e,lastRenderedState:t},r.queue=e,e=e.dispatch=Gi.bind(null,si,e),[r.memoizedState,e]},useRef:function(e){return e={current:e},yi().memoizedState=e},useState:Ti,useDebugValue:$i,useDeferredValue:function(e){return yi().memoizedState=e},useTransition:function(){var e=Ti(!1),t=e[0];return e=Vi.bind(null,e[1]),yi().memoizedState=e,[t,e]},useMutableSource:function(){},useSyncExternalStore:function(e,t,n){var r=si,o=yi();if(aa){if(void 0===n)throw Error(a(407));n=n()}else{if(n=t(),null===Cc)throw Error(a(349));30&ii||Ei(r,t,n)}o.memoizedState=n;var i={value:n,getSnapshot:t};return o.queue=i,Li(Oi.bind(null,r,i,e),[e]),r.flags|=2048,Pi(9,ji.bind(null,r,i,n,t),void 0,null),n},useId:function(){var e=yi(),t=Cc.identifierPrefix;if(aa){var n=Xo;t=":"+t+"R"+(n=(Zo&~(1<<32-it(Zo)-1)).toString(32)+n),0<(n=pi++)&&(t+="H"+n.toString(32)),t+=":"}else t=":"+t+"r"+(n=fi++).toString(32)+":";return e.memoizedState=t},unstable_isNewReconciler:!1},es={readContext:Pa,useCallback:Ui,useContext:Pa,useEffect:Di,useImperativeHandle:zi,useInsertionEffect:Mi,useLayoutEffect:Fi,useMemo:Hi,useReducer:Si,useRef:Ii,useState:function(){return Si(wi)},useDebugValue:$i,useDeferredValue:function(e){return qi(vi(),ci.memoizedState,e)},useTransition:function(){return[Si(wi)[0],vi().memoizedState]},useMutableSource:xi,useSyncExternalStore:_i,useId:Wi,unstable_isNewReconciler:!1},ts={readContext:Pa,useCallback:Ui,useContext:Pa,useEffect:Di,useImperativeHandle:zi,useInsertionEffect:Mi,useLayoutEffect:Fi,useMemo:Hi,useReducer:ki,useRef:Ii,useState:function(){return ki(wi)},useDebugValue:$i,useDeferredValue:function(e){var t=vi();return null===ci?t.memoizedState=e:qi(t,ci.memoizedState,e)},useTransition:function(){return[ki(wi)[0],vi().memoizedState]},useMutableSource:xi,useSyncExternalStore:_i,useId:Wi,unstable_isNewReconciler:!1};function ns(e,t){if(e&&e.defaultProps){for(var n in t=M({},t),e=e.defaultProps)void 0===t[n]&&(t[n]=e[n]);return t}return t}function rs(e,t,n,r){n=null==(n=n(r,t=e.memoizedState))?t:M({},t,n),e.memoizedState=n,0===e.lanes&&(e.updateQueue.baseState=n)}var os={isMounted:function(e){return!!(e=e._reactInternals)&&Ue(e)===e},enqueueSetState:function(e,t,n){e=e._reactInternals;var r=el(),o=tl(e),a=Ba(r,o);a.payload=t,null!=n&&(a.callback=n),null!==(t=za(e,a,o))&&(nl(t,e,o,r),$a(t,e,o))},enqueueReplaceState:function(e,t,n){e=e._reactInternals;var r=el(),o=tl(e),a=Ba(r,o);a.tag=1,a.payload=t,null!=n&&(a.callback=n),null!==(t=za(e,a,o))&&(nl(t,e,o,r),$a(t,e,o))},enqueueForceUpdate:function(e,t){e=e._reactInternals;var n=el(),r=tl(e),o=Ba(n,r);o.tag=2,null!=t&&(o.callback=t),null!==(t=za(e,o,r))&&(nl(t,e,r,n),$a(t,e,r))}};function as(e,t,n,r,o,a,i){return"function"==typeof(e=e.stateNode).shouldComponentUpdate?e.shouldComponentUpdate(r,a,i):!t.prototype||!t.prototype.isPureReactComponent||(!cr(n,r)||!cr(o,a))}function is(e,t,n){var r=!1,o=Ao,a=t.contextType;return"object"==typeof a&&null!==a?a=Pa(a):(o=No(t)?Po:Co.current,a=(r=null!=(r=t.contextTypes))?Io(e,o):Ao),t=new t(n,a),e.memoizedState=null!==t.state&&void 0!==t.state?t.state:null,t.updater=os,e.stateNode=t,t._reactInternals=e,r&&((e=e.stateNode).__reactInternalMemoizedUnmaskedChildContext=o,e.__reactInternalMemoizedMaskedChildContext=a),t}function ss(e,t,n,r){e=t.state,"function"==typeof t.componentWillReceiveProps&&t.componentWillReceiveProps(n,r),"function"==typeof t.UNSAFE_componentWillReceiveProps&&t.UNSAFE_componentWillReceiveProps(n,r),t.state!==e&&os.enqueueReplaceState(t,t.state,null)}function cs(e,t,n,r){var o=e.stateNode;o.props=n,o.state=e.memoizedState,o.refs={},Ma(e);var a=t.contextType;"object"==typeof a&&null!==a?o.context=Pa(a):(a=No(t)?Po:Co.current,o.context=Io(e,a)),o.state=e.memoizedState,"function"==typeof(a=t.getDerivedStateFromProps)&&(rs(e,t,a,n),o.state=e.memoizedState),"function"==typeof t.getDerivedStateFromProps||"function"==typeof o.getSnapshotBeforeUpdate||"function"!=typeof o.UNSAFE_componentWillMount&&"function"!=typeof o.componentWillMount||(t=o.state,"function"==typeof o.componentWillMount&&o.componentWillMount(),"function"==typeof o.UNSAFE_componentWillMount&&o.UNSAFE_componentWillMount(),t!==o.state&&os.enqueueReplaceState(o,o.state,null),Ha(e,n,o,r),o.state=e.memoizedState),"function"==typeof o.componentDidMount&&(e.flags|=4194308)}function ls(e,t){try{var n="",r=t;do{n+=$(r),r=r.return}while(r);var o=n}catch(a){o="\nError generating stack: "+a.message+"\n"+a.stack}return{value:e,source:t,stack:o,digest:null}}function us(e,t,n){return{value:e,source:null,stack:null!=n?n:null,digest:null!=t?t:null}}function ds(e,t){try{console.error(t.value)}catch(n){setTimeout((function(){throw n}))}}var ps="function"==typeof WeakMap?WeakMap:Map;function fs(e,t,n){(n=Ba(-1,n)).tag=3,n.payload={element:null};var r=t.value;return n.callback=function(){qc||(qc=!0,Vc=r),ds(0,t)},n}function ms(e,t,n){(n=Ba(-1,n)).tag=3;var r=e.type.getDerivedStateFromError;if("function"==typeof r){var o=t.value;n.payload=function(){return r(o)},n.callback=function(){ds(0,t)}}var a=e.stateNode;return null!==a&&"function"==typeof a.componentDidCatch&&(n.callback=function(){ds(0,t),"function"!=typeof r&&(null===Wc?Wc=new Set([this]):Wc.add(this));var e=t.stack;this.componentDidCatch(t.value,{componentStack:null!==e?e:""})}),n}function gs(e,t,n){var r=e.pingCache;if(null===r){r=e.pingCache=new ps;var o=new Set;r.set(t,o)}else void 0===(o=r.get(t))&&(o=new Set,r.set(t,o));o.has(n)||(o.add(n),e=El.bind(null,e,t,n),t.then(e,e))}function hs(e){do{var t;if((t=13===e.tag)&&(t=null===(t=e.memoizedState)||null!==t.dehydrated),t)return e;e=e.return}while(null!==e);return null}function bs(e,t,n,r,o){return 1&e.mode?(e.flags|=65536,e.lanes=o,e):(e===t?e.flags|=65536:(e.flags|=128,n.flags|=131072,n.flags&=-52805,1===n.tag&&(null===n.alternate?n.tag=17:((t=Ba(-1,1)).tag=2,za(n,t,1))),n.lanes|=1),e)}var ys=w.ReactCurrentOwner,vs=!1;function ws(e,t,n,r){t.child=null===e?ka(t,null,n,r):Sa(t,e.child,n,r)}function Ss(e,t,n,r,o){n=n.render;var a=t.ref;return Ta(t,o),r=hi(e,t,n,r,a,o),n=bi(),null===e||vs?(aa&&n&&ta(t),t.flags|=1,ws(e,t,r,o),t.child):(t.updateQueue=e.updateQueue,t.flags&=-2053,e.lanes&=~o,qs(e,t,o))}function ks(e,t,n,r,o){if(null===e){var a=n.type;return"function"!=typeof a||Il(a)||void 0!==a.defaultProps||null!==n.compare||void 0!==n.defaultProps?((e=Rl(n.type,null,r,t,t.mode,o)).ref=t.ref,e.return=t,t.child=e):(t.tag=15,t.type=a,xs(e,t,a,r,o))}if(a=e.child,!(e.lanes&o)){var i=a.memoizedProps;if((n=null!==(n=n.compare)?n:cr)(i,r)&&e.ref===t.ref)return qs(e,t,o)}return t.flags|=1,(e=Nl(a,r)).ref=t.ref,e.return=t,t.child=e}function xs(e,t,n,r,o){if(null!==e){var a=e.memoizedProps;if(cr(a,r)&&e.ref===t.ref){if(vs=!1,t.pendingProps=r=a,!(e.lanes&o))return t.lanes=e.lanes,qs(e,t,o);131072&e.flags&&(vs=!0)}}return js(e,t,n,r,o)}function _s(e,t,n){var r=t.pendingProps,o=r.children,a=null!==e?e.memoizedState:null;if("hidden"===r.mode)if(1&t.mode){if(!(1073741824&n))return e=null!==a?a.baseLanes|n:n,t.lanes=t.childLanes=1073741824,t.memoizedState={baseLanes:e,cachePool:null,transitions:null},t.updateQueue=null,Oo(Nc,Ic),Ic|=e,null;t.memoizedState={baseLanes:0,cachePool:null,transitions:null},r=null!==a?a.baseLanes:n,Oo(Nc,Ic),Ic|=r}else t.memoizedState={baseLanes:0,cachePool:null,transitions:null},Oo(Nc,Ic),Ic|=n;else null!==a?(r=a.baseLanes|n,t.memoizedState=null):r=n,Oo(Nc,Ic),Ic|=r;return ws(e,t,o,n),t.child}function Es(e,t){var n=t.ref;(null===e&&null!==n||null!==e&&e.ref!==n)&&(t.flags|=512,t.flags|=2097152)}function js(e,t,n,r,o){var a=No(n)?Po:Co.current;return a=Io(t,a),Ta(t,o),n=hi(e,t,n,r,a,o),r=bi(),null===e||vs?(aa&&r&&ta(t),t.flags|=1,ws(e,t,n,o),t.child):(t.updateQueue=e.updateQueue,t.flags&=-2053,e.lanes&=~o,qs(e,t,o))}function Os(e,t,n,r,o){if(No(n)){var a=!0;Mo(t)}else a=!1;if(Ta(t,o),null===t.stateNode)Hs(e,t),is(t,n,r),cs(t,n,r,o),r=!0;else if(null===e){var i=t.stateNode,s=t.memoizedProps;i.props=s;var c=i.context,l=n.contextType;"object"==typeof l&&null!==l?l=Pa(l):l=Io(t,l=No(n)?Po:Co.current);var u=n.getDerivedStateFromProps,d="function"==typeof u||"function"==typeof i.getSnapshotBeforeUpdate;d||"function"!=typeof i.UNSAFE_componentWillReceiveProps&&"function"!=typeof i.componentWillReceiveProps||(s!==r||c!==l)&&ss(t,i,r,l),Da=!1;var p=t.memoizedState;i.state=p,Ha(t,r,i,o),c=t.memoizedState,s!==r||p!==c||To.current||Da?("function"==typeof u&&(rs(t,n,u,r),c=t.memoizedState),(s=Da||as(t,n,s,r,p,c,l))?(d||"function"!=typeof i.UNSAFE_componentWillMount&&"function"!=typeof i.componentWillMount||("function"==typeof i.componentWillMount&&i.componentWillMount(),"function"==typeof i.UNSAFE_componentWillMount&&i.UNSAFE_componentWillMount()),"function"==typeof i.componentDidMount&&(t.flags|=4194308)):("function"==typeof i.componentDidMount&&(t.flags|=4194308),t.memoizedProps=r,t.memoizedState=c),i.props=r,i.state=c,i.context=l,r=s):("function"==typeof i.componentDidMount&&(t.flags|=4194308),r=!1)}else{i=t.stateNode,Fa(e,t),s=t.memoizedProps,l=t.type===t.elementType?s:ns(t.type,s),i.props=l,d=t.pendingProps,p=i.context,"object"==typeof(c=n.contextType)&&null!==c?c=Pa(c):c=Io(t,c=No(n)?Po:Co.current);var f=n.getDerivedStateFromProps;(u="function"==typeof f||"function"==typeof i.getSnapshotBeforeUpdate)||"function"!=typeof i.UNSAFE_componentWillReceiveProps&&"function"!=typeof i.componentWillReceiveProps||(s!==d||p!==c)&&ss(t,i,r,c),Da=!1,p=t.memoizedState,i.state=p,Ha(t,r,i,o);var m=t.memoizedState;s!==d||p!==m||To.current||Da?("function"==typeof f&&(rs(t,n,f,r),m=t.memoizedState),(l=Da||as(t,n,l,r,p,m,c)||!1)?(u||"function"!=typeof i.UNSAFE_componentWillUpdate&&"function"!=typeof i.componentWillUpdate||("function"==typeof i.componentWillUpdate&&i.componentWillUpdate(r,m,c),"function"==typeof i.UNSAFE_componentWillUpdate&&i.UNSAFE_componentWillUpdate(r,m,c)),"function"==typeof i.componentDidUpdate&&(t.flags|=4),"function"==typeof i.getSnapshotBeforeUpdate&&(t.flags|=1024)):("function"!=typeof i.componentDidUpdate||s===e.memoizedProps&&p===e.memoizedState||(t.flags|=4),"function"!=typeof i.getSnapshotBeforeUpdate||s===e.memoizedProps&&p===e.memoizedState||(t.flags|=1024),t.memoizedProps=r,t.memoizedState=m),i.props=r,i.state=m,i.context=c,r=l):("function"!=typeof i.componentDidUpdate||s===e.memoizedProps&&p===e.memoizedState||(t.flags|=4),"function"!=typeof i.getSnapshotBeforeUpdate||s===e.memoizedProps&&p===e.memoizedState||(t.flags|=1024),r=!1)}return As(e,t,n,r,a,o)}function As(e,t,n,r,o,a){Es(e,t);var i=!!(128&t.flags);if(!r&&!i)return o&&Fo(t,n,!1),qs(e,t,a);r=t.stateNode,ys.current=t;var s=i&&"function"!=typeof n.getDerivedStateFromError?null:r.render();return t.flags|=1,null!==e&&i?(t.child=Sa(t,e.child,null,a),t.child=Sa(t,null,s,a)):ws(e,t,s,a),t.memoizedState=r.state,o&&Fo(t,n,!0),t.child}function Cs(e){var t=e.stateNode;t.pendingContext?Lo(0,t.pendingContext,t.pendingContext!==t.context):t.context&&Lo(0,t.context,!1),Qa(e,t.containerInfo)}function Ts(e,t,n,r,o){return ma(),ga(o),t.flags|=256,ws(e,t,n,r),t.child}var Ps,Is,Ns,Rs,Ls={dehydrated:null,treeContext:null,retryLane:0};function Ds(e){return{baseLanes:e,cachePool:null,transitions:null}}function Ms(e,t,n){var r,o=t.pendingProps,i=ei.current,s=!1,c=!!(128&t.flags);if((r=c)||(r=(null===e||null!==e.memoizedState)&&!!(2&i)),r?(s=!0,t.flags&=-129):null!==e&&null===e.memoizedState||(i|=1),Oo(ei,1&i),null===e)return ua(t),null!==(e=t.memoizedState)&&null!==(e=e.dehydrated)?(1&t.mode?"$!"===e.data?t.lanes=8:t.lanes=1073741824:t.lanes=1,null):(c=o.children,e=o.fallback,s?(o=t.mode,s=t.child,c={mode:"hidden",children:c},1&o||null===s?s=Dl(c,o,0,null):(s.childLanes=0,s.pendingProps=c),e=Ll(e,o,n,null),s.return=t,e.return=t,s.sibling=e,t.child=s,t.child.memoizedState=Ds(n),t.memoizedState=Ls,e):Fs(t,c));if(null!==(i=e.memoizedState)&&null!==(r=i.dehydrated))return function(e,t,n,r,o,i,s){if(n)return 256&t.flags?(t.flags&=-257,Bs(e,t,s,r=us(Error(a(422))))):null!==t.memoizedState?(t.child=e.child,t.flags|=128,null):(i=r.fallback,o=t.mode,r=Dl({mode:"visible",children:r.children},o,0,null),(i=Ll(i,o,s,null)).flags|=2,r.return=t,i.return=t,r.sibling=i,t.child=r,1&t.mode&&Sa(t,e.child,null,s),t.child.memoizedState=Ds(s),t.memoizedState=Ls,i);if(!(1&t.mode))return Bs(e,t,s,null);if("$!"===o.data){if(r=o.nextSibling&&o.nextSibling.dataset)var c=r.dgst;return r=c,Bs(e,t,s,r=us(i=Error(a(419)),r,void 0))}if(c=!!(s&e.childLanes),vs||c){if(null!==(r=Cc)){switch(s&-s){case 4:o=2;break;case 16:o=8;break;case 64:case 128:case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:case 262144:case 524288:case 1048576:case 2097152:case 4194304:case 8388608:case 16777216:case 33554432:case 67108864:o=32;break;case 536870912:o=268435456;break;default:o=0}0!==(o=o&(r.suspendedLanes|s)?0:o)&&o!==i.retryLane&&(i.retryLane=o,La(e,o),nl(r,e,o,-1))}return gl(),Bs(e,t,s,r=us(Error(a(421))))}return"$?"===o.data?(t.flags|=128,t.child=e.child,t=Ol.bind(null,e),o._reactRetry=t,null):(e=i.treeContext,oa=lo(o.nextSibling),ra=t,aa=!0,ia=null,null!==e&&(Ko[Yo++]=Zo,Ko[Yo++]=Xo,Ko[Yo++]=Qo,Zo=e.id,Xo=e.overflow,Qo=t),t=Fs(t,r.children),t.flags|=4096,t)}(e,t,c,o,r,i,n);if(s){s=o.fallback,c=t.mode,r=(i=e.child).sibling;var l={mode:"hidden",children:o.children};return 1&c||t.child===i?(o=Nl(i,l)).subtreeFlags=14680064&i.subtreeFlags:((o=t.child).childLanes=0,o.pendingProps=l,t.deletions=null),null!==r?s=Nl(r,s):(s=Ll(s,c,n,null)).flags|=2,s.return=t,o.return=t,o.sibling=s,t.child=o,o=s,s=t.child,c=null===(c=e.child.memoizedState)?Ds(n):{baseLanes:c.baseLanes|n,cachePool:null,transitions:c.transitions},s.memoizedState=c,s.childLanes=e.childLanes&~n,t.memoizedState=Ls,o}return e=(s=e.child).sibling,o=Nl(s,{mode:"visible",children:o.children}),!(1&t.mode)&&(o.lanes=n),o.return=t,o.sibling=null,null!==e&&(null===(n=t.deletions)?(t.deletions=[e],t.flags|=16):n.push(e)),t.child=o,t.memoizedState=null,o}function Fs(e,t){return(t=Dl({mode:"visible",children:t},e.mode,0,null)).return=e,e.child=t}function Bs(e,t,n,r){return null!==r&&ga(r),Sa(t,e.child,null,n),(e=Fs(t,t.pendingProps.children)).flags|=2,t.memoizedState=null,e}function zs(e,t,n){e.lanes|=t;var r=e.alternate;null!==r&&(r.lanes|=t),Ca(e.return,t,n)}function $s(e,t,n,r,o){var a=e.memoizedState;null===a?e.memoizedState={isBackwards:t,rendering:null,renderingStartTime:0,last:r,tail:n,tailMode:o}:(a.isBackwards=t,a.rendering=null,a.renderingStartTime=0,a.last=r,a.tail=n,a.tailMode=o)}function Us(e,t,n){var r=t.pendingProps,o=r.revealOrder,a=r.tail;if(ws(e,t,r.children,n),2&(r=ei.current))r=1&r|2,t.flags|=128;else{if(null!==e&&128&e.flags)e:for(e=t.child;null!==e;){if(13===e.tag)null!==e.memoizedState&&zs(e,n,t);else if(19===e.tag)zs(e,n,t);else if(null!==e.child){e.child.return=e,e=e.child;continue}if(e===t)break e;for(;null===e.sibling;){if(null===e.return||e.return===t)break e;e=e.return}e.sibling.return=e.return,e=e.sibling}r&=1}if(Oo(ei,r),1&t.mode)switch(o){case"forwards":for(n=t.child,o=null;null!==n;)null!==(e=n.alternate)&&null===ti(e)&&(o=n),n=n.sibling;null===(n=o)?(o=t.child,t.child=null):(o=n.sibling,n.sibling=null),$s(t,!1,o,n,a);break;case"backwards":for(n=null,o=t.child,t.child=null;null!==o;){if(null!==(e=o.alternate)&&null===ti(e)){t.child=o;break}e=o.sibling,o.sibling=n,n=o,o=e}$s(t,!0,n,null,a);break;case"together":$s(t,!1,null,null,void 0);break;default:t.memoizedState=null}else t.memoizedState=null;return t.child}function Hs(e,t){!(1&t.mode)&&null!==e&&(e.alternate=null,t.alternate=null,t.flags|=2)}function qs(e,t,n){if(null!==e&&(t.dependencies=e.dependencies),Dc|=t.lanes,!(n&t.childLanes))return null;if(null!==e&&t.child!==e.child)throw Error(a(153));if(null!==t.child){for(n=Nl(e=t.child,e.pendingProps),t.child=n,n.return=t;null!==e.sibling;)e=e.sibling,(n=n.sibling=Nl(e,e.pendingProps)).return=t;n.sibling=null}return t.child}function Vs(e,t){if(!aa)switch(e.tailMode){case"hidden":t=e.tail;for(var n=null;null!==t;)null!==t.alternate&&(n=t),t=t.sibling;null===n?e.tail=null:n.sibling=null;break;case"collapsed":n=e.tail;for(var r=null;null!==n;)null!==n.alternate&&(r=n),n=n.sibling;null===r?t||null===e.tail?e.tail=null:e.tail.sibling=null:r.sibling=null}}function Ws(e){var t=null!==e.alternate&&e.alternate.child===e.child,n=0,r=0;if(t)for(var o=e.child;null!==o;)n|=o.lanes|o.childLanes,r|=14680064&o.subtreeFlags,r|=14680064&o.flags,o.return=e,o=o.sibling;else for(o=e.child;null!==o;)n|=o.lanes|o.childLanes,r|=o.subtreeFlags,r|=o.flags,o.return=e,o=o.sibling;return e.subtreeFlags|=r,e.childLanes=n,t}function Gs(e,t,n){var r=t.pendingProps;switch(na(t),t.tag){case 2:case 16:case 15:case 0:case 11:case 7:case 8:case 12:case 9:case 14:return Ws(t),null;case 1:case 17:return No(t.type)&&Ro(),Ws(t),null;case 3:return r=t.stateNode,Za(),jo(To),jo(Co),ri(),r.pendingContext&&(r.context=r.pendingContext,r.pendingContext=null),null!==e&&null!==e.child||(pa(t)?t.flags|=4:null===e||e.memoizedState.isDehydrated&&!(256&t.flags)||(t.flags|=1024,null!==ia&&(il(ia),ia=null))),Is(e,t),Ws(t),null;case 5:Ja(t);var o=Ya(Ka.current);if(n=t.type,null!==e&&null!=t.stateNode)Ns(e,t,n,r,o),e.ref!==t.ref&&(t.flags|=512,t.flags|=2097152);else{if(!r){if(null===t.stateNode)throw Error(a(166));return Ws(t),null}if(e=Ya(Wa.current),pa(t)){r=t.stateNode,n=t.type;var i=t.memoizedProps;switch(r[fo]=t,r[mo]=i,e=!!(1&t.mode),n){case"dialog":Br("cancel",r),Br("close",r);break;case"iframe":case"object":case"embed":Br("load",r);break;case"video":case"audio":for(o=0;o<Lr.length;o++)Br(Lr[o],r);break;case"source":Br("error",r);break;case"img":case"image":case"link":Br("error",r),Br("load",r);break;case"details":Br("toggle",r);break;case"input":Q(r,i),Br("invalid",r);break;case"select":r._wrapperState={wasMultiple:!!i.multiple},Br("invalid",r);break;case"textarea":oe(r,i),Br("invalid",r)}for(var c in ye(n,i),o=null,i)if(i.hasOwnProperty(c)){var l=i[c];"children"===c?"string"==typeof l?r.textContent!==l&&(!0!==i.suppressHydrationWarning&&Xr(r.textContent,l,e),o=["children",l]):"number"==typeof l&&r.textContent!==""+l&&(!0!==i.suppressHydrationWarning&&Xr(r.textContent,l,e),o=["children",""+l]):s.hasOwnProperty(c)&&null!=l&&"onScroll"===c&&Br("scroll",r)}switch(n){case"input":W(r),J(r,i,!0);break;case"textarea":W(r),ie(r);break;case"select":case"option":break;default:"function"==typeof i.onClick&&(r.onclick=Jr)}r=o,t.updateQueue=r,null!==r&&(t.flags|=4)}else{c=9===o.nodeType?o:o.ownerDocument,"http://www.w3.org/1999/xhtml"===e&&(e=se(n)),"http://www.w3.org/1999/xhtml"===e?"script"===n?((e=c.createElement("div")).innerHTML="<script><\/script>",e=e.removeChild(e.firstChild)):"string"==typeof r.is?e=c.createElement(n,{is:r.is}):(e=c.createElement(n),"select"===n&&(c=e,r.multiple?c.multiple=!0:r.size&&(c.size=r.size))):e=c.createElementNS(e,n),e[fo]=t,e[mo]=r,Ps(e,t,!1,!1),t.stateNode=e;e:{switch(c=ve(n,r),n){case"dialog":Br("cancel",e),Br("close",e),o=r;break;case"iframe":case"object":case"embed":Br("load",e),o=r;break;case"video":case"audio":for(o=0;o<Lr.length;o++)Br(Lr[o],e);o=r;break;case"source":Br("error",e),o=r;break;case"img":case"image":case"link":Br("error",e),Br("load",e),o=r;break;case"details":Br("toggle",e),o=r;break;case"input":Q(e,r),o=Y(e,r),Br("invalid",e);break;case"option":default:o=r;break;case"select":e._wrapperState={wasMultiple:!!r.multiple},o=M({},r,{value:void 0}),Br("invalid",e);break;case"textarea":oe(e,r),o=re(e,r),Br("invalid",e)}for(i in ye(n,o),l=o)if(l.hasOwnProperty(i)){var u=l[i];"style"===i?he(e,u):"dangerouslySetInnerHTML"===i?null!=(u=u?u.__html:void 0)&&de(e,u):"children"===i?"string"==typeof u?("textarea"!==n||""!==u)&&pe(e,u):"number"==typeof u&&pe(e,""+u):"suppressContentEditableWarning"!==i&&"suppressHydrationWarning"!==i&&"autoFocus"!==i&&(s.hasOwnProperty(i)?null!=u&&"onScroll"===i&&Br("scroll",e):null!=u&&v(e,i,u,c))}switch(n){case"input":W(e),J(e,r,!1);break;case"textarea":W(e),ie(e);break;case"option":null!=r.value&&e.setAttribute("value",""+q(r.value));break;case"select":e.multiple=!!r.multiple,null!=(i=r.value)?ne(e,!!r.multiple,i,!1):null!=r.defaultValue&&ne(e,!!r.multiple,r.defaultValue,!0);break;default:"function"==typeof o.onClick&&(e.onclick=Jr)}switch(n){case"button":case"input":case"select":case"textarea":r=!!r.autoFocus;break e;case"img":r=!0;break e;default:r=!1}}r&&(t.flags|=4)}null!==t.ref&&(t.flags|=512,t.flags|=2097152)}return Ws(t),null;case 6:if(e&&null!=t.stateNode)Rs(e,t,e.memoizedProps,r);else{if("string"!=typeof r&&null===t.stateNode)throw Error(a(166));if(n=Ya(Ka.current),Ya(Wa.current),pa(t)){if(r=t.stateNode,n=t.memoizedProps,r[fo]=t,(i=r.nodeValue!==n)&&null!==(e=ra))switch(e.tag){case 3:Xr(r.nodeValue,n,!!(1&e.mode));break;case 5:!0!==e.memoizedProps.suppressHydrationWarning&&Xr(r.nodeValue,n,!!(1&e.mode))}i&&(t.flags|=4)}else(r=(9===n.nodeType?n:n.ownerDocument).createTextNode(r))[fo]=t,t.stateNode=r}return Ws(t),null;case 13:if(jo(ei),r=t.memoizedState,null===e||null!==e.memoizedState&&null!==e.memoizedState.dehydrated){if(aa&&null!==oa&&1&t.mode&&!(128&t.flags))fa(),ma(),t.flags|=98560,i=!1;else if(i=pa(t),null!==r&&null!==r.dehydrated){if(null===e){if(!i)throw Error(a(318));if(!(i=null!==(i=t.memoizedState)?i.dehydrated:null))throw Error(a(317));i[fo]=t}else ma(),!(128&t.flags)&&(t.memoizedState=null),t.flags|=4;Ws(t),i=!1}else null!==ia&&(il(ia),ia=null),i=!0;if(!i)return 65536&t.flags?t:null}return 128&t.flags?(t.lanes=n,t):((r=null!==r)!==(null!==e&&null!==e.memoizedState)&&r&&(t.child.flags|=8192,1&t.mode&&(null===e||1&ei.current?0===Rc&&(Rc=3):gl())),null!==t.updateQueue&&(t.flags|=4),Ws(t),null);case 4:return Za(),Is(e,t),null===e&&Ur(t.stateNode.containerInfo),Ws(t),null;case 10:return Aa(t.type._context),Ws(t),null;case 19:if(jo(ei),null===(i=t.memoizedState))return Ws(t),null;if(r=!!(128&t.flags),null===(c=i.rendering))if(r)Vs(i,!1);else{if(0!==Rc||null!==e&&128&e.flags)for(e=t.child;null!==e;){if(null!==(c=ti(e))){for(t.flags|=128,Vs(i,!1),null!==(r=c.updateQueue)&&(t.updateQueue=r,t.flags|=4),t.subtreeFlags=0,r=n,n=t.child;null!==n;)e=r,(i=n).flags&=14680066,null===(c=i.alternate)?(i.childLanes=0,i.lanes=e,i.child=null,i.subtreeFlags=0,i.memoizedProps=null,i.memoizedState=null,i.updateQueue=null,i.dependencies=null,i.stateNode=null):(i.childLanes=c.childLanes,i.lanes=c.lanes,i.child=c.child,i.subtreeFlags=0,i.deletions=null,i.memoizedProps=c.memoizedProps,i.memoizedState=c.memoizedState,i.updateQueue=c.updateQueue,i.type=c.type,e=c.dependencies,i.dependencies=null===e?null:{lanes:e.lanes,firstContext:e.firstContext}),n=n.sibling;return Oo(ei,1&ei.current|2),t.child}e=e.sibling}null!==i.tail&&Ze()>Uc&&(t.flags|=128,r=!0,Vs(i,!1),t.lanes=4194304)}else{if(!r)if(null!==(e=ti(c))){if(t.flags|=128,r=!0,null!==(n=e.updateQueue)&&(t.updateQueue=n,t.flags|=4),Vs(i,!0),null===i.tail&&"hidden"===i.tailMode&&!c.alternate&&!aa)return Ws(t),null}else 2*Ze()-i.renderingStartTime>Uc&&1073741824!==n&&(t.flags|=128,r=!0,Vs(i,!1),t.lanes=4194304);i.isBackwards?(c.sibling=t.child,t.child=c):(null!==(n=i.last)?n.sibling=c:t.child=c,i.last=c)}return null!==i.tail?(t=i.tail,i.rendering=t,i.tail=t.sibling,i.renderingStartTime=Ze(),t.sibling=null,n=ei.current,Oo(ei,r?1&n|2:1&n),t):(Ws(t),null);case 22:case 23:return dl(),r=null!==t.memoizedState,null!==e&&null!==e.memoizedState!==r&&(t.flags|=8192),r&&1&t.mode?!!(1073741824&Ic)&&(Ws(t),6&t.subtreeFlags&&(t.flags|=8192)):Ws(t),null;case 24:case 25:return null}throw Error(a(156,t.tag))}function Ks(e,t){switch(na(t),t.tag){case 1:return No(t.type)&&Ro(),65536&(e=t.flags)?(t.flags=-65537&e|128,t):null;case 3:return Za(),jo(To),jo(Co),ri(),65536&(e=t.flags)&&!(128&e)?(t.flags=-65537&e|128,t):null;case 5:return Ja(t),null;case 13:if(jo(ei),null!==(e=t.memoizedState)&&null!==e.dehydrated){if(null===t.alternate)throw Error(a(340));ma()}return 65536&(e=t.flags)?(t.flags=-65537&e|128,t):null;case 19:return jo(ei),null;case 4:return Za(),null;case 10:return Aa(t.type._context),null;case 22:case 23:return dl(),null;default:return null}}Ps=function(e,t){for(var n=t.child;null!==n;){if(5===n.tag||6===n.tag)e.appendChild(n.stateNode);else if(4!==n.tag&&null!==n.child){n.child.return=n,n=n.child;continue}if(n===t)break;for(;null===n.sibling;){if(null===n.return||n.return===t)return;n=n.return}n.sibling.return=n.return,n=n.sibling}},Is=function(){},Ns=function(e,t,n,r){var o=e.memoizedProps;if(o!==r){e=t.stateNode,Ya(Wa.current);var a,i=null;switch(n){case"input":o=Y(e,o),r=Y(e,r),i=[];break;case"select":o=M({},o,{value:void 0}),r=M({},r,{value:void 0}),i=[];break;case"textarea":o=re(e,o),r=re(e,r),i=[];break;default:"function"!=typeof o.onClick&&"function"==typeof r.onClick&&(e.onclick=Jr)}for(u in ye(n,r),n=null,o)if(!r.hasOwnProperty(u)&&o.hasOwnProperty(u)&&null!=o[u])if("style"===u){var c=o[u];for(a in c)c.hasOwnProperty(a)&&(n||(n={}),n[a]="")}else"dangerouslySetInnerHTML"!==u&&"children"!==u&&"suppressContentEditableWarning"!==u&&"suppressHydrationWarning"!==u&&"autoFocus"!==u&&(s.hasOwnProperty(u)?i||(i=[]):(i=i||[]).push(u,null));for(u in r){var l=r[u];if(c=null!=o?o[u]:void 0,r.hasOwnProperty(u)&&l!==c&&(null!=l||null!=c))if("style"===u)if(c){for(a in c)!c.hasOwnProperty(a)||l&&l.hasOwnProperty(a)||(n||(n={}),n[a]="");for(a in l)l.hasOwnProperty(a)&&c[a]!==l[a]&&(n||(n={}),n[a]=l[a])}else n||(i||(i=[]),i.push(u,n)),n=l;else"dangerouslySetInnerHTML"===u?(l=l?l.__html:void 0,c=c?c.__html:void 0,null!=l&&c!==l&&(i=i||[]).push(u,l)):"children"===u?"string"!=typeof l&&"number"!=typeof l||(i=i||[]).push(u,""+l):"suppressContentEditableWarning"!==u&&"suppressHydrationWarning"!==u&&(s.hasOwnProperty(u)?(null!=l&&"onScroll"===u&&Br("scroll",e),i||c===l||(i=[])):(i=i||[]).push(u,l))}n&&(i=i||[]).push("style",n);var u=i;(t.updateQueue=u)&&(t.flags|=4)}},Rs=function(e,t,n,r){n!==r&&(t.flags|=4)};var Ys=!1,Qs=!1,Zs="function"==typeof WeakSet?WeakSet:Set,Xs=null;function Js(e,t){var n=e.ref;if(null!==n)if("function"==typeof n)try{n(null)}catch(r){_l(e,t,r)}else n.current=null}function ec(e,t,n){try{n()}catch(r){_l(e,t,r)}}var tc=!1;function nc(e,t,n){var r=t.updateQueue;if(null!==(r=null!==r?r.lastEffect:null)){var o=r=r.next;do{if((o.tag&e)===e){var a=o.destroy;o.destroy=void 0,void 0!==a&&ec(t,n,a)}o=o.next}while(o!==r)}}function rc(e,t){if(null!==(t=null!==(t=t.updateQueue)?t.lastEffect:null)){var n=t=t.next;do{if((n.tag&e)===e){var r=n.create;n.destroy=r()}n=n.next}while(n!==t)}}function oc(e){var t=e.ref;if(null!==t){var n=e.stateNode;e.tag,e=n,"function"==typeof t?t(e):t.current=e}}function ac(e){var t=e.alternate;null!==t&&(e.alternate=null,ac(t)),e.child=null,e.deletions=null,e.sibling=null,5===e.tag&&(null!==(t=e.stateNode)&&(delete t[fo],delete t[mo],delete t[ho],delete t[bo],delete t[yo])),e.stateNode=null,e.return=null,e.dependencies=null,e.memoizedProps=null,e.memoizedState=null,e.pendingProps=null,e.stateNode=null,e.updateQueue=null}function ic(e){return 5===e.tag||3===e.tag||4===e.tag}function sc(e){e:for(;;){for(;null===e.sibling;){if(null===e.return||ic(e.return))return null;e=e.return}for(e.sibling.return=e.return,e=e.sibling;5!==e.tag&&6!==e.tag&&18!==e.tag;){if(2&e.flags)continue e;if(null===e.child||4===e.tag)continue e;e.child.return=e,e=e.child}if(!(2&e.flags))return e.stateNode}}function cc(e,t,n){var r=e.tag;if(5===r||6===r)e=e.stateNode,t?8===n.nodeType?n.parentNode.insertBefore(e,t):n.insertBefore(e,t):(8===n.nodeType?(t=n.parentNode).insertBefore(e,n):(t=n).appendChild(e),null!=(n=n._reactRootContainer)||null!==t.onclick||(t.onclick=Jr));else if(4!==r&&null!==(e=e.child))for(cc(e,t,n),e=e.sibling;null!==e;)cc(e,t,n),e=e.sibling}function lc(e,t,n){var r=e.tag;if(5===r||6===r)e=e.stateNode,t?n.insertBefore(e,t):n.appendChild(e);else if(4!==r&&null!==(e=e.child))for(lc(e,t,n),e=e.sibling;null!==e;)lc(e,t,n),e=e.sibling}var uc=null,dc=!1;function pc(e,t,n){for(n=n.child;null!==n;)fc(e,t,n),n=n.sibling}function fc(e,t,n){if(at&&"function"==typeof at.onCommitFiberUnmount)try{at.onCommitFiberUnmount(ot,n)}catch(s){}switch(n.tag){case 5:Qs||Js(n,t);case 6:var r=uc,o=dc;uc=null,pc(e,t,n),dc=o,null!==(uc=r)&&(dc?(e=uc,n=n.stateNode,8===e.nodeType?e.parentNode.removeChild(n):e.removeChild(n)):uc.removeChild(n.stateNode));break;case 18:null!==uc&&(dc?(e=uc,n=n.stateNode,8===e.nodeType?co(e.parentNode,n):1===e.nodeType&&co(e,n),Ut(e)):co(uc,n.stateNode));break;case 4:r=uc,o=dc,uc=n.stateNode.containerInfo,dc=!0,pc(e,t,n),uc=r,dc=o;break;case 0:case 11:case 14:case 15:if(!Qs&&(null!==(r=n.updateQueue)&&null!==(r=r.lastEffect))){o=r=r.next;do{var a=o,i=a.destroy;a=a.tag,void 0!==i&&(2&a||4&a)&&ec(n,t,i),o=o.next}while(o!==r)}pc(e,t,n);break;case 1:if(!Qs&&(Js(n,t),"function"==typeof(r=n.stateNode).componentWillUnmount))try{r.props=n.memoizedProps,r.state=n.memoizedState,r.componentWillUnmount()}catch(s){_l(n,t,s)}pc(e,t,n);break;case 21:pc(e,t,n);break;case 22:1&n.mode?(Qs=(r=Qs)||null!==n.memoizedState,pc(e,t,n),Qs=r):pc(e,t,n);break;default:pc(e,t,n)}}function mc(e){var t=e.updateQueue;if(null!==t){e.updateQueue=null;var n=e.stateNode;null===n&&(n=e.stateNode=new Zs),t.forEach((function(t){var r=Al.bind(null,e,t);n.has(t)||(n.add(t),t.then(r,r))}))}}function gc(e,t){var n=t.deletions;if(null!==n)for(var r=0;r<n.length;r++){var o=n[r];try{var i=e,s=t,c=s;e:for(;null!==c;){switch(c.tag){case 5:uc=c.stateNode,dc=!1;break e;case 3:case 4:uc=c.stateNode.containerInfo,dc=!0;break e}c=c.return}if(null===uc)throw Error(a(160));fc(i,s,o),uc=null,dc=!1;var l=o.alternate;null!==l&&(l.return=null),o.return=null}catch(u){_l(o,t,u)}}if(12854&t.subtreeFlags)for(t=t.child;null!==t;)hc(t,e),t=t.sibling}function hc(e,t){var n=e.alternate,r=e.flags;switch(e.tag){case 0:case 11:case 14:case 15:if(gc(t,e),bc(e),4&r){try{nc(3,e,e.return),rc(3,e)}catch(h){_l(e,e.return,h)}try{nc(5,e,e.return)}catch(h){_l(e,e.return,h)}}break;case 1:gc(t,e),bc(e),512&r&&null!==n&&Js(n,n.return);break;case 5:if(gc(t,e),bc(e),512&r&&null!==n&&Js(n,n.return),32&e.flags){var o=e.stateNode;try{pe(o,"")}catch(h){_l(e,e.return,h)}}if(4&r&&null!=(o=e.stateNode)){var i=e.memoizedProps,s=null!==n?n.memoizedProps:i,c=e.type,l=e.updateQueue;if(e.updateQueue=null,null!==l)try{"input"===c&&"radio"===i.type&&null!=i.name&&Z(o,i),ve(c,s);var u=ve(c,i);for(s=0;s<l.length;s+=2){var d=l[s],p=l[s+1];"style"===d?he(o,p):"dangerouslySetInnerHTML"===d?de(o,p):"children"===d?pe(o,p):v(o,d,p,u)}switch(c){case"input":X(o,i);break;case"textarea":ae(o,i);break;case"select":var f=o._wrapperState.wasMultiple;o._wrapperState.wasMultiple=!!i.multiple;var m=i.value;null!=m?ne(o,!!i.multiple,m,!1):f!==!!i.multiple&&(null!=i.defaultValue?ne(o,!!i.multiple,i.defaultValue,!0):ne(o,!!i.multiple,i.multiple?[]:"",!1))}o[mo]=i}catch(h){_l(e,e.return,h)}}break;case 6:if(gc(t,e),bc(e),4&r){if(null===e.stateNode)throw Error(a(162));o=e.stateNode,i=e.memoizedProps;try{o.nodeValue=i}catch(h){_l(e,e.return,h)}}break;case 3:if(gc(t,e),bc(e),4&r&&null!==n&&n.memoizedState.isDehydrated)try{Ut(t.containerInfo)}catch(h){_l(e,e.return,h)}break;case 4:default:gc(t,e),bc(e);break;case 13:gc(t,e),bc(e),8192&(o=e.child).flags&&(i=null!==o.memoizedState,o.stateNode.isHidden=i,!i||null!==o.alternate&&null!==o.alternate.memoizedState||($c=Ze())),4&r&&mc(e);break;case 22:if(d=null!==n&&null!==n.memoizedState,1&e.mode?(Qs=(u=Qs)||d,gc(t,e),Qs=u):gc(t,e),bc(e),8192&r){if(u=null!==e.memoizedState,(e.stateNode.isHidden=u)&&!d&&1&e.mode)for(Xs=e,d=e.child;null!==d;){for(p=Xs=d;null!==Xs;){switch(m=(f=Xs).child,f.tag){case 0:case 11:case 14:case 15:nc(4,f,f.return);break;case 1:Js(f,f.return);var g=f.stateNode;if("function"==typeof g.componentWillUnmount){r=f,n=f.return;try{t=r,g.props=t.memoizedProps,g.state=t.memoizedState,g.componentWillUnmount()}catch(h){_l(r,n,h)}}break;case 5:Js(f,f.return);break;case 22:if(null!==f.memoizedState){Sc(p);continue}}null!==m?(m.return=f,Xs=m):Sc(p)}d=d.sibling}e:for(d=null,p=e;;){if(5===p.tag){if(null===d){d=p;try{o=p.stateNode,u?"function"==typeof(i=o.style).setProperty?i.setProperty("display","none","important"):i.display="none":(c=p.stateNode,s=null!=(l=p.memoizedProps.style)&&l.hasOwnProperty("display")?l.display:null,c.style.display=ge("display",s))}catch(h){_l(e,e.return,h)}}}else if(6===p.tag){if(null===d)try{p.stateNode.nodeValue=u?"":p.memoizedProps}catch(h){_l(e,e.return,h)}}else if((22!==p.tag&&23!==p.tag||null===p.memoizedState||p===e)&&null!==p.child){p.child.return=p,p=p.child;continue}if(p===e)break e;for(;null===p.sibling;){if(null===p.return||p.return===e)break e;d===p&&(d=null),p=p.return}d===p&&(d=null),p.sibling.return=p.return,p=p.sibling}}break;case 19:gc(t,e),bc(e),4&r&&mc(e);case 21:}}function bc(e){var t=e.flags;if(2&t){try{e:{for(var n=e.return;null!==n;){if(ic(n)){var r=n;break e}n=n.return}throw Error(a(160))}switch(r.tag){case 5:var o=r.stateNode;32&r.flags&&(pe(o,""),r.flags&=-33),lc(e,sc(e),o);break;case 3:case 4:var i=r.stateNode.containerInfo;cc(e,sc(e),i);break;default:throw Error(a(161))}}catch(s){_l(e,e.return,s)}e.flags&=-3}4096&t&&(e.flags&=-4097)}function yc(e,t,n){Xs=e,vc(e,t,n)}function vc(e,t,n){for(var r=!!(1&e.mode);null!==Xs;){var o=Xs,a=o.child;if(22===o.tag&&r){var i=null!==o.memoizedState||Ys;if(!i){var s=o.alternate,c=null!==s&&null!==s.memoizedState||Qs;s=Ys;var l=Qs;if(Ys=i,(Qs=c)&&!l)for(Xs=o;null!==Xs;)c=(i=Xs).child,22===i.tag&&null!==i.memoizedState?kc(o):null!==c?(c.return=i,Xs=c):kc(o);for(;null!==a;)Xs=a,vc(a,t,n),a=a.sibling;Xs=o,Ys=s,Qs=l}wc(e)}else 8772&o.subtreeFlags&&null!==a?(a.return=o,Xs=a):wc(e)}}function wc(e){for(;null!==Xs;){var t=Xs;if(8772&t.flags){var n=t.alternate;try{if(8772&t.flags)switch(t.tag){case 0:case 11:case 15:Qs||rc(5,t);break;case 1:var r=t.stateNode;if(4&t.flags&&!Qs)if(null===n)r.componentDidMount();else{var o=t.elementType===t.type?n.memoizedProps:ns(t.type,n.memoizedProps);r.componentDidUpdate(o,n.memoizedState,r.__reactInternalSnapshotBeforeUpdate)}var i=t.updateQueue;null!==i&&qa(t,i,r);break;case 3:var s=t.updateQueue;if(null!==s){if(n=null,null!==t.child)switch(t.child.tag){case 5:case 1:n=t.child.stateNode}qa(t,s,n)}break;case 5:var c=t.stateNode;if(null===n&&4&t.flags){n=c;var l=t.memoizedProps;switch(t.type){case"button":case"input":case"select":case"textarea":l.autoFocus&&n.focus();break;case"img":l.src&&(n.src=l.src)}}break;case 6:case 4:case 12:case 19:case 17:case 21:case 22:case 23:case 25:break;case 13:if(null===t.memoizedState){var u=t.alternate;if(null!==u){var d=u.memoizedState;if(null!==d){var p=d.dehydrated;null!==p&&Ut(p)}}}break;default:throw Error(a(163))}Qs||512&t.flags&&oc(t)}catch(f){_l(t,t.return,f)}}if(t===e){Xs=null;break}if(null!==(n=t.sibling)){n.return=t.return,Xs=n;break}Xs=t.return}}function Sc(e){for(;null!==Xs;){var t=Xs;if(t===e){Xs=null;break}var n=t.sibling;if(null!==n){n.return=t.return,Xs=n;break}Xs=t.return}}function kc(e){for(;null!==Xs;){var t=Xs;try{switch(t.tag){case 0:case 11:case 15:var n=t.return;try{rc(4,t)}catch(c){_l(t,n,c)}break;case 1:var r=t.stateNode;if("function"==typeof r.componentDidMount){var o=t.return;try{r.componentDidMount()}catch(c){_l(t,o,c)}}var a=t.return;try{oc(t)}catch(c){_l(t,a,c)}break;case 5:var i=t.return;try{oc(t)}catch(c){_l(t,i,c)}}}catch(c){_l(t,t.return,c)}if(t===e){Xs=null;break}var s=t.sibling;if(null!==s){s.return=t.return,Xs=s;break}Xs=t.return}}var xc,_c=Math.ceil,Ec=w.ReactCurrentDispatcher,jc=w.ReactCurrentOwner,Oc=w.ReactCurrentBatchConfig,Ac=0,Cc=null,Tc=null,Pc=0,Ic=0,Nc=Eo(0),Rc=0,Lc=null,Dc=0,Mc=0,Fc=0,Bc=null,zc=null,$c=0,Uc=1/0,Hc=null,qc=!1,Vc=null,Wc=null,Gc=!1,Kc=null,Yc=0,Qc=0,Zc=null,Xc=-1,Jc=0;function el(){return 6&Ac?Ze():-1!==Xc?Xc:Xc=Ze()}function tl(e){return 1&e.mode?2&Ac&&0!==Pc?Pc&-Pc:null!==ha.transition?(0===Jc&&(Jc=gt()),Jc):0!==(e=vt)?e:e=void 0===(e=window.event)?16:Qt(e.type):1}function nl(e,t,n,r){if(50<Qc)throw Qc=0,Zc=null,Error(a(185));bt(e,n,r),2&Ac&&e===Cc||(e===Cc&&(!(2&Ac)&&(Mc|=n),4===Rc&&sl(e,Pc)),rl(e,r),1===n&&0===Ac&&!(1&t.mode)&&(Uc=Ze()+500,zo&&Ho()))}function rl(e,t){var n=e.callbackNode;!function(e,t){for(var n=e.suspendedLanes,r=e.pingedLanes,o=e.expirationTimes,a=e.pendingLanes;0<a;){var i=31-it(a),s=1<<i,c=o[i];-1===c?s&n&&!(s&r)||(o[i]=ft(s,t)):c<=t&&(e.expiredLanes|=s),a&=~s}}(e,t);var r=pt(e,e===Cc?Pc:0);if(0===r)null!==n&&Ke(n),e.callbackNode=null,e.callbackPriority=0;else if(t=r&-r,e.callbackPriority!==t){if(null!=n&&Ke(n),1===t)0===e.tag?function(e){zo=!0,Uo(e)}(cl.bind(null,e)):Uo(cl.bind(null,e)),io((function(){!(6&Ac)&&Ho()})),n=null;else{switch(wt(r)){case 1:n=Je;break;case 4:n=et;break;case 16:default:n=tt;break;case 536870912:n=rt}n=Cl(n,ol.bind(null,e))}e.callbackPriority=t,e.callbackNode=n}}function ol(e,t){if(Xc=-1,Jc=0,6&Ac)throw Error(a(327));var n=e.callbackNode;if(kl()&&e.callbackNode!==n)return null;var r=pt(e,e===Cc?Pc:0);if(0===r)return null;if(30&r||r&e.expiredLanes||t)t=hl(e,r);else{t=r;var o=Ac;Ac|=2;var i=ml();for(Cc===e&&Pc===t||(Hc=null,Uc=Ze()+500,pl(e,t));;)try{yl();break}catch(c){fl(e,c)}Oa(),Ec.current=i,Ac=o,null!==Tc?t=0:(Cc=null,Pc=0,t=Rc)}if(0!==t){if(2===t&&(0!==(o=mt(e))&&(r=o,t=al(e,o))),1===t)throw n=Lc,pl(e,0),sl(e,r),rl(e,Ze()),n;if(6===t)sl(e,r);else{if(o=e.current.alternate,!(30&r||function(e){for(var t=e;;){if(16384&t.flags){var n=t.updateQueue;if(null!==n&&null!==(n=n.stores))for(var r=0;r<n.length;r++){var o=n[r],a=o.getSnapshot;o=o.value;try{if(!sr(a(),o))return!1}catch(s){return!1}}}if(n=t.child,16384&t.subtreeFlags&&null!==n)n.return=t,t=n;else{if(t===e)break;for(;null===t.sibling;){if(null===t.return||t.return===e)return!0;t=t.return}t.sibling.return=t.return,t=t.sibling}}return!0}(o)||(t=hl(e,r),2===t&&(i=mt(e),0!==i&&(r=i,t=al(e,i))),1!==t)))throw n=Lc,pl(e,0),sl(e,r),rl(e,Ze()),n;switch(e.finishedWork=o,e.finishedLanes=r,t){case 0:case 1:throw Error(a(345));case 2:case 5:Sl(e,zc,Hc);break;case 3:if(sl(e,r),(130023424&r)===r&&10<(t=$c+500-Ze())){if(0!==pt(e,0))break;if(((o=e.suspendedLanes)&r)!==r){el(),e.pingedLanes|=e.suspendedLanes&o;break}e.timeoutHandle=ro(Sl.bind(null,e,zc,Hc),t);break}Sl(e,zc,Hc);break;case 4:if(sl(e,r),(4194240&r)===r)break;for(t=e.eventTimes,o=-1;0<r;){var s=31-it(r);i=1<<s,(s=t[s])>o&&(o=s),r&=~i}if(r=o,10<(r=(120>(r=Ze()-r)?120:480>r?480:1080>r?1080:1920>r?1920:3e3>r?3e3:4320>r?4320:1960*_c(r/1960))-r)){e.timeoutHandle=ro(Sl.bind(null,e,zc,Hc),r);break}Sl(e,zc,Hc);break;default:throw Error(a(329))}}}return rl(e,Ze()),e.callbackNode===n?ol.bind(null,e):null}function al(e,t){var n=Bc;return e.current.memoizedState.isDehydrated&&(pl(e,t).flags|=256),2!==(e=hl(e,t))&&(t=zc,zc=n,null!==t&&il(t)),e}function il(e){null===zc?zc=e:zc.push.apply(zc,e)}function sl(e,t){for(t&=~Fc,t&=~Mc,e.suspendedLanes|=t,e.pingedLanes&=~t,e=e.expirationTimes;0<t;){var n=31-it(t),r=1<<n;e[n]=-1,t&=~r}}function cl(e){if(6&Ac)throw Error(a(327));kl();var t=pt(e,0);if(!(1&t))return rl(e,Ze()),null;var n=hl(e,t);if(0!==e.tag&&2===n){var r=mt(e);0!==r&&(t=r,n=al(e,r))}if(1===n)throw n=Lc,pl(e,0),sl(e,t),rl(e,Ze()),n;if(6===n)throw Error(a(345));return e.finishedWork=e.current.alternate,e.finishedLanes=t,Sl(e,zc,Hc),rl(e,Ze()),null}function ll(e,t){var n=Ac;Ac|=1;try{return e(t)}finally{0===(Ac=n)&&(Uc=Ze()+500,zo&&Ho())}}function ul(e){null!==Kc&&0===Kc.tag&&!(6&Ac)&&kl();var t=Ac;Ac|=1;var n=Oc.transition,r=vt;try{if(Oc.transition=null,vt=1,e)return e()}finally{vt=r,Oc.transition=n,!(6&(Ac=t))&&Ho()}}function dl(){Ic=Nc.current,jo(Nc)}function pl(e,t){e.finishedWork=null,e.finishedLanes=0;var n=e.timeoutHandle;if(-1!==n&&(e.timeoutHandle=-1,oo(n)),null!==Tc)for(n=Tc.return;null!==n;){var r=n;switch(na(r),r.tag){case 1:null!=(r=r.type.childContextTypes)&&Ro();break;case 3:Za(),jo(To),jo(Co),ri();break;case 5:Ja(r);break;case 4:Za();break;case 13:case 19:jo(ei);break;case 10:Aa(r.type._context);break;case 22:case 23:dl()}n=n.return}if(Cc=e,Tc=e=Nl(e.current,null),Pc=Ic=t,Rc=0,Lc=null,Fc=Mc=Dc=0,zc=Bc=null,null!==Ia){for(t=0;t<Ia.length;t++)if(null!==(r=(n=Ia[t]).interleaved)){n.interleaved=null;var o=r.next,a=n.pending;if(null!==a){var i=a.next;a.next=o,r.next=i}n.pending=r}Ia=null}return e}function fl(e,t){for(;;){var n=Tc;try{if(Oa(),oi.current=Xi,ui){for(var r=si.memoizedState;null!==r;){var o=r.queue;null!==o&&(o.pending=null),r=r.next}ui=!1}if(ii=0,li=ci=si=null,di=!1,pi=0,jc.current=null,null===n||null===n.return){Rc=1,Lc=t,Tc=null;break}e:{var i=e,s=n.return,c=n,l=t;if(t=Pc,c.flags|=32768,null!==l&&"object"==typeof l&&"function"==typeof l.then){var u=l,d=c,p=d.tag;if(!(1&d.mode||0!==p&&11!==p&&15!==p)){var f=d.alternate;f?(d.updateQueue=f.updateQueue,d.memoizedState=f.memoizedState,d.lanes=f.lanes):(d.updateQueue=null,d.memoizedState=null)}var m=hs(s);if(null!==m){m.flags&=-257,bs(m,s,c,0,t),1&m.mode&&gs(i,u,t),l=u;var g=(t=m).updateQueue;if(null===g){var h=new Set;h.add(l),t.updateQueue=h}else g.add(l);break e}if(!(1&t)){gs(i,u,t),gl();break e}l=Error(a(426))}else if(aa&&1&c.mode){var b=hs(s);if(null!==b){!(65536&b.flags)&&(b.flags|=256),bs(b,s,c,0,t),ga(ls(l,c));break e}}i=l=ls(l,c),4!==Rc&&(Rc=2),null===Bc?Bc=[i]:Bc.push(i),i=s;do{switch(i.tag){case 3:i.flags|=65536,t&=-t,i.lanes|=t,Ua(i,fs(0,l,t));break e;case 1:c=l;var y=i.type,v=i.stateNode;if(!(128&i.flags||"function"!=typeof y.getDerivedStateFromError&&(null===v||"function"!=typeof v.componentDidCatch||null!==Wc&&Wc.has(v)))){i.flags|=65536,t&=-t,i.lanes|=t,Ua(i,ms(i,c,t));break e}}i=i.return}while(null!==i)}wl(n)}catch(w){t=w,Tc===n&&null!==n&&(Tc=n=n.return);continue}break}}function ml(){var e=Ec.current;return Ec.current=Xi,null===e?Xi:e}function gl(){0!==Rc&&3!==Rc&&2!==Rc||(Rc=4),null===Cc||!(268435455&Dc)&&!(268435455&Mc)||sl(Cc,Pc)}function hl(e,t){var n=Ac;Ac|=2;var r=ml();for(Cc===e&&Pc===t||(Hc=null,pl(e,t));;)try{bl();break}catch(o){fl(e,o)}if(Oa(),Ac=n,Ec.current=r,null!==Tc)throw Error(a(261));return Cc=null,Pc=0,Rc}function bl(){for(;null!==Tc;)vl(Tc)}function yl(){for(;null!==Tc&&!Ye();)vl(Tc)}function vl(e){var t=xc(e.alternate,e,Ic);e.memoizedProps=e.pendingProps,null===t?wl(e):Tc=t,jc.current=null}function wl(e){var t=e;do{var n=t.alternate;if(e=t.return,32768&t.flags){if(null!==(n=Ks(n,t)))return n.flags&=32767,void(Tc=n);if(null===e)return Rc=6,void(Tc=null);e.flags|=32768,e.subtreeFlags=0,e.deletions=null}else if(null!==(n=Gs(n,t,Ic)))return void(Tc=n);if(null!==(t=t.sibling))return void(Tc=t);Tc=t=e}while(null!==t);0===Rc&&(Rc=5)}function Sl(e,t,n){var r=vt,o=Oc.transition;try{Oc.transition=null,vt=1,function(e,t,n,r){do{kl()}while(null!==Kc);if(6&Ac)throw Error(a(327));n=e.finishedWork;var o=e.finishedLanes;if(null===n)return null;if(e.finishedWork=null,e.finishedLanes=0,n===e.current)throw Error(a(177));e.callbackNode=null,e.callbackPriority=0;var i=n.lanes|n.childLanes;if(function(e,t){var n=e.pendingLanes&~t;e.pendingLanes=t,e.suspendedLanes=0,e.pingedLanes=0,e.expiredLanes&=t,e.mutableReadLanes&=t,e.entangledLanes&=t,t=e.entanglements;var r=e.eventTimes;for(e=e.expirationTimes;0<n;){var o=31-it(n),a=1<<o;t[o]=0,r[o]=-1,e[o]=-1,n&=~a}}(e,i),e===Cc&&(Tc=Cc=null,Pc=0),!(2064&n.subtreeFlags)&&!(2064&n.flags)||Gc||(Gc=!0,Cl(tt,(function(){return kl(),null}))),i=!!(15990&n.flags),!!(15990&n.subtreeFlags)||i){i=Oc.transition,Oc.transition=null;var s=vt;vt=1;var c=Ac;Ac|=4,jc.current=null,function(e,t){if(eo=qt,fr(e=pr())){if("selectionStart"in e)var n={start:e.selectionStart,end:e.selectionEnd};else e:{var r=(n=(n=e.ownerDocument)&&n.defaultView||window).getSelection&&n.getSelection();if(r&&0!==r.rangeCount){n=r.anchorNode;var o=r.anchorOffset,i=r.focusNode;r=r.focusOffset;try{n.nodeType,i.nodeType}catch(S){n=null;break e}var s=0,c=-1,l=-1,u=0,d=0,p=e,f=null;t:for(;;){for(var m;p!==n||0!==o&&3!==p.nodeType||(c=s+o),p!==i||0!==r&&3!==p.nodeType||(l=s+r),3===p.nodeType&&(s+=p.nodeValue.length),null!==(m=p.firstChild);)f=p,p=m;for(;;){if(p===e)break t;if(f===n&&++u===o&&(c=s),f===i&&++d===r&&(l=s),null!==(m=p.nextSibling))break;f=(p=f).parentNode}p=m}n=-1===c||-1===l?null:{start:c,end:l}}else n=null}n=n||{start:0,end:0}}else n=null;for(to={focusedElem:e,selectionRange:n},qt=!1,Xs=t;null!==Xs;)if(e=(t=Xs).child,1028&t.subtreeFlags&&null!==e)e.return=t,Xs=e;else for(;null!==Xs;){t=Xs;try{var g=t.alternate;if(1024&t.flags)switch(t.tag){case 0:case 11:case 15:case 5:case 6:case 4:case 17:break;case 1:if(null!==g){var h=g.memoizedProps,b=g.memoizedState,y=t.stateNode,v=y.getSnapshotBeforeUpdate(t.elementType===t.type?h:ns(t.type,h),b);y.__reactInternalSnapshotBeforeUpdate=v}break;case 3:var w=t.stateNode.containerInfo;1===w.nodeType?w.textContent="":9===w.nodeType&&w.documentElement&&w.removeChild(w.documentElement);break;default:throw Error(a(163))}}catch(S){_l(t,t.return,S)}if(null!==(e=t.sibling)){e.return=t.return,Xs=e;break}Xs=t.return}g=tc,tc=!1}(e,n),hc(n,e),mr(to),qt=!!eo,to=eo=null,e.current=n,yc(n,e,o),Qe(),Ac=c,vt=s,Oc.transition=i}else e.current=n;if(Gc&&(Gc=!1,Kc=e,Yc=o),i=e.pendingLanes,0===i&&(Wc=null),function(e){if(at&&"function"==typeof at.onCommitFiberRoot)try{at.onCommitFiberRoot(ot,e,void 0,!(128&~e.current.flags))}catch(t){}}(n.stateNode),rl(e,Ze()),null!==t)for(r=e.onRecoverableError,n=0;n<t.length;n++)o=t[n],r(o.value,{componentStack:o.stack,digest:o.digest});if(qc)throw qc=!1,e=Vc,Vc=null,e;!!(1&Yc)&&0!==e.tag&&kl(),i=e.pendingLanes,1&i?e===Zc?Qc++:(Qc=0,Zc=e):Qc=0,Ho()}(e,t,n,r)}finally{Oc.transition=o,vt=r}return null}function kl(){if(null!==Kc){var e=wt(Yc),t=Oc.transition,n=vt;try{if(Oc.transition=null,vt=16>e?16:e,null===Kc)var r=!1;else{if(e=Kc,Kc=null,Yc=0,6&Ac)throw Error(a(331));var o=Ac;for(Ac|=4,Xs=e.current;null!==Xs;){var i=Xs,s=i.child;if(16&Xs.flags){var c=i.deletions;if(null!==c){for(var l=0;l<c.length;l++){var u=c[l];for(Xs=u;null!==Xs;){var d=Xs;switch(d.tag){case 0:case 11:case 15:nc(8,d,i)}var p=d.child;if(null!==p)p.return=d,Xs=p;else for(;null!==Xs;){var f=(d=Xs).sibling,m=d.return;if(ac(d),d===u){Xs=null;break}if(null!==f){f.return=m,Xs=f;break}Xs=m}}}var g=i.alternate;if(null!==g){var h=g.child;if(null!==h){g.child=null;do{var b=h.sibling;h.sibling=null,h=b}while(null!==h)}}Xs=i}}if(2064&i.subtreeFlags&&null!==s)s.return=i,Xs=s;else e:for(;null!==Xs;){if(2048&(i=Xs).flags)switch(i.tag){case 0:case 11:case 15:nc(9,i,i.return)}var y=i.sibling;if(null!==y){y.return=i.return,Xs=y;break e}Xs=i.return}}var v=e.current;for(Xs=v;null!==Xs;){var w=(s=Xs).child;if(2064&s.subtreeFlags&&null!==w)w.return=s,Xs=w;else e:for(s=v;null!==Xs;){if(2048&(c=Xs).flags)try{switch(c.tag){case 0:case 11:case 15:rc(9,c)}}catch(k){_l(c,c.return,k)}if(c===s){Xs=null;break e}var S=c.sibling;if(null!==S){S.return=c.return,Xs=S;break e}Xs=c.return}}if(Ac=o,Ho(),at&&"function"==typeof at.onPostCommitFiberRoot)try{at.onPostCommitFiberRoot(ot,e)}catch(k){}r=!0}return r}finally{vt=n,Oc.transition=t}}return!1}function xl(e,t,n){e=za(e,t=fs(0,t=ls(n,t),1),1),t=el(),null!==e&&(bt(e,1,t),rl(e,t))}function _l(e,t,n){if(3===e.tag)xl(e,e,n);else for(;null!==t;){if(3===t.tag){xl(t,e,n);break}if(1===t.tag){var r=t.stateNode;if("function"==typeof t.type.getDerivedStateFromError||"function"==typeof r.componentDidCatch&&(null===Wc||!Wc.has(r))){t=za(t,e=ms(t,e=ls(n,e),1),1),e=el(),null!==t&&(bt(t,1,e),rl(t,e));break}}t=t.return}}function El(e,t,n){var r=e.pingCache;null!==r&&r.delete(t),t=el(),e.pingedLanes|=e.suspendedLanes&n,Cc===e&&(Pc&n)===n&&(4===Rc||3===Rc&&(130023424&Pc)===Pc&&500>Ze()-$c?pl(e,0):Fc|=n),rl(e,t)}function jl(e,t){0===t&&(1&e.mode?(t=ut,!(130023424&(ut<<=1))&&(ut=4194304)):t=1);var n=el();null!==(e=La(e,t))&&(bt(e,t,n),rl(e,n))}function Ol(e){var t=e.memoizedState,n=0;null!==t&&(n=t.retryLane),jl(e,n)}function Al(e,t){var n=0;switch(e.tag){case 13:var r=e.stateNode,o=e.memoizedState;null!==o&&(n=o.retryLane);break;case 19:r=e.stateNode;break;default:throw Error(a(314))}null!==r&&r.delete(t),jl(e,n)}function Cl(e,t){return Ge(e,t)}function Tl(e,t,n,r){this.tag=e,this.key=n,this.sibling=this.child=this.return=this.stateNode=this.type=this.elementType=null,this.index=0,this.ref=null,this.pendingProps=t,this.dependencies=this.memoizedState=this.updateQueue=this.memoizedProps=null,this.mode=r,this.subtreeFlags=this.flags=0,this.deletions=null,this.childLanes=this.lanes=0,this.alternate=null}function Pl(e,t,n,r){return new Tl(e,t,n,r)}function Il(e){return!(!(e=e.prototype)||!e.isReactComponent)}function Nl(e,t){var n=e.alternate;return null===n?((n=Pl(e.tag,t,e.key,e.mode)).elementType=e.elementType,n.type=e.type,n.stateNode=e.stateNode,n.alternate=e,e.alternate=n):(n.pendingProps=t,n.type=e.type,n.flags=0,n.subtreeFlags=0,n.deletions=null),n.flags=14680064&e.flags,n.childLanes=e.childLanes,n.lanes=e.lanes,n.child=e.child,n.memoizedProps=e.memoizedProps,n.memoizedState=e.memoizedState,n.updateQueue=e.updateQueue,t=e.dependencies,n.dependencies=null===t?null:{lanes:t.lanes,firstContext:t.firstContext},n.sibling=e.sibling,n.index=e.index,n.ref=e.ref,n}function Rl(e,t,n,r,o,i){var s=2;if(r=e,"function"==typeof e)Il(e)&&(s=1);else if("string"==typeof e)s=5;else e:switch(e){case x:return Ll(n.children,o,i,t);case _:s=8,o|=8;break;case E:return(e=Pl(12,n,t,2|o)).elementType=E,e.lanes=i,e;case C:return(e=Pl(13,n,t,o)).elementType=C,e.lanes=i,e;case T:return(e=Pl(19,n,t,o)).elementType=T,e.lanes=i,e;case N:return Dl(n,o,i,t);default:if("object"==typeof e&&null!==e)switch(e.$$typeof){case j:s=10;break e;case O:s=9;break e;case A:s=11;break e;case P:s=14;break e;case I:s=16,r=null;break e}throw Error(a(130,null==e?e:typeof e,""))}return(t=Pl(s,n,t,o)).elementType=e,t.type=r,t.lanes=i,t}function Ll(e,t,n,r){return(e=Pl(7,e,r,t)).lanes=n,e}function Dl(e,t,n,r){return(e=Pl(22,e,r,t)).elementType=N,e.lanes=n,e.stateNode={isHidden:!1},e}function Ml(e,t,n){return(e=Pl(6,e,null,t)).lanes=n,e}function Fl(e,t,n){return(t=Pl(4,null!==e.children?e.children:[],e.key,t)).lanes=n,t.stateNode={containerInfo:e.containerInfo,pendingChildren:null,implementation:e.implementation},t}function Bl(e,t,n,r,o){this.tag=t,this.containerInfo=e,this.finishedWork=this.pingCache=this.current=this.pendingChildren=null,this.timeoutHandle=-1,this.callbackNode=this.pendingContext=this.context=null,this.callbackPriority=0,this.eventTimes=ht(0),this.expirationTimes=ht(-1),this.entangledLanes=this.finishedLanes=this.mutableReadLanes=this.expiredLanes=this.pingedLanes=this.suspendedLanes=this.pendingLanes=0,this.entanglements=ht(0),this.identifierPrefix=r,this.onRecoverableError=o,this.mutableSourceEagerHydrationData=null}function zl(e,t,n,r,o,a,i,s,c){return e=new Bl(e,t,n,s,c),1===t?(t=1,!0===a&&(t|=8)):t=0,a=Pl(3,null,null,t),e.current=a,a.stateNode=e,a.memoizedState={element:r,isDehydrated:n,cache:null,transitions:null,pendingSuspenseBoundaries:null},Ma(a),e}function $l(e){if(!e)return Ao;e:{if(Ue(e=e._reactInternals)!==e||1!==e.tag)throw Error(a(170));var t=e;do{switch(t.tag){case 3:t=t.stateNode.context;break e;case 1:if(No(t.type)){t=t.stateNode.__reactInternalMemoizedMergedChildContext;break e}}t=t.return}while(null!==t);throw Error(a(171))}if(1===e.tag){var n=e.type;if(No(n))return Do(e,n,t)}return t}function Ul(e,t,n,r,o,a,i,s,c){return(e=zl(n,r,!0,e,0,a,0,s,c)).context=$l(null),n=e.current,(a=Ba(r=el(),o=tl(n))).callback=null!=t?t:null,za(n,a,o),e.current.lanes=o,bt(e,o,r),rl(e,r),e}function Hl(e,t,n,r){var o=t.current,a=el(),i=tl(o);return n=$l(n),null===t.context?t.context=n:t.pendingContext=n,(t=Ba(a,i)).payload={element:e},null!==(r=void 0===r?null:r)&&(t.callback=r),null!==(e=za(o,t,i))&&(nl(e,o,i,a),$a(e,o,i)),i}function ql(e){return(e=e.current).child?(e.child.tag,e.child.stateNode):null}function Vl(e,t){if(null!==(e=e.memoizedState)&&null!==e.dehydrated){var n=e.retryLane;e.retryLane=0!==n&&n<t?n:t}}function Wl(e,t){Vl(e,t),(e=e.alternate)&&Vl(e,t)}xc=function(e,t,n){if(null!==e)if(e.memoizedProps!==t.pendingProps||To.current)vs=!0;else{if(!(e.lanes&n||128&t.flags))return vs=!1,function(e,t,n){switch(t.tag){case 3:Cs(t),ma();break;case 5:Xa(t);break;case 1:No(t.type)&&Mo(t);break;case 4:Qa(t,t.stateNode.containerInfo);break;case 10:var r=t.type._context,o=t.memoizedProps.value;Oo(xa,r._currentValue),r._currentValue=o;break;case 13:if(null!==(r=t.memoizedState))return null!==r.dehydrated?(Oo(ei,1&ei.current),t.flags|=128,null):n&t.child.childLanes?Ms(e,t,n):(Oo(ei,1&ei.current),null!==(e=qs(e,t,n))?e.sibling:null);Oo(ei,1&ei.current);break;case 19:if(r=!!(n&t.childLanes),128&e.flags){if(r)return Us(e,t,n);t.flags|=128}if(null!==(o=t.memoizedState)&&(o.rendering=null,o.tail=null,o.lastEffect=null),Oo(ei,ei.current),r)break;return null;case 22:case 23:return t.lanes=0,_s(e,t,n)}return qs(e,t,n)}(e,t,n);vs=!!(131072&e.flags)}else vs=!1,aa&&1048576&t.flags&&ea(t,Go,t.index);switch(t.lanes=0,t.tag){case 2:var r=t.type;Hs(e,t),e=t.pendingProps;var o=Io(t,Co.current);Ta(t,n),o=hi(null,t,r,e,o,n);var i=bi();return t.flags|=1,"object"==typeof o&&null!==o&&"function"==typeof o.render&&void 0===o.$$typeof?(t.tag=1,t.memoizedState=null,t.updateQueue=null,No(r)?(i=!0,Mo(t)):i=!1,t.memoizedState=null!==o.state&&void 0!==o.state?o.state:null,Ma(t),o.updater=os,t.stateNode=o,o._reactInternals=t,cs(t,r,e,n),t=As(null,t,r,!0,i,n)):(t.tag=0,aa&&i&&ta(t),ws(null,t,o,n),t=t.child),t;case 16:r=t.elementType;e:{switch(Hs(e,t),e=t.pendingProps,r=(o=r._init)(r._payload),t.type=r,o=t.tag=function(e){if("function"==typeof e)return Il(e)?1:0;if(null!=e){if((e=e.$$typeof)===A)return 11;if(e===P)return 14}return 2}(r),e=ns(r,e),o){case 0:t=js(null,t,r,e,n);break e;case 1:t=Os(null,t,r,e,n);break e;case 11:t=Ss(null,t,r,e,n);break e;case 14:t=ks(null,t,r,ns(r.type,e),n);break e}throw Error(a(306,r,""))}return t;case 0:return r=t.type,o=t.pendingProps,js(e,t,r,o=t.elementType===r?o:ns(r,o),n);case 1:return r=t.type,o=t.pendingProps,Os(e,t,r,o=t.elementType===r?o:ns(r,o),n);case 3:e:{if(Cs(t),null===e)throw Error(a(387));r=t.pendingProps,o=(i=t.memoizedState).element,Fa(e,t),Ha(t,r,null,n);var s=t.memoizedState;if(r=s.element,i.isDehydrated){if(i={element:r,isDehydrated:!1,cache:s.cache,pendingSuspenseBoundaries:s.pendingSuspenseBoundaries,transitions:s.transitions},t.updateQueue.baseState=i,t.memoizedState=i,256&t.flags){t=Ts(e,t,r,n,o=ls(Error(a(423)),t));break e}if(r!==o){t=Ts(e,t,r,n,o=ls(Error(a(424)),t));break e}for(oa=lo(t.stateNode.containerInfo.firstChild),ra=t,aa=!0,ia=null,n=ka(t,null,r,n),t.child=n;n;)n.flags=-3&n.flags|4096,n=n.sibling}else{if(ma(),r===o){t=qs(e,t,n);break e}ws(e,t,r,n)}t=t.child}return t;case 5:return Xa(t),null===e&&ua(t),r=t.type,o=t.pendingProps,i=null!==e?e.memoizedProps:null,s=o.children,no(r,o)?s=null:null!==i&&no(r,i)&&(t.flags|=32),Es(e,t),ws(e,t,s,n),t.child;case 6:return null===e&&ua(t),null;case 13:return Ms(e,t,n);case 4:return Qa(t,t.stateNode.containerInfo),r=t.pendingProps,null===e?t.child=Sa(t,null,r,n):ws(e,t,r,n),t.child;case 11:return r=t.type,o=t.pendingProps,Ss(e,t,r,o=t.elementType===r?o:ns(r,o),n);case 7:return ws(e,t,t.pendingProps,n),t.child;case 8:case 12:return ws(e,t,t.pendingProps.children,n),t.child;case 10:e:{if(r=t.type._context,o=t.pendingProps,i=t.memoizedProps,s=o.value,Oo(xa,r._currentValue),r._currentValue=s,null!==i)if(sr(i.value,s)){if(i.children===o.children&&!To.current){t=qs(e,t,n);break e}}else for(null!==(i=t.child)&&(i.return=t);null!==i;){var c=i.dependencies;if(null!==c){s=i.child;for(var l=c.firstContext;null!==l;){if(l.context===r){if(1===i.tag){(l=Ba(-1,n&-n)).tag=2;var u=i.updateQueue;if(null!==u){var d=(u=u.shared).pending;null===d?l.next=l:(l.next=d.next,d.next=l),u.pending=l}}i.lanes|=n,null!==(l=i.alternate)&&(l.lanes|=n),Ca(i.return,n,t),c.lanes|=n;break}l=l.next}}else if(10===i.tag)s=i.type===t.type?null:i.child;else if(18===i.tag){if(null===(s=i.return))throw Error(a(341));s.lanes|=n,null!==(c=s.alternate)&&(c.lanes|=n),Ca(s,n,t),s=i.sibling}else s=i.child;if(null!==s)s.return=i;else for(s=i;null!==s;){if(s===t){s=null;break}if(null!==(i=s.sibling)){i.return=s.return,s=i;break}s=s.return}i=s}ws(e,t,o.children,n),t=t.child}return t;case 9:return o=t.type,r=t.pendingProps.children,Ta(t,n),r=r(o=Pa(o)),t.flags|=1,ws(e,t,r,n),t.child;case 14:return o=ns(r=t.type,t.pendingProps),ks(e,t,r,o=ns(r.type,o),n);case 15:return xs(e,t,t.type,t.pendingProps,n);case 17:return r=t.type,o=t.pendingProps,o=t.elementType===r?o:ns(r,o),Hs(e,t),t.tag=1,No(r)?(e=!0,Mo(t)):e=!1,Ta(t,n),is(t,r,o),cs(t,r,o,n),As(null,t,r,!0,e,n);case 19:return Us(e,t,n);case 22:return _s(e,t,n)}throw Error(a(156,t.tag))};var Gl="function"==typeof reportError?reportError:function(e){console.error(e)};function Kl(e){this._internalRoot=e}function Yl(e){this._internalRoot=e}function Ql(e){return!(!e||1!==e.nodeType&&9!==e.nodeType&&11!==e.nodeType)}function Zl(e){return!(!e||1!==e.nodeType&&9!==e.nodeType&&11!==e.nodeType&&(8!==e.nodeType||" react-mount-point-unstable "!==e.nodeValue))}function Xl(){}function Jl(e,t,n,r,o){var a=n._reactRootContainer;if(a){var i=a;if("function"==typeof o){var s=o;o=function(){var e=ql(i);s.call(e)}}Hl(t,i,e,o)}else i=function(e,t,n,r,o){if(o){if("function"==typeof r){var a=r;r=function(){var e=ql(i);a.call(e)}}var i=Ul(t,r,e,0,null,!1,0,"",Xl);return e._reactRootContainer=i,e[go]=i.current,Ur(8===e.nodeType?e.parentNode:e),ul(),i}for(;o=e.lastChild;)e.removeChild(o);if("function"==typeof r){var s=r;r=function(){var e=ql(c);s.call(e)}}var c=zl(e,0,!1,null,0,!1,0,"",Xl);return e._reactRootContainer=c,e[go]=c.current,Ur(8===e.nodeType?e.parentNode:e),ul((function(){Hl(t,c,n,r)})),c}(n,t,e,o,r);return ql(i)}Yl.prototype.render=Kl.prototype.render=function(e){var t=this._internalRoot;if(null===t)throw Error(a(409));Hl(e,t,null,null)},Yl.prototype.unmount=Kl.prototype.unmount=function(){var e=this._internalRoot;if(null!==e){this._internalRoot=null;var t=e.containerInfo;ul((function(){Hl(null,e,null,null)})),t[go]=null}},Yl.prototype.unstable_scheduleHydration=function(e){if(e){var t=_t();e={blockedOn:null,target:e,priority:t};for(var n=0;n<Nt.length&&0!==t&&t<Nt[n].priority;n++);Nt.splice(n,0,e),0===n&&Mt(e)}},St=function(e){switch(e.tag){case 3:var t=e.stateNode;if(t.current.memoizedState.isDehydrated){var n=dt(t.pendingLanes);0!==n&&(yt(t,1|n),rl(t,Ze()),!(6&Ac)&&(Uc=Ze()+500,Ho()))}break;case 13:ul((function(){var t=La(e,1);if(null!==t){var n=el();nl(t,e,1,n)}})),Wl(e,1)}},kt=function(e){if(13===e.tag){var t=La(e,134217728);if(null!==t)nl(t,e,134217728,el());Wl(e,134217728)}},xt=function(e){if(13===e.tag){var t=tl(e),n=La(e,t);if(null!==n)nl(n,e,t,el());Wl(e,t)}},_t=function(){return vt},Et=function(e,t){var n=vt;try{return vt=e,t()}finally{vt=n}},ke=function(e,t,n){switch(t){case"input":if(X(e,n),t=n.name,"radio"===n.type&&null!=t){for(n=e;n.parentNode;)n=n.parentNode;for(n=n.querySelectorAll("input[name="+JSON.stringify(""+t)+'][type="radio"]'),t=0;t<n.length;t++){var r=n[t];if(r!==e&&r.form===e.form){var o=ko(r);if(!o)throw Error(a(90));G(r),X(r,o)}}}break;case"textarea":ae(e,n);break;case"select":null!=(t=n.value)&&ne(e,!!n.multiple,t,!1)}},Ae=ll,Ce=ul;var eu={usingClientEntryPoint:!1,Events:[wo,So,ko,je,Oe,ll]},tu={findFiberByHostInstance:vo,bundleType:0,version:"18.3.1",rendererPackageName:"react-dom"},nu={bundleType:tu.bundleType,version:tu.version,rendererPackageName:tu.rendererPackageName,rendererConfig:tu.rendererConfig,overrideHookState:null,overrideHookStateDeletePath:null,overrideHookStateRenamePath:null,overrideProps:null,overridePropsDeletePath:null,overridePropsRenamePath:null,setErrorHandler:null,setSuspenseHandler:null,scheduleUpdate:null,currentDispatcherRef:w.ReactCurrentDispatcher,findHostInstanceByFiber:function(e){return null===(e=Ve(e))?null:e.stateNode},findFiberByHostInstance:tu.findFiberByHostInstance||function(){return null},findHostInstancesForRefresh:null,scheduleRefresh:null,scheduleRoot:null,setRefreshHandler:null,getCurrentFiber:null,reconcilerVersion:"18.3.1-next-f1338f8080-20240426"};if("undefined"!=typeof __REACT_DEVTOOLS_GLOBAL_HOOK__){var ru=__REACT_DEVTOOLS_GLOBAL_HOOK__;if(!ru.isDisabled&&ru.supportsFiber)try{ot=ru.inject(nu),at=ru}catch(ue){}}t.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED=eu,t.createPortal=function(e,t){var n=2<arguments.length&&void 0!==arguments[2]?arguments[2]:null;if(!Ql(t))throw Error(a(200));return function(e,t,n){var r=3<arguments.length&&void 0!==arguments[3]?arguments[3]:null;return{$$typeof:k,key:null==r?null:""+r,children:e,containerInfo:t,implementation:n}}(e,t,null,n)},t.createRoot=function(e,t){if(!Ql(e))throw Error(a(299));var n=!1,r="",o=Gl;return null!=t&&(!0===t.unstable_strictMode&&(n=!0),void 0!==t.identifierPrefix&&(r=t.identifierPrefix),void 0!==t.onRecoverableError&&(o=t.onRecoverableError)),t=zl(e,1,!1,null,0,n,0,r,o),e[go]=t.current,Ur(8===e.nodeType?e.parentNode:e),new Kl(t)},t.findDOMNode=function(e){if(null==e)return null;if(1===e.nodeType)return e;var t=e._reactInternals;if(void 0===t){if("function"==typeof e.render)throw Error(a(188));throw e=Object.keys(e).join(","),Error(a(268,e))}return e=null===(e=Ve(t))?null:e.stateNode},t.flushSync=function(e){return ul(e)},t.hydrate=function(e,t,n){if(!Zl(t))throw Error(a(200));return Jl(null,e,t,!0,n)},t.hydrateRoot=function(e,t,n){if(!Ql(e))throw Error(a(405));var r=null!=n&&n.hydratedSources||null,o=!1,i="",s=Gl;if(null!=n&&(!0===n.unstable_strictMode&&(o=!0),void 0!==n.identifierPrefix&&(i=n.identifierPrefix),void 0!==n.onRecoverableError&&(s=n.onRecoverableError)),t=Ul(t,null,e,1,null!=n?n:null,o,0,i,s),e[go]=t.current,Ur(e),r)for(e=0;e<r.length;e++)o=(o=(n=r[e])._getVersion)(n._source),null==t.mutableSourceEagerHydrationData?t.mutableSourceEagerHydrationData=[n,o]:t.mutableSourceEagerHydrationData.push(n,o);return new Yl(t)},t.render=function(e,t,n){if(!Zl(t))throw Error(a(200));return Jl(null,e,t,!1,n)},t.unmountComponentAtNode=function(e){if(!Zl(e))throw Error(a(40));return!!e._reactRootContainer&&(ul((function(){Jl(null,null,e,!1,(function(){e._reactRootContainer=null,e[go]=null}))})),!0)},t.unstable_batchedUpdates=ll,t.unstable_renderSubtreeIntoContainer=function(e,t,n,r){if(!Zl(n))throw Error(a(200));if(null==e||void 0===e._reactInternals)throw Error(a(38));return Jl(e,t,n,!1,r)},t.version="18.3.1-next-f1338f8080-20240426"},5338:(e,t,n)=>{"use strict";var r=n(961);t.createRoot=r.createRoot,t.hydrateRoot=r.hydrateRoot},961:(e,t,n)=>{"use strict";!function e(){if("undefined"!=typeof __REACT_DEVTOOLS_GLOBAL_HOOK__&&"function"==typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE)try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(e)}catch(t){console.error(t)}}(),e.exports=n(2551)},115:e=>{var t="undefined"!=typeof Element,n="function"==typeof Map,r="function"==typeof Set,o="function"==typeof ArrayBuffer&&!!ArrayBuffer.isView;function a(e,i){if(e===i)return!0;if(e&&i&&"object"==typeof e&&"object"==typeof i){if(e.constructor!==i.constructor)return!1;var s,c,l,u;if(Array.isArray(e)){if((s=e.length)!=i.length)return!1;for(c=s;0!=c--;)if(!a(e[c],i[c]))return!1;return!0}if(n&&e instanceof Map&&i instanceof Map){if(e.size!==i.size)return!1;for(u=e.entries();!(c=u.next()).done;)if(!i.has(c.value[0]))return!1;for(u=e.entries();!(c=u.next()).done;)if(!a(c.value[1],i.get(c.value[0])))return!1;return!0}if(r&&e instanceof Set&&i instanceof Set){if(e.size!==i.size)return!1;for(u=e.entries();!(c=u.next()).done;)if(!i.has(c.value[0]))return!1;return!0}if(o&&ArrayBuffer.isView(e)&&ArrayBuffer.isView(i)){if((s=e.length)!=i.length)return!1;for(c=s;0!=c--;)if(e[c]!==i[c])return!1;return!0}if(e.constructor===RegExp)return e.source===i.source&&e.flags===i.flags;if(e.valueOf!==Object.prototype.valueOf&&"function"==typeof e.valueOf&&"function"==typeof i.valueOf)return e.valueOf()===i.valueOf();if(e.toString!==Object.prototype.toString&&"function"==typeof e.toString&&"function"==typeof i.toString)return e.toString()===i.toString();if((s=(l=Object.keys(e)).length)!==Object.keys(i).length)return!1;for(c=s;0!=c--;)if(!Object.prototype.hasOwnProperty.call(i,l[c]))return!1;if(t&&e instanceof Element)return!1;for(c=s;0!=c--;)if(("_owner"!==l[c]&&"__v"!==l[c]&&"__o"!==l[c]||!e.$$typeof)&&!a(e[l[c]],i[l[c]]))return!1;return!0}return e!=e&&i!=i}e.exports=function(e,t){try{return a(e,t)}catch(n){if((n.message||"").match(/stack|recursion/i))return console.warn("react-fast-compare cannot handle circular refs"),!1;throw n}}},545:(e,t,n)=>{"use strict";n.d(t,{mg:()=>J,vd:()=>V});var r=n(6540),o=n(5556),a=n.n(o),i=n(115),s=n.n(i),c=n(311),l=n.n(c),u=n(2833),d=n.n(u);function p(){return p=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var r in n)Object.prototype.hasOwnProperty.call(n,r)&&(e[r]=n[r])}return e},p.apply(this,arguments)}function f(e,t){e.prototype=Object.create(t.prototype),e.prototype.constructor=e,m(e,t)}function m(e,t){return m=Object.setPrototypeOf||function(e,t){return e.__proto__=t,e},m(e,t)}function g(e,t){if(null==e)return{};var n,r,o={},a=Object.keys(e);for(r=0;r<a.length;r++)t.indexOf(n=a[r])>=0||(o[n]=e[n]);return o}var h={BASE:"base",BODY:"body",HEAD:"head",HTML:"html",LINK:"link",META:"meta",NOSCRIPT:"noscript",SCRIPT:"script",STYLE:"style",TITLE:"title",FRAGMENT:"Symbol(react.fragment)"},b={rel:["amphtml","canonical","alternate"]},y={type:["application/ld+json"]},v={charset:"",name:["robots","description"],property:["og:type","og:title","og:url","og:image","og:image:alt","og:description","twitter:url","twitter:title","twitter:description","twitter:image","twitter:image:alt","twitter:card","twitter:site"]},w=Object.keys(h).map((function(e){return h[e]})),S={accesskey:"accessKey",charset:"charSet",class:"className",contenteditable:"contentEditable",contextmenu:"contextMenu","http-equiv":"httpEquiv",itemprop:"itemProp",tabindex:"tabIndex"},k=Object.keys(S).reduce((function(e,t){return e[S[t]]=t,e}),{}),x=function(e,t){for(var n=e.length-1;n>=0;n-=1){var r=e[n];if(Object.prototype.hasOwnProperty.call(r,t))return r[t]}return null},_=function(e){var t=x(e,h.TITLE),n=x(e,"titleTemplate");if(Array.isArray(t)&&(t=t.join("")),n&&t)return n.replace(/%s/g,(function(){return t}));var r=x(e,"defaultTitle");return t||r||void 0},E=function(e){return x(e,"onChangeClientState")||function(){}},j=function(e,t){return t.filter((function(t){return void 0!==t[e]})).map((function(t){return t[e]})).reduce((function(e,t){return p({},e,t)}),{})},O=function(e,t){return t.filter((function(e){return void 0!==e[h.BASE]})).map((function(e){return e[h.BASE]})).reverse().reduce((function(t,n){if(!t.length)for(var r=Object.keys(n),o=0;o<r.length;o+=1){var a=r[o].toLowerCase();if(-1!==e.indexOf(a)&&n[a])return t.concat(n)}return t}),[])},A=function(e,t,n){var r={};return n.filter((function(t){return!!Array.isArray(t[e])||(void 0!==t[e]&&console&&"function"==typeof console.warn&&console.warn("Helmet: "+e+' should be of type "Array". Instead found type "'+typeof t[e]+'"'),!1)})).map((function(t){return t[e]})).reverse().reduce((function(e,n){var o={};n.filter((function(e){for(var n,a=Object.keys(e),i=0;i<a.length;i+=1){var s=a[i],c=s.toLowerCase();-1===t.indexOf(c)||"rel"===n&&"canonical"===e[n].toLowerCase()||"rel"===c&&"stylesheet"===e[c].toLowerCase()||(n=c),-1===t.indexOf(s)||"innerHTML"!==s&&"cssText"!==s&&"itemprop"!==s||(n=s)}if(!n||!e[n])return!1;var l=e[n].toLowerCase();return r[n]||(r[n]={}),o[n]||(o[n]={}),!r[n][l]&&(o[n][l]=!0,!0)})).reverse().forEach((function(t){return e.push(t)}));for(var a=Object.keys(o),i=0;i<a.length;i+=1){var s=a[i],c=p({},r[s],o[s]);r[s]=c}return e}),[]).reverse()},C=function(e,t){if(Array.isArray(e)&&e.length)for(var n=0;n<e.length;n+=1)if(e[n][t])return!0;return!1},T=function(e){return Array.isArray(e)?e.join(""):e},P=function(e,t){return Array.isArray(e)?e.reduce((function(e,n){return function(e,t){for(var n=Object.keys(e),r=0;r<n.length;r+=1)if(t[n[r]]&&t[n[r]].includes(e[n[r]]))return!0;return!1}(n,t)?e.priority.push(n):e.default.push(n),e}),{priority:[],default:[]}):{default:e}},I=function(e,t){var n;return p({},e,((n={})[t]=void 0,n))},N=[h.NOSCRIPT,h.SCRIPT,h.STYLE],R=function(e,t){return void 0===t&&(t=!0),!1===t?String(e):String(e).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'")},L=function(e){return Object.keys(e).reduce((function(t,n){var r=void 0!==e[n]?n+'="'+e[n]+'"':""+n;return t?t+" "+r:r}),"")},D=function(e,t){return void 0===t&&(t={}),Object.keys(e).reduce((function(t,n){return t[S[n]||n]=e[n],t}),t)},M=function(e,t){return t.map((function(t,n){var o,a=((o={key:n})["data-rh"]=!0,o);return Object.keys(t).forEach((function(e){var n=S[e]||e;"innerHTML"===n||"cssText"===n?a.dangerouslySetInnerHTML={__html:t.innerHTML||t.cssText}:a[n]=t[e]})),r.createElement(e,a)}))},F=function(e,t,n){switch(e){case h.TITLE:return{toComponent:function(){return n=t.titleAttributes,(o={key:e=t.title})["data-rh"]=!0,a=D(n,o),[r.createElement(h.TITLE,a,e)];var e,n,o,a},toString:function(){return function(e,t,n,r){var o=L(n),a=T(t);return o?"<"+e+' data-rh="true" '+o+">"+R(a,r)+"</"+e+">":"<"+e+' data-rh="true">'+R(a,r)+"</"+e+">"}(e,t.title,t.titleAttributes,n)}};case"bodyAttributes":case"htmlAttributes":return{toComponent:function(){return D(t)},toString:function(){return L(t)}};default:return{toComponent:function(){return M(e,t)},toString:function(){return function(e,t,n){return t.reduce((function(t,r){var o=Object.keys(r).filter((function(e){return!("innerHTML"===e||"cssText"===e)})).reduce((function(e,t){var o=void 0===r[t]?t:t+'="'+R(r[t],n)+'"';return e?e+" "+o:o}),""),a=r.innerHTML||r.cssText||"",i=-1===N.indexOf(e);return t+"<"+e+' data-rh="true" '+o+(i?"/>":">"+a+"</"+e+">")}),"")}(e,t,n)}}}},B=function(e){var t=e.baseTag,n=e.bodyAttributes,r=e.encode,o=e.htmlAttributes,a=e.noscriptTags,i=e.styleTags,s=e.title,c=void 0===s?"":s,l=e.titleAttributes,u=e.linkTags,d=e.metaTags,p=e.scriptTags,f={toComponent:function(){},toString:function(){return""}};if(e.prioritizeSeoTags){var m=function(e){var t=e.linkTags,n=e.scriptTags,r=e.encode,o=P(e.metaTags,v),a=P(t,b),i=P(n,y);return{priorityMethods:{toComponent:function(){return[].concat(M(h.META,o.priority),M(h.LINK,a.priority),M(h.SCRIPT,i.priority))},toString:function(){return F(h.META,o.priority,r)+" "+F(h.LINK,a.priority,r)+" "+F(h.SCRIPT,i.priority,r)}},metaTags:o.default,linkTags:a.default,scriptTags:i.default}}(e);f=m.priorityMethods,u=m.linkTags,d=m.metaTags,p=m.scriptTags}return{priority:f,base:F(h.BASE,t,r),bodyAttributes:F("bodyAttributes",n,r),htmlAttributes:F("htmlAttributes",o,r),link:F(h.LINK,u,r),meta:F(h.META,d,r),noscript:F(h.NOSCRIPT,a,r),script:F(h.SCRIPT,p,r),style:F(h.STYLE,i,r),title:F(h.TITLE,{title:c,titleAttributes:l},r)}},z=[],$=function(e,t){var n=this;void 0===t&&(t="undefined"!=typeof document),this.instances=[],this.value={setHelmet:function(e){n.context.helmet=e},helmetInstances:{get:function(){return n.canUseDOM?z:n.instances},add:function(e){(n.canUseDOM?z:n.instances).push(e)},remove:function(e){var t=(n.canUseDOM?z:n.instances).indexOf(e);(n.canUseDOM?z:n.instances).splice(t,1)}}},this.context=e,this.canUseDOM=t,t||(e.helmet=B({baseTag:[],bodyAttributes:{},encodeSpecialCharacters:!0,htmlAttributes:{},linkTags:[],metaTags:[],noscriptTags:[],scriptTags:[],styleTags:[],title:"",titleAttributes:{}}))},U=r.createContext({}),H=a().shape({setHelmet:a().func,helmetInstances:a().shape({get:a().func,add:a().func,remove:a().func})}),q="undefined"!=typeof document,V=function(e){function t(n){var r;return(r=e.call(this,n)||this).helmetData=new $(r.props.context,t.canUseDOM),r}return f(t,e),t.prototype.render=function(){return r.createElement(U.Provider,{value:this.helmetData.value},this.props.children)},t}(r.Component);V.canUseDOM=q,V.propTypes={context:a().shape({helmet:a().shape()}),children:a().node.isRequired},V.defaultProps={context:{}},V.displayName="HelmetProvider";var W=function(e,t){var n,r=document.head||document.querySelector(h.HEAD),o=r.querySelectorAll(e+"[data-rh]"),a=[].slice.call(o),i=[];return t&&t.length&&t.forEach((function(t){var r=document.createElement(e);for(var o in t)Object.prototype.hasOwnProperty.call(t,o)&&("innerHTML"===o?r.innerHTML=t.innerHTML:"cssText"===o?r.styleSheet?r.styleSheet.cssText=t.cssText:r.appendChild(document.createTextNode(t.cssText)):r.setAttribute(o,void 0===t[o]?"":t[o]));r.setAttribute("data-rh","true"),a.some((function(e,t){return n=t,r.isEqualNode(e)}))?a.splice(n,1):i.push(r)})),a.forEach((function(e){return e.parentNode.removeChild(e)})),i.forEach((function(e){return r.appendChild(e)})),{oldTags:a,newTags:i}},G=function(e,t){var n=document.getElementsByTagName(e)[0];if(n){for(var r=n.getAttribute("data-rh"),o=r?r.split(","):[],a=[].concat(o),i=Object.keys(t),s=0;s<i.length;s+=1){var c=i[s],l=t[c]||"";n.getAttribute(c)!==l&&n.setAttribute(c,l),-1===o.indexOf(c)&&o.push(c);var u=a.indexOf(c);-1!==u&&a.splice(u,1)}for(var d=a.length-1;d>=0;d-=1)n.removeAttribute(a[d]);o.length===a.length?n.removeAttribute("data-rh"):n.getAttribute("data-rh")!==i.join(",")&&n.setAttribute("data-rh",i.join(","))}},K=function(e,t){var n=e.baseTag,r=e.htmlAttributes,o=e.linkTags,a=e.metaTags,i=e.noscriptTags,s=e.onChangeClientState,c=e.scriptTags,l=e.styleTags,u=e.title,d=e.titleAttributes;G(h.BODY,e.bodyAttributes),G(h.HTML,r),function(e,t){void 0!==e&&document.title!==e&&(document.title=T(e)),G(h.TITLE,t)}(u,d);var p={baseTag:W(h.BASE,n),linkTags:W(h.LINK,o),metaTags:W(h.META,a),noscriptTags:W(h.NOSCRIPT,i),scriptTags:W(h.SCRIPT,c),styleTags:W(h.STYLE,l)},f={},m={};Object.keys(p).forEach((function(e){var t=p[e],n=t.newTags,r=t.oldTags;n.length&&(f[e]=n),r.length&&(m[e]=p[e].oldTags)})),t&&t(),s(e,f,m)},Y=null,Q=function(e){function t(){for(var t,n=arguments.length,r=new Array(n),o=0;o<n;o++)r[o]=arguments[o];return(t=e.call.apply(e,[this].concat(r))||this).rendered=!1,t}f(t,e);var n=t.prototype;return n.shouldComponentUpdate=function(e){return!d()(e,this.props)},n.componentDidUpdate=function(){this.emitChange()},n.componentWillUnmount=function(){this.props.context.helmetInstances.remove(this),this.emitChange()},n.emitChange=function(){var e,t,n=this.props.context,r=n.setHelmet,o=null,a=(e=n.helmetInstances.get().map((function(e){var t=p({},e.props);return delete t.context,t})),{baseTag:O(["href"],e),bodyAttributes:j("bodyAttributes",e),defer:x(e,"defer"),encode:x(e,"encodeSpecialCharacters"),htmlAttributes:j("htmlAttributes",e),linkTags:A(h.LINK,["rel","href"],e),metaTags:A(h.META,["name","charset","http-equiv","property","itemprop"],e),noscriptTags:A(h.NOSCRIPT,["innerHTML"],e),onChangeClientState:E(e),scriptTags:A(h.SCRIPT,["src","innerHTML"],e),styleTags:A(h.STYLE,["cssText"],e),title:_(e),titleAttributes:j("titleAttributes",e),prioritizeSeoTags:C(e,"prioritizeSeoTags")});V.canUseDOM?(t=a,Y&&cancelAnimationFrame(Y),t.defer?Y=requestAnimationFrame((function(){K(t,(function(){Y=null}))})):(K(t),Y=null)):B&&(o=B(a)),r(o)},n.init=function(){this.rendered||(this.rendered=!0,this.props.context.helmetInstances.add(this),this.emitChange())},n.render=function(){return this.init(),null},t}(r.Component);Q.propTypes={context:H.isRequired},Q.displayName="HelmetDispatcher";var Z=["children"],X=["children"],J=function(e){function t(){return e.apply(this,arguments)||this}f(t,e);var n=t.prototype;return n.shouldComponentUpdate=function(e){return!s()(I(this.props,"helmetData"),I(e,"helmetData"))},n.mapNestedChildrenToProps=function(e,t){if(!t)return null;switch(e.type){case h.SCRIPT:case h.NOSCRIPT:return{innerHTML:t};case h.STYLE:return{cssText:t};default:throw new Error("<"+e.type+" /> elements are self-closing and can not contain children. Refer to our API for more information.")}},n.flattenArrayTypeChildren=function(e){var t,n=e.child,r=e.arrayTypeChildren;return p({},r,((t={})[n.type]=[].concat(r[n.type]||[],[p({},e.newChildProps,this.mapNestedChildrenToProps(n,e.nestedChildren))]),t))},n.mapObjectTypeChildren=function(e){var t,n,r=e.child,o=e.newProps,a=e.newChildProps,i=e.nestedChildren;switch(r.type){case h.TITLE:return p({},o,((t={})[r.type]=i,t.titleAttributes=p({},a),t));case h.BODY:return p({},o,{bodyAttributes:p({},a)});case h.HTML:return p({},o,{htmlAttributes:p({},a)});default:return p({},o,((n={})[r.type]=p({},a),n))}},n.mapArrayTypeChildrenToProps=function(e,t){var n=p({},t);return Object.keys(e).forEach((function(t){var r;n=p({},n,((r={})[t]=e[t],r))})),n},n.warnOnInvalidChildren=function(e,t){return l()(w.some((function(t){return e.type===t})),"function"==typeof e.type?"You may be attempting to nest <Helmet> components within each other, which is not allowed. Refer to our API for more information.":"Only elements types "+w.join(", ")+" are allowed. Helmet does not support rendering <"+e.type+"> elements. Refer to our API for more information."),l()(!t||"string"==typeof t||Array.isArray(t)&&!t.some((function(e){return"string"!=typeof e})),"Helmet expects a string as a child of <"+e.type+">. Did you forget to wrap your children in braces? ( <"+e.type+">{``}</"+e.type+"> ) Refer to our API for more information."),!0},n.mapChildrenToProps=function(e,t){var n=this,o={};return r.Children.forEach(e,(function(e){if(e&&e.props){var r=e.props,a=r.children,i=g(r,Z),s=Object.keys(i).reduce((function(e,t){return e[k[t]||t]=i[t],e}),{}),c=e.type;switch("symbol"==typeof c?c=c.toString():n.warnOnInvalidChildren(e,a),c){case h.FRAGMENT:t=n.mapChildrenToProps(a,t);break;case h.LINK:case h.META:case h.NOSCRIPT:case h.SCRIPT:case h.STYLE:o=n.flattenArrayTypeChildren({child:e,arrayTypeChildren:o,newChildProps:s,nestedChildren:a});break;default:t=n.mapObjectTypeChildren({child:e,newProps:t,newChildProps:s,nestedChildren:a})}}})),this.mapArrayTypeChildrenToProps(o,t)},n.render=function(){var e=this.props,t=e.children,n=g(e,X),o=p({},n),a=n.helmetData;return t&&(o=this.mapChildrenToProps(t,o)),!a||a instanceof $||(a=new $(a.context,a.instances)),a?r.createElement(Q,p({},o,{context:a.value,helmetData:void 0})):r.createElement(U.Consumer,null,(function(e){return r.createElement(Q,p({},o,{context:e}))}))},t}(r.Component);J.propTypes={base:a().object,bodyAttributes:a().object,children:a().oneOfType([a().arrayOf(a().node),a().node]),defaultTitle:a().string,defer:a().bool,encodeSpecialCharacters:a().bool,htmlAttributes:a().object,link:a().arrayOf(a().object),meta:a().arrayOf(a().object),noscript:a().arrayOf(a().object),onChangeClientState:a().func,script:a().arrayOf(a().object),style:a().arrayOf(a().object),title:a().string,titleAttributes:a().object,titleTemplate:a().string,prioritizeSeoTags:a().bool,helmetData:a().object},J.defaultProps={defer:!0,encodeSpecialCharacters:!0,prioritizeSeoTags:!1},J.displayName="Helmet"},2799:(e,t)=>{"use strict";var n="function"==typeof Symbol&&Symbol.for,r=n?Symbol.for("react.element"):60103,o=n?Symbol.for("react.portal"):60106,a=n?Symbol.for("react.fragment"):60107,i=n?Symbol.for("react.strict_mode"):60108,s=n?Symbol.for("react.profiler"):60114,c=n?Symbol.for("react.provider"):60109,l=n?Symbol.for("react.context"):60110,u=n?Symbol.for("react.async_mode"):60111,d=n?Symbol.for("react.concurrent_mode"):60111,p=n?Symbol.for("react.forward_ref"):60112,f=n?Symbol.for("react.suspense"):60113,m=n?Symbol.for("react.suspense_list"):60120,g=n?Symbol.for("react.memo"):60115,h=n?Symbol.for("react.lazy"):60116,b=n?Symbol.for("react.block"):60121,y=n?Symbol.for("react.fundamental"):60117,v=n?Symbol.for("react.responder"):60118,w=n?Symbol.for("react.scope"):60119;function S(e){if("object"==typeof e&&null!==e){var t=e.$$typeof;switch(t){case r:switch(e=e.type){case u:case d:case a:case s:case i:case f:return e;default:switch(e=e&&e.$$typeof){case l:case p:case h:case g:case c:return e;default:return t}}case o:return t}}}function k(e){return S(e)===d}t.AsyncMode=u,t.ConcurrentMode=d,t.ContextConsumer=l,t.ContextProvider=c,t.Element=r,t.ForwardRef=p,t.Fragment=a,t.Lazy=h,t.Memo=g,t.Portal=o,t.Profiler=s,t.StrictMode=i,t.Suspense=f,t.isAsyncMode=function(e){return k(e)||S(e)===u},t.isConcurrentMode=k,t.isContextConsumer=function(e){return S(e)===l},t.isContextProvider=function(e){return S(e)===c},t.isElement=function(e){return"object"==typeof e&&null!==e&&e.$$typeof===r},t.isForwardRef=function(e){return S(e)===p},t.isFragment=function(e){return S(e)===a},t.isLazy=function(e){return S(e)===h},t.isMemo=function(e){return S(e)===g},t.isPortal=function(e){return S(e)===o},t.isProfiler=function(e){return S(e)===s},t.isStrictMode=function(e){return S(e)===i},t.isSuspense=function(e){return S(e)===f},t.isValidElementType=function(e){return"string"==typeof e||"function"==typeof e||e===a||e===d||e===s||e===i||e===f||e===m||"object"==typeof e&&null!==e&&(e.$$typeof===h||e.$$typeof===g||e.$$typeof===c||e.$$typeof===l||e.$$typeof===p||e.$$typeof===y||e.$$typeof===v||e.$$typeof===w||e.$$typeof===b)},t.typeOf=S},4363:(e,t,n)=>{"use strict";e.exports=n(2799)},3259:(e,t,n)=>{"use strict";function r(e,t){e.prototype=Object.create(t.prototype),e.prototype.constructor=e,e.__proto__=t}function o(e){if(void 0===e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return e}function a(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function i(){return i=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var r in n)Object.prototype.hasOwnProperty.call(n,r)&&(e[r]=n[r])}return e},i.apply(this,arguments)}var s=n(6540),c=[],l=[];var u=s.createContext(null);function d(e){var t=e(),n={loading:!0,loaded:null,error:null};return n.promise=t.then((function(e){return n.loading=!1,n.loaded=e,e})).catch((function(e){throw n.loading=!1,n.error=e,e})),n}function p(e){var t={loading:!1,loaded:{},error:null},n=[];try{Object.keys(e).forEach((function(r){var o=d(e[r]);o.loading?t.loading=!0:(t.loaded[r]=o.loaded,t.error=o.error),n.push(o.promise),o.promise.then((function(e){t.loaded[r]=e})).catch((function(e){t.error=e}))}))}catch(r){t.error=r}return t.promise=Promise.all(n).then((function(e){return t.loading=!1,e})).catch((function(e){throw t.loading=!1,e})),t}function f(e,t){return s.createElement((n=e)&&n.__esModule?n.default:n,t);var n}function m(e,t){var d,p;if(!t.loading)throw new Error("react-loadable requires a `loading` component");var m=i({loader:null,loading:null,delay:200,timeout:null,render:f,webpack:null,modules:null},t),g=null;function h(){return g||(g=e(m.loader)),g.promise}return c.push(h),"function"==typeof m.webpack&&l.push((function(){if((0,m.webpack)().every((function(e){return void 0!==e&&void 0!==n.m[e]})))return h()})),p=d=function(t){function n(n){var r;return a(o(o(r=t.call(this,n)||this)),"retry",(function(){r.setState({error:null,loading:!0,timedOut:!1}),g=e(m.loader),r._loadModule()})),h(),r.state={error:g.error,pastDelay:!1,timedOut:!1,loading:g.loading,loaded:g.loaded},r}r(n,t),n.preload=function(){return h()};var i=n.prototype;return i.UNSAFE_componentWillMount=function(){this._loadModule()},i.componentDidMount=function(){this._mounted=!0},i._loadModule=function(){var e=this;if(this.context&&Array.isArray(m.modules)&&m.modules.forEach((function(t){e.context.report(t)})),g.loading){var t=function(t){e._mounted&&e.setState(t)};"number"==typeof m.delay&&(0===m.delay?this.setState({pastDelay:!0}):this._delay=setTimeout((function(){t({pastDelay:!0})}),m.delay)),"number"==typeof m.timeout&&(this._timeout=setTimeout((function(){t({timedOut:!0})}),m.timeout));var n=function(){t({error:g.error,loaded:g.loaded,loading:g.loading}),e._clearTimeouts()};g.promise.then((function(){return n(),null})).catch((function(e){return n(),null}))}},i.componentWillUnmount=function(){this._mounted=!1,this._clearTimeouts()},i._clearTimeouts=function(){clearTimeout(this._delay),clearTimeout(this._timeout)},i.render=function(){return this.state.loading||this.state.error?s.createElement(m.loading,{isLoading:this.state.loading,pastDelay:this.state.pastDelay,timedOut:this.state.timedOut,error:this.state.error,retry:this.retry}):this.state.loaded?m.render(this.state.loaded,this.props):null},n}(s.Component),a(d,"contextType",u),p}function g(e){return m(d,e)}g.Map=function(e){if("function"!=typeof e.render)throw new Error("LoadableMap requires a `render(loaded, props)` function");return m(p,e)};var h=function(e){function t(){return e.apply(this,arguments)||this}return r(t,e),t.prototype.render=function(){return s.createElement(u.Provider,{value:{report:this.props.report}},s.Children.only(this.props.children))},t}(s.Component);function b(e){for(var t=[];e.length;){var n=e.pop();t.push(n())}return Promise.all(t).then((function(){if(e.length)return b(e)}))}g.Capture=h,g.preloadAll=function(){return new Promise((function(e,t){b(c).then(e,t)}))},g.preloadReady=function(){return new Promise((function(e,t){b(l).then(e,e)}))},e.exports=g},2831:(e,t,n)=>{"use strict";n.d(t,{u:()=>i,v:()=>s});var r=n(6347),o=n(8168),a=n(6540);function i(e,t,n){return void 0===n&&(n=[]),e.some((function(e){var o=e.path?(0,r.B6)(t,e):n.length?n[n.length-1].match:r.Ix.computeRootMatch(t);return o&&(n.push({route:e,match:o}),e.routes&&i(e.routes,t,n)),o})),n}function s(e,t,n){return void 0===t&&(t={}),void 0===n&&(n={}),e?a.createElement(r.dO,n,e.map((function(e,n){return a.createElement(r.qh,{key:e.key||n,path:e.path,exact:e.exact,strict:e.strict,render:function(n){return e.render?e.render((0,o.A)({},n,{},t,{route:e})):a.createElement(e.component,(0,o.A)({},n,t,{route:e}))}})}))):null}},4625:(e,t,n)=>{"use strict";n.d(t,{I9:()=>d,Kd:()=>u,N_:()=>b,k2:()=>w});var r=n(6347),o=n(2892),a=n(6540),i=n(1513),s=n(8168),c=n(8587),l=n(1561),u=function(e){function t(){for(var t,n=arguments.length,r=new Array(n),o=0;o<n;o++)r[o]=arguments[o];return(t=e.call.apply(e,[this].concat(r))||this).history=(0,i.zR)(t.props),t}return(0,o.A)(t,e),t.prototype.render=function(){return a.createElement(r.Ix,{history:this.history,children:this.props.children})},t}(a.Component);var d=function(e){function t(){for(var t,n=arguments.length,r=new Array(n),o=0;o<n;o++)r[o]=arguments[o];return(t=e.call.apply(e,[this].concat(r))||this).history=(0,i.TM)(t.props),t}return(0,o.A)(t,e),t.prototype.render=function(){return a.createElement(r.Ix,{history:this.history,children:this.props.children})},t}(a.Component);var p=function(e,t){return"function"==typeof e?e(t):e},f=function(e,t){return"string"==typeof e?(0,i.yJ)(e,null,null,t):e},m=function(e){return e},g=a.forwardRef;void 0===g&&(g=m);var h=g((function(e,t){var n=e.innerRef,r=e.navigate,o=e.onClick,i=(0,c.A)(e,["innerRef","navigate","onClick"]),l=i.target,u=(0,s.A)({},i,{onClick:function(e){try{o&&o(e)}catch(t){throw e.preventDefault(),t}e.defaultPrevented||0!==e.button||l&&"_self"!==l||function(e){return!!(e.metaKey||e.altKey||e.ctrlKey||e.shiftKey)}(e)||(e.preventDefault(),r())}});return u.ref=m!==g&&t||n,a.createElement("a",u)}));var b=g((function(e,t){var n=e.component,o=void 0===n?h:n,u=e.replace,d=e.to,b=e.innerRef,y=(0,c.A)(e,["component","replace","to","innerRef"]);return a.createElement(r.XZ.Consumer,null,(function(e){e||(0,l.A)(!1);var n=e.history,r=f(p(d,e.location),e.location),c=r?n.createHref(r):"",h=(0,s.A)({},y,{href:c,navigate:function(){var t=p(d,e.location),r=(0,i.AO)(e.location)===(0,i.AO)(f(t));(u||r?n.replace:n.push)(t)}});return m!==g?h.ref=t||b:h.innerRef=b,a.createElement(o,h)}))})),y=function(e){return e},v=a.forwardRef;void 0===v&&(v=y);var w=v((function(e,t){var n=e["aria-current"],o=void 0===n?"page":n,i=e.activeClassName,u=void 0===i?"active":i,d=e.activeStyle,m=e.className,g=e.exact,h=e.isActive,w=e.location,S=e.sensitive,k=e.strict,x=e.style,_=e.to,E=e.innerRef,j=(0,c.A)(e,["aria-current","activeClassName","activeStyle","className","exact","isActive","location","sensitive","strict","style","to","innerRef"]);return a.createElement(r.XZ.Consumer,null,(function(e){e||(0,l.A)(!1);var n=w||e.location,i=f(p(_,n),n),c=i.pathname,O=c&&c.replace(/([.+*?=^!:${}()[\]|/\\])/g,"\\$1"),A=O?(0,r.B6)(n.pathname,{path:O,exact:g,sensitive:S,strict:k}):null,C=!!(h?h(A,n):A),T="function"==typeof m?m(C):m,P="function"==typeof x?x(C):x;C&&(T=function(){for(var e=arguments.length,t=new Array(e),n=0;n<e;n++)t[n]=arguments[n];return t.filter((function(e){return e})).join(" ")}(T,u),P=(0,s.A)({},P,d));var I=(0,s.A)({"aria-current":C&&o||null,className:T,style:P,to:i},j);return y!==v?I.ref=t||E:I.innerRef=E,a.createElement(b,I)}))}))},6347:(e,t,n)=>{"use strict";n.d(t,{B6:()=>x,Ix:()=>v,W6:()=>I,XZ:()=>y,dO:()=>T,qh:()=>_,zy:()=>N});var r=n(2892),o=n(6540),a=n(5556),i=n.n(a),s=n(1513),c=n(1561),l=n(8168),u=n(5302),d=n.n(u),p=(n(4363),n(8587)),f=(n(4146),1073741823),m="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof window?window:void 0!==n.g?n.g:{};var g=o.createContext||function(e,t){var n,a,s="__create-react-context-"+function(){var e="__global_unique_id__";return m[e]=(m[e]||0)+1}()+"__",c=function(e){function n(){for(var t,n,r,o=arguments.length,a=new Array(o),i=0;i<o;i++)a[i]=arguments[i];return(t=e.call.apply(e,[this].concat(a))||this).emitter=(n=t.props.value,r=[],{on:function(e){r.push(e)},off:function(e){r=r.filter((function(t){return t!==e}))},get:function(){return n},set:function(e,t){n=e,r.forEach((function(e){return e(n,t)}))}}),t}(0,r.A)(n,e);var o=n.prototype;return o.getChildContext=function(){var e;return(e={})[s]=this.emitter,e},o.componentWillReceiveProps=function(e){if(this.props.value!==e.value){var n,r=this.props.value,o=e.value;((a=r)===(i=o)?0!==a||1/a==1/i:a!=a&&i!=i)?n=0:(n="function"==typeof t?t(r,o):f,0!==(n|=0)&&this.emitter.set(e.value,n))}var a,i},o.render=function(){return this.props.children},n}(o.Component);c.childContextTypes=((n={})[s]=i().object.isRequired,n);var l=function(t){function n(){for(var e,n=arguments.length,r=new Array(n),o=0;o<n;o++)r[o]=arguments[o];return(e=t.call.apply(t,[this].concat(r))||this).observedBits=void 0,e.state={value:e.getValue()},e.onUpdate=function(t,n){(0|e.observedBits)&n&&e.setState({value:e.getValue()})},e}(0,r.A)(n,t);var o=n.prototype;return o.componentWillReceiveProps=function(e){var t=e.observedBits;this.observedBits=null==t?f:t},o.componentDidMount=function(){this.context[s]&&this.context[s].on(this.onUpdate);var e=this.props.observedBits;this.observedBits=null==e?f:e},o.componentWillUnmount=function(){this.context[s]&&this.context[s].off(this.onUpdate)},o.getValue=function(){return this.context[s]?this.context[s].get():e},o.render=function(){return(e=this.props.children,Array.isArray(e)?e[0]:e)(this.state.value);var e},n}(o.Component);return l.contextTypes=((a={})[s]=i().object,a),{Provider:c,Consumer:l}},h=function(e){var t=g();return t.displayName=e,t},b=h("Router-History"),y=h("Router"),v=function(e){function t(t){var n;return(n=e.call(this,t)||this).state={location:t.history.location},n._isMounted=!1,n._pendingLocation=null,t.staticContext||(n.unlisten=t.history.listen((function(e){n._pendingLocation=e}))),n}(0,r.A)(t,e),t.computeRootMatch=function(e){return{path:"/",url:"/",params:{},isExact:"/"===e}};var n=t.prototype;return n.componentDidMount=function(){var e=this;this._isMounted=!0,this.unlisten&&this.unlisten(),this.props.staticContext||(this.unlisten=this.props.history.listen((function(t){e._isMounted&&e.setState({location:t})}))),this._pendingLocation&&this.setState({location:this._pendingLocation})},n.componentWillUnmount=function(){this.unlisten&&(this.unlisten(),this._isMounted=!1,this._pendingLocation=null)},n.render=function(){return o.createElement(y.Provider,{value:{history:this.props.history,location:this.state.location,match:t.computeRootMatch(this.state.location.pathname),staticContext:this.props.staticContext}},o.createElement(b.Provider,{children:this.props.children||null,value:this.props.history}))},t}(o.Component);o.Component;o.Component;var w={},S=1e4,k=0;function x(e,t){void 0===t&&(t={}),("string"==typeof t||Array.isArray(t))&&(t={path:t});var n=t,r=n.path,o=n.exact,a=void 0!==o&&o,i=n.strict,s=void 0!==i&&i,c=n.sensitive,l=void 0!==c&&c;return[].concat(r).reduce((function(t,n){if(!n&&""!==n)return null;if(t)return t;var r=function(e,t){var n=""+t.end+t.strict+t.sensitive,r=w[n]||(w[n]={});if(r[e])return r[e];var o=[],a={regexp:d()(e,o,t),keys:o};return k<S&&(r[e]=a,k++),a}(n,{end:a,strict:s,sensitive:l}),o=r.regexp,i=r.keys,c=o.exec(e);if(!c)return null;var u=c[0],p=c.slice(1),f=e===u;return a&&!f?null:{path:n,url:"/"===n&&""===u?"/":u,isExact:f,params:i.reduce((function(e,t,n){return e[t.name]=p[n],e}),{})}}),null)}var _=function(e){function t(){return e.apply(this,arguments)||this}return(0,r.A)(t,e),t.prototype.render=function(){var e=this;return o.createElement(y.Consumer,null,(function(t){t||(0,c.A)(!1);var n=e.props.location||t.location,r=e.props.computedMatch?e.props.computedMatch:e.props.path?x(n.pathname,e.props):t.match,a=(0,l.A)({},t,{location:n,match:r}),i=e.props,s=i.children,u=i.component,d=i.render;return Array.isArray(s)&&function(e){return 0===o.Children.count(e)}(s)&&(s=null),o.createElement(y.Provider,{value:a},a.match?s?"function"==typeof s?s(a):s:u?o.createElement(u,a):d?d(a):null:"function"==typeof s?s(a):null)}))},t}(o.Component);function E(e){return"/"===e.charAt(0)?e:"/"+e}function j(e,t){if(!e)return t;var n=E(e);return 0!==t.pathname.indexOf(n)?t:(0,l.A)({},t,{pathname:t.pathname.substr(n.length)})}function O(e){return"string"==typeof e?e:(0,s.AO)(e)}function A(e){return function(){(0,c.A)(!1)}}function C(){}o.Component;var T=function(e){function t(){return e.apply(this,arguments)||this}return(0,r.A)(t,e),t.prototype.render=function(){var e=this;return o.createElement(y.Consumer,null,(function(t){t||(0,c.A)(!1);var n,r,a=e.props.location||t.location;return o.Children.forEach(e.props.children,(function(e){if(null==r&&o.isValidElement(e)){n=e;var i=e.props.path||e.props.from;r=i?x(a.pathname,(0,l.A)({},e.props,{path:i})):t.match}})),r?o.cloneElement(n,{location:a,computedMatch:r}):null}))},t}(o.Component);var P=o.useContext;function I(){return P(b)}function N(){return P(y).location}},1020:(e,t,n)=>{"use strict";var r=n(6540),o=Symbol.for("react.element"),a=Symbol.for("react.fragment"),i=Object.prototype.hasOwnProperty,s=r.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.ReactCurrentOwner,c={key:!0,ref:!0,__self:!0,__source:!0};function l(e,t,n){var r,a={},l=null,u=null;for(r in void 0!==n&&(l=""+n),void 0!==t.key&&(l=""+t.key),void 0!==t.ref&&(u=t.ref),t)i.call(t,r)&&!c.hasOwnProperty(r)&&(a[r]=t[r]);if(e&&e.defaultProps)for(r in t=e.defaultProps)void 0===a[r]&&(a[r]=t[r]);return{$$typeof:o,type:e,key:l,ref:u,props:a,_owner:s.current}}t.Fragment=a,t.jsx=l,t.jsxs=l},5287:(e,t)=>{"use strict";var n=Symbol.for("react.element"),r=Symbol.for("react.portal"),o=Symbol.for("react.fragment"),a=Symbol.for("react.strict_mode"),i=Symbol.for("react.profiler"),s=Symbol.for("react.provider"),c=Symbol.for("react.context"),l=Symbol.for("react.forward_ref"),u=Symbol.for("react.suspense"),d=Symbol.for("react.memo"),p=Symbol.for("react.lazy"),f=Symbol.iterator;var m={isMounted:function(){return!1},enqueueForceUpdate:function(){},enqueueReplaceState:function(){},enqueueSetState:function(){}},g=Object.assign,h={};function b(e,t,n){this.props=e,this.context=t,this.refs=h,this.updater=n||m}function y(){}function v(e,t,n){this.props=e,this.context=t,this.refs=h,this.updater=n||m}b.prototype.isReactComponent={},b.prototype.setState=function(e,t){if("object"!=typeof e&&"function"!=typeof e&&null!=e)throw Error("setState(...): takes an object of state variables to update or a function which returns an object of state variables.");this.updater.enqueueSetState(this,e,t,"setState")},b.prototype.forceUpdate=function(e){this.updater.enqueueForceUpdate(this,e,"forceUpdate")},y.prototype=b.prototype;var w=v.prototype=new y;w.constructor=v,g(w,b.prototype),w.isPureReactComponent=!0;var S=Array.isArray,k=Object.prototype.hasOwnProperty,x={current:null},_={key:!0,ref:!0,__self:!0,__source:!0};function E(e,t,r){var o,a={},i=null,s=null;if(null!=t)for(o in void 0!==t.ref&&(s=t.ref),void 0!==t.key&&(i=""+t.key),t)k.call(t,o)&&!_.hasOwnProperty(o)&&(a[o]=t[o]);var c=arguments.length-2;if(1===c)a.children=r;else if(1<c){for(var l=Array(c),u=0;u<c;u++)l[u]=arguments[u+2];a.children=l}if(e&&e.defaultProps)for(o in c=e.defaultProps)void 0===a[o]&&(a[o]=c[o]);return{$$typeof:n,type:e,key:i,ref:s,props:a,_owner:x.current}}function j(e){return"object"==typeof e&&null!==e&&e.$$typeof===n}var O=/\/+/g;function A(e,t){return"object"==typeof e&&null!==e&&null!=e.key?function(e){var t={"=":"=0",":":"=2"};return"$"+e.replace(/[=:]/g,(function(e){return t[e]}))}(""+e.key):t.toString(36)}function C(e,t,o,a,i){var s=typeof e;"undefined"!==s&&"boolean"!==s||(e=null);var c=!1;if(null===e)c=!0;else switch(s){case"string":case"number":c=!0;break;case"object":switch(e.$$typeof){case n:case r:c=!0}}if(c)return i=i(c=e),e=""===a?"."+A(c,0):a,S(i)?(o="",null!=e&&(o=e.replace(O,"$&/")+"/"),C(i,t,o,"",(function(e){return e}))):null!=i&&(j(i)&&(i=function(e,t){return{$$typeof:n,type:e.type,key:t,ref:e.ref,props:e.props,_owner:e._owner}}(i,o+(!i.key||c&&c.key===i.key?"":(""+i.key).replace(O,"$&/")+"/")+e)),t.push(i)),1;if(c=0,a=""===a?".":a+":",S(e))for(var l=0;l<e.length;l++){var u=a+A(s=e[l],l);c+=C(s,t,o,u,i)}else if(u=function(e){return null===e||"object"!=typeof e?null:"function"==typeof(e=f&&e[f]||e["@@iterator"])?e:null}(e),"function"==typeof u)for(e=u.call(e),l=0;!(s=e.next()).done;)c+=C(s=s.value,t,o,u=a+A(s,l++),i);else if("object"===s)throw t=String(e),Error("Objects are not valid as a React child (found: "+("[object Object]"===t?"object with keys {"+Object.keys(e).join(", ")+"}":t)+"). If you meant to render a collection of children, use an array instead.");return c}function T(e,t,n){if(null==e)return e;var r=[],o=0;return C(e,r,"","",(function(e){return t.call(n,e,o++)})),r}function P(e){if(-1===e._status){var t=e._result;(t=t()).then((function(t){0!==e._status&&-1!==e._status||(e._status=1,e._result=t)}),(function(t){0!==e._status&&-1!==e._status||(e._status=2,e._result=t)})),-1===e._status&&(e._status=0,e._result=t)}if(1===e._status)return e._result.default;throw e._result}var I={current:null},N={transition:null},R={ReactCurrentDispatcher:I,ReactCurrentBatchConfig:N,ReactCurrentOwner:x};function L(){throw Error("act(...) is not supported in production builds of React.")}t.Children={map:T,forEach:function(e,t,n){T(e,(function(){t.apply(this,arguments)}),n)},count:function(e){var t=0;return T(e,(function(){t++})),t},toArray:function(e){return T(e,(function(e){return e}))||[]},only:function(e){if(!j(e))throw Error("React.Children.only expected to receive a single React element child.");return e}},t.Component=b,t.Fragment=o,t.Profiler=i,t.PureComponent=v,t.StrictMode=a,t.Suspense=u,t.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED=R,t.act=L,t.cloneElement=function(e,t,r){if(null==e)throw Error("React.cloneElement(...): The argument must be a React element, but you passed "+e+".");var o=g({},e.props),a=e.key,i=e.ref,s=e._owner;if(null!=t){if(void 0!==t.ref&&(i=t.ref,s=x.current),void 0!==t.key&&(a=""+t.key),e.type&&e.type.defaultProps)var c=e.type.defaultProps;for(l in t)k.call(t,l)&&!_.hasOwnProperty(l)&&(o[l]=void 0===t[l]&&void 0!==c?c[l]:t[l])}var l=arguments.length-2;if(1===l)o.children=r;else if(1<l){c=Array(l);for(var u=0;u<l;u++)c[u]=arguments[u+2];o.children=c}return{$$typeof:n,type:e.type,key:a,ref:i,props:o,_owner:s}},t.createContext=function(e){return(e={$$typeof:c,_currentValue:e,_currentValue2:e,_threadCount:0,Provider:null,Consumer:null,_defaultValue:null,_globalName:null}).Provider={$$typeof:s,_context:e},e.Consumer=e},t.createElement=E,t.createFactory=function(e){var t=E.bind(null,e);return t.type=e,t},t.createRef=function(){return{current:null}},t.forwardRef=function(e){return{$$typeof:l,render:e}},t.isValidElement=j,t.lazy=function(e){return{$$typeof:p,_payload:{_status:-1,_result:e},_init:P}},t.memo=function(e,t){return{$$typeof:d,type:e,compare:void 0===t?null:t}},t.startTransition=function(e){var t=N.transition;N.transition={};try{e()}finally{N.transition=t}},t.unstable_act=L,t.useCallback=function(e,t){return I.current.useCallback(e,t)},t.useContext=function(e){return I.current.useContext(e)},t.useDebugValue=function(){},t.useDeferredValue=function(e){return I.current.useDeferredValue(e)},t.useEffect=function(e,t){return I.current.useEffect(e,t)},t.useId=function(){return I.current.useId()},t.useImperativeHandle=function(e,t,n){return I.current.useImperativeHandle(e,t,n)},t.useInsertionEffect=function(e,t){return I.current.useInsertionEffect(e,t)},t.useLayoutEffect=function(e,t){return I.current.useLayoutEffect(e,t)},t.useMemo=function(e,t){return I.current.useMemo(e,t)},t.useReducer=function(e,t,n){return I.current.useReducer(e,t,n)},t.useRef=function(e){return I.current.useRef(e)},t.useState=function(e){return I.current.useState(e)},t.useSyncExternalStore=function(e,t,n){return I.current.useSyncExternalStore(e,t,n)},t.useTransition=function(){return I.current.useTransition()},t.version="18.3.1"},6540:(e,t,n)=>{"use strict";e.exports=n(5287)},4848:(e,t,n)=>{"use strict";e.exports=n(1020)},7463:(e,t)=>{"use strict";function n(e,t){var n=e.length;e.push(t);e:for(;0<n;){var r=n-1>>>1,o=e[r];if(!(0<a(o,t)))break e;e[r]=t,e[n]=o,n=r}}function r(e){return 0===e.length?null:e[0]}function o(e){if(0===e.length)return null;var t=e[0],n=e.pop();if(n!==t){e[0]=n;e:for(var r=0,o=e.length,i=o>>>1;r<i;){var s=2*(r+1)-1,c=e[s],l=s+1,u=e[l];if(0>a(c,n))l<o&&0>a(u,c)?(e[r]=u,e[l]=n,r=l):(e[r]=c,e[s]=n,r=s);else{if(!(l<o&&0>a(u,n)))break e;e[r]=u,e[l]=n,r=l}}}return t}function a(e,t){var n=e.sortIndex-t.sortIndex;return 0!==n?n:e.id-t.id}if("object"==typeof performance&&"function"==typeof performance.now){var i=performance;t.unstable_now=function(){return i.now()}}else{var s=Date,c=s.now();t.unstable_now=function(){return s.now()-c}}var l=[],u=[],d=1,p=null,f=3,m=!1,g=!1,h=!1,b="function"==typeof setTimeout?setTimeout:null,y="function"==typeof clearTimeout?clearTimeout:null,v="undefined"!=typeof setImmediate?setImmediate:null;function w(e){for(var t=r(u);null!==t;){if(null===t.callback)o(u);else{if(!(t.startTime<=e))break;o(u),t.sortIndex=t.expirationTime,n(l,t)}t=r(u)}}function S(e){if(h=!1,w(e),!g)if(null!==r(l))g=!0,N(k);else{var t=r(u);null!==t&&R(S,t.startTime-e)}}function k(e,n){g=!1,h&&(h=!1,y(j),j=-1),m=!0;var a=f;try{for(w(n),p=r(l);null!==p&&(!(p.expirationTime>n)||e&&!C());){var i=p.callback;if("function"==typeof i){p.callback=null,f=p.priorityLevel;var s=i(p.expirationTime<=n);n=t.unstable_now(),"function"==typeof s?p.callback=s:p===r(l)&&o(l),w(n)}else o(l);p=r(l)}if(null!==p)var c=!0;else{var d=r(u);null!==d&&R(S,d.startTime-n),c=!1}return c}finally{p=null,f=a,m=!1}}"undefined"!=typeof navigator&&void 0!==navigator.scheduling&&void 0!==navigator.scheduling.isInputPending&&navigator.scheduling.isInputPending.bind(navigator.scheduling);var x,_=!1,E=null,j=-1,O=5,A=-1;function C(){return!(t.unstable_now()-A<O)}function T(){if(null!==E){var e=t.unstable_now();A=e;var n=!0;try{n=E(!0,e)}finally{n?x():(_=!1,E=null)}}else _=!1}if("function"==typeof v)x=function(){v(T)};else if("undefined"!=typeof MessageChannel){var P=new MessageChannel,I=P.port2;P.port1.onmessage=T,x=function(){I.postMessage(null)}}else x=function(){b(T,0)};function N(e){E=e,_||(_=!0,x())}function R(e,n){j=b((function(){e(t.unstable_now())}),n)}t.unstable_IdlePriority=5,t.unstable_ImmediatePriority=1,t.unstable_LowPriority=4,t.unstable_NormalPriority=3,t.unstable_Profiling=null,t.unstable_UserBlockingPriority=2,t.unstable_cancelCallback=function(e){e.callback=null},t.unstable_continueExecution=function(){g||m||(g=!0,N(k))},t.unstable_forceFrameRate=function(e){0>e||125<e?console.error("forceFrameRate takes a positive int between 0 and 125, forcing frame rates higher than 125 fps is not supported"):O=0<e?Math.floor(1e3/e):5},t.unstable_getCurrentPriorityLevel=function(){return f},t.unstable_getFirstCallbackNode=function(){return r(l)},t.unstable_next=function(e){switch(f){case 1:case 2:case 3:var t=3;break;default:t=f}var n=f;f=t;try{return e()}finally{f=n}},t.unstable_pauseExecution=function(){},t.unstable_requestPaint=function(){},t.unstable_runWithPriority=function(e,t){switch(e){case 1:case 2:case 3:case 4:case 5:break;default:e=3}var n=f;f=e;try{return t()}finally{f=n}},t.unstable_scheduleCallback=function(e,o,a){var i=t.unstable_now();switch("object"==typeof a&&null!==a?a="number"==typeof(a=a.delay)&&0<a?i+a:i:a=i,e){case 1:var s=-1;break;case 2:s=250;break;case 5:s=1073741823;break;case 4:s=1e4;break;default:s=5e3}return e={id:d++,callback:o,priorityLevel:e,startTime:a,expirationTime:s=a+s,sortIndex:-1},a>i?(e.sortIndex=a,n(u,e),null===r(l)&&e===r(u)&&(h?(y(j),j=-1):h=!0,R(S,a-i))):(e.sortIndex=s,n(l,e),g||m||(g=!0,N(k))),e},t.unstable_shouldYield=C,t.unstable_wrapCallback=function(e){var t=f;return function(){var n=f;f=t;try{return e.apply(this,arguments)}finally{f=n}}}},9982:(e,t,n)=>{"use strict";e.exports=n(7463)},2833:e=>{e.exports=function(e,t,n,r){var o=n?n.call(r,e,t):void 0;if(void 0!==o)return!!o;if(e===t)return!0;if("object"!=typeof e||!e||"object"!=typeof t||!t)return!1;var a=Object.keys(e),i=Object.keys(t);if(a.length!==i.length)return!1;for(var s=Object.prototype.hasOwnProperty.bind(t),c=0;c<a.length;c++){var l=a[c];if(!s(l))return!1;var u=e[l],d=t[l];if(!1===(o=n?n.call(r,u,d,l):void 0)||void 0===o&&u!==d)return!1}return!0}},4784:(e,t,n)=>{"use strict";n.r(t),n.d(t,{default:()=>r});const r={title:"Cadence",tagline:"Orchestrate with Confidence: The Open-Source Workflow Engine for Tomorrow",favicon:"img/favicon.ico",url:"https://cadenceworkflow.io",baseUrl:"/",organizationName:"cadence-workflow",projectName:"Cadence-Docs",trailingSlash:!1,onBrokenLinks:"throw",onBrokenMarkdownLinks:"warn",i18n:{defaultLocale:"en",locales:["en"],path:"i18n",localeConfigs:{}},presets:[["@docusaurus/preset-classic",{docs:{sidebarPath:"./sidebars.ts",editUrl:"https://github.com/cadence-workflow/Cadence-Docs/tree/master/",remarkPlugins:[null]},blog:{blogTitle:"Cadence Blog",blogDescription:"The latest news and updates from the Cadence team",showReadingTime:!0,feedOptions:{type:["rss","atom"],xslt:!0},blogSidebarTitle:"Recent Posts",editUrl:"https://github.com/cadence-workflow/Cadence-Docs/tree/master/",onInlineTags:"warn",onInlineAuthors:"warn",onUntruncatedBlogPosts:"warn",blogSidebarCount:"ALL"},theme:{customCss:"./src/css/custom.css"},googleTagManager:{containerId:"G-W63QD8QE6E"},gtag:{trackingID:"G-W63QD8QE6E",anonymizeIP:!0}}]],plugins:[["./src/plugins/changelog/index.js",{blogTitle:"Cadence changelog",blogDescription:"Keep yourself up-to-date about new features in every release",blogSidebarCount:"ALL",blogSidebarTitle:"Changelog",routeBasePath:"/changelog",showReadingTime:!1,postsPerPage:20,archiveBasePath:null,authorsMapPath:"authors.json",feedOptions:{type:"all",title:"Cadence Docs changelog",description:"Keep yourself up-to-date about new features in every release",copyright:"Copyright \xa9 2024 Uber Technologies, Inc.",language:"en"},onInlineAuthors:"warn"}],["@docusaurus/plugin-content-docs",{id:"community",path:"community",routeBasePath:"community",editUrl:"https://github.com/cadence-workflow/Cadence-Docs/edit/master/",remarkPlugins:[null],sidebarPath:"./sidebarsCommunity.js",showLastUpdateAuthor:!0,showLastUpdateTime:!0}],["@docusaurus/plugin-client-redirects",{fromExtensions:["html"],redirects:[{from:["/docs/support","/docs/next/support"],to:"/community/support"},{from:["/docs/team","/docs/next/team"],to:"/community/team"},{from:["/docs/resources","/docs/next/resources"],to:"/community/resources"}]}]],themeConfig:{announcementBar:{id:"survey_announcement",content:'We are looking to hear your feedback, please fill the <a target="_blank" rel="noopener noreferrer" href="https://www.surveymonkey.com/r/9RL7YX9">Cadence 2024 OSS community survey</a>',backgroundColor:"#fafbfc",textColor:"#091E42",isCloseable:!0},algolia:{appId:"J7SVDVT89Z",apiKey:"e96333af9178875d6417a55ac276d718",indexName:"cadenceworkflow",contextualSearch:!1,externalUrlRegex:"external\\.com|domain\\.com",searchParameters:{},searchPagePath:"search",insights:!0},image:"img/social-card-min.jpg",navbar:{title:"",logo:{alt:"Cadence Logo",src:"img/cadence-logo.svg",srcDark:"img/logo-white.svg"},items:[{type:"docSidebar",sidebarId:"docsSidebar",position:"left",label:"Docs"},{to:"/blog",label:"Blog",position:"left"},{to:"/community/support",label:"Community",position:"left",activeBaseRegex:"/community/"},{type:"dropdown",position:"right",label:"Repositories",items:[{label:"Cadence Service",href:"https://github.com/cadence-workflow/cadence"},{label:"Go Client",href:"https://github.com/cadence-workflow/cadence-go-client"},{label:"Java Client",href:"https://github.com/cadence-workflow/cadence-java-client"},{label:"Go Samples",href:"https://github.com/cadence-workflow/cadence-samples"},{label:"Java Samples",href:"https://github.com/cadence-workflow/cadence-java-samples"},{label:"Cadence Web",href:"https://github.com/cadence-workflow/cadence-web"},{label:"Cadence IDLs",href:"https://github.com/cadence-workflow/cadence-idl"},{label:"Helm Charts",href:"https://github.com/cadence-workflow/cadence-charts"}]}],hideOnScroll:!1},footer:{style:"dark",links:[{title:"Docs",items:[{label:"Getting Started",to:"docs/get-started/"},{label:"Go Client",to:"docs/go-client/"},{label:"Java Client",to:"docs/java-client/"},{label:"Command Line Interface",to:"docs/cli/"},{label:"Operation Guide",to:"docs/operation-guide/"}]},{title:"Community",items:[{label:"Stack Overflow",href:"https://stackoverflow.com/questions/tagged/cadence-workflow+uber-cadence"},{label:"Cadence Community Slack",href:"http://t.uber.com/cadence-slack"},{label:"LinkedIn",href:"https://www.linkedin.com/company/cadenceworkflow/"}]},{title:"More",items:[{label:"Blog",to:"/blog"},{label:"GitHub",href:"https://github.com/cadence-workflow/cadence"}]}],copyright:"Copyright \xa9 2024 Uber Technologies, Inc."},prism:{theme:{plain:{color:"#393A34",backgroundColor:"#f6f8fa"},styles:[{types:["comment","prolog","doctype","cdata"],style:{color:"#999988",fontStyle:"italic"}},{types:["namespace"],style:{opacity:.7}},{types:["string","attr-value"],style:{color:"#e3116c"}},{types:["punctuation","operator"],style:{color:"#393A34"}},{types:["entity","url","symbol","number","boolean","variable","constant","property","regex","inserted"],style:{color:"#36acaa"}},{types:["atrule","keyword","attr-name","selector"],style:{color:"#00a4db"}},{types:["function","deleted","tag"],style:{color:"#d73a49"}},{types:["function-variable"],style:{color:"#6f42c1"}},{types:["tag","selector","keyword"],style:{color:"#00009f"}}]},darkTheme:{plain:{color:"#F8F8F2",backgroundColor:"#282A36"},styles:[{types:["prolog","constant","builtin"],style:{color:"rgb(189, 147, 249)"}},{types:["inserted","function"],style:{color:"rgb(80, 250, 123)"}},{types:["deleted"],style:{color:"rgb(255, 85, 85)"}},{types:["changed"],style:{color:"rgb(255, 184, 108)"}},{types:["punctuation","symbol"],style:{color:"rgb(248, 248, 242)"}},{types:["string","char","tag","selector"],style:{color:"rgb(255, 121, 198)"}},{types:["keyword","variable"],style:{color:"rgb(189, 147, 249)",fontStyle:"italic"}},{types:["comment"],style:{color:"rgb(98, 114, 164)"}},{types:["attr-name"],style:{color:"rgb(241, 250, 140)"}}]},additionalLanguages:["go","java","bash","markup","json","shell-session","yaml","gradle","log"],magicComments:[{className:"theme-code-block-highlighted-line",line:"highlight-next-line",block:{start:"highlight-start",end:"highlight-end"}}]},colorMode:{defaultMode:"light",disableSwitch:!1,respectPrefersColorScheme:!1},docs:{versionPersistence:"localStorage",sidebar:{hideable:!1,autoCollapseCategories:!1}},blog:{sidebar:{groupByYear:!0}},metadata:[],tableOfContents:{minHeadingLevel:2,maxHeadingLevel:3}},baseUrlIssueBanner:!0,future:{experimental_faster:{swcJsLoader:!1,swcJsMinimizer:!1,swcHtmlMinimizer:!1,lightningCssMinimizer:!1,mdxCrossCompilerCache:!1,rspackBundler:!1},experimental_storage:{type:"localStorage",namespace:!1},experimental_router:"browser"},onBrokenAnchors:"warn",onDuplicateRoutes:"warn",staticDirectories:["static"],customFields:{},themes:[],scripts:[],headTags:[],stylesheets:[],clientModules:[],titleDelimiter:"|",noIndex:!1,markdown:{format:"mdx",mermaid:!1,mdx1Compat:{comments:!0,admonitions:!0,headingIds:!0},anchors:{maintainCase:!1}}}},8168:(e,t,n)=>{"use strict";function r(){return r=Object.assign?Object.assign.bind():function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var r in n)({}).hasOwnProperty.call(n,r)&&(e[r]=n[r])}return e},r.apply(null,arguments)}n.d(t,{A:()=>r})},2892:(e,t,n)=>{"use strict";function r(e,t){return r=Object.setPrototypeOf?Object.setPrototypeOf.bind():function(e,t){return e.__proto__=t,e},r(e,t)}function o(e,t){e.prototype=Object.create(t.prototype),e.prototype.constructor=e,r(e,t)}n.d(t,{A:()=>o})},8587:(e,t,n)=>{"use strict";function r(e,t){if(null==e)return{};var n={};for(var r in e)if({}.hasOwnProperty.call(e,r)){if(t.includes(r))continue;n[r]=e[r]}return n}n.d(t,{A:()=>r})},4164:(e,t,n)=>{"use strict";function r(e){var t,n,o="";if("string"==typeof e||"number"==typeof e)o+=e;else if("object"==typeof e)if(Array.isArray(e)){var a=e.length;for(t=0;t<a;t++)e[t]&&(n=r(e[t]))&&(o&&(o+=" "),o+=n)}else for(n in e)e[n]&&(o&&(o+=" "),o+=n);return o}n.d(t,{A:()=>o});const o=function(){for(var e,t,n=0,o="",a=arguments.length;n<a;n++)(e=arguments[n])&&(t=r(e))&&(o&&(o+=" "),o+=t);return o}},1765:(e,t,n)=>{"use strict";n.d(t,{My:()=>S,f4:()=>Q});var r,o,a=n(6540),i=n(4164),s=Object.create,c=Object.defineProperty,l=Object.defineProperties,u=Object.getOwnPropertyDescriptor,d=Object.getOwnPropertyDescriptors,p=Object.getOwnPropertyNames,f=Object.getOwnPropertySymbols,m=Object.getPrototypeOf,g=Object.prototype.hasOwnProperty,h=Object.prototype.propertyIsEnumerable,b=(e,t,n)=>t in e?c(e,t,{enumerable:!0,configurable:!0,writable:!0,value:n}):e[t]=n,y=(e,t)=>{for(var n in t||(t={}))g.call(t,n)&&b(e,n,t[n]);if(f)for(var n of f(t))h.call(t,n)&&b(e,n,t[n]);return e},v=(e,t)=>l(e,d(t)),w=(e,t)=>{var n={};for(var r in e)g.call(e,r)&&t.indexOf(r)<0&&(n[r]=e[r]);if(null!=e&&f)for(var r of f(e))t.indexOf(r)<0&&h.call(e,r)&&(n[r]=e[r]);return n},S=((e,t,n)=>(n=null!=e?s(m(e)):{},((e,t,n,r)=>{if(t&&"object"==typeof t||"function"==typeof t)for(let o of p(t))g.call(e,o)||o===n||c(e,o,{get:()=>t[o],enumerable:!(r=u(t,o))||r.enumerable});return e})(!t&&e&&e.__esModule?n:c(n,"default",{value:e,enumerable:!0}),e)))((r={"../../node_modules/.pnpm/prismjs@1.29.0_patch_hash=vrxx3pzkik6jpmgpayxfjunetu/node_modules/prismjs/prism.js"(e,t){var n=function(){var e=/(?:^|\s)lang(?:uage)?-([\w-]+)(?=\s|$)/i,t=0,n={},r={util:{encode:function e(t){return t instanceof o?new o(t.type,e(t.content),t.alias):Array.isArray(t)?t.map(e):t.replace(/&/g,"&").replace(/</g,"<").replace(/\u00a0/g," ")},type:function(e){return Object.prototype.toString.call(e).slice(8,-1)},objId:function(e){return e.__id||Object.defineProperty(e,"__id",{value:++t}),e.__id},clone:function e(t,n){var o,a;switch(n=n||{},r.util.type(t)){case"Object":if(a=r.util.objId(t),n[a])return n[a];for(var i in o={},n[a]=o,t)t.hasOwnProperty(i)&&(o[i]=e(t[i],n));return o;case"Array":return a=r.util.objId(t),n[a]?n[a]:(o=[],n[a]=o,t.forEach((function(t,r){o[r]=e(t,n)})),o);default:return t}},getLanguage:function(t){for(;t;){var n=e.exec(t.className);if(n)return n[1].toLowerCase();t=t.parentElement}return"none"},setLanguage:function(t,n){t.className=t.className.replace(RegExp(e,"gi"),""),t.classList.add("language-"+n)},isActive:function(e,t,n){for(var r="no-"+t;e;){var o=e.classList;if(o.contains(t))return!0;if(o.contains(r))return!1;e=e.parentElement}return!!n}},languages:{plain:n,plaintext:n,text:n,txt:n,extend:function(e,t){var n=r.util.clone(r.languages[e]);for(var o in t)n[o]=t[o];return n},insertBefore:function(e,t,n,o){var a=(o=o||r.languages)[e],i={};for(var s in a)if(a.hasOwnProperty(s)){if(s==t)for(var c in n)n.hasOwnProperty(c)&&(i[c]=n[c]);n.hasOwnProperty(s)||(i[s]=a[s])}var l=o[e];return o[e]=i,r.languages.DFS(r.languages,(function(t,n){n===l&&t!=e&&(this[t]=i)})),i},DFS:function e(t,n,o,a){a=a||{};var i=r.util.objId;for(var s in t)if(t.hasOwnProperty(s)){n.call(t,s,t[s],o||s);var c=t[s],l=r.util.type(c);"Object"!==l||a[i(c)]?"Array"!==l||a[i(c)]||(a[i(c)]=!0,e(c,n,s,a)):(a[i(c)]=!0,e(c,n,null,a))}}},plugins:{},highlight:function(e,t,n){var a={code:e,grammar:t,language:n};if(r.hooks.run("before-tokenize",a),!a.grammar)throw new Error('The language "'+a.language+'" has no grammar.');return a.tokens=r.tokenize(a.code,a.grammar),r.hooks.run("after-tokenize",a),o.stringify(r.util.encode(a.tokens),a.language)},tokenize:function(e,t){var n=t.rest;if(n){for(var r in n)t[r]=n[r];delete t.rest}var o=new s;return c(o,o.head,e),i(e,o,t,o.head,0),function(e){for(var t=[],n=e.head.next;n!==e.tail;)t.push(n.value),n=n.next;return t}(o)},hooks:{all:{},add:function(e,t){var n=r.hooks.all;n[e]=n[e]||[],n[e].push(t)},run:function(e,t){var n=r.hooks.all[e];if(n&&n.length)for(var o,a=0;o=n[a++];)o(t)}},Token:o};function o(e,t,n,r){this.type=e,this.content=t,this.alias=n,this.length=0|(r||"").length}function a(e,t,n,r){e.lastIndex=t;var o=e.exec(n);if(o&&r&&o[1]){var a=o[1].length;o.index+=a,o[0]=o[0].slice(a)}return o}function i(e,t,n,s,u,d){for(var p in n)if(n.hasOwnProperty(p)&&n[p]){var f=n[p];f=Array.isArray(f)?f:[f];for(var m=0;m<f.length;++m){if(d&&d.cause==p+","+m)return;var g=f[m],h=g.inside,b=!!g.lookbehind,y=!!g.greedy,v=g.alias;if(y&&!g.pattern.global){var w=g.pattern.toString().match(/[imsuy]*$/)[0];g.pattern=RegExp(g.pattern.source,w+"g")}for(var S=g.pattern||g,k=s.next,x=u;k!==t.tail&&!(d&&x>=d.reach);x+=k.value.length,k=k.next){var _=k.value;if(t.length>e.length)return;if(!(_ instanceof o)){var E,j=1;if(y){if(!(E=a(S,x,e,b))||E.index>=e.length)break;var O=E.index,A=E.index+E[0].length,C=x;for(C+=k.value.length;O>=C;)C+=(k=k.next).value.length;if(x=C-=k.value.length,k.value instanceof o)continue;for(var T=k;T!==t.tail&&(C<A||"string"==typeof T.value);T=T.next)j++,C+=T.value.length;j--,_=e.slice(x,C),E.index-=x}else if(!(E=a(S,0,_,b)))continue;O=E.index;var P=E[0],I=_.slice(0,O),N=_.slice(O+P.length),R=x+_.length;d&&R>d.reach&&(d.reach=R);var L=k.prev;if(I&&(L=c(t,L,I),x+=I.length),l(t,L,j),k=c(t,L,new o(p,h?r.tokenize(P,h):P,v,P)),N&&c(t,k,N),j>1){var D={cause:p+","+m,reach:R};i(e,t,n,k.prev,x,D),d&&D.reach>d.reach&&(d.reach=D.reach)}}}}}}function s(){var e={value:null,prev:null,next:null},t={value:null,prev:e,next:null};e.next=t,this.head=e,this.tail=t,this.length=0}function c(e,t,n){var r=t.next,o={value:n,prev:t,next:r};return t.next=o,r.prev=o,e.length++,o}function l(e,t,n){for(var r=t.next,o=0;o<n&&r!==e.tail;o++)r=r.next;t.next=r,r.prev=t,e.length-=o}return o.stringify=function e(t,n){if("string"==typeof t)return t;if(Array.isArray(t)){var o="";return t.forEach((function(t){o+=e(t,n)})),o}var a={type:t.type,content:e(t.content,n),tag:"span",classes:["token",t.type],attributes:{},language:n},i=t.alias;i&&(Array.isArray(i)?Array.prototype.push.apply(a.classes,i):a.classes.push(i)),r.hooks.run("wrap",a);var s="";for(var c in a.attributes)s+=" "+c+'="'+(a.attributes[c]||"").replace(/"/g,""")+'"';return"<"+a.tag+' class="'+a.classes.join(" ")+'"'+s+">"+a.content+"</"+a.tag+">"},r}();t.exports=n,n.default=n}},function(){return o||(0,r[p(r)[0]])((o={exports:{}}).exports,o),o.exports})());S.languages.markup={comment:{pattern:/<!--(?:(?!<!--)[\s\S])*?-->/,greedy:!0},prolog:{pattern:/<\?[\s\S]+?\?>/,greedy:!0},doctype:{pattern:/<!DOCTYPE(?:[^>"'[\]]|"[^"]*"|'[^']*')+(?:\[(?:[^<"'\]]|"[^"]*"|'[^']*'|<(?!!--)|<!--(?:[^-]|-(?!->))*-->)*\]\s*)?>/i,greedy:!0,inside:{"internal-subset":{pattern:/(^[^\[]*\[)[\s\S]+(?=\]>$)/,lookbehind:!0,greedy:!0,inside:null},string:{pattern:/"[^"]*"|'[^']*'/,greedy:!0},punctuation:/^<!|>$|[[\]]/,"doctype-tag":/^DOCTYPE/i,name:/[^\s<>'"]+/}},cdata:{pattern:/<!\[CDATA\[[\s\S]*?\]\]>/i,greedy:!0},tag:{pattern:/<\/?(?!\d)[^\s>\/=$<%]+(?:\s(?:\s*[^\s>\/=]+(?:\s*=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+(?=[\s>]))|(?=[\s/>])))+)?\s*\/?>/,greedy:!0,inside:{tag:{pattern:/^<\/?[^\s>\/]+/,inside:{punctuation:/^<\/?/,namespace:/^[^\s>\/:]+:/}},"special-attr":[],"attr-value":{pattern:/=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+)/,inside:{punctuation:[{pattern:/^=/,alias:"attr-equals"},{pattern:/^(\s*)["']|["']$/,lookbehind:!0}]}},punctuation:/\/?>/,"attr-name":{pattern:/[^\s>\/]+/,inside:{namespace:/^[^\s>\/:]+:/}}}},entity:[{pattern:/&[\da-z]{1,8};/i,alias:"named-entity"},/&#x?[\da-f]{1,8};/i]},S.languages.markup.tag.inside["attr-value"].inside.entity=S.languages.markup.entity,S.languages.markup.doctype.inside["internal-subset"].inside=S.languages.markup,S.hooks.add("wrap",(function(e){"entity"===e.type&&(e.attributes.title=e.content.replace(/&/,"&"))})),Object.defineProperty(S.languages.markup.tag,"addInlined",{value:function(e,t){var n;(t=((n=((n={})["language-"+t]={pattern:/(^<!\[CDATA\[)[\s\S]+?(?=\]\]>$)/i,lookbehind:!0,inside:S.languages[t]},n.cdata=/^<!\[CDATA\[|\]\]>$/i,{"included-cdata":{pattern:/<!\[CDATA\[[\s\S]*?\]\]>/i,inside:n}}))["language-"+t]={pattern:/[\s\S]+/,inside:S.languages[t]},{}))[e]={pattern:RegExp(/(<__[^>]*>)(?:<!\[CDATA\[(?:[^\]]|\](?!\]>))*\]\]>|(?!<!\[CDATA\[)[\s\S])*?(?=<\/__>)/.source.replace(/__/g,(function(){return e})),"i"),lookbehind:!0,greedy:!0,inside:n},S.languages.insertBefore("markup","cdata",t)}}),Object.defineProperty(S.languages.markup.tag,"addAttribute",{value:function(e,t){S.languages.markup.tag.inside["special-attr"].push({pattern:RegExp(/(^|["'\s])/.source+"(?:"+e+")"+/\s*=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+(?=[\s>]))/.source,"i"),lookbehind:!0,inside:{"attr-name":/^[^\s=]+/,"attr-value":{pattern:/=[\s\S]+/,inside:{value:{pattern:/(^=\s*(["']|(?!["'])))\S[\s\S]*(?=\2$)/,lookbehind:!0,alias:[t,"language-"+t],inside:S.languages[t]},punctuation:[{pattern:/^=/,alias:"attr-equals"},/"|'/]}}}})}}),S.languages.html=S.languages.markup,S.languages.mathml=S.languages.markup,S.languages.svg=S.languages.markup,S.languages.xml=S.languages.extend("markup",{}),S.languages.ssml=S.languages.xml,S.languages.atom=S.languages.xml,S.languages.rss=S.languages.xml,function(e){var t={pattern:/\\[\\(){}[\]^$+*?|.]/,alias:"escape"},n=/\\(?:x[\da-fA-F]{2}|u[\da-fA-F]{4}|u\{[\da-fA-F]+\}|0[0-7]{0,2}|[123][0-7]{2}|c[a-zA-Z]|.)/,r="(?:[^\\\\-]|"+n.source+")",o=(r=RegExp(r+"-"+r),{pattern:/(<|')[^<>']+(?=[>']$)/,lookbehind:!0,alias:"variable"});e.languages.regex={"char-class":{pattern:/((?:^|[^\\])(?:\\\\)*)\[(?:[^\\\]]|\\[\s\S])*\]/,lookbehind:!0,inside:{"char-class-negation":{pattern:/(^\[)\^/,lookbehind:!0,alias:"operator"},"char-class-punctuation":{pattern:/^\[|\]$/,alias:"punctuation"},range:{pattern:r,inside:{escape:n,"range-punctuation":{pattern:/-/,alias:"operator"}}},"special-escape":t,"char-set":{pattern:/\\[wsd]|\\p\{[^{}]+\}/i,alias:"class-name"},escape:n}},"special-escape":t,"char-set":{pattern:/\.|\\[wsd]|\\p\{[^{}]+\}/i,alias:"class-name"},backreference:[{pattern:/\\(?![123][0-7]{2})[1-9]/,alias:"keyword"},{pattern:/\\k<[^<>']+>/,alias:"keyword",inside:{"group-name":o}}],anchor:{pattern:/[$^]|\\[ABbGZz]/,alias:"function"},escape:n,group:[{pattern:/\((?:\?(?:<[^<>']+>|'[^<>']+'|[>:]|<?[=!]|[idmnsuxU]+(?:-[idmnsuxU]+)?:?))?/,alias:"punctuation",inside:{"group-name":o}},{pattern:/\)/,alias:"punctuation"}],quantifier:{pattern:/(?:[+*?]|\{\d+(?:,\d*)?\})[?+]?/,alias:"number"},alternation:{pattern:/\|/,alias:"keyword"}}}(S),S.languages.clike={comment:[{pattern:/(^|[^\\])\/\*[\s\S]*?(?:\*\/|$)/,lookbehind:!0,greedy:!0},{pattern:/(^|[^\\:])\/\/.*/,lookbehind:!0,greedy:!0}],string:{pattern:/(["'])(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,greedy:!0},"class-name":{pattern:/(\b(?:class|extends|implements|instanceof|interface|new|trait)\s+|\bcatch\s+\()[\w.\\]+/i,lookbehind:!0,inside:{punctuation:/[.\\]/}},keyword:/\b(?:break|catch|continue|do|else|finally|for|function|if|in|instanceof|new|null|return|throw|try|while)\b/,boolean:/\b(?:false|true)\b/,function:/\b\w+(?=\()/,number:/\b0x[\da-f]+\b|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:e[+-]?\d+)?/i,operator:/[<>]=?|[!=]=?=?|--?|\+\+?|&&?|\|\|?|[?*/~^%]/,punctuation:/[{}[\];(),.:]/},S.languages.javascript=S.languages.extend("clike",{"class-name":[S.languages.clike["class-name"],{pattern:/(^|[^$\w\xA0-\uFFFF])(?!\s)[_$A-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\.(?:constructor|prototype))/,lookbehind:!0}],keyword:[{pattern:/((?:^|\})\s*)catch\b/,lookbehind:!0},{pattern:/(^|[^.]|\.\.\.\s*)\b(?:as|assert(?=\s*\{)|async(?=\s*(?:function\b|\(|[$\w\xA0-\uFFFF]|$))|await|break|case|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally(?=\s*(?:\{|$))|for|from(?=\s*(?:['"]|$))|function|(?:get|set)(?=\s*(?:[#\[$\w\xA0-\uFFFF]|$))|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)\b/,lookbehind:!0}],function:/#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*(?:\.\s*(?:apply|bind|call)\s*)?\()/,number:{pattern:RegExp(/(^|[^\w$])/.source+"(?:"+/NaN|Infinity/.source+"|"+/0[bB][01]+(?:_[01]+)*n?/.source+"|"+/0[oO][0-7]+(?:_[0-7]+)*n?/.source+"|"+/0[xX][\dA-Fa-f]+(?:_[\dA-Fa-f]+)*n?/.source+"|"+/\d+(?:_\d+)*n/.source+"|"+/(?:\d+(?:_\d+)*(?:\.(?:\d+(?:_\d+)*)?)?|\.\d+(?:_\d+)*)(?:[Ee][+-]?\d+(?:_\d+)*)?/.source+")"+/(?![\w$])/.source),lookbehind:!0},operator:/--|\+\+|\*\*=?|=>|&&=?|\|\|=?|[!=]==|<<=?|>>>?=?|[-+*/%&|^!=<>]=?|\.{3}|\?\?=?|\?\.?|[~:]/}),S.languages.javascript["class-name"][0].pattern=/(\b(?:class|extends|implements|instanceof|interface|new)\s+)[\w.\\]+/,S.languages.insertBefore("javascript","keyword",{regex:{pattern:RegExp(/((?:^|[^$\w\xA0-\uFFFF."'\])\s]|\b(?:return|yield))\s*)/.source+/\//.source+"(?:"+/(?:\[(?:[^\]\\\r\n]|\\.)*\]|\\.|[^/\\\[\r\n])+\/[dgimyus]{0,7}/.source+"|"+/(?:\[(?:[^[\]\\\r\n]|\\.|\[(?:[^[\]\\\r\n]|\\.|\[(?:[^[\]\\\r\n]|\\.)*\])*\])*\]|\\.|[^/\\\[\r\n])+\/[dgimyus]{0,7}v[dgimyus]{0,7}/.source+")"+/(?=(?:\s|\/\*(?:[^*]|\*(?!\/))*\*\/)*(?:$|[\r\n,.;:})\]]|\/\/))/.source),lookbehind:!0,greedy:!0,inside:{"regex-source":{pattern:/^(\/)[\s\S]+(?=\/[a-z]*$)/,lookbehind:!0,alias:"language-regex",inside:S.languages.regex},"regex-delimiter":/^\/|\/$/,"regex-flags":/^[a-z]+$/}},"function-variable":{pattern:/#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*[=:]\s*(?:async\s*)?(?:\bfunction\b|(?:\((?:[^()]|\([^()]*\))*\)|(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*)\s*=>))/,alias:"function"},parameter:[{pattern:/(function(?:\s+(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*)?\s*\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\))/,lookbehind:!0,inside:S.languages.javascript},{pattern:/(^|[^$\w\xA0-\uFFFF])(?!\s)[_$a-z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*=>)/i,lookbehind:!0,inside:S.languages.javascript},{pattern:/(\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\)\s*=>)/,lookbehind:!0,inside:S.languages.javascript},{pattern:/((?:\b|\s|^)(?!(?:as|async|await|break|case|catch|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally|for|from|function|get|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|set|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)(?![$\w\xA0-\uFFFF]))(?:(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*\s*)\(\s*|\]\s*\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\)\s*\{)/,lookbehind:!0,inside:S.languages.javascript}],constant:/\b[A-Z](?:[A-Z_]|\dx?)*\b/}),S.languages.insertBefore("javascript","string",{hashbang:{pattern:/^#!.*/,greedy:!0,alias:"comment"},"template-string":{pattern:/`(?:\\[\s\S]|\$\{(?:[^{}]|\{(?:[^{}]|\{[^}]*\})*\})+\}|(?!\$\{)[^\\`])*`/,greedy:!0,inside:{"template-punctuation":{pattern:/^`|`$/,alias:"string"},interpolation:{pattern:/((?:^|[^\\])(?:\\{2})*)\$\{(?:[^{}]|\{(?:[^{}]|\{[^}]*\})*\})+\}/,lookbehind:!0,inside:{"interpolation-punctuation":{pattern:/^\$\{|\}$/,alias:"punctuation"},rest:S.languages.javascript}},string:/[\s\S]+/}},"string-property":{pattern:/((?:^|[,{])[ \t]*)(["'])(?:\\(?:\r\n|[\s\S])|(?!\2)[^\\\r\n])*\2(?=\s*:)/m,lookbehind:!0,greedy:!0,alias:"property"}}),S.languages.insertBefore("javascript","operator",{"literal-property":{pattern:/((?:^|[,{])[ \t]*)(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*:)/m,lookbehind:!0,alias:"property"}}),S.languages.markup&&(S.languages.markup.tag.addInlined("script","javascript"),S.languages.markup.tag.addAttribute(/on(?:abort|blur|change|click|composition(?:end|start|update)|dblclick|error|focus(?:in|out)?|key(?:down|up)|load|mouse(?:down|enter|leave|move|out|over|up)|reset|resize|scroll|select|slotchange|submit|unload|wheel)/.source,"javascript")),S.languages.js=S.languages.javascript,S.languages.actionscript=S.languages.extend("javascript",{keyword:/\b(?:as|break|case|catch|class|const|default|delete|do|dynamic|each|else|extends|final|finally|for|function|get|if|implements|import|in|include|instanceof|interface|internal|is|namespace|native|new|null|override|package|private|protected|public|return|set|static|super|switch|this|throw|try|typeof|use|var|void|while|with)\b/,operator:/\+\+|--|(?:[+\-*\/%^]|&&?|\|\|?|<<?|>>?>?|[!=]=?)=?|[~?@]/}),S.languages.actionscript["class-name"].alias="function",delete S.languages.actionscript.parameter,delete S.languages.actionscript["literal-property"],S.languages.markup&&S.languages.insertBefore("actionscript","string",{xml:{pattern:/(^|[^.])<\/?\w+(?:\s+[^\s>\/=]+=("|')(?:\\[\s\S]|(?!\2)[^\\])*\2)*\s*\/?>/,lookbehind:!0,inside:S.languages.markup}}),function(e){var t=/#(?!\{).+/,n={pattern:/#\{[^}]+\}/,alias:"variable"};e.languages.coffeescript=e.languages.extend("javascript",{comment:t,string:[{pattern:/'(?:\\[\s\S]|[^\\'])*'/,greedy:!0},{pattern:/"(?:\\[\s\S]|[^\\"])*"/,greedy:!0,inside:{interpolation:n}}],keyword:/\b(?:and|break|by|catch|class|continue|debugger|delete|do|each|else|extend|extends|false|finally|for|if|in|instanceof|is|isnt|let|loop|namespace|new|no|not|null|of|off|on|or|own|return|super|switch|then|this|throw|true|try|typeof|undefined|unless|until|when|while|window|with|yes|yield)\b/,"class-member":{pattern:/@(?!\d)\w+/,alias:"variable"}}),e.languages.insertBefore("coffeescript","comment",{"multiline-comment":{pattern:/###[\s\S]+?###/,alias:"comment"},"block-regex":{pattern:/\/{3}[\s\S]*?\/{3}/,alias:"regex",inside:{comment:t,interpolation:n}}}),e.languages.insertBefore("coffeescript","string",{"inline-javascript":{pattern:/`(?:\\[\s\S]|[^\\`])*`/,inside:{delimiter:{pattern:/^`|`$/,alias:"punctuation"},script:{pattern:/[\s\S]+/,alias:"language-javascript",inside:e.languages.javascript}}},"multiline-string":[{pattern:/'''[\s\S]*?'''/,greedy:!0,alias:"string"},{pattern:/"""[\s\S]*?"""/,greedy:!0,alias:"string",inside:{interpolation:n}}]}),e.languages.insertBefore("coffeescript","keyword",{property:/(?!\d)\w+(?=\s*:(?!:))/}),delete e.languages.coffeescript["template-string"],e.languages.coffee=e.languages.coffeescript}(S),function(e){var t=e.languages.javadoclike={parameter:{pattern:/(^[\t ]*(?:\/{3}|\*|\/\*\*)\s*@(?:arg|arguments|param)\s+)\w+/m,lookbehind:!0},keyword:{pattern:/(^[\t ]*(?:\/{3}|\*|\/\*\*)\s*|\{)@[a-z][a-zA-Z-]+\b/m,lookbehind:!0},punctuation:/[{}]/};Object.defineProperty(t,"addSupport",{value:function(t,n){(t="string"==typeof t?[t]:t).forEach((function(t){var r=function(e){e.inside||(e.inside={}),e.inside.rest=n},o="doc-comment";if(a=e.languages[t]){var a,i=a[o];if((i=i||(a=e.languages.insertBefore(t,"comment",{"doc-comment":{pattern:/(^|[^\\])\/\*\*[^/][\s\S]*?(?:\*\/|$)/,lookbehind:!0,alias:"comment"}}))[o])instanceof RegExp&&(i=a[o]={pattern:i}),Array.isArray(i))for(var s=0,c=i.length;s<c;s++)i[s]instanceof RegExp&&(i[s]={pattern:i[s]}),r(i[s]);else r(i)}}))}}),t.addSupport(["java","javascript","php"],t)}(S),function(e){var t=/(?:"(?:\\(?:\r\n|[\s\S])|[^"\\\r\n])*"|'(?:\\(?:\r\n|[\s\S])|[^'\\\r\n])*')/;(t=(e.languages.css={comment:/\/\*[\s\S]*?\*\//,atrule:{pattern:RegExp("@[\\w-](?:"+/[^;{\s"']|\s+(?!\s)/.source+"|"+t.source+")*?"+/(?:;|(?=\s*\{))/.source),inside:{rule:/^@[\w-]+/,"selector-function-argument":{pattern:/(\bselector\s*\(\s*(?![\s)]))(?:[^()\s]|\s+(?![\s)])|\((?:[^()]|\([^()]*\))*\))+(?=\s*\))/,lookbehind:!0,alias:"selector"},keyword:{pattern:/(^|[^\w-])(?:and|not|only|or)(?![\w-])/,lookbehind:!0}}},url:{pattern:RegExp("\\burl\\((?:"+t.source+"|"+/(?:[^\\\r\n()"']|\\[\s\S])*/.source+")\\)","i"),greedy:!0,inside:{function:/^url/i,punctuation:/^\(|\)$/,string:{pattern:RegExp("^"+t.source+"$"),alias:"url"}}},selector:{pattern:RegExp("(^|[{}\\s])[^{}\\s](?:[^{};\"'\\s]|\\s+(?![\\s{])|"+t.source+")*(?=\\s*\\{)"),lookbehind:!0},string:{pattern:t,greedy:!0},property:{pattern:/(^|[^-\w\xA0-\uFFFF])(?!\s)[-_a-z\xA0-\uFFFF](?:(?!\s)[-\w\xA0-\uFFFF])*(?=\s*:)/i,lookbehind:!0},important:/!important\b/i,function:{pattern:/(^|[^-a-z0-9])[-a-z0-9]+(?=\()/i,lookbehind:!0},punctuation:/[(){};:,]/},e.languages.css.atrule.inside.rest=e.languages.css,e.languages.markup))&&(t.tag.addInlined("style","css"),t.tag.addAttribute("style","css"))}(S),function(e){var t=/("|')(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,n=(t=(e.languages.css.selector={pattern:e.languages.css.selector.pattern,lookbehind:!0,inside:t={"pseudo-element":/:(?:after|before|first-letter|first-line|selection)|::[-\w]+/,"pseudo-class":/:[-\w]+/,class:/\.[-\w]+/,id:/#[-\w]+/,attribute:{pattern:RegExp("\\[(?:[^[\\]\"']|"+t.source+")*\\]"),greedy:!0,inside:{punctuation:/^\[|\]$/,"case-sensitivity":{pattern:/(\s)[si]$/i,lookbehind:!0,alias:"keyword"},namespace:{pattern:/^(\s*)(?:(?!\s)[-*\w\xA0-\uFFFF])*\|(?!=)/,lookbehind:!0,inside:{punctuation:/\|$/}},"attr-name":{pattern:/^(\s*)(?:(?!\s)[-\w\xA0-\uFFFF])+/,lookbehind:!0},"attr-value":[t,{pattern:/(=\s*)(?:(?!\s)[-\w\xA0-\uFFFF])+(?=\s*$)/,lookbehind:!0}],operator:/[|~*^$]?=/}},"n-th":[{pattern:/(\(\s*)[+-]?\d*[\dn](?:\s*[+-]\s*\d+)?(?=\s*\))/,lookbehind:!0,inside:{number:/[\dn]+/,operator:/[+-]/}},{pattern:/(\(\s*)(?:even|odd)(?=\s*\))/i,lookbehind:!0}],combinator:/>|\+|~|\|\|/,punctuation:/[(),]/}},e.languages.css.atrule.inside["selector-function-argument"].inside=t,e.languages.insertBefore("css","property",{variable:{pattern:/(^|[^-\w\xA0-\uFFFF])--(?!\s)[-_a-z\xA0-\uFFFF](?:(?!\s)[-\w\xA0-\uFFFF])*/i,lookbehind:!0}}),{pattern:/(\b\d+)(?:%|[a-z]+(?![\w-]))/,lookbehind:!0}),{pattern:/(^|[^\w.-])-?(?:\d+(?:\.\d+)?|\.\d+)/,lookbehind:!0});e.languages.insertBefore("css","function",{operator:{pattern:/(\s)[+\-*\/](?=\s)/,lookbehind:!0},hexcode:{pattern:/\B#[\da-f]{3,8}\b/i,alias:"color"},color:[{pattern:/(^|[^\w-])(?:AliceBlue|AntiqueWhite|Aqua|Aquamarine|Azure|Beige|Bisque|Black|BlanchedAlmond|Blue|BlueViolet|Brown|BurlyWood|CadetBlue|Chartreuse|Chocolate|Coral|CornflowerBlue|Cornsilk|Crimson|Cyan|DarkBlue|DarkCyan|DarkGoldenRod|DarkGr[ae]y|DarkGreen|DarkKhaki|DarkMagenta|DarkOliveGreen|DarkOrange|DarkOrchid|DarkRed|DarkSalmon|DarkSeaGreen|DarkSlateBlue|DarkSlateGr[ae]y|DarkTurquoise|DarkViolet|DeepPink|DeepSkyBlue|DimGr[ae]y|DodgerBlue|FireBrick|FloralWhite|ForestGreen|Fuchsia|Gainsboro|GhostWhite|Gold|GoldenRod|Gr[ae]y|Green|GreenYellow|HoneyDew|HotPink|IndianRed|Indigo|Ivory|Khaki|Lavender|LavenderBlush|LawnGreen|LemonChiffon|LightBlue|LightCoral|LightCyan|LightGoldenRodYellow|LightGr[ae]y|LightGreen|LightPink|LightSalmon|LightSeaGreen|LightSkyBlue|LightSlateGr[ae]y|LightSteelBlue|LightYellow|Lime|LimeGreen|Linen|Magenta|Maroon|MediumAquaMarine|MediumBlue|MediumOrchid|MediumPurple|MediumSeaGreen|MediumSlateBlue|MediumSpringGreen|MediumTurquoise|MediumVioletRed|MidnightBlue|MintCream|MistyRose|Moccasin|NavajoWhite|Navy|OldLace|Olive|OliveDrab|Orange|OrangeRed|Orchid|PaleGoldenRod|PaleGreen|PaleTurquoise|PaleVioletRed|PapayaWhip|PeachPuff|Peru|Pink|Plum|PowderBlue|Purple|RebeccaPurple|Red|RosyBrown|RoyalBlue|SaddleBrown|Salmon|SandyBrown|SeaGreen|SeaShell|Sienna|Silver|SkyBlue|SlateBlue|SlateGr[ae]y|Snow|SpringGreen|SteelBlue|Tan|Teal|Thistle|Tomato|Transparent|Turquoise|Violet|Wheat|White|WhiteSmoke|Yellow|YellowGreen)(?![\w-])/i,lookbehind:!0},{pattern:/\b(?:hsl|rgb)\(\s*\d{1,3}\s*,\s*\d{1,3}%?\s*,\s*\d{1,3}%?\s*\)\B|\b(?:hsl|rgb)a\(\s*\d{1,3}\s*,\s*\d{1,3}%?\s*,\s*\d{1,3}%?\s*,\s*(?:0|0?\.\d+|1)\s*\)\B/i,inside:{unit:t,number:n,function:/[\w-]+(?=\()/,punctuation:/[(),]/}}],entity:/\\[\da-f]{1,8}/i,unit:t,number:n})}(S),function(e){var t=/[*&][^\s[\]{},]+/,n=/!(?:<[\w\-%#;/?:@&=+$,.!~*'()[\]]+>|(?:[a-zA-Z\d-]*!)?[\w\-%#;/?:@&=+$.~*'()]+)?/,r="(?:"+n.source+"(?:[ \t]+"+t.source+")?|"+t.source+"(?:[ \t]+"+n.source+")?)",o=/(?:[^\s\x00-\x08\x0e-\x1f!"#%&'*,\-:>?@[\]`{|}\x7f-\x84\x86-\x9f\ud800-\udfff\ufffe\uffff]|[?:-]<PLAIN>)(?:[ \t]*(?:(?![#:])<PLAIN>|:<PLAIN>))*/.source.replace(/<PLAIN>/g,(function(){return/[^\s\x00-\x08\x0e-\x1f,[\]{}\x7f-\x84\x86-\x9f\ud800-\udfff\ufffe\uffff]/.source})),a=/"(?:[^"\\\r\n]|\\.)*"|'(?:[^'\\\r\n]|\\.)*'/.source;function i(e,t){t=(t||"").replace(/m/g,"")+"m";var n=/([:\-,[{]\s*(?:\s<<prop>>[ \t]+)?)(?:<<value>>)(?=[ \t]*(?:$|,|\]|\}|(?:[\r\n]\s*)?#))/.source.replace(/<<prop>>/g,(function(){return r})).replace(/<<value>>/g,(function(){return e}));return RegExp(n,t)}e.languages.yaml={scalar:{pattern:RegExp(/([\-:]\s*(?:\s<<prop>>[ \t]+)?[|>])[ \t]*(?:((?:\r?\n|\r)[ \t]+)\S[^\r\n]*(?:\2[^\r\n]+)*)/.source.replace(/<<prop>>/g,(function(){return r}))),lookbehind:!0,alias:"string"},comment:/#.*/,key:{pattern:RegExp(/((?:^|[:\-,[{\r\n?])[ \t]*(?:<<prop>>[ \t]+)?)<<key>>(?=\s*:\s)/.source.replace(/<<prop>>/g,(function(){return r})).replace(/<<key>>/g,(function(){return"(?:"+o+"|"+a+")"}))),lookbehind:!0,greedy:!0,alias:"atrule"},directive:{pattern:/(^[ \t]*)%.+/m,lookbehind:!0,alias:"important"},datetime:{pattern:i(/\d{4}-\d\d?-\d\d?(?:[tT]|[ \t]+)\d\d?:\d{2}:\d{2}(?:\.\d*)?(?:[ \t]*(?:Z|[-+]\d\d?(?::\d{2})?))?|\d{4}-\d{2}-\d{2}|\d\d?:\d{2}(?::\d{2}(?:\.\d*)?)?/.source),lookbehind:!0,alias:"number"},boolean:{pattern:i(/false|true/.source,"i"),lookbehind:!0,alias:"important"},null:{pattern:i(/null|~/.source,"i"),lookbehind:!0,alias:"important"},string:{pattern:i(a),lookbehind:!0,greedy:!0},number:{pattern:i(/[+-]?(?:0x[\da-f]+|0o[0-7]+|(?:\d+(?:\.\d*)?|\.\d+)(?:e[+-]?\d+)?|\.inf|\.nan)/.source,"i"),lookbehind:!0},tag:n,important:t,punctuation:/---|[:[\]{}\-,|>?]|\.\.\./},e.languages.yml=e.languages.yaml}(S),function(e){var t=/(?:\\.|[^\\\n\r]|(?:\n|\r\n?)(?![\r\n]))/.source;function n(e){return e=e.replace(/<inner>/g,(function(){return t})),RegExp(/((?:^|[^\\])(?:\\{2})*)/.source+"(?:"+e+")")}var r=/(?:\\.|``(?:[^`\r\n]|`(?!`))+``|`[^`\r\n]+`|[^\\|\r\n`])+/.source,o=/\|?__(?:\|__)+\|?(?:(?:\n|\r\n?)|(?![\s\S]))/.source.replace(/__/g,(function(){return r})),a=/\|?[ \t]*:?-{3,}:?[ \t]*(?:\|[ \t]*:?-{3,}:?[ \t]*)+\|?(?:\n|\r\n?)/.source,i=(e.languages.markdown=e.languages.extend("markup",{}),e.languages.insertBefore("markdown","prolog",{"front-matter-block":{pattern:/(^(?:\s*[\r\n])?)---(?!.)[\s\S]*?[\r\n]---(?!.)/,lookbehind:!0,greedy:!0,inside:{punctuation:/^---|---$/,"front-matter":{pattern:/\S+(?:\s+\S+)*/,alias:["yaml","language-yaml"],inside:e.languages.yaml}}},blockquote:{pattern:/^>(?:[\t ]*>)*/m,alias:"punctuation"},table:{pattern:RegExp("^"+o+a+"(?:"+o+")*","m"),inside:{"table-data-rows":{pattern:RegExp("^("+o+a+")(?:"+o+")*$"),lookbehind:!0,inside:{"table-data":{pattern:RegExp(r),inside:e.languages.markdown},punctuation:/\|/}},"table-line":{pattern:RegExp("^("+o+")"+a+"$"),lookbehind:!0,inside:{punctuation:/\||:?-{3,}:?/}},"table-header-row":{pattern:RegExp("^"+o+"$"),inside:{"table-header":{pattern:RegExp(r),alias:"important",inside:e.languages.markdown},punctuation:/\|/}}}},code:[{pattern:/((?:^|\n)[ \t]*\n|(?:^|\r\n?)[ \t]*\r\n?)(?: {4}|\t).+(?:(?:\n|\r\n?)(?: {4}|\t).+)*/,lookbehind:!0,alias:"keyword"},{pattern:/^```[\s\S]*?^```$/m,greedy:!0,inside:{"code-block":{pattern:/^(```.*(?:\n|\r\n?))[\s\S]+?(?=(?:\n|\r\n?)^```$)/m,lookbehind:!0},"code-language":{pattern:/^(```).+/,lookbehind:!0},punctuation:/```/}}],title:[{pattern:/\S.*(?:\n|\r\n?)(?:==+|--+)(?=[ \t]*$)/m,alias:"important",inside:{punctuation:/==+$|--+$/}},{pattern:/(^\s*)#.+/m,lookbehind:!0,alias:"important",inside:{punctuation:/^#+|#+$/}}],hr:{pattern:/(^\s*)([*-])(?:[\t ]*\2){2,}(?=\s*$)/m,lookbehind:!0,alias:"punctuation"},list:{pattern:/(^\s*)(?:[*+-]|\d+\.)(?=[\t ].)/m,lookbehind:!0,alias:"punctuation"},"url-reference":{pattern:/!?\[[^\]]+\]:[\t ]+(?:\S+|<(?:\\.|[^>\\])+>)(?:[\t ]+(?:"(?:\\.|[^"\\])*"|'(?:\\.|[^'\\])*'|\((?:\\.|[^)\\])*\)))?/,inside:{variable:{pattern:/^(!?\[)[^\]]+/,lookbehind:!0},string:/(?:"(?:\\.|[^"\\])*"|'(?:\\.|[^'\\])*'|\((?:\\.|[^)\\])*\))$/,punctuation:/^[\[\]!:]|[<>]/},alias:"url"},bold:{pattern:n(/\b__(?:(?!_)<inner>|_(?:(?!_)<inner>)+_)+__\b|\*\*(?:(?!\*)<inner>|\*(?:(?!\*)<inner>)+\*)+\*\*/.source),lookbehind:!0,greedy:!0,inside:{content:{pattern:/(^..)[\s\S]+(?=..$)/,lookbehind:!0,inside:{}},punctuation:/\*\*|__/}},italic:{pattern:n(/\b_(?:(?!_)<inner>|__(?:(?!_)<inner>)+__)+_\b|\*(?:(?!\*)<inner>|\*\*(?:(?!\*)<inner>)+\*\*)+\*/.source),lookbehind:!0,greedy:!0,inside:{content:{pattern:/(^.)[\s\S]+(?=.$)/,lookbehind:!0,inside:{}},punctuation:/[*_]/}},strike:{pattern:n(/(~~?)(?:(?!~)<inner>)+\2/.source),lookbehind:!0,greedy:!0,inside:{content:{pattern:/(^~~?)[\s\S]+(?=\1$)/,lookbehind:!0,inside:{}},punctuation:/~~?/}},"code-snippet":{pattern:/(^|[^\\`])(?:``[^`\r\n]+(?:`[^`\r\n]+)*``(?!`)|`[^`\r\n]+`(?!`))/,lookbehind:!0,greedy:!0,alias:["code","keyword"]},url:{pattern:n(/!?\[(?:(?!\])<inner>)+\](?:\([^\s)]+(?:[\t ]+"(?:\\.|[^"\\])*")?\)|[ \t]?\[(?:(?!\])<inner>)+\])/.source),lookbehind:!0,greedy:!0,inside:{operator:/^!/,content:{pattern:/(^\[)[^\]]+(?=\])/,lookbehind:!0,inside:{}},variable:{pattern:/(^\][ \t]?\[)[^\]]+(?=\]$)/,lookbehind:!0},url:{pattern:/(^\]\()[^\s)]+/,lookbehind:!0},string:{pattern:/(^[ \t]+)"(?:\\.|[^"\\])*"(?=\)$)/,lookbehind:!0}}}}),["url","bold","italic","strike"].forEach((function(t){["url","bold","italic","strike","code-snippet"].forEach((function(n){t!==n&&(e.languages.markdown[t].inside.content.inside[n]=e.languages.markdown[n])}))})),e.hooks.add("after-tokenize",(function(e){"markdown"!==e.language&&"md"!==e.language||function e(t){if(t&&"string"!=typeof t)for(var n=0,r=t.length;n<r;n++){var o,a=t[n];"code"!==a.type?e(a.content):(o=a.content[1],a=a.content[3],o&&a&&"code-language"===o.type&&"code-block"===a.type&&"string"==typeof o.content&&(o=o.content.replace(/\b#/g,"sharp").replace(/\b\+\+/g,"pp"),o="language-"+(o=(/[a-z][\w-]*/i.exec(o)||[""])[0].toLowerCase()),a.alias?"string"==typeof a.alias?a.alias=[a.alias,o]:a.alias.push(o):a.alias=[o]))}}(e.tokens)})),e.hooks.add("wrap",(function(t){if("code-block"===t.type){for(var n="",r=0,o=t.classes.length;r<o;r++){var a=t.classes[r];if(a=/language-(.+)/.exec(a)){n=a[1];break}}var l,u=e.languages[n];u?t.content=e.highlight(t.content.replace(i,"").replace(/&(\w{1,8}|#x?[\da-f]{1,8});/gi,(function(e,t){var n;return"#"===(t=t.toLowerCase())[0]?(n="x"===t[1]?parseInt(t.slice(2),16):Number(t.slice(1)),c(n)):s[t]||e})),u,n):n&&"none"!==n&&e.plugins.autoloader&&(l="md-"+(new Date).valueOf()+"-"+Math.floor(1e16*Math.random()),t.attributes.id=l,e.plugins.autoloader.loadLanguages(n,(function(){var t=document.getElementById(l);t&&(t.innerHTML=e.highlight(t.textContent,e.languages[n],n))})))}})),RegExp(e.languages.markup.tag.pattern.source,"gi")),s={amp:"&",lt:"<",gt:">",quot:'"'},c=String.fromCodePoint||String.fromCharCode;e.languages.md=e.languages.markdown}(S),S.languages.graphql={comment:/#.*/,description:{pattern:/(?:"""(?:[^"]|(?!""")")*"""|"(?:\\.|[^\\"\r\n])*")(?=\s*[a-z_])/i,greedy:!0,alias:"string",inside:{"language-markdown":{pattern:/(^"(?:"")?)(?!\1)[\s\S]+(?=\1$)/,lookbehind:!0,inside:S.languages.markdown}}},string:{pattern:/"""(?:[^"]|(?!""")")*"""|"(?:\\.|[^\\"\r\n])*"/,greedy:!0},number:/(?:\B-|\b)\d+(?:\.\d+)?(?:e[+-]?\d+)?\b/i,boolean:/\b(?:false|true)\b/,variable:/\$[a-z_]\w*/i,directive:{pattern:/@[a-z_]\w*/i,alias:"function"},"attr-name":{pattern:/\b[a-z_]\w*(?=\s*(?:\((?:[^()"]|"(?:\\.|[^\\"\r\n])*")*\))?:)/i,greedy:!0},"atom-input":{pattern:/\b[A-Z]\w*Input\b/,alias:"class-name"},scalar:/\b(?:Boolean|Float|ID|Int|String)\b/,constant:/\b[A-Z][A-Z_\d]*\b/,"class-name":{pattern:/(\b(?:enum|implements|interface|on|scalar|type|union)\s+|&\s*|:\s*|\[)[A-Z_]\w*/,lookbehind:!0},fragment:{pattern:/(\bfragment\s+|\.{3}\s*(?!on\b))[a-zA-Z_]\w*/,lookbehind:!0,alias:"function"},"definition-mutation":{pattern:/(\bmutation\s+)[a-zA-Z_]\w*/,lookbehind:!0,alias:"function"},"definition-query":{pattern:/(\bquery\s+)[a-zA-Z_]\w*/,lookbehind:!0,alias:"function"},keyword:/\b(?:directive|enum|extend|fragment|implements|input|interface|mutation|on|query|repeatable|scalar|schema|subscription|type|union)\b/,operator:/[!=|&]|\.{3}/,"property-query":/\w+(?=\s*\()/,object:/\w+(?=\s*\{)/,punctuation:/[!(){}\[\]:=,]/,property:/\w+/},S.hooks.add("after-tokenize",(function(e){if("graphql"===e.language)for(var t=e.tokens.filter((function(e){return"string"!=typeof e&&"comment"!==e.type&&"scalar"!==e.type})),n=0;n<t.length;){var r=t[n++];if("keyword"===r.type&&"mutation"===r.content){var o=[];if(d(["definition-mutation","punctuation"])&&"("===u(1).content){n+=2;var a=p(/^\($/,/^\)$/);if(-1===a)continue;for(;n<a;n++){var i=u(0);"variable"===i.type&&(f(i,"variable-input"),o.push(i.content))}n=a+1}if(d(["punctuation","property-query"])&&"{"===u(0).content&&(n++,f(u(0),"property-mutation"),0<o.length)){var s=p(/^\{$/,/^\}$/);if(-1!==s)for(var c=n;c<s;c++){var l=t[c];"variable"===l.type&&0<=o.indexOf(l.content)&&f(l,"variable-input")}}}}function u(e){return t[n+e]}function d(e,t){t=t||0;for(var n=0;n<e.length;n++){var r=u(n+t);if(!r||r.type!==e[n])return}return 1}function p(e,r){for(var o=1,a=n;a<t.length;a++){var i=t[a],s=i.content;if("punctuation"===i.type&&"string"==typeof s)if(e.test(s))o++;else if(r.test(s)&&0==--o)return a}return-1}function f(e,t){var n=e.alias;n?Array.isArray(n)||(e.alias=n=[n]):e.alias=n=[],n.push(t)}})),S.languages.sql={comment:{pattern:/(^|[^\\])(?:\/\*[\s\S]*?\*\/|(?:--|\/\/|#).*)/,lookbehind:!0},variable:[{pattern:/@(["'`])(?:\\[\s\S]|(?!\1)[^\\])+\1/,greedy:!0},/@[\w.$]+/],string:{pattern:/(^|[^@\\])("|')(?:\\[\s\S]|(?!\2)[^\\]|\2\2)*\2/,greedy:!0,lookbehind:!0},identifier:{pattern:/(^|[^@\\])`(?:\\[\s\S]|[^`\\]|``)*`/,greedy:!0,lookbehind:!0,inside:{punctuation:/^`|`$/}},function:/\b(?:AVG|COUNT|FIRST|FORMAT|LAST|LCASE|LEN|MAX|MID|MIN|MOD|NOW|ROUND|SUM|UCASE)(?=\s*\()/i,keyword:/\b(?:ACTION|ADD|AFTER|ALGORITHM|ALL|ALTER|ANALYZE|ANY|APPLY|AS|ASC|AUTHORIZATION|AUTO_INCREMENT|BACKUP|BDB|BEGIN|BERKELEYDB|BIGINT|BINARY|BIT|BLOB|BOOL|BOOLEAN|BREAK|BROWSE|BTREE|BULK|BY|CALL|CASCADED?|CASE|CHAIN|CHAR(?:ACTER|SET)?|CHECK(?:POINT)?|CLOSE|CLUSTERED|COALESCE|COLLATE|COLUMNS?|COMMENT|COMMIT(?:TED)?|COMPUTE|CONNECT|CONSISTENT|CONSTRAINT|CONTAINS(?:TABLE)?|CONTINUE|CONVERT|CREATE|CROSS|CURRENT(?:_DATE|_TIME|_TIMESTAMP|_USER)?|CURSOR|CYCLE|DATA(?:BASES?)?|DATE(?:TIME)?|DAY|DBCC|DEALLOCATE|DEC|DECIMAL|DECLARE|DEFAULT|DEFINER|DELAYED|DELETE|DELIMITERS?|DENY|DESC|DESCRIBE|DETERMINISTIC|DISABLE|DISCARD|DISK|DISTINCT|DISTINCTROW|DISTRIBUTED|DO|DOUBLE|DROP|DUMMY|DUMP(?:FILE)?|DUPLICATE|ELSE(?:IF)?|ENABLE|ENCLOSED|END|ENGINE|ENUM|ERRLVL|ERRORS|ESCAPED?|EXCEPT|EXEC(?:UTE)?|EXISTS|EXIT|EXPLAIN|EXTENDED|FETCH|FIELDS|FILE|FILLFACTOR|FIRST|FIXED|FLOAT|FOLLOWING|FOR(?: EACH ROW)?|FORCE|FOREIGN|FREETEXT(?:TABLE)?|FROM|FULL|FUNCTION|GEOMETRY(?:COLLECTION)?|GLOBAL|GOTO|GRANT|GROUP|HANDLER|HASH|HAVING|HOLDLOCK|HOUR|IDENTITY(?:COL|_INSERT)?|IF|IGNORE|IMPORT|INDEX|INFILE|INNER|INNODB|INOUT|INSERT|INT|INTEGER|INTERSECT|INTERVAL|INTO|INVOKER|ISOLATION|ITERATE|JOIN|KEYS?|KILL|LANGUAGE|LAST|LEAVE|LEFT|LEVEL|LIMIT|LINENO|LINES|LINESTRING|LOAD|LOCAL|LOCK|LONG(?:BLOB|TEXT)|LOOP|MATCH(?:ED)?|MEDIUM(?:BLOB|INT|TEXT)|MERGE|MIDDLEINT|MINUTE|MODE|MODIFIES|MODIFY|MONTH|MULTI(?:LINESTRING|POINT|POLYGON)|NATIONAL|NATURAL|NCHAR|NEXT|NO|NONCLUSTERED|NULLIF|NUMERIC|OFF?|OFFSETS?|ON|OPEN(?:DATASOURCE|QUERY|ROWSET)?|OPTIMIZE|OPTION(?:ALLY)?|ORDER|OUT(?:ER|FILE)?|OVER|PARTIAL|PARTITION|PERCENT|PIVOT|PLAN|POINT|POLYGON|PRECEDING|PRECISION|PREPARE|PREV|PRIMARY|PRINT|PRIVILEGES|PROC(?:EDURE)?|PUBLIC|PURGE|QUICK|RAISERROR|READS?|REAL|RECONFIGURE|REFERENCES|RELEASE|RENAME|REPEAT(?:ABLE)?|REPLACE|REPLICATION|REQUIRE|RESIGNAL|RESTORE|RESTRICT|RETURN(?:ING|S)?|REVOKE|RIGHT|ROLLBACK|ROUTINE|ROW(?:COUNT|GUIDCOL|S)?|RTREE|RULE|SAVE(?:POINT)?|SCHEMA|SECOND|SELECT|SERIAL(?:IZABLE)?|SESSION(?:_USER)?|SET(?:USER)?|SHARE|SHOW|SHUTDOWN|SIMPLE|SMALLINT|SNAPSHOT|SOME|SONAME|SQL|START(?:ING)?|STATISTICS|STATUS|STRIPED|SYSTEM_USER|TABLES?|TABLESPACE|TEMP(?:ORARY|TABLE)?|TERMINATED|TEXT(?:SIZE)?|THEN|TIME(?:STAMP)?|TINY(?:BLOB|INT|TEXT)|TOP?|TRAN(?:SACTIONS?)?|TRIGGER|TRUNCATE|TSEQUAL|TYPES?|UNBOUNDED|UNCOMMITTED|UNDEFINED|UNION|UNIQUE|UNLOCK|UNPIVOT|UNSIGNED|UPDATE(?:TEXT)?|USAGE|USE|USER|USING|VALUES?|VAR(?:BINARY|CHAR|CHARACTER|YING)|VIEW|WAITFOR|WARNINGS|WHEN|WHERE|WHILE|WITH(?: ROLLUP|IN)?|WORK|WRITE(?:TEXT)?|YEAR)\b/i,boolean:/\b(?:FALSE|NULL|TRUE)\b/i,number:/\b0x[\da-f]+\b|\b\d+(?:\.\d*)?|\B\.\d+\b/i,operator:/[-+*\/=%^~]|&&?|\|\|?|!=?|<(?:=>?|<|>)?|>[>=]?|\b(?:AND|BETWEEN|DIV|ILIKE|IN|IS|LIKE|NOT|OR|REGEXP|RLIKE|SOUNDS LIKE|XOR)\b/i,punctuation:/[;[\]()`,.]/},function(e){var t=e.languages.javascript["template-string"],n=t.pattern.source,r=t.inside.interpolation,o=r.inside["interpolation-punctuation"],a=r.pattern.source;function i(t,r){if(e.languages[t])return{pattern:RegExp("((?:"+r+")\\s*)"+n),lookbehind:!0,greedy:!0,inside:{"template-punctuation":{pattern:/^`|`$/,alias:"string"},"embedded-code":{pattern:/[\s\S]+/,alias:t}}}}function s(t,n,r){return t={code:t,grammar:n,language:r},e.hooks.run("before-tokenize",t),t.tokens=e.tokenize(t.code,t.grammar),e.hooks.run("after-tokenize",t),t.tokens}function c(t,n,i){var c=e.tokenize(t,{interpolation:{pattern:RegExp(a),lookbehind:!0}}),l=0,u={},d=(c=s(c.map((function(e){if("string"==typeof e)return e;var n,r;for(e=e.content;-1!==t.indexOf((r=l++,n="___"+i.toUpperCase()+"_"+r+"___")););return u[n]=e,n})).join(""),n,i),Object.keys(u));return l=0,function t(n){for(var a=0;a<n.length;a++){if(l>=d.length)return;var i,c,p,f,m,g,h,b=n[a];"string"==typeof b||"string"==typeof b.content?(i=d[l],-1!==(h=(g="string"==typeof b?b:b.content).indexOf(i))&&(++l,c=g.substring(0,h),m=u[i],p=void 0,(f={})["interpolation-punctuation"]=o,3===(f=e.tokenize(m,f)).length&&((p=[1,1]).push.apply(p,s(f[1],e.languages.javascript,"javascript")),f.splice.apply(f,p)),p=new e.Token("interpolation",f,r.alias,m),f=g.substring(h+i.length),m=[],c&&m.push(c),m.push(p),f&&(t(g=[f]),m.push.apply(m,g)),"string"==typeof b?(n.splice.apply(n,[a,1].concat(m)),a+=m.length-1):b.content=m)):(h=b.content,Array.isArray(h)?t(h):t([h]))}}(c),new e.Token(i,c,"language-"+i,t)}e.languages.javascript["template-string"]=[i("css",/\b(?:styled(?:\([^)]*\))?(?:\s*\.\s*\w+(?:\([^)]*\))*)*|css(?:\s*\.\s*(?:global|resolve))?|createGlobalStyle|keyframes)/.source),i("html",/\bhtml|\.\s*(?:inner|outer)HTML\s*\+?=/.source),i("svg",/\bsvg/.source),i("markdown",/\b(?:markdown|md)/.source),i("graphql",/\b(?:gql|graphql(?:\s*\.\s*experimental)?)/.source),i("sql",/\bsql/.source),t].filter(Boolean);var l={javascript:!0,js:!0,typescript:!0,ts:!0,jsx:!0,tsx:!0};function u(e){return"string"==typeof e?e:Array.isArray(e)?e.map(u).join(""):u(e.content)}e.hooks.add("after-tokenize",(function(t){t.language in l&&function t(n){for(var r=0,o=n.length;r<o;r++){var a,i,s,l=n[r];"string"!=typeof l&&(a=l.content,Array.isArray(a)?"template-string"===l.type?(l=a[1],3===a.length&&"string"!=typeof l&&"embedded-code"===l.type&&(i=u(l),l=l.alias,l=Array.isArray(l)?l[0]:l,s=e.languages[l])&&(a[1]=c(i,s,l))):t(a):"string"!=typeof a&&t([a]))}}(t.tokens)}))}(S),function(e){e.languages.typescript=e.languages.extend("javascript",{"class-name":{pattern:/(\b(?:class|extends|implements|instanceof|interface|new|type)\s+)(?!keyof\b)(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?:\s*<(?:[^<>]|<(?:[^<>]|<[^<>]*>)*>)*>)?/,lookbehind:!0,greedy:!0,inside:null},builtin:/\b(?:Array|Function|Promise|any|boolean|console|never|number|string|symbol|unknown)\b/}),e.languages.typescript.keyword.push(/\b(?:abstract|declare|is|keyof|readonly|require)\b/,/\b(?:asserts|infer|interface|module|namespace|type)\b(?=\s*(?:[{_$a-zA-Z\xA0-\uFFFF]|$))/,/\btype\b(?=\s*(?:[\{*]|$))/),delete e.languages.typescript.parameter,delete e.languages.typescript["literal-property"];var t=e.languages.extend("typescript",{});delete t["class-name"],e.languages.typescript["class-name"].inside=t,e.languages.insertBefore("typescript","function",{decorator:{pattern:/@[$\w\xA0-\uFFFF]+/,inside:{at:{pattern:/^@/,alias:"operator"},function:/^[\s\S]+/}},"generic-function":{pattern:/#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*\s*<(?:[^<>]|<(?:[^<>]|<[^<>]*>)*>)*>(?=\s*\()/,greedy:!0,inside:{function:/^#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*/,generic:{pattern:/<[\s\S]+/,alias:"class-name",inside:t}}}}),e.languages.ts=e.languages.typescript}(S),function(e){var t=e.languages.javascript,n=/\{(?:[^{}]|\{(?:[^{}]|\{[^{}]*\})*\})+\}/.source,r="(@(?:arg|argument|param|property)\\s+(?:"+n+"\\s+)?)";e.languages.jsdoc=e.languages.extend("javadoclike",{parameter:{pattern:RegExp(r+/(?:(?!\s)[$\w\xA0-\uFFFF.])+(?=\s|$)/.source),lookbehind:!0,inside:{punctuation:/\./}}}),e.languages.insertBefore("jsdoc","keyword",{"optional-parameter":{pattern:RegExp(r+/\[(?:(?!\s)[$\w\xA0-\uFFFF.])+(?:=[^[\]]+)?\](?=\s|$)/.source),lookbehind:!0,inside:{parameter:{pattern:/(^\[)[$\w\xA0-\uFFFF\.]+/,lookbehind:!0,inside:{punctuation:/\./}},code:{pattern:/(=)[\s\S]*(?=\]$)/,lookbehind:!0,inside:t,alias:"language-javascript"},punctuation:/[=[\]]/}},"class-name":[{pattern:RegExp(/(@(?:augments|class|extends|interface|memberof!?|template|this|typedef)\s+(?:<TYPE>\s+)?)[A-Z]\w*(?:\.[A-Z]\w*)*/.source.replace(/<TYPE>/g,(function(){return n}))),lookbehind:!0,inside:{punctuation:/\./}},{pattern:RegExp("(@[a-z]+\\s+)"+n),lookbehind:!0,inside:{string:t.string,number:t.number,boolean:t.boolean,keyword:e.languages.typescript.keyword,operator:/=>|\.\.\.|[&|?:*]/,punctuation:/[.,;=<>{}()[\]]/}}],example:{pattern:/(@example\s+(?!\s))(?:[^@\s]|\s+(?!\s))+?(?=\s*(?:\*\s*)?(?:@\w|\*\/))/,lookbehind:!0,inside:{code:{pattern:/^([\t ]*(?:\*\s*)?)\S.*$/m,lookbehind:!0,inside:t,alias:"language-javascript"}}}}),e.languages.javadoclike.addSupport("javascript",e.languages.jsdoc)}(S),function(e){e.languages.flow=e.languages.extend("javascript",{}),e.languages.insertBefore("flow","keyword",{type:[{pattern:/\b(?:[Bb]oolean|Function|[Nn]umber|[Ss]tring|[Ss]ymbol|any|mixed|null|void)\b/,alias:"class-name"}]}),e.languages.flow["function-variable"].pattern=/(?!\s)[_$a-z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*=\s*(?:function\b|(?:\([^()]*\)(?:\s*:\s*\w+)?|(?!\s)[_$a-z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*)\s*=>))/i,delete e.languages.flow.parameter,e.languages.insertBefore("flow","operator",{"flow-punctuation":{pattern:/\{\||\|\}/,alias:"punctuation"}}),Array.isArray(e.languages.flow.keyword)||(e.languages.flow.keyword=[e.languages.flow.keyword]),e.languages.flow.keyword.unshift({pattern:/(^|[^$]\b)(?:Class|declare|opaque|type)\b(?!\$)/,lookbehind:!0},{pattern:/(^|[^$]\B)\$(?:Diff|Enum|Exact|Keys|ObjMap|PropertyType|Record|Shape|Subtype|Supertype|await)\b(?!\$)/,lookbehind:!0})}(S),S.languages.n4js=S.languages.extend("javascript",{keyword:/\b(?:Array|any|boolean|break|case|catch|class|const|constructor|continue|debugger|declare|default|delete|do|else|enum|export|extends|false|finally|for|from|function|get|if|implements|import|in|instanceof|interface|let|module|new|null|number|package|private|protected|public|return|set|static|string|super|switch|this|throw|true|try|typeof|var|void|while|with|yield)\b/}),S.languages.insertBefore("n4js","constant",{annotation:{pattern:/@+\w+/,alias:"operator"}}),S.languages.n4jsd=S.languages.n4js,function(e){function t(e,t){return RegExp(e.replace(/<ID>/g,(function(){return/(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*/.source})),t)}e.languages.insertBefore("javascript","function-variable",{"method-variable":{pattern:RegExp("(\\.\\s*)"+e.languages.javascript["function-variable"].pattern.source),lookbehind:!0,alias:["function-variable","method","function","property-access"]}}),e.languages.insertBefore("javascript","function",{method:{pattern:RegExp("(\\.\\s*)"+e.languages.javascript.function.source),lookbehind:!0,alias:["function","property-access"]}}),e.languages.insertBefore("javascript","constant",{"known-class-name":[{pattern:/\b(?:(?:Float(?:32|64)|(?:Int|Uint)(?:8|16|32)|Uint8Clamped)?Array|ArrayBuffer|BigInt|Boolean|DataView|Date|Error|Function|Intl|JSON|(?:Weak)?(?:Map|Set)|Math|Number|Object|Promise|Proxy|Reflect|RegExp|String|Symbol|WebAssembly)\b/,alias:"class-name"},{pattern:/\b(?:[A-Z]\w*)Error\b/,alias:"class-name"}]}),e.languages.insertBefore("javascript","keyword",{imports:{pattern:t(/(\bimport\b\s*)(?:<ID>(?:\s*,\s*(?:\*\s*as\s+<ID>|\{[^{}]*\}))?|\*\s*as\s+<ID>|\{[^{}]*\})(?=\s*\bfrom\b)/.source),lookbehind:!0,inside:e.languages.javascript},exports:{pattern:t(/(\bexport\b\s*)(?:\*(?:\s*as\s+<ID>)?(?=\s*\bfrom\b)|\{[^{}]*\})/.source),lookbehind:!0,inside:e.languages.javascript}}),e.languages.javascript.keyword.unshift({pattern:/\b(?:as|default|export|from|import)\b/,alias:"module"},{pattern:/\b(?:await|break|catch|continue|do|else|finally|for|if|return|switch|throw|try|while|yield)\b/,alias:"control-flow"},{pattern:/\bnull\b/,alias:["null","nil"]},{pattern:/\bundefined\b/,alias:"nil"}),e.languages.insertBefore("javascript","operator",{spread:{pattern:/\.{3}/,alias:"operator"},arrow:{pattern:/=>/,alias:"operator"}}),e.languages.insertBefore("javascript","punctuation",{"property-access":{pattern:t(/(\.\s*)#?<ID>/.source),lookbehind:!0},"maybe-class-name":{pattern:/(^|[^$\w\xA0-\uFFFF])[A-Z][$\w\xA0-\uFFFF]+/,lookbehind:!0},dom:{pattern:/\b(?:document|(?:local|session)Storage|location|navigator|performance|window)\b/,alias:"variable"},console:{pattern:/\bconsole(?=\s*\.)/,alias:"class-name"}});for(var n=["function","function-variable","method","method-variable","property-access"],r=0;r<n.length;r++){var o=n[r],a=e.languages.javascript[o];o=(a="RegExp"===e.util.type(a)?e.languages.javascript[o]={pattern:a}:a).inside||{};(a.inside=o)["maybe-class-name"]=/^[A-Z][\s\S]*/}}(S),function(e){var t=e.util.clone(e.languages.javascript),n=/(?:\s|\/\/.*(?!.)|\/\*(?:[^*]|\*(?!\/))\*\/)/.source,r=/(?:\{(?:\{(?:\{[^{}]*\}|[^{}])*\}|[^{}])*\})/.source,o=/(?:\{<S>*\.{3}(?:[^{}]|<BRACES>)*\})/.source;function a(e,t){return e=e.replace(/<S>/g,(function(){return n})).replace(/<BRACES>/g,(function(){return r})).replace(/<SPREAD>/g,(function(){return o})),RegExp(e,t)}function i(t){for(var n=[],r=0;r<t.length;r++){var o=t[r],a=!1;"string"!=typeof o&&("tag"===o.type&&o.content[0]&&"tag"===o.content[0].type?"</"===o.content[0].content[0].content?0<n.length&&n[n.length-1].tagName===s(o.content[0].content[1])&&n.pop():"/>"!==o.content[o.content.length-1].content&&n.push({tagName:s(o.content[0].content[1]),openedBraces:0}):0<n.length&&"punctuation"===o.type&&"{"===o.content?n[n.length-1].openedBraces++:0<n.length&&0<n[n.length-1].openedBraces&&"punctuation"===o.type&&"}"===o.content?n[n.length-1].openedBraces--:a=!0),(a||"string"==typeof o)&&0<n.length&&0===n[n.length-1].openedBraces&&(a=s(o),r<t.length-1&&("string"==typeof t[r+1]||"plain-text"===t[r+1].type)&&(a+=s(t[r+1]),t.splice(r+1,1)),0<r&&("string"==typeof t[r-1]||"plain-text"===t[r-1].type)&&(a=s(t[r-1])+a,t.splice(r-1,1),r--),t[r]=new e.Token("plain-text",a,null,a)),o.content&&"string"!=typeof o.content&&i(o.content)}}o=a(o).source,e.languages.jsx=e.languages.extend("markup",t),e.languages.jsx.tag.pattern=a(/<\/?(?:[\w.:-]+(?:<S>+(?:[\w.:$-]+(?:=(?:"(?:\\[\s\S]|[^\\"])*"|'(?:\\[\s\S]|[^\\'])*'|[^\s{'"/>=]+|<BRACES>))?|<SPREAD>))*<S>*\/?)?>/.source),e.languages.jsx.tag.inside.tag.pattern=/^<\/?[^\s>\/]*/,e.languages.jsx.tag.inside["attr-value"].pattern=/=(?!\{)(?:"(?:\\[\s\S]|[^\\"])*"|'(?:\\[\s\S]|[^\\'])*'|[^\s'">]+)/,e.languages.jsx.tag.inside.tag.inside["class-name"]=/^[A-Z]\w*(?:\.[A-Z]\w*)*$/,e.languages.jsx.tag.inside.comment=t.comment,e.languages.insertBefore("inside","attr-name",{spread:{pattern:a(/<SPREAD>/.source),inside:e.languages.jsx}},e.languages.jsx.tag),e.languages.insertBefore("inside","special-attr",{script:{pattern:a(/=<BRACES>/.source),alias:"language-javascript",inside:{"script-punctuation":{pattern:/^=(?=\{)/,alias:"punctuation"},rest:e.languages.jsx}}},e.languages.jsx.tag);var s=function(e){return e?"string"==typeof e?e:"string"==typeof e.content?e.content:e.content.map(s).join(""):""};e.hooks.add("after-tokenize",(function(e){"jsx"!==e.language&&"tsx"!==e.language||i(e.tokens)}))}(S),function(e){var t=e.util.clone(e.languages.typescript);(t=(e.languages.tsx=e.languages.extend("jsx",t),delete e.languages.tsx.parameter,delete e.languages.tsx["literal-property"],e.languages.tsx.tag)).pattern=RegExp(/(^|[^\w$]|(?=<\/))/.source+"(?:"+t.pattern.source+")",t.pattern.flags),t.lookbehind=!0}(S),S.languages.swift={comment:{pattern:/(^|[^\\:])(?:\/\/.*|\/\*(?:[^/*]|\/(?!\*)|\*(?!\/)|\/\*(?:[^*]|\*(?!\/))*\*\/)*\*\/)/,lookbehind:!0,greedy:!0},"string-literal":[{pattern:RegExp(/(^|[^"#])/.source+"(?:"+/"(?:\\(?:\((?:[^()]|\([^()]*\))*\)|\r\n|[^(])|[^\\\r\n"])*"/.source+"|"+/"""(?:\\(?:\((?:[^()]|\([^()]*\))*\)|[^(])|[^\\"]|"(?!""))*"""/.source+")"+/(?!["#])/.source),lookbehind:!0,greedy:!0,inside:{interpolation:{pattern:/(\\\()(?:[^()]|\([^()]*\))*(?=\))/,lookbehind:!0,inside:null},"interpolation-punctuation":{pattern:/^\)|\\\($/,alias:"punctuation"},punctuation:/\\(?=[\r\n])/,string:/[\s\S]+/}},{pattern:RegExp(/(^|[^"#])(#+)/.source+"(?:"+/"(?:\\(?:#+\((?:[^()]|\([^()]*\))*\)|\r\n|[^#])|[^\\\r\n])*?"/.source+"|"+/"""(?:\\(?:#+\((?:[^()]|\([^()]*\))*\)|[^#])|[^\\])*?"""/.source+")\\2"),lookbehind:!0,greedy:!0,inside:{interpolation:{pattern:/(\\#+\()(?:[^()]|\([^()]*\))*(?=\))/,lookbehind:!0,inside:null},"interpolation-punctuation":{pattern:/^\)|\\#+\($/,alias:"punctuation"},string:/[\s\S]+/}}],directive:{pattern:RegExp(/#/.source+"(?:"+/(?:elseif|if)\b/.source+"(?:[ \t]*"+/(?:![ \t]*)?(?:\b\w+\b(?:[ \t]*\((?:[^()]|\([^()]*\))*\))?|\((?:[^()]|\([^()]*\))*\))(?:[ \t]*(?:&&|\|\|))?/.source+")+|"+/(?:else|endif)\b/.source+")"),alias:"property",inside:{"directive-name":/^#\w+/,boolean:/\b(?:false|true)\b/,number:/\b\d+(?:\.\d+)*\b/,operator:/!|&&|\|\||[<>]=?/,punctuation:/[(),]/}},literal:{pattern:/#(?:colorLiteral|column|dsohandle|file(?:ID|Literal|Path)?|function|imageLiteral|line)\b/,alias:"constant"},"other-directive":{pattern:/#\w+\b/,alias:"property"},attribute:{pattern:/@\w+/,alias:"atrule"},"function-definition":{pattern:/(\bfunc\s+)\w+/,lookbehind:!0,alias:"function"},label:{pattern:/\b(break|continue)\s+\w+|\b[a-zA-Z_]\w*(?=\s*:\s*(?:for|repeat|while)\b)/,lookbehind:!0,alias:"important"},keyword:/\b(?:Any|Protocol|Self|Type|actor|as|assignment|associatedtype|associativity|async|await|break|case|catch|class|continue|convenience|default|defer|deinit|didSet|do|dynamic|else|enum|extension|fallthrough|fileprivate|final|for|func|get|guard|higherThan|if|import|in|indirect|infix|init|inout|internal|is|isolated|lazy|left|let|lowerThan|mutating|none|nonisolated|nonmutating|open|operator|optional|override|postfix|precedencegroup|prefix|private|protocol|public|repeat|required|rethrows|return|right|safe|self|set|some|static|struct|subscript|super|switch|throw|throws|try|typealias|unowned|unsafe|var|weak|where|while|willSet)\b/,boolean:/\b(?:false|true)\b/,nil:{pattern:/\bnil\b/,alias:"constant"},"short-argument":/\$\d+\b/,omit:{pattern:/\b_\b/,alias:"keyword"},number:/\b(?:[\d_]+(?:\.[\de_]+)?|0x[a-f0-9_]+(?:\.[a-f0-9p_]+)?|0b[01_]+|0o[0-7_]+)\b/i,"class-name":/\b[A-Z](?:[A-Z_\d]*[a-z]\w*)?\b/,function:/\b[a-z_]\w*(?=\s*\()/i,constant:/\b(?:[A-Z_]{2,}|k[A-Z][A-Za-z_]+)\b/,operator:/[-+*/%=!<>&|^~?]+|\.[.\-+*/%=!<>&|^~?]+/,punctuation:/[{}[\]();,.:\\]/},S.languages.swift["string-literal"].forEach((function(e){e.inside.interpolation.inside=S.languages.swift})),function(e){e.languages.kotlin=e.languages.extend("clike",{keyword:{pattern:/(^|[^.])\b(?:abstract|actual|annotation|as|break|by|catch|class|companion|const|constructor|continue|crossinline|data|do|dynamic|else|enum|expect|external|final|finally|for|fun|get|if|import|in|infix|init|inline|inner|interface|internal|is|lateinit|noinline|null|object|open|operator|out|override|package|private|protected|public|reified|return|sealed|set|super|suspend|tailrec|this|throw|to|try|typealias|val|var|vararg|when|where|while)\b/,lookbehind:!0},function:[{pattern:/(?:`[^\r\n`]+`|\b\w+)(?=\s*\()/,greedy:!0},{pattern:/(\.)(?:`[^\r\n`]+`|\w+)(?=\s*\{)/,lookbehind:!0,greedy:!0}],number:/\b(?:0[xX][\da-fA-F]+(?:_[\da-fA-F]+)*|0[bB][01]+(?:_[01]+)*|\d+(?:_\d+)*(?:\.\d+(?:_\d+)*)?(?:[eE][+-]?\d+(?:_\d+)*)?[fFL]?)\b/,operator:/\+[+=]?|-[-=>]?|==?=?|!(?:!|==?)?|[\/*%<>]=?|[?:]:?|\.\.|&&|\|\||\b(?:and|inv|or|shl|shr|ushr|xor)\b/}),delete e.languages.kotlin["class-name"];var t={"interpolation-punctuation":{pattern:/^\$\{?|\}$/,alias:"punctuation"},expression:{pattern:/[\s\S]+/,inside:e.languages.kotlin}};e.languages.insertBefore("kotlin","string",{"string-literal":[{pattern:/"""(?:[^$]|\$(?:(?!\{)|\{[^{}]*\}))*?"""/,alias:"multiline",inside:{interpolation:{pattern:/\$(?:[a-z_]\w*|\{[^{}]*\})/i,inside:t},string:/[\s\S]+/}},{pattern:/"(?:[^"\\\r\n$]|\\.|\$(?:(?!\{)|\{[^{}]*\}))*"/,alias:"singleline",inside:{interpolation:{pattern:/((?:^|[^\\])(?:\\{2})*)\$(?:[a-z_]\w*|\{[^{}]*\})/i,lookbehind:!0,inside:t},string:/[\s\S]+/}}],char:{pattern:/'(?:[^'\\\r\n]|\\(?:.|u[a-fA-F0-9]{0,4}))'/,greedy:!0}}),delete e.languages.kotlin.string,e.languages.insertBefore("kotlin","keyword",{annotation:{pattern:/\B@(?:\w+:)?(?:[A-Z]\w*|\[[^\]]+\])/,alias:"builtin"}}),e.languages.insertBefore("kotlin","function",{label:{pattern:/\b\w+@|@\w+\b/,alias:"symbol"}}),e.languages.kt=e.languages.kotlin,e.languages.kts=e.languages.kotlin}(S),S.languages.c=S.languages.extend("clike",{comment:{pattern:/\/\/(?:[^\r\n\\]|\\(?:\r\n?|\n|(?![\r\n])))*|\/\*[\s\S]*?(?:\*\/|$)/,greedy:!0},string:{pattern:/"(?:\\(?:\r\n|[\s\S])|[^"\\\r\n])*"/,greedy:!0},"class-name":{pattern:/(\b(?:enum|struct)\s+(?:__attribute__\s*\(\([\s\S]*?\)\)\s*)?)\w+|\b[a-z]\w*_t\b/,lookbehind:!0},keyword:/\b(?:_Alignas|_Alignof|_Atomic|_Bool|_Complex|_Generic|_Imaginary|_Noreturn|_Static_assert|_Thread_local|__attribute__|asm|auto|break|case|char|const|continue|default|do|double|else|enum|extern|float|for|goto|if|inline|int|long|register|return|short|signed|sizeof|static|struct|switch|typedef|typeof|union|unsigned|void|volatile|while)\b/,function:/\b[a-z_]\w*(?=\s*\()/i,number:/(?:\b0x(?:[\da-f]+(?:\.[\da-f]*)?|\.[\da-f]+)(?:p[+-]?\d+)?|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:e[+-]?\d+)?)[ful]{0,4}/i,operator:/>>=?|<<=?|->|([-+&|:])\1|[?:~]|[-+*/%&|^!=<>]=?/}),S.languages.insertBefore("c","string",{char:{pattern:/'(?:\\(?:\r\n|[\s\S])|[^'\\\r\n]){0,32}'/,greedy:!0}}),S.languages.insertBefore("c","string",{macro:{pattern:/(^[\t ]*)#\s*[a-z](?:[^\r\n\\/]|\/(?!\*)|\/\*(?:[^*]|\*(?!\/))*\*\/|\\(?:\r\n|[\s\S]))*/im,lookbehind:!0,greedy:!0,alias:"property",inside:{string:[{pattern:/^(#\s*include\s*)<[^>]+>/,lookbehind:!0},S.languages.c.string],char:S.languages.c.char,comment:S.languages.c.comment,"macro-name":[{pattern:/(^#\s*define\s+)\w+\b(?!\()/i,lookbehind:!0},{pattern:/(^#\s*define\s+)\w+\b(?=\()/i,lookbehind:!0,alias:"function"}],directive:{pattern:/^(#\s*)[a-z]+/,lookbehind:!0,alias:"keyword"},"directive-hash":/^#/,punctuation:/##|\\(?=[\r\n])/,expression:{pattern:/\S[\s\S]*/,inside:S.languages.c}}}}),S.languages.insertBefore("c","function",{constant:/\b(?:EOF|NULL|SEEK_CUR|SEEK_END|SEEK_SET|__DATE__|__FILE__|__LINE__|__TIMESTAMP__|__TIME__|__func__|stderr|stdin|stdout)\b/}),delete S.languages.c.boolean,S.languages.objectivec=S.languages.extend("c",{string:{pattern:/@?"(?:\\(?:\r\n|[\s\S])|[^"\\\r\n])*"/,greedy:!0},keyword:/\b(?:asm|auto|break|case|char|const|continue|default|do|double|else|enum|extern|float|for|goto|if|in|inline|int|long|register|return|self|short|signed|sizeof|static|struct|super|switch|typedef|typeof|union|unsigned|void|volatile|while)\b|(?:@interface|@end|@implementation|@protocol|@class|@public|@protected|@private|@property|@try|@catch|@finally|@throw|@synthesize|@dynamic|@selector)\b/,operator:/-[->]?|\+\+?|!=?|<<?=?|>>?=?|==?|&&?|\|\|?|[~^%?*\/@]/}),delete S.languages.objectivec["class-name"],S.languages.objc=S.languages.objectivec,S.languages.reason=S.languages.extend("clike",{string:{pattern:/"(?:\\(?:\r\n|[\s\S])|[^\\\r\n"])*"/,greedy:!0},"class-name":/\b[A-Z]\w*/,keyword:/\b(?:and|as|assert|begin|class|constraint|do|done|downto|else|end|exception|external|for|fun|function|functor|if|in|include|inherit|initializer|lazy|let|method|module|mutable|new|nonrec|object|of|open|or|private|rec|sig|struct|switch|then|to|try|type|val|virtual|when|while|with)\b/,operator:/\.{3}|:[:=]|\|>|->|=(?:==?|>)?|<=?|>=?|[|^?'#!~`]|[+\-*\/]\.?|\b(?:asr|land|lor|lsl|lsr|lxor|mod)\b/}),S.languages.insertBefore("reason","class-name",{char:{pattern:/'(?:\\x[\da-f]{2}|\\o[0-3][0-7][0-7]|\\\d{3}|\\.|[^'\\\r\n])'/,greedy:!0},constructor:/\b[A-Z]\w*\b(?!\s*\.)/,label:{pattern:/\b[a-z]\w*(?=::)/,alias:"symbol"}}),delete S.languages.reason.function,function(e){for(var t=/\/\*(?:[^*/]|\*(?!\/)|\/(?!\*)|<self>)*\*\//.source,n=0;n<2;n++)t=t.replace(/<self>/g,(function(){return t}));t=t.replace(/<self>/g,(function(){return/[^\s\S]/.source})),e.languages.rust={comment:[{pattern:RegExp(/(^|[^\\])/.source+t),lookbehind:!0,greedy:!0},{pattern:/(^|[^\\:])\/\/.*/,lookbehind:!0,greedy:!0}],string:{pattern:/b?"(?:\\[\s\S]|[^\\"])*"|b?r(#*)"(?:[^"]|"(?!\1))*"\1/,greedy:!0},char:{pattern:/b?'(?:\\(?:x[0-7][\da-fA-F]|u\{(?:[\da-fA-F]_*){1,6}\}|.)|[^\\\r\n\t'])'/,greedy:!0},attribute:{pattern:/#!?\[(?:[^\[\]"]|"(?:\\[\s\S]|[^\\"])*")*\]/,greedy:!0,alias:"attr-name",inside:{string:null}},"closure-params":{pattern:/([=(,:]\s*|\bmove\s*)\|[^|]*\||\|[^|]*\|(?=\s*(?:\{|->))/,lookbehind:!0,greedy:!0,inside:{"closure-punctuation":{pattern:/^\||\|$/,alias:"punctuation"},rest:null}},"lifetime-annotation":{pattern:/'\w+/,alias:"symbol"},"fragment-specifier":{pattern:/(\$\w+:)[a-z]+/,lookbehind:!0,alias:"punctuation"},variable:/\$\w+/,"function-definition":{pattern:/(\bfn\s+)\w+/,lookbehind:!0,alias:"function"},"type-definition":{pattern:/(\b(?:enum|struct|trait|type|union)\s+)\w+/,lookbehind:!0,alias:"class-name"},"module-declaration":[{pattern:/(\b(?:crate|mod)\s+)[a-z][a-z_\d]*/,lookbehind:!0,alias:"namespace"},{pattern:/(\b(?:crate|self|super)\s*)::\s*[a-z][a-z_\d]*\b(?:\s*::(?:\s*[a-z][a-z_\d]*\s*::)*)?/,lookbehind:!0,alias:"namespace",inside:{punctuation:/::/}}],keyword:[/\b(?:Self|abstract|as|async|await|become|box|break|const|continue|crate|do|dyn|else|enum|extern|final|fn|for|if|impl|in|let|loop|macro|match|mod|move|mut|override|priv|pub|ref|return|self|static|struct|super|trait|try|type|typeof|union|unsafe|unsized|use|virtual|where|while|yield)\b/,/\b(?:bool|char|f(?:32|64)|[ui](?:8|16|32|64|128|size)|str)\b/],function:/\b[a-z_]\w*(?=\s*(?:::\s*<|\())/,macro:{pattern:/\b\w+!/,alias:"property"},constant:/\b[A-Z_][A-Z_\d]+\b/,"class-name":/\b[A-Z]\w*\b/,namespace:{pattern:/(?:\b[a-z][a-z_\d]*\s*::\s*)*\b[a-z][a-z_\d]*\s*::(?!\s*<)/,inside:{punctuation:/::/}},number:/\b(?:0x[\dA-Fa-f](?:_?[\dA-Fa-f])*|0o[0-7](?:_?[0-7])*|0b[01](?:_?[01])*|(?:(?:\d(?:_?\d)*)?\.)?\d(?:_?\d)*(?:[Ee][+-]?\d+)?)(?:_?(?:f32|f64|[iu](?:8|16|32|64|size)?))?\b/,boolean:/\b(?:false|true)\b/,punctuation:/->|\.\.=|\.{1,3}|::|[{}[\];(),:]/,operator:/[-+*\/%!^]=?|=[=>]?|&[&=]?|\|[|=]?|<<?=?|>>?=?|[@?]/},e.languages.rust["closure-params"].inside.rest=e.languages.rust,e.languages.rust.attribute.inside.string=e.languages.rust.string}(S),S.languages.go=S.languages.extend("clike",{string:{pattern:/(^|[^\\])"(?:\\.|[^"\\\r\n])*"|`[^`]*`/,lookbehind:!0,greedy:!0},keyword:/\b(?:break|case|chan|const|continue|default|defer|else|fallthrough|for|func|go(?:to)?|if|import|interface|map|package|range|return|select|struct|switch|type|var)\b/,boolean:/\b(?:_|false|iota|nil|true)\b/,number:[/\b0(?:b[01_]+|o[0-7_]+)i?\b/i,/\b0x(?:[a-f\d_]+(?:\.[a-f\d_]*)?|\.[a-f\d_]+)(?:p[+-]?\d+(?:_\d+)*)?i?(?!\w)/i,/(?:\b\d[\d_]*(?:\.[\d_]*)?|\B\.\d[\d_]*)(?:e[+-]?[\d_]+)?i?(?!\w)/i],operator:/[*\/%^!=]=?|\+[=+]?|-[=-]?|\|[=|]?|&(?:=|&|\^=?)?|>(?:>=?|=)?|<(?:<=?|=|-)?|:=|\.\.\./,builtin:/\b(?:append|bool|byte|cap|close|complex|complex(?:64|128)|copy|delete|error|float(?:32|64)|u?int(?:8|16|32|64)?|imag|len|make|new|panic|print(?:ln)?|real|recover|rune|string|uintptr)\b/}),S.languages.insertBefore("go","string",{char:{pattern:/'(?:\\.|[^'\\\r\n]){0,10}'/,greedy:!0}}),delete S.languages.go["class-name"],function(e){var t=/\b(?:alignas|alignof|asm|auto|bool|break|case|catch|char|char16_t|char32_t|char8_t|class|co_await|co_return|co_yield|compl|concept|const|const_cast|consteval|constexpr|constinit|continue|decltype|default|delete|do|double|dynamic_cast|else|enum|explicit|export|extern|final|float|for|friend|goto|if|import|inline|int|int16_t|int32_t|int64_t|int8_t|long|module|mutable|namespace|new|noexcept|nullptr|operator|override|private|protected|public|register|reinterpret_cast|requires|return|short|signed|sizeof|static|static_assert|static_cast|struct|switch|template|this|thread_local|throw|try|typedef|typeid|typename|uint16_t|uint32_t|uint64_t|uint8_t|union|unsigned|using|virtual|void|volatile|wchar_t|while)\b/,n=/\b(?!<keyword>)\w+(?:\s*\.\s*\w+)*\b/.source.replace(/<keyword>/g,(function(){return t.source}));e.languages.cpp=e.languages.extend("c",{"class-name":[{pattern:RegExp(/(\b(?:class|concept|enum|struct|typename)\s+)(?!<keyword>)\w+/.source.replace(/<keyword>/g,(function(){return t.source}))),lookbehind:!0},/\b[A-Z]\w*(?=\s*::\s*\w+\s*\()/,/\b[A-Z_]\w*(?=\s*::\s*~\w+\s*\()/i,/\b\w+(?=\s*<(?:[^<>]|<(?:[^<>]|<[^<>]*>)*>)*>\s*::\s*\w+\s*\()/],keyword:t,number:{pattern:/(?:\b0b[01']+|\b0x(?:[\da-f']+(?:\.[\da-f']*)?|\.[\da-f']+)(?:p[+-]?[\d']+)?|(?:\b[\d']+(?:\.[\d']*)?|\B\.[\d']+)(?:e[+-]?[\d']+)?)[ful]{0,4}/i,greedy:!0},operator:/>>=?|<<=?|->|--|\+\+|&&|\|\||[?:~]|<=>|[-+*/%&|^!=<>]=?|\b(?:and|and_eq|bitand|bitor|not|not_eq|or|or_eq|xor|xor_eq)\b/,boolean:/\b(?:false|true)\b/}),e.languages.insertBefore("cpp","string",{module:{pattern:RegExp(/(\b(?:import|module)\s+)/.source+"(?:"+/"(?:\\(?:\r\n|[\s\S])|[^"\\\r\n])*"|<[^<>\r\n]*>/.source+"|"+/<mod-name>(?:\s*:\s*<mod-name>)?|:\s*<mod-name>/.source.replace(/<mod-name>/g,(function(){return n}))+")"),lookbehind:!0,greedy:!0,inside:{string:/^[<"][\s\S]+/,operator:/:/,punctuation:/\./}},"raw-string":{pattern:/R"([^()\\ ]{0,16})\([\s\S]*?\)\1"/,alias:"string",greedy:!0}}),e.languages.insertBefore("cpp","keyword",{"generic-function":{pattern:/\b(?!operator\b)[a-z_]\w*\s*<(?:[^<>]|<[^<>]*>)*>(?=\s*\()/i,inside:{function:/^\w+/,generic:{pattern:/<[\s\S]+/,alias:"class-name",inside:e.languages.cpp}}}}),e.languages.insertBefore("cpp","operator",{"double-colon":{pattern:/::/,alias:"punctuation"}}),e.languages.insertBefore("cpp","class-name",{"base-clause":{pattern:/(\b(?:class|struct)\s+\w+\s*:\s*)[^;{}"'\s]+(?:\s+[^;{}"'\s]+)*(?=\s*[;{])/,lookbehind:!0,greedy:!0,inside:e.languages.extend("cpp",{})}}),e.languages.insertBefore("inside","double-colon",{"class-name":/\b[a-z_]\w*\b(?!\s*::)/i},e.languages.cpp["base-clause"])}(S),S.languages.python={comment:{pattern:/(^|[^\\])#.*/,lookbehind:!0,greedy:!0},"string-interpolation":{pattern:/(?:f|fr|rf)(?:("""|''')[\s\S]*?\1|("|')(?:\\.|(?!\2)[^\\\r\n])*\2)/i,greedy:!0,inside:{interpolation:{pattern:/((?:^|[^{])(?:\{\{)*)\{(?!\{)(?:[^{}]|\{(?!\{)(?:[^{}]|\{(?!\{)(?:[^{}])+\})+\})+\}/,lookbehind:!0,inside:{"format-spec":{pattern:/(:)[^:(){}]+(?=\}$)/,lookbehind:!0},"conversion-option":{pattern:/![sra](?=[:}]$)/,alias:"punctuation"},rest:null}},string:/[\s\S]+/}},"triple-quoted-string":{pattern:/(?:[rub]|br|rb)?("""|''')[\s\S]*?\1/i,greedy:!0,alias:"string"},string:{pattern:/(?:[rub]|br|rb)?("|')(?:\\.|(?!\1)[^\\\r\n])*\1/i,greedy:!0},function:{pattern:/((?:^|\s)def[ \t]+)[a-zA-Z_]\w*(?=\s*\()/g,lookbehind:!0},"class-name":{pattern:/(\bclass\s+)\w+/i,lookbehind:!0},decorator:{pattern:/(^[\t ]*)@\w+(?:\.\w+)*/m,lookbehind:!0,alias:["annotation","punctuation"],inside:{punctuation:/\./}},keyword:/\b(?:_(?=\s*:)|and|as|assert|async|await|break|case|class|continue|def|del|elif|else|except|exec|finally|for|from|global|if|import|in|is|lambda|match|nonlocal|not|or|pass|print|raise|return|try|while|with|yield)\b/,builtin:/\b(?:__import__|abs|all|any|apply|ascii|basestring|bin|bool|buffer|bytearray|bytes|callable|chr|classmethod|cmp|coerce|compile|complex|delattr|dict|dir|divmod|enumerate|eval|execfile|file|filter|float|format|frozenset|getattr|globals|hasattr|hash|help|hex|id|input|int|intern|isinstance|issubclass|iter|len|list|locals|long|map|max|memoryview|min|next|object|oct|open|ord|pow|property|range|raw_input|reduce|reload|repr|reversed|round|set|setattr|slice|sorted|staticmethod|str|sum|super|tuple|type|unichr|unicode|vars|xrange|zip)\b/,boolean:/\b(?:False|None|True)\b/,number:/\b0(?:b(?:_?[01])+|o(?:_?[0-7])+|x(?:_?[a-f0-9])+)\b|(?:\b\d+(?:_\d+)*(?:\.(?:\d+(?:_\d+)*)?)?|\B\.\d+(?:_\d+)*)(?:e[+-]?\d+(?:_\d+)*)?j?(?!\w)/i,operator:/[-+%=]=?|!=|:=|\*\*?=?|\/\/?=?|<[<=>]?|>[=>]?|[&|^~]/,punctuation:/[{}[\];(),.:]/},S.languages.python["string-interpolation"].inside.interpolation.inside.rest=S.languages.python,S.languages.py=S.languages.python,S.languages.json={property:{pattern:/(^|[^\\])"(?:\\.|[^\\"\r\n])*"(?=\s*:)/,lookbehind:!0,greedy:!0},string:{pattern:/(^|[^\\])"(?:\\.|[^\\"\r\n])*"(?!\s*:)/,lookbehind:!0,greedy:!0},comment:{pattern:/\/\/.*|\/\*[\s\S]*?(?:\*\/|$)/,greedy:!0},number:/-?\b\d+(?:\.\d+)?(?:e[+-]?\d+)?\b/i,punctuation:/[{}[\],]/,operator:/:/,boolean:/\b(?:false|true)\b/,null:{pattern:/\bnull\b/,alias:"keyword"}},S.languages.webmanifest=S.languages.json;((e,t)=>{for(var n in t)c(e,n,{get:t[n],enumerable:!0})})({},{dracula:()=>k,duotoneDark:()=>x,duotoneLight:()=>_,github:()=>E,gruvboxMaterialDark:()=>U,gruvboxMaterialLight:()=>H,jettwaveDark:()=>F,jettwaveLight:()=>B,nightOwl:()=>j,nightOwlLight:()=>O,oceanicNext:()=>T,okaidia:()=>P,oneDark:()=>z,oneLight:()=>$,palenight:()=>I,shadesOfPurple:()=>N,synthwave84:()=>R,ultramin:()=>L,vsDark:()=>D,vsLight:()=>M});var k={plain:{color:"#F8F8F2",backgroundColor:"#282A36"},styles:[{types:["prolog","constant","builtin"],style:{color:"rgb(189, 147, 249)"}},{types:["inserted","function"],style:{color:"rgb(80, 250, 123)"}},{types:["deleted"],style:{color:"rgb(255, 85, 85)"}},{types:["changed"],style:{color:"rgb(255, 184, 108)"}},{types:["punctuation","symbol"],style:{color:"rgb(248, 248, 242)"}},{types:["string","char","tag","selector"],style:{color:"rgb(255, 121, 198)"}},{types:["keyword","variable"],style:{color:"rgb(189, 147, 249)",fontStyle:"italic"}},{types:["comment"],style:{color:"rgb(98, 114, 164)"}},{types:["attr-name"],style:{color:"rgb(241, 250, 140)"}}]},x={plain:{backgroundColor:"#2a2734",color:"#9a86fd"},styles:[{types:["comment","prolog","doctype","cdata","punctuation"],style:{color:"#6c6783"}},{types:["namespace"],style:{opacity:.7}},{types:["tag","operator","number"],style:{color:"#e09142"}},{types:["property","function"],style:{color:"#9a86fd"}},{types:["tag-id","selector","atrule-id"],style:{color:"#eeebff"}},{types:["attr-name"],style:{color:"#c4b9fe"}},{types:["boolean","string","entity","url","attr-value","keyword","control","directive","unit","statement","regex","atrule","placeholder","variable"],style:{color:"#ffcc99"}},{types:["deleted"],style:{textDecorationLine:"line-through"}},{types:["inserted"],style:{textDecorationLine:"underline"}},{types:["italic"],style:{fontStyle:"italic"}},{types:["important","bold"],style:{fontWeight:"bold"}},{types:["important"],style:{color:"#c4b9fe"}}]},_={plain:{backgroundColor:"#faf8f5",color:"#728fcb"},styles:[{types:["comment","prolog","doctype","cdata","punctuation"],style:{color:"#b6ad9a"}},{types:["namespace"],style:{opacity:.7}},{types:["tag","operator","number"],style:{color:"#063289"}},{types:["property","function"],style:{color:"#b29762"}},{types:["tag-id","selector","atrule-id"],style:{color:"#2d2006"}},{types:["attr-name"],style:{color:"#896724"}},{types:["boolean","string","entity","url","attr-value","keyword","control","directive","unit","statement","regex","atrule"],style:{color:"#728fcb"}},{types:["placeholder","variable"],style:{color:"#93abdc"}},{types:["deleted"],style:{textDecorationLine:"line-through"}},{types:["inserted"],style:{textDecorationLine:"underline"}},{types:["italic"],style:{fontStyle:"italic"}},{types:["important","bold"],style:{fontWeight:"bold"}},{types:["important"],style:{color:"#896724"}}]},E={plain:{color:"#393A34",backgroundColor:"#f6f8fa"},styles:[{types:["comment","prolog","doctype","cdata"],style:{color:"#999988",fontStyle:"italic"}},{types:["namespace"],style:{opacity:.7}},{types:["string","attr-value"],style:{color:"#e3116c"}},{types:["punctuation","operator"],style:{color:"#393A34"}},{types:["entity","url","symbol","number","boolean","variable","constant","property","regex","inserted"],style:{color:"#36acaa"}},{types:["atrule","keyword","attr-name","selector"],style:{color:"#00a4db"}},{types:["function","deleted","tag"],style:{color:"#d73a49"}},{types:["function-variable"],style:{color:"#6f42c1"}},{types:["tag","selector","keyword"],style:{color:"#00009f"}}]},j={plain:{color:"#d6deeb",backgroundColor:"#011627"},styles:[{types:["changed"],style:{color:"rgb(162, 191, 252)",fontStyle:"italic"}},{types:["deleted"],style:{color:"rgba(239, 83, 80, 0.56)",fontStyle:"italic"}},{types:["inserted","attr-name"],style:{color:"rgb(173, 219, 103)",fontStyle:"italic"}},{types:["comment"],style:{color:"rgb(99, 119, 119)",fontStyle:"italic"}},{types:["string","url"],style:{color:"rgb(173, 219, 103)"}},{types:["variable"],style:{color:"rgb(214, 222, 235)"}},{types:["number"],style:{color:"rgb(247, 140, 108)"}},{types:["builtin","char","constant","function"],style:{color:"rgb(130, 170, 255)"}},{types:["punctuation"],style:{color:"rgb(199, 146, 234)"}},{types:["selector","doctype"],style:{color:"rgb(199, 146, 234)",fontStyle:"italic"}},{types:["class-name"],style:{color:"rgb(255, 203, 139)"}},{types:["tag","operator","keyword"],style:{color:"rgb(127, 219, 202)"}},{types:["boolean"],style:{color:"rgb(255, 88, 116)"}},{types:["property"],style:{color:"rgb(128, 203, 196)"}},{types:["namespace"],style:{color:"rgb(178, 204, 214)"}}]},O={plain:{color:"#403f53",backgroundColor:"#FBFBFB"},styles:[{types:["changed"],style:{color:"rgb(162, 191, 252)",fontStyle:"italic"}},{types:["deleted"],style:{color:"rgba(239, 83, 80, 0.56)",fontStyle:"italic"}},{types:["inserted","attr-name"],style:{color:"rgb(72, 118, 214)",fontStyle:"italic"}},{types:["comment"],style:{color:"rgb(152, 159, 177)",fontStyle:"italic"}},{types:["string","builtin","char","constant","url"],style:{color:"rgb(72, 118, 214)"}},{types:["variable"],style:{color:"rgb(201, 103, 101)"}},{types:["number"],style:{color:"rgb(170, 9, 130)"}},{types:["punctuation"],style:{color:"rgb(153, 76, 195)"}},{types:["function","selector","doctype"],style:{color:"rgb(153, 76, 195)",fontStyle:"italic"}},{types:["class-name"],style:{color:"rgb(17, 17, 17)"}},{types:["tag"],style:{color:"rgb(153, 76, 195)"}},{types:["operator","property","keyword","namespace"],style:{color:"rgb(12, 150, 155)"}},{types:["boolean"],style:{color:"rgb(188, 84, 84)"}}]},A="#c5a5c5",C="#8dc891",T={plain:{backgroundColor:"#282c34",color:"#ffffff"},styles:[{types:["attr-name"],style:{color:A}},{types:["attr-value"],style:{color:C}},{types:["comment","block-comment","prolog","doctype","cdata","shebang"],style:{color:"#999999"}},{types:["property","number","function-name","constant","symbol","deleted"],style:{color:"#5a9bcf"}},{types:["boolean"],style:{color:"#ff8b50"}},{types:["tag"],style:{color:"#fc929e"}},{types:["string"],style:{color:C}},{types:["punctuation"],style:{color:C}},{types:["selector","char","builtin","inserted"],style:{color:"#D8DEE9"}},{types:["function"],style:{color:"#79b6f2"}},{types:["operator","entity","url","variable"],style:{color:"#d7deea"}},{types:["keyword"],style:{color:A}},{types:["atrule","class-name"],style:{color:"#FAC863"}},{types:["important"],style:{fontWeight:"400"}},{types:["bold"],style:{fontWeight:"bold"}},{types:["italic"],style:{fontStyle:"italic"}},{types:["namespace"],style:{opacity:.7}}]},P={plain:{color:"#f8f8f2",backgroundColor:"#272822"},styles:[{types:["changed"],style:{color:"rgb(162, 191, 252)",fontStyle:"italic"}},{types:["deleted"],style:{color:"#f92672",fontStyle:"italic"}},{types:["inserted"],style:{color:"rgb(173, 219, 103)",fontStyle:"italic"}},{types:["comment"],style:{color:"#8292a2",fontStyle:"italic"}},{types:["string","url"],style:{color:"#a6e22e"}},{types:["variable"],style:{color:"#f8f8f2"}},{types:["number"],style:{color:"#ae81ff"}},{types:["builtin","char","constant","function","class-name"],style:{color:"#e6db74"}},{types:["punctuation"],style:{color:"#f8f8f2"}},{types:["selector","doctype"],style:{color:"#a6e22e",fontStyle:"italic"}},{types:["tag","operator","keyword"],style:{color:"#66d9ef"}},{types:["boolean"],style:{color:"#ae81ff"}},{types:["namespace"],style:{color:"rgb(178, 204, 214)",opacity:.7}},{types:["tag","property"],style:{color:"#f92672"}},{types:["attr-name"],style:{color:"#a6e22e !important"}},{types:["doctype"],style:{color:"#8292a2"}},{types:["rule"],style:{color:"#e6db74"}}]},I={plain:{color:"#bfc7d5",backgroundColor:"#292d3e"},styles:[{types:["comment"],style:{color:"rgb(105, 112, 152)",fontStyle:"italic"}},{types:["string","inserted"],style:{color:"rgb(195, 232, 141)"}},{types:["number"],style:{color:"rgb(247, 140, 108)"}},{types:["builtin","char","constant","function"],style:{color:"rgb(130, 170, 255)"}},{types:["punctuation","selector"],style:{color:"rgb(199, 146, 234)"}},{types:["variable"],style:{color:"rgb(191, 199, 213)"}},{types:["class-name","attr-name"],style:{color:"rgb(255, 203, 107)"}},{types:["tag","deleted"],style:{color:"rgb(255, 85, 114)"}},{types:["operator"],style:{color:"rgb(137, 221, 255)"}},{types:["boolean"],style:{color:"rgb(255, 88, 116)"}},{types:["keyword"],style:{fontStyle:"italic"}},{types:["doctype"],style:{color:"rgb(199, 146, 234)",fontStyle:"italic"}},{types:["namespace"],style:{color:"rgb(178, 204, 214)"}},{types:["url"],style:{color:"rgb(221, 221, 221)"}}]},N={plain:{color:"#9EFEFF",backgroundColor:"#2D2A55"},styles:[{types:["changed"],style:{color:"rgb(255, 238, 128)"}},{types:["deleted"],style:{color:"rgba(239, 83, 80, 0.56)"}},{types:["inserted"],style:{color:"rgb(173, 219, 103)"}},{types:["comment"],style:{color:"rgb(179, 98, 255)",fontStyle:"italic"}},{types:["punctuation"],style:{color:"rgb(255, 255, 255)"}},{types:["constant"],style:{color:"rgb(255, 98, 140)"}},{types:["string","url"],style:{color:"rgb(165, 255, 144)"}},{types:["variable"],style:{color:"rgb(255, 238, 128)"}},{types:["number","boolean"],style:{color:"rgb(255, 98, 140)"}},{types:["attr-name"],style:{color:"rgb(255, 180, 84)"}},{types:["keyword","operator","property","namespace","tag","selector","doctype"],style:{color:"rgb(255, 157, 0)"}},{types:["builtin","char","constant","function","class-name"],style:{color:"rgb(250, 208, 0)"}}]},R={plain:{backgroundColor:"linear-gradient(to bottom, #2a2139 75%, #34294f)",backgroundImage:"#34294f",color:"#f92aad",textShadow:"0 0 2px #100c0f, 0 0 5px #dc078e33, 0 0 10px #fff3"},styles:[{types:["comment","block-comment","prolog","doctype","cdata"],style:{color:"#495495",fontStyle:"italic"}},{types:["punctuation"],style:{color:"#ccc"}},{types:["tag","attr-name","namespace","number","unit","hexcode","deleted"],style:{color:"#e2777a"}},{types:["property","selector"],style:{color:"#72f1b8",textShadow:"0 0 2px #100c0f, 0 0 10px #257c5575, 0 0 35px #21272475"}},{types:["function-name"],style:{color:"#6196cc"}},{types:["boolean","selector-id","function"],style:{color:"#fdfdfd",textShadow:"0 0 2px #001716, 0 0 3px #03edf975, 0 0 5px #03edf975, 0 0 8px #03edf975"}},{types:["class-name","maybe-class-name","builtin"],style:{color:"#fff5f6",textShadow:"0 0 2px #000, 0 0 10px #fc1f2c75, 0 0 5px #fc1f2c75, 0 0 25px #fc1f2c75"}},{types:["constant","symbol"],style:{color:"#f92aad",textShadow:"0 0 2px #100c0f, 0 0 5px #dc078e33, 0 0 10px #fff3"}},{types:["important","atrule","keyword","selector-class"],style:{color:"#f4eee4",textShadow:"0 0 2px #393a33, 0 0 8px #f39f0575, 0 0 2px #f39f0575"}},{types:["string","char","attr-value","regex","variable"],style:{color:"#f87c32"}},{types:["parameter"],style:{fontStyle:"italic"}},{types:["entity","url"],style:{color:"#67cdcc"}},{types:["operator"],style:{color:"ffffffee"}},{types:["important","bold"],style:{fontWeight:"bold"}},{types:["italic"],style:{fontStyle:"italic"}},{types:["entity"],style:{cursor:"help"}},{types:["inserted"],style:{color:"green"}}]},L={plain:{color:"#282a2e",backgroundColor:"#ffffff"},styles:[{types:["comment"],style:{color:"rgb(197, 200, 198)"}},{types:["string","number","builtin","variable"],style:{color:"rgb(150, 152, 150)"}},{types:["class-name","function","tag","attr-name"],style:{color:"rgb(40, 42, 46)"}}]},D={plain:{color:"#9CDCFE",backgroundColor:"#1E1E1E"},styles:[{types:["prolog"],style:{color:"rgb(0, 0, 128)"}},{types:["comment"],style:{color:"rgb(106, 153, 85)"}},{types:["builtin","changed","keyword","interpolation-punctuation"],style:{color:"rgb(86, 156, 214)"}},{types:["number","inserted"],style:{color:"rgb(181, 206, 168)"}},{types:["constant"],style:{color:"rgb(100, 102, 149)"}},{types:["attr-name","variable"],style:{color:"rgb(156, 220, 254)"}},{types:["deleted","string","attr-value","template-punctuation"],style:{color:"rgb(206, 145, 120)"}},{types:["selector"],style:{color:"rgb(215, 186, 125)"}},{types:["tag"],style:{color:"rgb(78, 201, 176)"}},{types:["tag"],languages:["markup"],style:{color:"rgb(86, 156, 214)"}},{types:["punctuation","operator"],style:{color:"rgb(212, 212, 212)"}},{types:["punctuation"],languages:["markup"],style:{color:"#808080"}},{types:["function"],style:{color:"rgb(220, 220, 170)"}},{types:["class-name"],style:{color:"rgb(78, 201, 176)"}},{types:["char"],style:{color:"rgb(209, 105, 105)"}}]},M={plain:{color:"#000000",backgroundColor:"#ffffff"},styles:[{types:["comment"],style:{color:"rgb(0, 128, 0)"}},{types:["builtin"],style:{color:"rgb(0, 112, 193)"}},{types:["number","variable","inserted"],style:{color:"rgb(9, 134, 88)"}},{types:["operator"],style:{color:"rgb(0, 0, 0)"}},{types:["constant","char"],style:{color:"rgb(129, 31, 63)"}},{types:["tag"],style:{color:"rgb(128, 0, 0)"}},{types:["attr-name"],style:{color:"rgb(255, 0, 0)"}},{types:["deleted","string"],style:{color:"rgb(163, 21, 21)"}},{types:["changed","punctuation"],style:{color:"rgb(4, 81, 165)"}},{types:["function","keyword"],style:{color:"rgb(0, 0, 255)"}},{types:["class-name"],style:{color:"rgb(38, 127, 153)"}}]},F={plain:{color:"#f8fafc",backgroundColor:"#011627"},styles:[{types:["prolog"],style:{color:"#000080"}},{types:["comment"],style:{color:"#6A9955"}},{types:["builtin","changed","keyword","interpolation-punctuation"],style:{color:"#569CD6"}},{types:["number","inserted"],style:{color:"#B5CEA8"}},{types:["constant"],style:{color:"#f8fafc"}},{types:["attr-name","variable"],style:{color:"#9CDCFE"}},{types:["deleted","string","attr-value","template-punctuation"],style:{color:"#cbd5e1"}},{types:["selector"],style:{color:"#D7BA7D"}},{types:["tag"],style:{color:"#0ea5e9"}},{types:["tag"],languages:["markup"],style:{color:"#0ea5e9"}},{types:["punctuation","operator"],style:{color:"#D4D4D4"}},{types:["punctuation"],languages:["markup"],style:{color:"#808080"}},{types:["function"],style:{color:"#7dd3fc"}},{types:["class-name"],style:{color:"#0ea5e9"}},{types:["char"],style:{color:"#D16969"}}]},B={plain:{color:"#0f172a",backgroundColor:"#f1f5f9"},styles:[{types:["prolog"],style:{color:"#000080"}},{types:["comment"],style:{color:"#6A9955"}},{types:["builtin","changed","keyword","interpolation-punctuation"],style:{color:"#0c4a6e"}},{types:["number","inserted"],style:{color:"#B5CEA8"}},{types:["constant"],style:{color:"#0f172a"}},{types:["attr-name","variable"],style:{color:"#0c4a6e"}},{types:["deleted","string","attr-value","template-punctuation"],style:{color:"#64748b"}},{types:["selector"],style:{color:"#D7BA7D"}},{types:["tag"],style:{color:"#0ea5e9"}},{types:["tag"],languages:["markup"],style:{color:"#0ea5e9"}},{types:["punctuation","operator"],style:{color:"#475569"}},{types:["punctuation"],languages:["markup"],style:{color:"#808080"}},{types:["function"],style:{color:"#0e7490"}},{types:["class-name"],style:{color:"#0ea5e9"}},{types:["char"],style:{color:"#D16969"}}]},z={plain:{backgroundColor:"hsl(220, 13%, 18%)",color:"hsl(220, 14%, 71%)",textShadow:"0 1px rgba(0, 0, 0, 0.3)"},styles:[{types:["comment","prolog","cdata"],style:{color:"hsl(220, 10%, 40%)"}},{types:["doctype","punctuation","entity"],style:{color:"hsl(220, 14%, 71%)"}},{types:["attr-name","class-name","maybe-class-name","boolean","constant","number","atrule"],style:{color:"hsl(29, 54%, 61%)"}},{types:["keyword"],style:{color:"hsl(286, 60%, 67%)"}},{types:["property","tag","symbol","deleted","important"],style:{color:"hsl(355, 65%, 65%)"}},{types:["selector","string","char","builtin","inserted","regex","attr-value"],style:{color:"hsl(95, 38%, 62%)"}},{types:["variable","operator","function"],style:{color:"hsl(207, 82%, 66%)"}},{types:["url"],style:{color:"hsl(187, 47%, 55%)"}},{types:["deleted"],style:{textDecorationLine:"line-through"}},{types:["inserted"],style:{textDecorationLine:"underline"}},{types:["italic"],style:{fontStyle:"italic"}},{types:["important","bold"],style:{fontWeight:"bold"}},{types:["important"],style:{color:"hsl(220, 14%, 71%)"}}]},$={plain:{backgroundColor:"hsl(230, 1%, 98%)",color:"hsl(230, 8%, 24%)"},styles:[{types:["comment","prolog","cdata"],style:{color:"hsl(230, 4%, 64%)"}},{types:["doctype","punctuation","entity"],style:{color:"hsl(230, 8%, 24%)"}},{types:["attr-name","class-name","boolean","constant","number","atrule"],style:{color:"hsl(35, 99%, 36%)"}},{types:["keyword"],style:{color:"hsl(301, 63%, 40%)"}},{types:["property","tag","symbol","deleted","important"],style:{color:"hsl(5, 74%, 59%)"}},{types:["selector","string","char","builtin","inserted","regex","attr-value","punctuation"],style:{color:"hsl(119, 34%, 47%)"}},{types:["variable","operator","function"],style:{color:"hsl(221, 87%, 60%)"}},{types:["url"],style:{color:"hsl(198, 99%, 37%)"}},{types:["deleted"],style:{textDecorationLine:"line-through"}},{types:["inserted"],style:{textDecorationLine:"underline"}},{types:["italic"],style:{fontStyle:"italic"}},{types:["important","bold"],style:{fontWeight:"bold"}},{types:["important"],style:{color:"hsl(230, 8%, 24%)"}}]},U={plain:{color:"#ebdbb2",backgroundColor:"#292828"},styles:[{types:["imports","class-name","maybe-class-name","constant","doctype","builtin","function"],style:{color:"#d8a657"}},{types:["property-access"],style:{color:"#7daea3"}},{types:["tag"],style:{color:"#e78a4e"}},{types:["attr-name","char","url","regex"],style:{color:"#a9b665"}},{types:["attr-value","string"],style:{color:"#89b482"}},{types:["comment","prolog","cdata","operator","inserted"],style:{color:"#a89984"}},{types:["delimiter","boolean","keyword","selector","important","atrule","property","variable","deleted"],style:{color:"#ea6962"}},{types:["entity","number","symbol"],style:{color:"#d3869b"}}]},H={plain:{color:"#654735",backgroundColor:"#f9f5d7"},styles:[{types:["delimiter","boolean","keyword","selector","important","atrule","property","variable","deleted"],style:{color:"#af2528"}},{types:["imports","class-name","maybe-class-name","constant","doctype","builtin"],style:{color:"#b4730e"}},{types:["string","attr-value"],style:{color:"#477a5b"}},{types:["property-access"],style:{color:"#266b79"}},{types:["function","attr-name","char","url"],style:{color:"#72761e"}},{types:["tag"],style:{color:"#b94c07"}},{types:["comment","prolog","cdata","operator","inserted"],style:{color:"#a89984"}},{types:["entity","number","symbol"],style:{color:"#924f79"}}]},q=(e,t)=>{const{plain:n}=e,r=e.styles.reduce(((e,n)=>{const{languages:r,style:o}=n;return r&&!r.includes(t)||n.types.forEach((t=>{const n=y(y({},e[t]),o);e[t]=n})),e}),{});return r.root=n,r.plain=v(y({},n),{backgroundColor:void 0}),r},V=/\r\n|\r|\n/,W=e=>{0===e.length?e.push({types:["plain"],content:"\n",empty:!0}):1===e.length&&""===e[0].content&&(e[0].content="\n",e[0].empty=!0)},G=(e,t)=>{const n=e.length;return n>0&&e[n-1]===t?e:e.concat(t)},K=e=>{const t=[[]],n=[e],r=[0],o=[e.length];let a=0,i=0,s=[];const c=[s];for(;i>-1;){for(;(a=r[i]++)<o[i];){let e,l=t[i];const u=n[i][a];if("string"==typeof u?(l=i>0?l:["plain"],e=u):(l=G(l,u.type),u.alias&&(l=G(l,u.alias)),e=u.content),"string"!=typeof e){i++,t.push(l),n.push(e),r.push(0),o.push(e.length);continue}const d=e.split(V),p=d.length;s.push({types:l,content:d[0]});for(let t=1;t<p;t++)W(s),c.push(s=[]),s.push({types:l,content:d[t]})}i--,t.pop(),n.pop(),r.pop(),o.pop()}return W(s),c},Y=({children:e,language:t,code:n,theme:r,prism:o})=>{const s=t.toLowerCase(),c=((e,t)=>{const[n,r]=(0,a.useState)(q(t,e)),o=(0,a.useRef)(),i=(0,a.useRef)();return(0,a.useEffect)((()=>{t===o.current&&e===i.current||(o.current=t,i.current=e,r(q(t,e)))}),[e,t]),n})(s,r),l=(e=>(0,a.useCallback)((t=>{var n=t,{className:r,style:o,line:a}=n,s=w(n,["className","style","line"]);const c=v(y({},s),{className:(0,i.A)("token-line",r)});return"object"==typeof e&&"plain"in e&&(c.style=e.plain),"object"==typeof o&&(c.style=y(y({},c.style||{}),o)),c}),[e]))(c),u=(e=>{const t=(0,a.useCallback)((({types:t,empty:n})=>{if(null!=e)return 1===t.length&&"plain"===t[0]?null!=n?{display:"inline-block"}:void 0:1===t.length&&null!=n?e[t[0]]:Object.assign(null!=n?{display:"inline-block"}:{},...t.map((t=>e[t])))}),[e]);return(0,a.useCallback)((e=>{var n=e,{token:r,className:o,style:a}=n,s=w(n,["token","className","style"]);const c=v(y({},s),{className:(0,i.A)("token",...r.types,o),children:r.content,style:t(r)});return null!=a&&(c.style=y(y({},c.style||{}),a)),c}),[t])})(c),d=(({prism:e,code:t,grammar:n,language:r})=>{const o=(0,a.useRef)(e);return(0,a.useMemo)((()=>{if(null==n)return K([t]);const e={code:t,grammar:n,language:r,tokens:[]};return o.current.hooks.run("before-tokenize",e),e.tokens=o.current.tokenize(t,n),o.current.hooks.run("after-tokenize",e),K(e.tokens)}),[t,n,r])})({prism:o,language:s,code:n,grammar:o.languages[s]});return e({tokens:d,className:`prism-code language-${s}`,style:null!=c?c.root:{},getLineProps:l,getTokenProps:u})},Q=e=>(0,a.createElement)(Y,v(y({},e),{prism:e.prism||S,theme:e.theme||D,code:e.code,language:e.language}))},1561:(e,t,n)=>{"use strict";n.d(t,{A:()=>a});var r=!0,o="Invariant failed";function a(e,t){if(!e){if(r)throw new Error(o);var n="function"==typeof t?t():t,a=n?"".concat(o,": ").concat(n):o;throw new Error(a)}}},1635:(e,t,n)=>{"use strict";n.r(t),n.d(t,{__addDisposableResource:()=>L,__assign:()=>a,__asyncDelegator:()=>E,__asyncGenerator:()=>_,__asyncValues:()=>j,__await:()=>x,__awaiter:()=>m,__classPrivateFieldGet:()=>I,__classPrivateFieldIn:()=>R,__classPrivateFieldSet:()=>N,__createBinding:()=>h,__decorate:()=>s,__disposeResources:()=>M,__esDecorate:()=>l,__exportStar:()=>b,__extends:()=>o,__generator:()=>g,__importDefault:()=>P,__importStar:()=>T,__makeTemplateObject:()=>O,__metadata:()=>f,__param:()=>c,__propKey:()=>d,__read:()=>v,__rest:()=>i,__rewriteRelativeImportExtension:()=>F,__runInitializers:()=>u,__setFunctionName:()=>p,__spread:()=>w,__spreadArray:()=>k,__spreadArrays:()=>S,__values:()=>y,default:()=>B});var r=function(e,t){return r=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)Object.prototype.hasOwnProperty.call(t,n)&&(e[n]=t[n])},r(e,t)};function o(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Class extends value "+String(t)+" is not a constructor or null");function n(){this.constructor=e}r(e,t),e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)}var a=function(){return a=Object.assign||function(e){for(var t,n=1,r=arguments.length;n<r;n++)for(var o in t=arguments[n])Object.prototype.hasOwnProperty.call(t,o)&&(e[o]=t[o]);return e},a.apply(this,arguments)};function i(e,t){var n={};for(var r in e)Object.prototype.hasOwnProperty.call(e,r)&&t.indexOf(r)<0&&(n[r]=e[r]);if(null!=e&&"function"==typeof Object.getOwnPropertySymbols){var o=0;for(r=Object.getOwnPropertySymbols(e);o<r.length;o++)t.indexOf(r[o])<0&&Object.prototype.propertyIsEnumerable.call(e,r[o])&&(n[r[o]]=e[r[o]])}return n}function s(e,t,n,r){var o,a=arguments.length,i=a<3?t:null===r?r=Object.getOwnPropertyDescriptor(t,n):r;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)i=Reflect.decorate(e,t,n,r);else for(var s=e.length-1;s>=0;s--)(o=e[s])&&(i=(a<3?o(i):a>3?o(t,n,i):o(t,n))||i);return a>3&&i&&Object.defineProperty(t,n,i),i}function c(e,t){return function(n,r){t(n,r,e)}}function l(e,t,n,r,o,a){function i(e){if(void 0!==e&&"function"!=typeof e)throw new TypeError("Function expected");return e}for(var s,c=r.kind,l="getter"===c?"get":"setter"===c?"set":"value",u=!t&&e?r.static?e:e.prototype:null,d=t||(u?Object.getOwnPropertyDescriptor(u,r.name):{}),p=!1,f=n.length-1;f>=0;f--){var m={};for(var g in r)m[g]="access"===g?{}:r[g];for(var g in r.access)m.access[g]=r.access[g];m.addInitializer=function(e){if(p)throw new TypeError("Cannot add initializers after decoration has completed");a.push(i(e||null))};var h=(0,n[f])("accessor"===c?{get:d.get,set:d.set}:d[l],m);if("accessor"===c){if(void 0===h)continue;if(null===h||"object"!=typeof h)throw new TypeError("Object expected");(s=i(h.get))&&(d.get=s),(s=i(h.set))&&(d.set=s),(s=i(h.init))&&o.unshift(s)}else(s=i(h))&&("field"===c?o.unshift(s):d[l]=s)}u&&Object.defineProperty(u,r.name,d),p=!0}function u(e,t,n){for(var r=arguments.length>2,o=0;o<t.length;o++)n=r?t[o].call(e,n):t[o].call(e);return r?n:void 0}function d(e){return"symbol"==typeof e?e:"".concat(e)}function p(e,t,n){return"symbol"==typeof t&&(t=t.description?"[".concat(t.description,"]"):""),Object.defineProperty(e,"name",{configurable:!0,value:n?"".concat(n," ",t):t})}function f(e,t){if("object"==typeof Reflect&&"function"==typeof Reflect.metadata)return Reflect.metadata(e,t)}function m(e,t,n,r){return new(n||(n=Promise))((function(o,a){function i(e){try{c(r.next(e))}catch(t){a(t)}}function s(e){try{c(r.throw(e))}catch(t){a(t)}}function c(e){var t;e.done?o(e.value):(t=e.value,t instanceof n?t:new n((function(e){e(t)}))).then(i,s)}c((r=r.apply(e,t||[])).next())}))}function g(e,t){var n,r,o,a={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]},i=Object.create(("function"==typeof Iterator?Iterator:Object).prototype);return i.next=s(0),i.throw=s(1),i.return=s(2),"function"==typeof Symbol&&(i[Symbol.iterator]=function(){return this}),i;function s(s){return function(c){return function(s){if(n)throw new TypeError("Generator is already executing.");for(;i&&(i=0,s[0]&&(a=0)),a;)try{if(n=1,r&&(o=2&s[0]?r.return:s[0]?r.throw||((o=r.return)&&o.call(r),0):r.next)&&!(o=o.call(r,s[1])).done)return o;switch(r=0,o&&(s=[2&s[0],o.value]),s[0]){case 0:case 1:o=s;break;case 4:return a.label++,{value:s[1],done:!1};case 5:a.label++,r=s[1],s=[0];continue;case 7:s=a.ops.pop(),a.trys.pop();continue;default:if(!(o=a.trys,(o=o.length>0&&o[o.length-1])||6!==s[0]&&2!==s[0])){a=0;continue}if(3===s[0]&&(!o||s[1]>o[0]&&s[1]<o[3])){a.label=s[1];break}if(6===s[0]&&a.label<o[1]){a.label=o[1],o=s;break}if(o&&a.label<o[2]){a.label=o[2],a.ops.push(s);break}o[2]&&a.ops.pop(),a.trys.pop();continue}s=t.call(e,a)}catch(c){s=[6,c],r=0}finally{n=o=0}if(5&s[0])throw s[1];return{value:s[0]?s[1]:void 0,done:!0}}([s,c])}}}var h=Object.create?function(e,t,n,r){void 0===r&&(r=n);var o=Object.getOwnPropertyDescriptor(t,n);o&&!("get"in o?!t.__esModule:o.writable||o.configurable)||(o={enumerable:!0,get:function(){return t[n]}}),Object.defineProperty(e,r,o)}:function(e,t,n,r){void 0===r&&(r=n),e[r]=t[n]};function b(e,t){for(var n in e)"default"===n||Object.prototype.hasOwnProperty.call(t,n)||h(t,e,n)}function y(e){var t="function"==typeof Symbol&&Symbol.iterator,n=t&&e[t],r=0;if(n)return n.call(e);if(e&&"number"==typeof e.length)return{next:function(){return e&&r>=e.length&&(e=void 0),{value:e&&e[r++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")}function v(e,t){var n="function"==typeof Symbol&&e[Symbol.iterator];if(!n)return e;var r,o,a=n.call(e),i=[];try{for(;(void 0===t||t-- >0)&&!(r=a.next()).done;)i.push(r.value)}catch(s){o={error:s}}finally{try{r&&!r.done&&(n=a.return)&&n.call(a)}finally{if(o)throw o.error}}return i}function w(){for(var e=[],t=0;t<arguments.length;t++)e=e.concat(v(arguments[t]));return e}function S(){for(var e=0,t=0,n=arguments.length;t<n;t++)e+=arguments[t].length;var r=Array(e),o=0;for(t=0;t<n;t++)for(var a=arguments[t],i=0,s=a.length;i<s;i++,o++)r[o]=a[i];return r}function k(e,t,n){if(n||2===arguments.length)for(var r,o=0,a=t.length;o<a;o++)!r&&o in t||(r||(r=Array.prototype.slice.call(t,0,o)),r[o]=t[o]);return e.concat(r||Array.prototype.slice.call(t))}function x(e){return this instanceof x?(this.v=e,this):new x(e)}function _(e,t,n){if(!Symbol.asyncIterator)throw new TypeError("Symbol.asyncIterator is not defined.");var r,o=n.apply(e,t||[]),a=[];return r=Object.create(("function"==typeof AsyncIterator?AsyncIterator:Object).prototype),i("next"),i("throw"),i("return",(function(e){return function(t){return Promise.resolve(t).then(e,l)}})),r[Symbol.asyncIterator]=function(){return this},r;function i(e,t){o[e]&&(r[e]=function(t){return new Promise((function(n,r){a.push([e,t,n,r])>1||s(e,t)}))},t&&(r[e]=t(r[e])))}function s(e,t){try{(n=o[e](t)).value instanceof x?Promise.resolve(n.value.v).then(c,l):u(a[0][2],n)}catch(r){u(a[0][3],r)}var n}function c(e){s("next",e)}function l(e){s("throw",e)}function u(e,t){e(t),a.shift(),a.length&&s(a[0][0],a[0][1])}}function E(e){var t,n;return t={},r("next"),r("throw",(function(e){throw e})),r("return"),t[Symbol.iterator]=function(){return this},t;function r(r,o){t[r]=e[r]?function(t){return(n=!n)?{value:x(e[r](t)),done:!1}:o?o(t):t}:o}}function j(e){if(!Symbol.asyncIterator)throw new TypeError("Symbol.asyncIterator is not defined.");var t,n=e[Symbol.asyncIterator];return n?n.call(e):(e=y(e),t={},r("next"),r("throw"),r("return"),t[Symbol.asyncIterator]=function(){return this},t);function r(n){t[n]=e[n]&&function(t){return new Promise((function(r,o){(function(e,t,n,r){Promise.resolve(r).then((function(t){e({value:t,done:n})}),t)})(r,o,(t=e[n](t)).done,t.value)}))}}}function O(e,t){return Object.defineProperty?Object.defineProperty(e,"raw",{value:t}):e.raw=t,e}var A=Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:!0,value:t})}:function(e,t){e.default=t},C=function(e){return C=Object.getOwnPropertyNames||function(e){var t=[];for(var n in e)Object.prototype.hasOwnProperty.call(e,n)&&(t[t.length]=n);return t},C(e)};function T(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var n=C(e),r=0;r<n.length;r++)"default"!==n[r]&&h(t,e,n[r]);return A(t,e),t}function P(e){return e&&e.__esModule?e:{default:e}}function I(e,t,n,r){if("a"===n&&!r)throw new TypeError("Private accessor was defined without a getter");if("function"==typeof t?e!==t||!r:!t.has(e))throw new TypeError("Cannot read private member from an object whose class did not declare it");return"m"===n?r:"a"===n?r.call(e):r?r.value:t.get(e)}function N(e,t,n,r,o){if("m"===r)throw new TypeError("Private method is not writable");if("a"===r&&!o)throw new TypeError("Private accessor was defined without a setter");if("function"==typeof t?e!==t||!o:!t.has(e))throw new TypeError("Cannot write private member to an object whose class did not declare it");return"a"===r?o.call(e,n):o?o.value=n:t.set(e,n),n}function R(e,t){if(null===t||"object"!=typeof t&&"function"!=typeof t)throw new TypeError("Cannot use 'in' operator on non-object");return"function"==typeof e?t===e:e.has(t)}function L(e,t,n){if(null!=t){if("object"!=typeof t&&"function"!=typeof t)throw new TypeError("Object expected.");var r,o;if(n){if(!Symbol.asyncDispose)throw new TypeError("Symbol.asyncDispose is not defined.");r=t[Symbol.asyncDispose]}if(void 0===r){if(!Symbol.dispose)throw new TypeError("Symbol.dispose is not defined.");r=t[Symbol.dispose],n&&(o=r)}if("function"!=typeof r)throw new TypeError("Object not disposable.");o&&(r=function(){try{o.call(this)}catch(e){return Promise.reject(e)}}),e.stack.push({value:t,dispose:r,async:n})}else n&&e.stack.push({async:!0});return t}var D="function"==typeof SuppressedError?SuppressedError:function(e,t,n){var r=new Error(n);return r.name="SuppressedError",r.error=e,r.suppressed=t,r};function M(e){function t(t){e.error=e.hasError?new D(t,e.error,"An error was suppressed during disposal."):t,e.hasError=!0}var n,r=0;return function o(){for(;n=e.stack.pop();)try{if(!n.async&&1===r)return r=0,e.stack.push(n),Promise.resolve().then(o);if(n.dispose){var a=n.dispose.call(n.value);if(n.async)return r|=2,Promise.resolve(a).then(o,(function(e){return t(e),o()}))}else r|=1}catch(i){t(i)}if(1===r)return e.hasError?Promise.reject(e.error):Promise.resolve();if(e.hasError)throw e.error}()}function F(e,t){return"string"==typeof e&&/^\.\.?\//.test(e)?e.replace(/\.(tsx)$|((?:\.d)?)((?:\.[^./]+?)?)\.([cm]?)ts$/i,(function(e,n,r,o,a){return n?t?".jsx":".js":!r||o&&a?r+o+"."+a.toLowerCase()+"js":e})):e}const B={__extends:o,__assign:a,__rest:i,__decorate:s,__param:c,__esDecorate:l,__runInitializers:u,__propKey:d,__setFunctionName:p,__metadata:f,__awaiter:m,__generator:g,__createBinding:h,__exportStar:b,__values:y,__read:v,__spread:w,__spreadArrays:S,__spreadArray:k,__await:x,__asyncGenerator:_,__asyncDelegator:E,__asyncValues:j,__makeTemplateObject:O,__importStar:T,__importDefault:P,__classPrivateFieldGet:I,__classPrivateFieldSet:N,__classPrivateFieldIn:R,__addDisposableResource:L,__disposeResources:M,__rewriteRelativeImportExtension:F}},2654:e=>{"use strict";e.exports={}},4054:e=>{"use strict";e.exports=JSON.parse('{"/blog-775":{"__comp":"a6aa9e1f","__context":{"plugin":"36994c47"},"sidebar":"814f3328","items":[{"content":"31f8b8ae"},{"content":"80e02aec"},{"content":"5806acc5"},{"content":"76dc6352"},{"content":"44d6dde1"},{"content":"9e9bbe09"},{"content":"981d14b8"},{"content":"965c09ae"},{"content":"5b895f91"},{"content":"d70bd24b"}],"__props":"c15d9823"},"/blog/2021/09/30/long-term-commitment-and-support-for-the-cadence-project-and-its-community-bcb":{"__comp":"ccc49370","__context":{"data":{"blogMetadata":"acecf23e"},"plugin":"36994c47"},"sidebar":"814f3328","content":"278bd730"},"/blog/2021/10/13/announcing-cadence-oss-office-hours-and-community-sync-up-0d6":{"__comp":"ccc49370","__context":{"data":{"blogMetadata":"acecf23e"},"plugin":"36994c47"},"sidebar":"814f3328","content":"de3708c6"},"/blog/2021/10/19/2021-10-19-moving-to-grpc/moving-to-grpc-7db":{"__comp":"ccc49370","__context":{"data":{"blogMetadata":"acecf23e"},"plugin":"36994c47"},"sidebar":"814f3328","content":"177ff540"},"/blog/2022/01/31/community-spotlight-january-2022-511":{"__comp":"ccc49370","__context":{"data":{"blogMetadata":"acecf23e"},"plugin":"36994c47"},"sidebar":"814f3328","content":"3ca3c927"},"/blog/2022/02/28/community-spotlight-february-2022-b9d":{"__comp":"ccc49370","__context":{"data":{"blogMetadata":"acecf23e"},"plugin":"36994c47"},"sidebar":"814f3328","content":"a3dd65a2"},"/blog/2022/03/31/community-spotlight-update-march-2022-fa6":{"__comp":"ccc49370","__context":{"data":{"blogMetadata":"acecf23e"},"plugin":"36994c47"},"sidebar":"814f3328","content":"88d84d8e"},"/blog/2022/04/30/community-spotlight-update-april-2022-6c1":{"__comp":"ccc49370","__context":{"data":{"blogMetadata":"acecf23e"},"plugin":"36994c47"},"sidebar":"814f3328","content":"3d5497b2"},"/blog/2022/05/31/community-spotlight-update-may-2022-7b3":{"__comp":"ccc49370","__context":{"data":{"blogMetadata":"acecf23e"},"plugin":"36994c47"},"sidebar":"814f3328","content":"b69803f5"},"/blog/2022/06/30/community-spotlight-update-june-2022-f54":{"__comp":"ccc49370","__context":{"data":{"blogMetadata":"acecf23e"},"plugin":"36994c47"},"sidebar":"814f3328","content":"4b94b3ad"},"/blog/2022/07/31/community-spotlight-update-july-2022-c4f":{"__comp":"ccc49370","__context":{"data":{"blogMetadata":"acecf23e"},"plugin":"36994c47"},"sidebar":"814f3328","content":"d27d92a2"},"/blog/2022/08/31/community-spotlight-august-2022-697":{"__comp":"ccc49370","__context":{"data":{"blogMetadata":"acecf23e"},"plugin":"36994c47"},"sidebar":"814f3328","content":"a94774ec"},"/blog/2022/09/30/community-spotlight-september-2022-0e6":{"__comp":"ccc49370","__context":{"data":{"blogMetadata":"acecf23e"},"plugin":"36994c47"},"sidebar":"814f3328","content":"6081a96a"},"/blog/2022/10/31/community-spotlight-october-2022-829":{"__comp":"ccc49370","__context":{"data":{"blogMetadata":"acecf23e"},"plugin":"36994c47"},"sidebar":"814f3328","content":"ea1e4697"},"/blog/2022/11/30/community-spotlight-november-2022-30a":{"__comp":"ccc49370","__context":{"data":{"blogMetadata":"acecf23e"},"plugin":"36994c47"},"sidebar":"814f3328","content":"e9c26ae5"},"/blog/2022/12/23/community-spotlight-december-2022-618":{"__comp":"ccc49370","__context":{"data":{"blogMetadata":"acecf23e"},"plugin":"36994c47"},"sidebar":"814f3328","content":"775920c1"},"/blog/2023/01/31/community-spotlight-january-2023-47e":{"__comp":"ccc49370","__context":{"data":{"blogMetadata":"acecf23e"},"plugin":"36994c47"},"sidebar":"814f3328","content":"ef69cbb3"},"/blog/2023/02/28/community-spotlight-february-943":{"__comp":"ccc49370","__context":{"data":{"blogMetadata":"acecf23e"},"plugin":"36994c47"},"sidebar":"814f3328","content":"7afb0752"},"/blog/2023/03/31/community-spotlight-march-2023-580":{"__comp":"ccc49370","__context":{"data":{"blogMetadata":"acecf23e"},"plugin":"36994c47"},"sidebar":"814f3328","content":"9366521c"},"/blog/2023/06/08/2023-06-08-survey-results/survey-results-ee6":{"__comp":"ccc49370","__context":{"data":{"blogMetadata":"acecf23e"},"plugin":"36994c47"},"sidebar":"814f3328","content":"92ce93dc"},"/blog/2023/06/28/components-of-cadence-application-setup-060":{"__comp":"ccc49370","__context":{"data":{"blogMetadata":"acecf23e"},"plugin":"36994c47"},"sidebar":"814f3328","content":"0bc129c0"},"/blog/2023/06/30/community-spotlight-june-2023-3cc":{"__comp":"ccc49370","__context":{"data":{"blogMetadata":"acecf23e"},"plugin":"36994c47"},"sidebar":"814f3328","content":"98f5ac88"},"/blog/2023/07/05/implement-cadence-worker-from-scratch-f2f":{"__comp":"ccc49370","__context":{"data":{"blogMetadata":"acecf23e"},"plugin":"36994c47"},"sidebar":"814f3328","content":"18e1ae2c"},"/blog/2023/07/10/cadence-bad-practices-part-1-4d6":{"__comp":"ccc49370","__context":{"data":{"blogMetadata":"acecf23e"},"plugin":"36994c47"},"sidebar":"814f3328","content":"5f63c9de"},"/blog/2023/07/16/2023-07-16-write-your-first-workflow-with-cadence/write-your-first-workflow-with-cadence-342":{"__comp":"ccc49370","__context":{"data":{"blogMetadata":"acecf23e"},"plugin":"36994c47"},"sidebar":"814f3328","content":"a197b989"},"/blog/2023/07/31/community-spotlight-july-2023-c49":{"__comp":"ccc49370","__context":{"data":{"blogMetadata":"acecf23e"},"plugin":"36994c47"},"sidebar":"814f3328","content":"647edc7e"},"/blog/2023/08/28/nondeterministic-errors-replayers-shadowers-0c6":{"__comp":"ccc49370","__context":{"data":{"blogMetadata":"acecf23e"},"plugin":"36994c47"},"sidebar":"814f3328","content":"2955167d"},"/blog/2023/08/31/community-spotlight-august-2023-221":{"__comp":"ccc49370","__context":{"data":{"blogMetadata":"acecf23e"},"plugin":"36994c47"},"sidebar":"814f3328","content":"f1de825c"},"/blog/2023/11/30/community-spotlight-update-november-2023-174":{"__comp":"ccc49370","__context":{"data":{"blogMetadata":"acecf23e"},"plugin":"36994c47"},"sidebar":"814f3328","content":"580cfca3"},"/blog/2024/02/15/cadence-non-deterministic-common-qa-ed4":{"__comp":"ccc49370","__context":{"data":{"blogMetadata":"acecf23e"},"plugin":"36994c47"},"sidebar":"814f3328","content":"7fda255c"},"/blog/2024/07/11/2024-07-11-yearly-roadmap-update/yearly-roadmap-update-cef":{"__comp":"ccc49370","__context":{"data":{"blogMetadata":"acecf23e"},"plugin":"36994c47"},"sidebar":"814f3328","content":"c47f6b82"},"/blog/2024/09/05/workflow-specific-rate-limits-778":{"__comp":"ccc49370","__context":{"data":{"blogMetadata":"acecf23e"},"plugin":"36994c47"},"sidebar":"814f3328","content":"849b28af"},"/blog/2024/10/01/announcing-cadence-helm-charts-v0-8fb":{"__comp":"ccc49370","__context":{"data":{"blogMetadata":"acecf23e"},"plugin":"36994c47"},"sidebar":"814f3328","content":"d33895f8"},"/blog/2024/11/18/cadence-workflows-github-organization-6df":{"__comp":"ccc49370","__context":{"data":{"blogMetadata":"acecf23e"},"plugin":"36994c47"},"sidebar":"814f3328","content":"115ec24d"},"/blog/2024/3/11/community-spotlight-update-march-2024-7a7":{"__comp":"ccc49370","__context":{"data":{"blogMetadata":"acecf23e"},"plugin":"36994c47"},"sidebar":"814f3328","content":"8edf5fa8"},"/blog/archive-182":{"__comp":"9e4087bc","__context":{"plugin":"36994c47"},"__props":"f81c1134"},"/blog/authors-0b7":{"__comp":"621db11d","__context":{"data":{"blogMetadata":"acecf23e"},"plugin":"36994c47"},"sidebar":"814f3328","__props":"ef8b811a"},"/blog/authors/chopincode-b0f":{"__comp":"33fc5bb8","__context":{"data":{"blogMetadata":"acecf23e"},"plugin":"36994c47"},"items":[{"content":"9e9bbe09"},{"content":"5b895f91"},{"content":"8a72c69a"},{"content":"534a6068"},{"content":"d6960a6f"},{"content":"667be76f"}],"sidebar":"814f3328","__props":"9250e00d"},"/blog/authors/enderdemirkaya-5c6":{"__comp":"33fc5bb8","__context":{"data":{"blogMetadata":"acecf23e"},"plugin":"36994c47"},"items":[{"content":"44d6dde1"},{"content":"7613fcd7"}],"sidebar":"814f3328","__props":"a3886376"},"/blog/authors/ibarrajo-353":{"__comp":"33fc5bb8","__context":{"data":{"blogMetadata":"acecf23e"},"plugin":"36994c47"},"items":[{"content":"31f8b8ae"}],"sidebar":"814f3328","__props":"0922f36e"},"/blog/authors/jakobht-e9a":{"__comp":"33fc5bb8","__context":{"data":{"blogMetadata":"acecf23e"},"plugin":"36994c47"},"items":[{"content":"76dc6352"}],"sidebar":"814f3328","__props":"aa55d0af"},"/blog/authors/kcorbett-netapp-34e":{"__comp":"33fc5bb8","__context":{"data":{"blogMetadata":"acecf23e"},"plugin":"36994c47"},"items":[{"content":"33348b0e"}],"sidebar":"814f3328","__props":"17896883"},"/blog/authors/meiliang-86-00a":{"__comp":"33fc5bb8","__context":{"data":{"blogMetadata":"acecf23e"},"plugin":"36994c47"},"items":[{"content":"fda2e45a"},{"content":"df4cf6e6"}],"sidebar":"814f3328","__props":"f09be712"},"/blog/authors/shaddoll-91b":{"__comp":"33fc5bb8","__context":{"data":{"blogMetadata":"acecf23e"},"plugin":"36994c47"},"items":[{"content":"80e02aec"}],"sidebar":"814f3328","__props":"0cfc60d3"},"/blog/authors/sharanf-293":{"__comp":"33fc5bb8","__context":{"data":{"blogMetadata":"acecf23e"},"plugin":"36994c47"},"items":[{"content":"981d14b8"},{"content":"965c09ae"},{"content":"d70bd24b"},{"content":"cdf6e634"},{"content":"f7be646d"},{"content":"36aefe7c"},{"content":"33cf8314"},{"content":"87d83cd2"},{"content":"528620f0"},{"content":"dec4f520"}],"sidebar":"814f3328","__props":"741d205a"},"/blog/authors/sharanf/authors/2-e3a":{"__comp":"33fc5bb8","__context":{"data":{"blogMetadata":"acecf23e"},"plugin":"36994c47"},"items":[{"content":"959827cd"},{"content":"4d332630"},{"content":"cfb807c8"},{"content":"aac593d4"},{"content":"1c90ed0c"},{"content":"98f77afb"},{"content":"d33bd0ff"},{"content":"144c3ace"},{"content":"acfca6f1"}],"sidebar":"814f3328","__props":"a48fa53f"},"/blog/authors/taylanisikdemir-2ca":{"__comp":"33fc5bb8","__context":{"data":{"blogMetadata":"acecf23e"},"plugin":"36994c47"},"items":[{"content":"5806acc5"}],"sidebar":"814f3328","__props":"004bd3e7"},"/blog/authors/vytautas-karpavicius-e09":{"__comp":"33fc5bb8","__context":{"data":{"blogMetadata":"acecf23e"},"plugin":"36994c47"},"items":[{"content":"28f6f2b5"}],"sidebar":"814f3328","__props":"3485e756"},"/blog/page/2-10f":{"__comp":"a6aa9e1f","__context":{"plugin":"36994c47"},"sidebar":"814f3328","items":[{"content":"8a72c69a"},{"content":"534a6068"},{"content":"d6960a6f"},{"content":"667be76f"},{"content":"cdf6e634"},{"content":"7613fcd7"},{"content":"f7be646d"},{"content":"33348b0e"},{"content":"36aefe7c"},{"content":"33cf8314"}],"__props":"8ea09047"},"/blog/page/3-b5e":{"__comp":"a6aa9e1f","__context":{"plugin":"36994c47"},"sidebar":"814f3328","items":[{"content":"87d83cd2"},{"content":"528620f0"},{"content":"dec4f520"},{"content":"959827cd"},{"content":"4d332630"},{"content":"cfb807c8"},{"content":"aac593d4"},{"content":"1c90ed0c"},{"content":"98f77afb"},{"content":"d33bd0ff"}],"__props":"18ffe98c"},"/blog/page/4-3a4":{"__comp":"a6aa9e1f","__context":{"plugin":"36994c47"},"sidebar":"814f3328","items":[{"content":"144c3ace"},{"content":"acfca6f1"},{"content":"28f6f2b5"},{"content":"fda2e45a"},{"content":"df4cf6e6"}],"__props":"40011a75"},"/blog/tags-287":{"__comp":"01a85c17","__context":{"plugin":"36994c47"},"sidebar":"814f3328","__props":"3a2db09e"},"/blog/tags/announcements-83f":{"__comp":"6875c492","__context":{"plugin":"36994c47"},"sidebar":"814f3328","items":[{"content":"31f8b8ae"},{"content":"5806acc5"},{"content":"981d14b8"},{"content":"d70bd24b"},{"content":"7613fcd7"},{"content":"fda2e45a"},{"content":"df4cf6e6"}],"__props":"04e595f1"},"/blog/tags/cadence-operations-8cc":{"__comp":"6875c492","__context":{"plugin":"36994c47"},"sidebar":"814f3328","items":[{"content":"80e02aec"},{"content":"28f6f2b5"}],"__props":"93e7684d"},"/blog/tags/community-spotlights-d90":{"__comp":"6875c492","__context":{"plugin":"36994c47"},"sidebar":"814f3328","items":[{"content":"981d14b8"},{"content":"965c09ae"},{"content":"d70bd24b"},{"content":"cdf6e634"},{"content":"f7be646d"},{"content":"33348b0e"},{"content":"36aefe7c"},{"content":"33cf8314"},{"content":"87d83cd2"},{"content":"528620f0"}],"__props":"80db4ed1"},"/blog/tags/community-spotlights/page/2-62d":{"__comp":"6875c492","__context":{"plugin":"36994c47"},"sidebar":"814f3328","items":[{"content":"dec4f520"},{"content":"959827cd"},{"content":"4d332630"},{"content":"cfb807c8"},{"content":"aac593d4"},{"content":"1c90ed0c"},{"content":"98f77afb"},{"content":"d33bd0ff"},{"content":"144c3ace"},{"content":"acfca6f1"}],"__props":"d0bf664b"},"/blog/tags/deep-dives-cd9":{"__comp":"6875c492","__context":{"plugin":"36994c47"},"sidebar":"814f3328","items":[{"content":"80e02aec"},{"content":"76dc6352"},{"content":"44d6dde1"},{"content":"9e9bbe09"},{"content":"5b895f91"},{"content":"8a72c69a"},{"content":"534a6068"},{"content":"d6960a6f"},{"content":"667be76f"},{"content":"28f6f2b5"}],"__props":"5ab0d6d5"},"/blog/tags/introduction-to-cadence-c8c":{"__comp":"6875c492","__context":{"plugin":"36994c47"},"sidebar":"814f3328","items":[{"content":"965c09ae"},{"content":"8a72c69a"},{"content":"534a6068"},{"content":"d6960a6f"},{"content":"667be76f"}],"__props":"f0ea030e"},"/blog/tags/releases-194":{"__comp":"6875c492","__context":{"plugin":"36994c47"},"sidebar":"814f3328","items":[{"content":"d70bd24b"},{"content":"cdf6e634"}],"__props":"97fa9516"},"/blog/tags/roadmap-df5":{"__comp":"6875c492","__context":{"plugin":"36994c47"},"sidebar":"814f3328","items":[{"content":"44d6dde1"},{"content":"acfca6f1"},{"content":"fda2e45a"}],"__props":"92fb1dcd"},"/blog/tags/testing-550":{"__comp":"6875c492","__context":{"plugin":"36994c47"},"sidebar":"814f3328","items":[{"content":"5b895f91"}],"__props":"82c81335"},"/blog/zonal-isolation-v1/zonal-isolation-v1-093":{"__comp":"ccc49370","__context":{"data":{"blogMetadata":"acecf23e"},"plugin":"36994c47"},"sidebar":"814f3328","content":"5cfaf3a2"},"/markdown-page-3d7":{"__comp":"1f391b9e","__context":{"plugin":"a7456010"},"content":"393be207"},"/search-5de":{"__comp":"1a4e3797","__context":{"plugin":"c141421f"}},"/community-c2a":{"__comp":"5e95c892","__context":{"plugin":"e0719818"}},"/community-41a":{"__comp":"a7bd4aaa","__props":"d2436a2b"},"/community-143":{"__comp":"a94703ab"},"/community/contributing-5ca":{"__comp":"17896441","content":"20139c40"},"/community/resources-3cf":{"__comp":"17896441","content":"3ce9624a"},"/community/support-35e":{"__comp":"17896441","content":"3e206144"},"/community/team-112":{"__comp":"17896441","content":"4c9d8eaa"},"/docs-3eb":{"__comp":"5e95c892","__context":{"plugin":"aba21aa0"}},"/docs-75e":{"__comp":"a7bd4aaa","__props":"0058b4c6"},"/docs-14f":{"__comp":"a94703ab"},"/docs/about-280":{"__comp":"17896441","content":"0b211f8a"},"/docs/about/license-75f":{"__comp":"17896441","content":"27f46eca"},"/docs/cli-c8b":{"__comp":"17896441","content":"f8f32361"},"/docs/concepts-c76":{"__comp":"17896441","content":"99c90dae"},"/docs/concepts/activities-6a3":{"__comp":"17896441","content":"b4266c8b"},"/docs/concepts/archival-71e":{"__comp":"17896441","content":"814003d2"},"/docs/concepts/cross-dc-replication-5b1":{"__comp":"17896441","content":"9674d0ef"},"/docs/concepts/events-7e7":{"__comp":"17896441","content":"3525dd13"},"/docs/concepts/http-api-3fb":{"__comp":"17896441","content":"cd7e9a8f"},"/docs/concepts/queries-9a8":{"__comp":"17896441","content":"7373c0c0"},"/docs/concepts/search-workflows-bdb":{"__comp":"17896441","content":"fde82b69"},"/docs/concepts/task-lists-805":{"__comp":"17896441","content":"2a3fd662"},"/docs/concepts/topology-3fa":{"__comp":"17896441","content":"cdada9ee"},"/docs/concepts/workflows-280":{"__comp":"17896441","content":"02fb669a"},"/docs/get-started-b10":{"__comp":"17896441","content":"cccd73f1"},"/docs/get-started/golang-hello-world-154":{"__comp":"17896441","content":"28839895"},"/docs/get-started/java-hello-world-94d":{"__comp":"17896441","content":"3408eb41"},"/docs/get-started/server-installation-223":{"__comp":"17896441","content":"7f8511d4"},"/docs/get-started/video-tutorials-bef":{"__comp":"17896441","content":"ad9e871f"},"/docs/glossary-9c6":{"__comp":"17896441","content":"aeb329ea"},"/docs/go-client-9b9":{"__comp":"17896441","content":"86c2314d"},"/docs/go-client/02.5-starting-workflows-ea1":{"__comp":"17896441","content":"3e30df86"},"/docs/go-client/activities-c4d":{"__comp":"17896441","content":"ec02fbe0"},"/docs/go-client/activity-async-completion-42b":{"__comp":"17896441","content":"bde620bf"},"/docs/go-client/child-workflows-4fd":{"__comp":"17896441","content":"f0efcb43"},"/docs/go-client/continue-as-new-2d0":{"__comp":"17896441","content":"90f276f1"},"/docs/go-client/create-workflows-5de":{"__comp":"17896441","content":"643bf5c6"},"/docs/go-client/distributed-cron-ae6":{"__comp":"17896441","content":"003b6e74"},"/docs/go-client/error-handling-d9a":{"__comp":"17896441","content":"aacb5a6b"},"/docs/go-client/execute-activity-63f":{"__comp":"17896441","content":"69a323c8"},"/docs/go-client/queries-83a":{"__comp":"17896441","content":"e8c8106b"},"/docs/go-client/retries-b66":{"__comp":"17896441","content":"2bc7f48b"},"/docs/go-client/sessions-ef2":{"__comp":"17896441","content":"c5abbc6d"},"/docs/go-client/side-effect-807":{"__comp":"17896441","content":"eb57c500"},"/docs/go-client/signals-f35":{"__comp":"17896441","content":"d280f29d"},"/docs/go-client/tracing-83a":{"__comp":"17896441","content":"0826fbec"},"/docs/go-client/workers-2e9":{"__comp":"17896441","content":"2b58a6fe"},"/docs/go-client/workflow-non-deterministic-error-08a":{"__comp":"17896441","content":"a4f1f4dd"},"/docs/go-client/workflow-replay-shadowing-398":{"__comp":"17896441","content":"95cc356a"},"/docs/go-client/workflow-testing-034":{"__comp":"17896441","content":"f81e7c5e"},"/docs/go-client/workflow-versioning-764":{"__comp":"17896441","content":"d67a7980"},"/docs/java-client-6d4":{"__comp":"17896441","content":"61aeb84e"},"/docs/java-client/activity-interface-fcd":{"__comp":"17896441","content":"d0ac2d40"},"/docs/java-client/child-workflows-187":{"__comp":"17896441","content":"6601f8a9"},"/docs/java-client/client-overview-94c":{"__comp":"17896441","content":"0ece390c"},"/docs/java-client/continue-as-new-def":{"__comp":"17896441","content":"47f0ea92"},"/docs/java-client/distributed-cron-ac5":{"__comp":"17896441","content":"77a860e9"},"/docs/java-client/exception-handling-d3e":{"__comp":"17896441","content":"4c35ffca"},"/docs/java-client/implementing-activities-871":{"__comp":"17896441","content":"a7552915"},"/docs/java-client/implementing-workflows-007":{"__comp":"17896441","content":"73759d73"},"/docs/java-client/queries-92f":{"__comp":"17896441","content":"7a568d1f"},"/docs/java-client/retries-dcf":{"__comp":"17896441","content":"67affde7"},"/docs/java-client/side-effect-f90":{"__comp":"17896441","content":"5d1ead22"},"/docs/java-client/signals-a8e":{"__comp":"17896441","content":"f2a162ea"},"/docs/java-client/starting-workflow-executions-452":{"__comp":"17896441","content":"44abbaf5"},"/docs/java-client/testing-28b":{"__comp":"17896441","content":"f5140c76"},"/docs/java-client/versioning-36a":{"__comp":"17896441","content":"05d44d04"},"/docs/java-client/workers-132":{"__comp":"17896441","content":"848b9863"},"/docs/java-client/workflow-interface-8b6":{"__comp":"17896441","content":"1685be14"},"/docs/java-client/workflow-replay-shadowing-dd8":{"__comp":"17896441","content":"95d054c5"},"/docs/operation-guide-18d":{"__comp":"17896441","content":"f997f9c8"},"/docs/operation-guide/maintain-54d":{"__comp":"17896441","content":"5450051a"},"/docs/operation-guide/migration-b5e":{"__comp":"17896441","content":"3faec549"},"/docs/operation-guide/monitoring-b13":{"__comp":"17896441","content":"6e9b4a66"},"/docs/operation-guide/setup-3a6":{"__comp":"17896441","content":"55db2bea"},"/docs/operation-guide/troubleshooting-454":{"__comp":"17896441","content":"43e9f1b6"},"/docs/use-cases-236":{"__comp":"17896441","content":"cfd61dd5"},"/docs/use-cases/batch-job-420":{"__comp":"17896441","content":"fa0e6b45"},"/docs/use-cases/big-ml-a02":{"__comp":"17896441","content":"79f715ea"},"/docs/use-cases/deployment-5a6":{"__comp":"17896441","content":"41417ef6"},"/docs/use-cases/dsl-c7f":{"__comp":"17896441","content":"a7de3fbd"},"/docs/use-cases/event-driven-bb0":{"__comp":"17896441","content":"fcdcf093"},"/docs/use-cases/interactive-d9f":{"__comp":"17896441","content":"c4da92db"},"/docs/use-cases/operational-management-ec1":{"__comp":"17896441","content":"d87fba2a"},"/docs/use-cases/orchestration-757":{"__comp":"17896441","content":"d7b037f3"},"/docs/use-cases/partitioned-scan-95e":{"__comp":"17896441","content":"7684a5b2"},"/docs/use-cases/periodic-execution-77d":{"__comp":"17896441","content":"bc79ac75"},"/docs/use-cases/polling-ca2":{"__comp":"17896441","content":"e1ea741a"},"/docs/use-cases/provisioning-922":{"__comp":"17896441","content":"5cd48241"},"/docs/workflow-troubleshooting-58e":{"__comp":"17896441","content":"8d2e039e"},"/docs/workflow-troubleshooting/activity-failures-d2f":{"__comp":"17896441","content":"7d996443"},"/docs/workflow-troubleshooting/retries-337":{"__comp":"17896441","content":"67d45d0f"},"/docs/workflow-troubleshooting/timeouts-d77":{"__comp":"17896441","content":"1dec29fa"},"/-e5f":{"__comp":"1df93b7f","__context":{"plugin":"a7456010"},"config":"5e9f5e1a"}}')}},e=>{e.O(0,[1869],(()=>{return t=8536,e(e.s=t);var t}));e.O()}]); \ No newline at end of file diff --git a/assets/js/runtime~main.4f69c908.js b/assets/js/runtime~main.4f69c908.js new file mode 100644 index 000000000..6799ccb71 --- /dev/null +++ b/assets/js/runtime~main.4f69c908.js @@ -0,0 +1 @@ +(()=>{"use strict";var e,a,f,d,c,b={},t={};function r(e){var a=t[e];if(void 0!==a)return a.exports;var f=t[e]={exports:{}};return b[e].call(f.exports,f,f.exports,r),f.exports}r.m=b,e=[],r.O=(a,f,d,c)=>{if(!f){var b=1/0;for(i=0;i<e.length;i++){f=e[i][0],d=e[i][1],c=e[i][2];for(var t=!0,o=0;o<f.length;o++)(!1&c||b>=c)&&Object.keys(r.O).every((e=>r.O[e](f[o])))?f.splice(o--,1):(t=!1,c<b&&(b=c));if(t){e.splice(i--,1);var n=d();void 0!==n&&(a=n)}}return a}c=c||0;for(var i=e.length;i>0&&e[i-1][2]>c;i--)e[i]=e[i-1];e[i]=[f,d,c]},r.n=e=>{var a=e&&e.__esModule?()=>e.default:()=>e;return r.d(a,{a:a}),a},f=Object.getPrototypeOf?e=>Object.getPrototypeOf(e):e=>e.__proto__,r.t=function(e,d){if(1&d&&(e=this(e)),8&d)return e;if("object"==typeof e&&e){if(4&d&&e.__esModule)return e;if(16&d&&"function"==typeof e.then)return e}var c=Object.create(null);r.r(c);var b={};a=a||[null,f({}),f([]),f(f)];for(var t=2&d&&e;"object"==typeof t&&!~a.indexOf(t);t=f(t))Object.getOwnPropertyNames(t).forEach((a=>b[a]=()=>e[a]));return b.default=()=>e,r.d(c,b),c},r.d=(e,a)=>{for(var f in a)r.o(a,f)&&!r.o(e,f)&&Object.defineProperty(e,f,{enumerable:!0,get:a[f]})},r.f={},r.e=e=>Promise.all(Object.keys(r.f).reduce(((a,f)=>(r.f[f](e,a),a)),[])),r.u=e=>"assets/js/"+({22:"e8c8106b",62:"0b21c5b6",104:"d87fba2a",150:"959827cd",207:"67d45d0f",245:"91c0087d",278:"4807c528",447:"27f46eca",573:"55db2bea",647:"177ff540",672:"0b5e41cc",734:"f8f32361",751:"814003d2",783:"a7de3fbd",862:"534a6068",867:"33fc5bb8",957:"c141421f",1010:"9674d0ef",1094:"88d84d8e",1118:"d70bd24b",1193:"98f77afb",1198:"278bd730",1235:"a7456010",1249:"cdada9ee",1314:"0b6b8c62",1328:"fa0e6b45",1337:"c5abbc6d",1347:"76dc6352",1485:"a3dd65a2",1507:"4d0beaf2",1653:"fda2e45a",1662:"bc79ac75",1700:"c4da92db",1759:"d33bd0ff",1816:"4b94b3ad",1839:"02fb669a",1898:"3e206144",1903:"acecf23e",1919:"1685be14",1963:"80e02aec",1973:"d8ddffe9",2010:"c74af710",2093:"23beb9a4",2138:"1a4e3797",2192:"e1ea741a",2222:"3e30df86",2235:"98f5ac88",2370:"7613fcd7",2379:"df4cf6e6",2422:"e8018edf",2450:"3ce9624a",2469:"965c09ae",2529:"3d5497b2",2559:"3faec549",2641:"61aeb84e",2709:"6abab11b",2711:"9e4087bc",2779:"7373c0c0",2813:"2a3fd662",2872:"4c35ffca",2887:"a94774ec",2937:"aeb329ea",3029:"18e1ae2c",3044:"cfd61dd5",3060:"d27d92a2",3087:"f2a162ea",3116:"4c9d8eaa",3190:"2b58a6fe",3249:"ccc49370",3252:"6e9b4a66",3314:"79f715ea",3334:"cdf6e634",3364:"73759d73",3685:"7d996443",3700:"ad4570fb",3718:"9e9bbe09",3732:"5cd48241",3774:"05d44d04",3890:"bde620bf",3992:"ad9e871f",4120:"667be76f",4134:"393be207",4144:"f0efcb43",4196:"8a72c69a",4212:"621db11d",4324:"95cc356a",4344:"5cfaf3a2",4422:"7684a5b2",4468:"2b6d3152",4471:"44d6dde1",4505:"8d2e039e",4552:"3ca3c927",4569:"31f8b8ae",4582:"c0e193ae",4583:"1df93b7f",4619:"de3708c6",4639:"d530ea3c",4669:"47f0ea92",4713:"5d1ead22",4739:"33348b0e",4790:"45f9d173",4813:"6875c492",4830:"28f6f2b5",4860:"1c90ed0c",4881:"d280f29d",4898:"dec4f520",4950:"643bf5c6",4960:"90f276f1",4962:"b4266c8b",4973:"4f20e2dc",4978:"7fda255c",4993:"08e09fce",5078:"c7e5f436",5086:"9366521c",5138:"f997f9c8",5220:"e0719818",5332:"115ec24d",5351:"f81e7c5e",5371:"0bc129c0",5385:"d7b037f3",5429:"f7be646d",5438:"ec02fbe0",5484:"acfca6f1",5538:"77a860e9",5541:"533eb95b",5552:"b69803f5",5557:"d6960a6f",5620:"aacb5a6b",5733:"d67a7980",5742:"aba21aa0",5861:"2bc7f48b",5910:"8edf5fa8",6061:"1f391b9e",6076:"4d8144ae",6156:"69a323c8",6185:"fde82b69",6267:"ef69cbb3",6269:"aac593d4",6323:"41417ef6",6401:"d0ac2d40",6758:"0b211f8a",6763:"f5140c76",6806:"33cf8314",6941:"92ce93dc",6975:"a197b989",7009:"775920c1",7098:"a7bd4aaa",7125:"d33895f8",7157:"a9771bf1",7180:"5b895f91",7207:"848b9863",7240:"3525dd13",7246:"eb57c500",7262:"86c2314d",7338:"cd7e9a8f",7472:"814f3328",7478:"647edc7e",7562:"003b6e74",7600:"528620f0",7643:"a6aa9e1f",7682:"44abbaf5",7748:"4d332630",7770:"580cfca3",7940:"a844cb54",7970:"981d14b8",7998:"6601f8a9",8035:"144c3ace",8067:"0826fbec",8125:"0ece390c",8202:"2955167d",8209:"01a85c17",8363:"7f8511d4",8372:"90ce9713",8401:"17896441",8631:"e9c26ae5",8729:"6081a96a",8770:"5f63c9de",8817:"43e9f1b6",8929:"7afb0752",9048:"a94703ab",9051:"fcdcf093",9053:"04634098",9090:"a17e1a1b",9092:"4c8ff8e7",9171:"28839895",9203:"99c90dae",9306:"5806acc5",9308:"cfb807c8",9369:"20139c40",9379:"36aefe7c",9407:"f1de825c",9433:"a82a64d4",9513:"cccd73f1",9520:"a7552915",9528:"5450051a",9533:"02de9280",9586:"95d054c5",9609:"67affde7",9612:"1dec29fa",9617:"ea1e4697",9647:"5e95c892",9699:"7a568d1f",9855:"c47f6b82",9858:"36994c47",9866:"3408eb41",9881:"849b28af",9928:"87d83cd2",9961:"a4f1f4dd"}[e]||e)+"."+{22:"e17be639",62:"91e86b39",104:"1e35568c",150:"e0792857",207:"691d25f4",245:"7488e4a4",278:"34de51fe",416:"a9ddc348",447:"bf4e8268",573:"b7e4e4a4",647:"8328b22b",672:"aebef198",734:"65347fb7",751:"7159ace6",783:"93cd659d",862:"90692c0c",867:"e3f788be",957:"1bba1b16",1010:"3364f8cb",1094:"bd47e9b5",1118:"6efb43f1",1193:"432f310b",1198:"81ac964c",1235:"6ef5456c",1249:"5251b911",1314:"47f9e873",1328:"97bcdd1c",1337:"4ee0aba8",1347:"34ab7350",1485:"dbc5d255",1507:"78a8e7a9",1653:"b7d575ef",1662:"5aaf5895",1700:"9beb5e3e",1759:"eabe4dbb",1816:"e7f89e40",1839:"2aa7c065",1898:"3079e23a",1903:"e0b0ec0e",1919:"b40f46bf",1963:"722ce13d",1973:"b0a661ee",2010:"8d0deb15",2093:"148a9a8e",2138:"f5622438",2192:"d6a99047",2222:"238a33ad",2235:"11a58769",2237:"de4ff6bc",2370:"3220b068",2379:"f027bd9e",2422:"083b7cba",2450:"01c0ada4",2469:"812cb177",2529:"d7badbc4",2559:"6ba3d7c4",2641:"b051285d",2709:"dd0f9a59",2711:"4be47135",2779:"447b3f38",2813:"e107e194",2872:"80b7cc98",2887:"3c16e9e5",2937:"89bf067d",3029:"185d36d3",3044:"c7194c80",3060:"e180642c",3087:"660341e3",3116:"4d42e69d",3190:"9ff3e12f",3249:"9f54d5f5",3252:"7fe6da2b",3314:"f22e7e3d",3334:"2e392cc2",3347:"8bcb7a91",3364:"12f54153",3685:"742a8a61",3700:"ca66dc6e",3718:"e35cf0d2",3732:"2597ea98",3774:"c5c1b724",3890:"dd0e3f78",3992:"fd2309b0",4120:"d8e51ae2",4134:"5f69cc18",4144:"c22f362b",4196:"01ff779c",4212:"9eae86f0",4324:"1d9d46a3",4344:"fdd156a0",4422:"97768783",4468:"b9f02f3e",4471:"25e7264c",4505:"b41be10f",4552:"f3b6a47f",4569:"f5c35a14",4582:"17b89c8d",4583:"f924378b",4619:"820e22e3",4639:"ad59a794",4669:"7860b482",4713:"3ddcd12b",4739:"47f64d26",4790:"9cbe9fac",4813:"6067e842",4830:"00cf4faf",4860:"4a6c3b6a",4881:"c4924f81",4898:"04aa9673",4950:"88245425",4960:"b4874ef6",4962:"211c587f",4973:"09c92d90",4978:"059ce0cc",4993:"e5e53f8b",5078:"c393799e",5086:"bbdf5568",5138:"413e3664",5220:"4a993a11",5332:"85585615",5351:"77858357",5371:"0774e3d1",5385:"40a19d54",5429:"fe7f4eab",5438:"f75756a8",5484:"1b17377c",5538:"8ac5975c",5541:"32408520",5552:"8b7d5d22",5557:"b963172c",5620:"0f31c27b",5733:"5c7df669",5742:"ec102c47",5861:"58c6c915",5910:"2282b2fb",6061:"d30b29bf",6076:"8e3b6910",6156:"52cc3671",6185:"993e17e6",6267:"6cc269cf",6269:"40f077e5",6323:"c7c3692e",6401:"a5968188",6758:"1ed54eec",6763:"0fa5d57f",6806:"5a52ce83",6941:"ea84aa43",6975:"86ac0e2d",7009:"8add127c",7098:"71775f97",7125:"558861c1",7157:"9c404020",7180:"d7024f31",7207:"5ea04886",7240:"649d5746",7246:"a7ba6131",7262:"cdd3c4f8",7338:"33b0f1d1",7472:"e2306031",7478:"7faa1898",7562:"14cbdba7",7600:"b0244194",7643:"41680036",7682:"d310d2f5",7748:"22650505",7770:"76026c4c",7940:"d01bcae6",7970:"43550098",7998:"9ea154cd",8035:"9a12438b",8067:"4c9925e7",8125:"9e4668ed",8158:"d991b10f",8202:"0094316b",8209:"938ede46",8363:"fe265c26",8372:"c578cf3b",8401:"0630e72f",8498:"095e3977",8631:"e33a84c2",8729:"7b56cf7e",8770:"9c513c71",8817:"d87d7fac",8913:"cb88832a",8929:"bdca23a0",9048:"c6ba3a70",9051:"652e25f3",9053:"b49ec1e6",9090:"5089a5b2",9092:"d567bd35",9171:"0d8c1b0d",9203:"2490f04f",9306:"f7c50722",9308:"5d3e3ac1",9369:"4fc9927f",9379:"78389325",9407:"b641c329",9433:"31f567ec",9513:"4d013750",9520:"21801cc4",9528:"2ee40998",9533:"f379b4d1",9586:"bf0bd990",9609:"a4a51df2",9612:"27d7aff3",9617:"fbfecff3",9647:"1667949b",9699:"7a793f0a",9855:"34ea6b4c",9858:"768c3aeb",9866:"96cbd93f",9881:"891b9b7f",9928:"6b71d628",9961:"7cf1027b"}[e]+".js",r.miniCssF=e=>{},r.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"==typeof window)return window}}(),r.o=(e,a)=>Object.prototype.hasOwnProperty.call(e,a),d={},c="cadence:",r.l=(e,a,f,b)=>{if(d[e])d[e].push(a);else{var t,o;if(void 0!==f)for(var n=document.getElementsByTagName("script"),i=0;i<n.length;i++){var u=n[i];if(u.getAttribute("src")==e||u.getAttribute("data-webpack")==c+f){t=u;break}}t||(o=!0,(t=document.createElement("script")).charset="utf-8",t.timeout=120,r.nc&&t.setAttribute("nonce",r.nc),t.setAttribute("data-webpack",c+f),t.src=e),d[e]=[a];var l=(a,f)=>{t.onerror=t.onload=null,clearTimeout(s);var c=d[e];if(delete d[e],t.parentNode&&t.parentNode.removeChild(t),c&&c.forEach((e=>e(f))),a)return a(f)},s=setTimeout(l.bind(null,void 0,{type:"timeout",target:t}),12e4);t.onerror=l.bind(null,t.onerror),t.onload=l.bind(null,t.onload),o&&document.head.appendChild(t)}},r.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},r.p="/Cadence-Docs/",r.gca=function(e){return e={17896441:"8401",28839895:"9171",e8c8106b:"22","0b21c5b6":"62",d87fba2a:"104","959827cd":"150","67d45d0f":"207","91c0087d":"245","4807c528":"278","27f46eca":"447","55db2bea":"573","177ff540":"647","0b5e41cc":"672",f8f32361:"734","814003d2":"751",a7de3fbd:"783","534a6068":"862","33fc5bb8":"867",c141421f:"957","9674d0ef":"1010","88d84d8e":"1094",d70bd24b:"1118","98f77afb":"1193","278bd730":"1198",a7456010:"1235",cdada9ee:"1249","0b6b8c62":"1314",fa0e6b45:"1328",c5abbc6d:"1337","76dc6352":"1347",a3dd65a2:"1485","4d0beaf2":"1507",fda2e45a:"1653",bc79ac75:"1662",c4da92db:"1700",d33bd0ff:"1759","4b94b3ad":"1816","02fb669a":"1839","3e206144":"1898",acecf23e:"1903","1685be14":"1919","80e02aec":"1963",d8ddffe9:"1973",c74af710:"2010","23beb9a4":"2093","1a4e3797":"2138",e1ea741a:"2192","3e30df86":"2222","98f5ac88":"2235","7613fcd7":"2370",df4cf6e6:"2379",e8018edf:"2422","3ce9624a":"2450","965c09ae":"2469","3d5497b2":"2529","3faec549":"2559","61aeb84e":"2641","6abab11b":"2709","9e4087bc":"2711","7373c0c0":"2779","2a3fd662":"2813","4c35ffca":"2872",a94774ec:"2887",aeb329ea:"2937","18e1ae2c":"3029",cfd61dd5:"3044",d27d92a2:"3060",f2a162ea:"3087","4c9d8eaa":"3116","2b58a6fe":"3190",ccc49370:"3249","6e9b4a66":"3252","79f715ea":"3314",cdf6e634:"3334","73759d73":"3364","7d996443":"3685",ad4570fb:"3700","9e9bbe09":"3718","5cd48241":"3732","05d44d04":"3774",bde620bf:"3890",ad9e871f:"3992","667be76f":"4120","393be207":"4134",f0efcb43:"4144","8a72c69a":"4196","621db11d":"4212","95cc356a":"4324","5cfaf3a2":"4344","7684a5b2":"4422","2b6d3152":"4468","44d6dde1":"4471","8d2e039e":"4505","3ca3c927":"4552","31f8b8ae":"4569",c0e193ae:"4582","1df93b7f":"4583",de3708c6:"4619",d530ea3c:"4639","47f0ea92":"4669","5d1ead22":"4713","33348b0e":"4739","45f9d173":"4790","6875c492":"4813","28f6f2b5":"4830","1c90ed0c":"4860",d280f29d:"4881",dec4f520:"4898","643bf5c6":"4950","90f276f1":"4960",b4266c8b:"4962","4f20e2dc":"4973","7fda255c":"4978","08e09fce":"4993",c7e5f436:"5078","9366521c":"5086",f997f9c8:"5138",e0719818:"5220","115ec24d":"5332",f81e7c5e:"5351","0bc129c0":"5371",d7b037f3:"5385",f7be646d:"5429",ec02fbe0:"5438",acfca6f1:"5484","77a860e9":"5538","533eb95b":"5541",b69803f5:"5552",d6960a6f:"5557",aacb5a6b:"5620",d67a7980:"5733",aba21aa0:"5742","2bc7f48b":"5861","8edf5fa8":"5910","1f391b9e":"6061","4d8144ae":"6076","69a323c8":"6156",fde82b69:"6185",ef69cbb3:"6267",aac593d4:"6269","41417ef6":"6323",d0ac2d40:"6401","0b211f8a":"6758",f5140c76:"6763","33cf8314":"6806","92ce93dc":"6941",a197b989:"6975","775920c1":"7009",a7bd4aaa:"7098",d33895f8:"7125",a9771bf1:"7157","5b895f91":"7180","848b9863":"7207","3525dd13":"7240",eb57c500:"7246","86c2314d":"7262",cd7e9a8f:"7338","814f3328":"7472","647edc7e":"7478","003b6e74":"7562","528620f0":"7600",a6aa9e1f:"7643","44abbaf5":"7682","4d332630":"7748","580cfca3":"7770",a844cb54:"7940","981d14b8":"7970","6601f8a9":"7998","144c3ace":"8035","0826fbec":"8067","0ece390c":"8125","2955167d":"8202","01a85c17":"8209","7f8511d4":"8363","90ce9713":"8372",e9c26ae5:"8631","6081a96a":"8729","5f63c9de":"8770","43e9f1b6":"8817","7afb0752":"8929",a94703ab:"9048",fcdcf093:"9051","04634098":"9053",a17e1a1b:"9090","4c8ff8e7":"9092","99c90dae":"9203","5806acc5":"9306",cfb807c8:"9308","20139c40":"9369","36aefe7c":"9379",f1de825c:"9407",a82a64d4:"9433",cccd73f1:"9513",a7552915:"9520","5450051a":"9528","02de9280":"9533","95d054c5":"9586","67affde7":"9609","1dec29fa":"9612",ea1e4697:"9617","5e95c892":"9647","7a568d1f":"9699",c47f6b82:"9855","36994c47":"9858","3408eb41":"9866","849b28af":"9881","87d83cd2":"9928",a4f1f4dd:"9961"}[e]||e,r.p+r.u(e)},(()=>{var e={5354:0,1869:0};r.f.j=(a,f)=>{var d=r.o(e,a)?e[a]:void 0;if(0!==d)if(d)f.push(d[2]);else if(/^(1869|5354)$/.test(a))e[a]=0;else{var c=new Promise(((f,c)=>d=e[a]=[f,c]));f.push(d[2]=c);var b=r.p+r.u(a),t=new Error;r.l(b,(f=>{if(r.o(e,a)&&(0!==(d=e[a])&&(e[a]=void 0),d)){var c=f&&("load"===f.type?"missing":f.type),b=f&&f.target&&f.target.src;t.message="Loading chunk "+a+" failed.\n("+c+": "+b+")",t.name="ChunkLoadError",t.type=c,t.request=b,d[1](t)}}),"chunk-"+a,a)}},r.O.j=a=>0===e[a];var a=(a,f)=>{var d,c,b=f[0],t=f[1],o=f[2],n=0;if(b.some((a=>0!==e[a]))){for(d in t)r.o(t,d)&&(r.m[d]=t[d]);if(o)var i=o(r)}for(a&&a(f);n<b.length;n++)c=b[n],r.o(e,c)&&e[c]&&e[c][0](),e[c]=0;return r.O(i)},f=self.webpackChunkcadence=self.webpackChunkcadence||[];f.forEach(a.bind(null,0)),f.push=a.bind(null,f.push.bind(f))})()})(); \ No newline at end of file diff --git a/assets/js/runtime~main.8d781cad.js b/assets/js/runtime~main.8d781cad.js deleted file mode 100644 index faeb7b9ee..000000000 --- a/assets/js/runtime~main.8d781cad.js +++ /dev/null @@ -1 +0,0 @@ -(()=>{"use strict";var e,a,f,c,d,b={},t={};function r(e){var a=t[e];if(void 0!==a)return a.exports;var f=t[e]={exports:{}};return b[e].call(f.exports,f,f.exports,r),f.exports}r.m=b,e=[],r.O=(a,f,c,d)=>{if(!f){var b=1/0;for(i=0;i<e.length;i++){f=e[i][0],c=e[i][1],d=e[i][2];for(var t=!0,o=0;o<f.length;o++)(!1&d||b>=d)&&Object.keys(r.O).every((e=>r.O[e](f[o])))?f.splice(o--,1):(t=!1,d<b&&(b=d));if(t){e.splice(i--,1);var n=c();void 0!==n&&(a=n)}}return a}d=d||0;for(var i=e.length;i>0&&e[i-1][2]>d;i--)e[i]=e[i-1];e[i]=[f,c,d]},r.n=e=>{var a=e&&e.__esModule?()=>e.default:()=>e;return r.d(a,{a:a}),a},f=Object.getPrototypeOf?e=>Object.getPrototypeOf(e):e=>e.__proto__,r.t=function(e,c){if(1&c&&(e=this(e)),8&c)return e;if("object"==typeof e&&e){if(4&c&&e.__esModule)return e;if(16&c&&"function"==typeof e.then)return e}var d=Object.create(null);r.r(d);var b={};a=a||[null,f({}),f([]),f(f)];for(var t=2&c&&e;"object"==typeof t&&!~a.indexOf(t);t=f(t))Object.getOwnPropertyNames(t).forEach((a=>b[a]=()=>e[a]));return b.default=()=>e,r.d(d,b),d},r.d=(e,a)=>{for(var f in a)r.o(a,f)&&!r.o(e,f)&&Object.defineProperty(e,f,{enumerable:!0,get:a[f]})},r.f={},r.e=e=>Promise.all(Object.keys(r.f).reduce(((a,f)=>(r.f[f](e,a),a)),[])),r.u=e=>"assets/js/"+({22:"e8c8106b",93:"f0ea030e",104:"d87fba2a",150:"959827cd",207:"67d45d0f",447:"27f46eca",492:"40011a75",573:"55db2bea",647:"177ff540",734:"f8f32361",751:"814003d2",783:"a7de3fbd",837:"d2436a2b",849:"0058b4c6",862:"534a6068",867:"33fc5bb8",908:"04e595f1",957:"c141421f",1010:"9674d0ef",1094:"88d84d8e",1118:"d70bd24b",1193:"98f77afb",1198:"278bd730",1235:"a7456010",1249:"cdada9ee",1328:"fa0e6b45",1337:"c5abbc6d",1347:"76dc6352",1485:"a3dd65a2",1584:"82c81335",1594:"004bd3e7",1640:"0922f36e",1643:"17896883",1653:"fda2e45a",1662:"bc79ac75",1700:"c4da92db",1759:"d33bd0ff",1816:"4b94b3ad",1839:"02fb669a",1898:"3e206144",1903:"acecf23e",1919:"1685be14",1963:"80e02aec",2138:"1a4e3797",2192:"e1ea741a",2222:"3e30df86",2235:"98f5ac88",2370:"7613fcd7",2379:"df4cf6e6",2450:"3ce9624a",2469:"965c09ae",2529:"3d5497b2",2559:"3faec549",2641:"61aeb84e",2711:"9e4087bc",2761:"93e7684d",2779:"7373c0c0",2813:"2a3fd662",2872:"4c35ffca",2887:"a94774ec",2937:"aeb329ea",3029:"18e1ae2c",3044:"cfd61dd5",3060:"d27d92a2",3087:"f2a162ea",3116:"4c9d8eaa",3190:"2b58a6fe",3249:"ccc49370",3252:"6e9b4a66",3314:"79f715ea",3333:"80db4ed1",3334:"cdf6e634",3355:"97fa9516",3364:"73759d73",3493:"f09be712",3685:"7d996443",3718:"9e9bbe09",3732:"5cd48241",3774:"05d44d04",3890:"bde620bf",3914:"9250e00d",3992:"ad9e871f",4120:"667be76f",4134:"393be207",4144:"f0efcb43",4177:"d0bf664b",4196:"8a72c69a",4212:"621db11d",4269:"18ffe98c",4324:"95cc356a",4344:"5cfaf3a2",4378:"3485e756",4422:"7684a5b2",4471:"44d6dde1",4505:"8d2e039e",4552:"3ca3c927",4569:"31f8b8ae",4583:"1df93b7f",4619:"de3708c6",4669:"47f0ea92",4713:"5d1ead22",4739:"33348b0e",4813:"6875c492",4830:"28f6f2b5",4860:"1c90ed0c",4881:"d280f29d",4898:"dec4f520",4950:"643bf5c6",4960:"90f276f1",4962:"b4266c8b",4978:"7fda255c",5086:"9366521c",5138:"f997f9c8",5220:"e0719818",5332:"115ec24d",5349:"a3886376",5351:"f81e7c5e",5371:"0bc129c0",5385:"d7b037f3",5429:"f7be646d",5438:"ec02fbe0",5484:"acfca6f1",5538:"77a860e9",5552:"b69803f5",5557:"d6960a6f",5620:"aacb5a6b",5733:"d67a7980",5742:"aba21aa0",5861:"2bc7f48b",5910:"8edf5fa8",6061:"1f391b9e",6156:"69a323c8",6185:"fde82b69",6267:"ef69cbb3",6269:"aac593d4",6323:"41417ef6",6401:"d0ac2d40",6758:"0b211f8a",6763:"f5140c76",6806:"33cf8314",6941:"92ce93dc",6975:"a197b989",7009:"775920c1",7098:"a7bd4aaa",7125:"d33895f8",7180:"5b895f91",7207:"848b9863",7240:"3525dd13",7246:"eb57c500",7262:"86c2314d",7338:"cd7e9a8f",7472:"814f3328",7478:"647edc7e",7562:"003b6e74",7600:"528620f0",7643:"a6aa9e1f",7682:"44abbaf5",7748:"4d332630",7770:"580cfca3",7970:"981d14b8",7998:"6601f8a9",8035:"144c3ace",8067:"0826fbec",8121:"3a2db09e",8125:"0ece390c",8130:"f81c1134",8146:"c15d9823",8202:"2955167d",8209:"01a85c17",8330:"aa55d0af",8363:"7f8511d4",8396:"0cfc60d3",8401:"17896441",8631:"e9c26ae5",8729:"6081a96a",8770:"5f63c9de",8817:"43e9f1b6",8848:"5ab0d6d5",8929:"7afb0752",8941:"741d205a",8947:"ef8b811a",9048:"a94703ab",9051:"fcdcf093",9171:"28839895",9203:"99c90dae",9306:"5806acc5",9308:"cfb807c8",9369:"20139c40",9379:"36aefe7c",9385:"8ea09047",9387:"a48fa53f",9407:"f1de825c",9513:"cccd73f1",9520:"a7552915",9528:"5450051a",9552:"92fb1dcd",9586:"95d054c5",9609:"67affde7",9612:"1dec29fa",9617:"ea1e4697",9647:"5e95c892",9699:"7a568d1f",9855:"c47f6b82",9858:"36994c47",9866:"3408eb41",9881:"849b28af",9928:"87d83cd2",9961:"a4f1f4dd"}[e]||e)+"."+{22:"8bfef7ff",93:"101cbb3e",104:"94f01d21",150:"19116a70",207:"18a33aeb",416:"a9ddc348",447:"4d1ff655",492:"43cf0444",573:"ee4deac8",647:"a2742758",734:"60809238",751:"6882937e",783:"67fdf090",837:"d6e0255e",849:"a81002c0",862:"76f8e63d",867:"e3f788be",908:"dc6f2f6f",957:"1bba1b16",1010:"b89b74bb",1094:"c9d7ea2f",1118:"a9e49c4b",1193:"c48f878c",1198:"87fa8dfd",1235:"6ef5456c",1249:"d2a78d8f",1328:"273bd646",1337:"d0022e8b",1347:"3a33489d",1485:"584bd5fb",1584:"1a93aeed",1594:"cbcda52b",1640:"e8603763",1643:"680e0e06",1653:"d2d91c08",1662:"31de2fc6",1700:"1142d0ee",1759:"0202e01a",1816:"7b3691f7",1839:"1b3e222c",1898:"9c7dec07",1903:"bc51da36",1919:"a35fd5cd",1963:"21eee472",2138:"f5622438",2192:"8d1c0417",2222:"88ff1f58",2235:"916513ba",2237:"de4ff6bc",2370:"f715150c",2379:"aff7098c",2450:"0e422100",2469:"fcd4d823",2529:"d5b73ab5",2559:"b14e7ae2",2641:"3ad98202",2711:"4be47135",2761:"7f67dd89",2779:"08dfd38a",2813:"b43041cb",2872:"12f32ac3",2887:"0bbe74fe",2937:"4aaeade0",3029:"3dde30da",3044:"65104469",3060:"fa23e5d9",3087:"03af1bea",3116:"771c094c",3190:"b463a0c8",3249:"9f54d5f5",3252:"f413300e",3314:"4cc73919",3333:"0a1913d6",3334:"4c655d2a",3347:"8bcb7a91",3355:"32206c7c",3364:"b9fedb09",3493:"35008691",3685:"a20315dc",3718:"0d260b5d",3732:"fe1e1a66",3774:"8787bf98",3890:"e3193c79",3914:"63ecac5c",3992:"a7318599",4120:"d1cad4dd",4134:"825f5c39",4144:"b5ca7984",4177:"3a3af1d5",4196:"5d2091f8",4212:"9eae86f0",4269:"de26ef7e",4324:"e8082267",4344:"c31bbd79",4378:"a92df76b",4422:"2684a972",4471:"691185e4",4505:"e6f31b8f",4552:"02badfed",4569:"06ee186c",4583:"f924378b",4619:"8c0038c5",4669:"d05b70b3",4713:"d4f49fa9",4739:"cd91b4b1",4813:"6067e842",4830:"92a656e2",4860:"09b814ea",4881:"cd209164",4898:"fa5af0ec",4950:"15ecbcc3",4960:"c6c8d5d7",4962:"393e8d17",4978:"046cc7e7",5086:"8dd92d41",5138:"18a43177",5220:"4a993a11",5332:"8b154ac8",5349:"0badbb19",5351:"a97005a8",5371:"1751af83",5385:"38bce024",5429:"39465925",5438:"d779414d",5484:"a19c40ea",5538:"19b7d9f8",5552:"d3ed1ab6",5557:"38d08e72",5620:"a80f14bb",5733:"6f8efc72",5742:"ec102c47",5861:"d670efc8",5910:"c9891f16",6061:"d30b29bf",6156:"e094494d",6185:"e4eeae89",6267:"d4ae49c6",6269:"d9eac105",6323:"6e42ecef",6401:"6e91bc5b",6758:"66a27957",6763:"d0a614cd",6806:"2949d817",6941:"6cd896be",6975:"5019c634",7009:"e89602fb",7098:"71775f97",7125:"aa403fb7",7180:"2cb025b2",7207:"5c957d7e",7240:"1d38f764",7246:"225e3359",7262:"8b8de600",7338:"e870c77c",7472:"721bb31b",7478:"53f565b0",7562:"814290f3",7600:"cde2c83a",7643:"41680036",7682:"e200fa03",7748:"09e4bd50",7770:"2bebdbfb",7970:"592b7d62",7998:"cf53fd6a",8035:"60296059",8067:"637d09dd",8121:"3787f744",8125:"89ee49b3",8130:"3f16e91e",8146:"22d444d3",8158:"d991b10f",8202:"7691892b",8209:"938ede46",8330:"34532fcb",8363:"df3eb1df",8396:"8c2ddb40",8401:"0630e72f",8498:"b45384a3",8631:"68917989",8729:"fa1eb8e0",8770:"e66461de",8817:"9d9f2509",8848:"63711599",8913:"cb88832a",8929:"eb7eb3f1",8941:"c828b574",8947:"34f08480",9048:"c6ba3a70",9051:"5cc5644d",9171:"be9e60a7",9203:"e8bf1305",9306:"05ca9dd1",9308:"ef4959bc",9369:"44ed83b8",9379:"6501ae5a",9385:"84ab407b",9387:"c7dd8c5d",9407:"301e9aa7",9513:"d85dafd4",9520:"b96a4321",9528:"fbb1dd55",9552:"e1ea9f65",9586:"9d8d05cd",9609:"ca974799",9612:"c54d4098",9617:"dc7eff37",9647:"1667949b",9699:"7f4e451b",9855:"215fc5e7",9858:"768c3aeb",9866:"efbfc908",9881:"21ef411d",9928:"b8386a4e",9961:"c8373370"}[e]+".js",r.miniCssF=e=>{},r.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"==typeof window)return window}}(),r.o=(e,a)=>Object.prototype.hasOwnProperty.call(e,a),c={},d="cadence:",r.l=(e,a,f,b)=>{if(c[e])c[e].push(a);else{var t,o;if(void 0!==f)for(var n=document.getElementsByTagName("script"),i=0;i<n.length;i++){var u=n[i];if(u.getAttribute("src")==e||u.getAttribute("data-webpack")==d+f){t=u;break}}t||(o=!0,(t=document.createElement("script")).charset="utf-8",t.timeout=120,r.nc&&t.setAttribute("nonce",r.nc),t.setAttribute("data-webpack",d+f),t.src=e),c[e]=[a];var l=(a,f)=>{t.onerror=t.onload=null,clearTimeout(s);var d=c[e];if(delete c[e],t.parentNode&&t.parentNode.removeChild(t),d&&d.forEach((e=>e(f))),a)return a(f)},s=setTimeout(l.bind(null,void 0,{type:"timeout",target:t}),12e4);t.onerror=l.bind(null,t.onerror),t.onload=l.bind(null,t.onload),o&&document.head.appendChild(t)}},r.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},r.p="/",r.gca=function(e){return e={17896441:"8401",17896883:"1643",28839895:"9171",e8c8106b:"22",f0ea030e:"93",d87fba2a:"104","959827cd":"150","67d45d0f":"207","27f46eca":"447","40011a75":"492","55db2bea":"573","177ff540":"647",f8f32361:"734","814003d2":"751",a7de3fbd:"783",d2436a2b:"837","0058b4c6":"849","534a6068":"862","33fc5bb8":"867","04e595f1":"908",c141421f:"957","9674d0ef":"1010","88d84d8e":"1094",d70bd24b:"1118","98f77afb":"1193","278bd730":"1198",a7456010:"1235",cdada9ee:"1249",fa0e6b45:"1328",c5abbc6d:"1337","76dc6352":"1347",a3dd65a2:"1485","82c81335":"1584","004bd3e7":"1594","0922f36e":"1640",fda2e45a:"1653",bc79ac75:"1662",c4da92db:"1700",d33bd0ff:"1759","4b94b3ad":"1816","02fb669a":"1839","3e206144":"1898",acecf23e:"1903","1685be14":"1919","80e02aec":"1963","1a4e3797":"2138",e1ea741a:"2192","3e30df86":"2222","98f5ac88":"2235","7613fcd7":"2370",df4cf6e6:"2379","3ce9624a":"2450","965c09ae":"2469","3d5497b2":"2529","3faec549":"2559","61aeb84e":"2641","9e4087bc":"2711","93e7684d":"2761","7373c0c0":"2779","2a3fd662":"2813","4c35ffca":"2872",a94774ec:"2887",aeb329ea:"2937","18e1ae2c":"3029",cfd61dd5:"3044",d27d92a2:"3060",f2a162ea:"3087","4c9d8eaa":"3116","2b58a6fe":"3190",ccc49370:"3249","6e9b4a66":"3252","79f715ea":"3314","80db4ed1":"3333",cdf6e634:"3334","97fa9516":"3355","73759d73":"3364",f09be712:"3493","7d996443":"3685","9e9bbe09":"3718","5cd48241":"3732","05d44d04":"3774",bde620bf:"3890","9250e00d":"3914",ad9e871f:"3992","667be76f":"4120","393be207":"4134",f0efcb43:"4144",d0bf664b:"4177","8a72c69a":"4196","621db11d":"4212","18ffe98c":"4269","95cc356a":"4324","5cfaf3a2":"4344","3485e756":"4378","7684a5b2":"4422","44d6dde1":"4471","8d2e039e":"4505","3ca3c927":"4552","31f8b8ae":"4569","1df93b7f":"4583",de3708c6:"4619","47f0ea92":"4669","5d1ead22":"4713","33348b0e":"4739","6875c492":"4813","28f6f2b5":"4830","1c90ed0c":"4860",d280f29d:"4881",dec4f520:"4898","643bf5c6":"4950","90f276f1":"4960",b4266c8b:"4962","7fda255c":"4978","9366521c":"5086",f997f9c8:"5138",e0719818:"5220","115ec24d":"5332",a3886376:"5349",f81e7c5e:"5351","0bc129c0":"5371",d7b037f3:"5385",f7be646d:"5429",ec02fbe0:"5438",acfca6f1:"5484","77a860e9":"5538",b69803f5:"5552",d6960a6f:"5557",aacb5a6b:"5620",d67a7980:"5733",aba21aa0:"5742","2bc7f48b":"5861","8edf5fa8":"5910","1f391b9e":"6061","69a323c8":"6156",fde82b69:"6185",ef69cbb3:"6267",aac593d4:"6269","41417ef6":"6323",d0ac2d40:"6401","0b211f8a":"6758",f5140c76:"6763","33cf8314":"6806","92ce93dc":"6941",a197b989:"6975","775920c1":"7009",a7bd4aaa:"7098",d33895f8:"7125","5b895f91":"7180","848b9863":"7207","3525dd13":"7240",eb57c500:"7246","86c2314d":"7262",cd7e9a8f:"7338","814f3328":"7472","647edc7e":"7478","003b6e74":"7562","528620f0":"7600",a6aa9e1f:"7643","44abbaf5":"7682","4d332630":"7748","580cfca3":"7770","981d14b8":"7970","6601f8a9":"7998","144c3ace":"8035","0826fbec":"8067","3a2db09e":"8121","0ece390c":"8125",f81c1134:"8130",c15d9823:"8146","2955167d":"8202","01a85c17":"8209",aa55d0af:"8330","7f8511d4":"8363","0cfc60d3":"8396",e9c26ae5:"8631","6081a96a":"8729","5f63c9de":"8770","43e9f1b6":"8817","5ab0d6d5":"8848","7afb0752":"8929","741d205a":"8941",ef8b811a:"8947",a94703ab:"9048",fcdcf093:"9051","99c90dae":"9203","5806acc5":"9306",cfb807c8:"9308","20139c40":"9369","36aefe7c":"9379","8ea09047":"9385",a48fa53f:"9387",f1de825c:"9407",cccd73f1:"9513",a7552915:"9520","5450051a":"9528","92fb1dcd":"9552","95d054c5":"9586","67affde7":"9609","1dec29fa":"9612",ea1e4697:"9617","5e95c892":"9647","7a568d1f":"9699",c47f6b82:"9855","36994c47":"9858","3408eb41":"9866","849b28af":"9881","87d83cd2":"9928",a4f1f4dd:"9961"}[e]||e,r.p+r.u(e)},(()=>{var e={5354:0,1869:0};r.f.j=(a,f)=>{var c=r.o(e,a)?e[a]:void 0;if(0!==c)if(c)f.push(c[2]);else if(/^(1869|5354)$/.test(a))e[a]=0;else{var d=new Promise(((f,d)=>c=e[a]=[f,d]));f.push(c[2]=d);var b=r.p+r.u(a),t=new Error;r.l(b,(f=>{if(r.o(e,a)&&(0!==(c=e[a])&&(e[a]=void 0),c)){var d=f&&("load"===f.type?"missing":f.type),b=f&&f.target&&f.target.src;t.message="Loading chunk "+a+" failed.\n("+d+": "+b+")",t.name="ChunkLoadError",t.type=d,t.request=b,c[1](t)}}),"chunk-"+a,a)}},r.O.j=a=>0===e[a];var a=(a,f)=>{var c,d,b=f[0],t=f[1],o=f[2],n=0;if(b.some((a=>0!==e[a]))){for(c in t)r.o(t,c)&&(r.m[c]=t[c]);if(o)var i=o(r)}for(a&&a(f);n<b.length;n++)d=b[n],r.o(e,d)&&e[d]&&e[d][0](),e[d]=0;return r.O(i)},f=self.webpackChunkcadence=self.webpackChunkcadence||[];f.forEach(a.bind(null,0)),f.push=a.bind(null,f.push.bind(f))})()})(); \ No newline at end of file diff --git a/blog.html b/blog.html index f48963673..c4c8125e3 100644 --- a/blog.html +++ b/blog.html @@ -3,8 +3,8 @@ <head> <meta charset="UTF-8"> <meta name="generator" content="Docusaurus v3.6.3"> -<title data-rh="true">Cadence Blog | Cadence - +Cadence Blog | Cadence + @@ -15,20 +15,20 @@ - - - + + + -

Cadence Repositories Have Moved!

· One min read
Josué Alexander Ibarra
Developer Advocate @ Uber

We’re excited to announce that all Cadence GitHub repositories have been consolidated under the cadence-workflow organization! 🎉

+

Cadence Repositories Have Moved!

· One min read
Josué Alexander Ibarra
Developer Advocate @ Uber

We’re excited to announce that all Cadence GitHub repositories have been consolidated under the cadence-workflow organization! 🎉

Previously, Cadence repositories were distributed across multiple organizations at Uber: uber, uber-go, uber-common. To improve developer cohesiveness and simplify access, the Cadence Core team has migrated all open-source repositories to the cadence-workflow organization.

For example, our main repository has moved from:

👉 uber/cadence

To its new home:

👉 cadence-workflow/cadence

-

You can find the full list of Cadence repositories here 👉 orgs/cadence-workflow/repositories

Zonal Isolation for Cadence Workflows

· 8 min read
Zijian Chen
Software Engineer @ Uber

At Uber, we want to achieve regional resilience such that losing a zone within a region can be tolerated without requiring a cross-region failover. We also want to make sure that losing a zone only affects a subset of workload, at most, rather than everything. However, in Cadence-based systems, the workload in a region is distributed randomly across all workers in the region at a “task-level granularity”, which means a workflow may be worked on by any worker in the region where the domain is active. To achieve this goal, we introduced Zonal Isolation for Cadence Workflows - a feature designed to pin workflows to the zone they are started in, so that zonal isolation can be achieved at a workflow-level.

+

You can find the full list of Cadence repositories here 👉 orgs/cadence-workflow/repositories

Zonal Isolation for Cadence Workflows

· 8 min read
Zijian Chen
Software Engineer @ Uber

At Uber, we want to achieve regional resilience such that losing a zone within a region can be tolerated without requiring a cross-region failover. We also want to make sure that losing a zone only affects a subset of workload, at most, rather than everything. However, in Cadence-based systems, the workload in a region is distributed randomly across all workers in the region at a “task-level granularity”, which means a workflow may be worked on by any worker in the region where the domain is active. To achieve this goal, we introduced Zonal Isolation for Cadence Workflows - a feature designed to pin workflows to the zone they are started in, so that zonal isolation can be achieved at a workflow-level.

What is Zonal Isolation for Cadence Workflows?

At high-level, Zonal Isolation for Cadence Workflows can be thought in 2 levels:

    @@ -36,15 +36,15 @@

Announcement: Cadence Helm Charts v0 Release

· 3 min read
Taylan Isikdemir
Sr. Staff Software Engineer @ Uber

We’ve heard your feedback: deploying Cadence has been a challenge, especially with limited documentation on operational aspects. So far, we’ve only provided a few docker compose files to help you get started on a development machine. However, deploying and managing Cadence at scale requires a deep understanding of underlying services, configurations and their dependencies.

-

To address these challenges, we’re launching several initiatives to make it easier to deploy and operate Cadence clusters. These include deployment specs for common scenarios, monitoring dashboards, alerts, runbooks, and more comprehensive documentation.

Minimizing blast radius in Cadence: Introducing Workflow ID-based Rate Limits

· 7 min read
Jakob Haahr Taankvist
Software Engineer II @ Uber

At Uber, we run several big multitenant Cadence clusters with hundreds of domains in each. The clusters being multi-tenant means potential noisy neighbor effects between domains.

+

As a result, the focus remains on achieving task-level zonal isolation outside the Cadence server, which offers a more practical and immediate way to improve system resilience. It provides the capability of ensuring that an unhealthy zone (i.e. bad deployment of workers) only affect a subset of workflows (started from a certain zone) rather than every workflow in a Cadence domain.

Announcement: Cadence Helm Charts v0 Release

· 3 min read
Taylan Isikdemir
Sr. Staff Software Engineer @ Uber

We’ve heard your feedback: deploying Cadence has been a challenge, especially with limited documentation on operational aspects. So far, we’ve only provided a few docker compose files to help you get started on a development machine. However, deploying and managing Cadence at scale requires a deep understanding of underlying services, configurations and their dependencies.

+

To address these challenges, we’re launching several initiatives to make it easier to deploy and operate Cadence clusters. These include deployment specs for common scenarios, monitoring dashboards, alerts, runbooks, and more comprehensive documentation.

Minimizing blast radius in Cadence: Introducing Workflow ID-based Rate Limits

· 7 min read
Jakob Haahr Taankvist
Software Engineer II @ Uber

At Uber, we run several big multitenant Cadence clusters with hundreds of domains in each. The clusters being multi-tenant means potential noisy neighbor effects between domains.

An essential aspect of avoiding this is managing how workflows interact with our infrastructure to prevent any single workflow from causing instability for the whole cluster. To this end, we are excited to introduce Workflow ID-based rate limits — a new feature designed to protect our clusters from problematic workflows and ensure stability across the board.

Why Workflow ID-based Rate Limits?

We already have rate limits for how many requests can be sent to a domain. However, since Cadence is sharded on the workflow ID, a user-provided input, an overused workflow with a particular id might overwhelm a shard by making too many requests. There are two main ways this happens:

  1. A user starts, or signals the same workflow ID too aggressively,
  2. A workflow starts too many activities over a short period of time (e.g. thousands of activities in seconds).
  3. -

2024 Cadence Yearly Roadmap Update

· 17 min read
Ender Demirkaya
Senior Manager at Uber, Cadence. Author of the Software Engineering Handbook

Introduction

If you haven’t heard about Cadence, this section is for you. In a short description, Cadence is a code-driven workflow orchestration engine. The definition itself may not tell enough, so it would help splitting it into three parts:

  • What’s a workflow? (everyone has a different definition)
  • @@ -52,8 +52,8 @@

    What is a Workflow?

    -

    workflow.png

    -

    In the simplest definition, it is “a multi-step execution”. Step here represents individual operations that are a little heavier than small in-process function calls. Although they are not limited to those: it could be a separate service call, processing a large dataset, map-reduce, thread sleep, scheduling next run, waiting for an external input, starting a sub workflow etc. It’s anything a user thinks as a single unit of logic in their code. Those steps often have dependencies among themselves. Some steps, including the very first step, might require external triggers (e.g. button click) or schedules. In the more broader meaning, any multi-step function or service is a workflow in principle.

Cadence non-derministic errors common question Q&A (part 1)

· 3 min read
Chris Qin
Applications Developer @ Uber

If I change code logic inside an Cadence activity (for example, my activity is calling database A but now I want it to call database B), will it trigger an non-deterministic error?

+

workflow.png

+

In the simplest definition, it is “a multi-step execution”. Step here represents individual operations that are a little heavier than small in-process function calls. Although they are not limited to those: it could be a separate service call, processing a large dataset, map-reduce, thread sleep, scheduling next run, waiting for an external input, starting a sub workflow etc. It’s anything a user thinks as a single unit of logic in their code. Those steps often have dependencies among themselves. Some steps, including the very first step, might require external triggers (e.g. button click) or schedules. In the more broader meaning, any multi-step function or service is a workflow in principle.

Cadence non-derministic errors common question Q&A (part 1)

· 3 min read
Chris Qin
Applications Developer @ Uber

If I change code logic inside an Cadence activity (for example, my activity is calling database A but now I want it to call database B), will it trigger an non-deterministic error?

NO. This change will not trigger non-deterministic error.

An Activity is the smallest unit of execution for Cadence and what happens inside activities are not recorded as historical events and therefore will not be replayed. In short, this change is deterministic and it is fine to modify logic inside activities.

Does changing the workflow definition trigger non-determinstic errors?

@@ -72,9 +72,9 @@

Cadence Community Spotlight Update - August 2023

· 3 min read
Sharan Foga
Director of Operations & Customer Success @ Encube Technologies

Welcome to the latest of our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!

Please see below for a roundup of the highlights:

More Cadence How To's

You might have noticed that we have had a few more contributions to our blog from Chris Qin. Chris has been busy sharing insights, and tips on a few important Cadence topics. The objective is to help the community with any potential problems.

@@ -89,12 +89,12 @@

More Ca

Even if you have not encountered these use cases - it is good to be prepared and have a solution ready.Please take a look and let us have your feedback.

Chris is also going to take a look at the Cadence Samples to make sure they are all working and if not - he's going to re-write them so that they do!

-

Thanks very much Chris for all the work you are doing to help improve the project!

Non-deterministic errors, replayers and shadowers

· 3 min read
Chris Qin
Applications Developer @ Uber

It is conceivable that developers constantly update their Cadence workflow code based upon new business use cases and needs. However, the definition of a Cadence workflow must be deterministic because behind the scenes cadence uses event sourcing to construct the workflow state by replaying the historical events stored for this specific workflow. Introducing components that are not compatible with an existing running workflow will yield to non-deterministic errors and sometimes developers find it tricky to debug. Consider the following workflow that executes two activities.

-
func SampleWorkflow(ctx workflow.Context, data string) (string, error) {
ao := workflow.ActivityOptions{
ScheduleToStartTimeout: time.Minute,
StartToCloseTimeout: time.Minute,
}
ctx = workflow.WithActivityOptions(ctx, ao)
var result1 string
err := workflow.ExecuteActivity(ctx, ActivityA, data).Get(ctx, &result1)
if err != nil {
return "", err
}
var result2 string
err = workflow.ExecuteActivity(ctx, ActivityB, result1).Get(ctx, &result2)
return result2, err
}

Cadence Community Spotlight Update - July 2023

· 3 min read
Sharan Foga
Director of Operations & Customer Success @ Encube Technologies

Welcome to the latest of our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!

+
func SampleWorkflow(ctx workflow.Context, data string) (string, error) {
ao := workflow.ActivityOptions{
ScheduleToStartTimeout: time.Minute,
StartToCloseTimeout: time.Minute,
}
ctx = workflow.WithActivityOptions(ctx, ao)
var result1 string
err := workflow.ExecuteActivity(ctx, ActivityA, data).Get(ctx, &result1)
if err != nil {
return "", err
}
var result2 string
err = workflow.ExecuteActivity(ctx, ActivityB, result1).Get(ctx, &result2)
return result2, err
}

Cadence Community Spotlight Update - July 2023

· 3 min read
Sharan Foga
Director of Operations & Customer Success @ Encube Technologies

Welcome to the latest of our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!

Please see below for a roundup of the highlights:

Getting Started with Cadence

Are you new to Cadence and want to understand the basic concepts and architecture? Well we have some great information for you!

@@ -102,6 +102,6 @@

Thanks Chris for sharing your knowledge and helping others to get started.

Cadence Go Client v1.0 Released

This month saw the release of v1.0 of the Cadence Go Client. Note that the work done on this release was as a result of community feedback asking for it - so we are listening and responding to community needs.

-

Thanks very much to everyone who worked hard to get this release out!

+

Thanks very much to everyone who worked hard to get this release out!

\ No newline at end of file diff --git a/blog.html.html b/blog.html.html index 2768d0f14..ee28b6e2c 100644 --- a/blog.html.html +++ b/blog.html.html @@ -2,10 +2,10 @@ - - + + \ No newline at end of file diff --git a/blog/2021/09/30/long-term-commitment-and-support-for-the-cadence-project-and-its-community.html b/blog/2021/09/30/long-term-commitment-and-support-for-the-cadence-project-and-its-community.html index 69614bf00..4c0d46e79 100644 --- a/blog/2021/09/30/long-term-commitment-and-support-for-the-cadence-project-and-its-community.html +++ b/blog/2021/09/30/long-term-commitment-and-support-for-the-cadence-project-and-its-community.html @@ -3,8 +3,8 @@ -Long-term commitment and support for the Cadence project, and its community | Cadence - +Long-term commitment and support for the Cadence project, and its community | Cadence + @@ -15,20 +15,20 @@ - - - + + + -

Long-term commitment and support for the Cadence project, and its community

· 3 min read
Liang Mei
Engineering Manager @ Uber

Dear valued Cadence users and developers,

+

Long-term commitment and support for the Cadence project, and its community

· 3 min read
Liang Mei
Engineering Manager @ Uber

Dear valued Cadence users and developers,

Some of you might have read Temporal’s recent announcement about their decision to drop the support for the Cadence project. This message caused some confusion in the community, so we would like to take this opportunity to clear things out.

First of all, Uber is committed to the long-term success of the Cadence project. Since its inception 5 years ago, use cases built on Cadence and their scale have grown significantly at Uber. Today, Cadence powers a variety of our most business-critical use cases (some public stories are available here and here). At the same time, the Cadence development team at Uber has enjoyed rapid growth with the product and has been driving innovations of workflow technology across the board, from new features (e.g. graceful failover, workflow shadowing, UI improvements) to better engineering foundations (e.g. gRPC support, multi-tenancy support), all in a backwards compatible manner. Neither Uber’s use nor support of Cadence is going to change with Temporal’s announcement. We have a long list of features and exciting roadmaps ahead of us, and we will share more details in our next meetup in November ‘21. As always we will continue to push the boundaries of scale and reliability as our usage within Uber grows.

Secondly, we are committed to maintaining and growing a healthy and collaborative community. Cadence continues to attract attention as a popular open source platform, with more than 100 contributors to our project, and more than 1500 developers in our open source Slack support channel. The Uber Cadence team, along with our open source partners like Long from Indeed, have been behind the management and support of the Cadence open source community for the past 2 years. Moving forward, we are going to work even more closely with our community, through a series of online and offline channels including meetups, office hours, tech deep dives, and design consultations. We would also like to scale the way we operate, by creating a Cadence OSS Committee that allows us to maintain a closer relationship with its members, so that we can learn from each other's Cadence experiences and grow together. Please definitely let us know your suggestions on the type of engagements that you would like to see with the core team.

About Temporal and its “EOL announcement”

Temporal is a startup that was started 2 years ago based on a Cadence fork by some of the original Cadence team members. We are always grateful for their original contribution to the Cadence project and wish them the best of luck in their future endeavours. That said the announcement from Temporal only means that their team will focus on Temporal (which has always been the case for the last 2 years), and not an official stance on Cadence since they have not been involved with the project for quite some time now.

Feel free to reach out to us (cadence-oss@googlegroups.com or slack) if you have any questions. And we look forward to your contribution and collaboration.

-

The Uber Cadence team

+

The Uber Cadence team

\ No newline at end of file diff --git a/blog/2021/09/30/long-term-commitment-and-support-for-the-cadence-project-and-its-community.html.html b/blog/2021/09/30/long-term-commitment-and-support-for-the-cadence-project-and-its-community.html.html index 96dc50159..e8b98add0 100644 --- a/blog/2021/09/30/long-term-commitment-and-support-for-the-cadence-project-and-its-community.html.html +++ b/blog/2021/09/30/long-term-commitment-and-support-for-the-cadence-project-and-its-community.html.html @@ -2,10 +2,10 @@ - - + + \ No newline at end of file diff --git a/blog/2021/10/13/announcing-cadence-oss-office-hours-and-community-sync-up.html b/blog/2021/10/13/announcing-cadence-oss-office-hours-and-community-sync-up.html index d4a819b53..4a3107899 100644 --- a/blog/2021/10/13/announcing-cadence-oss-office-hours-and-community-sync-up.html +++ b/blog/2021/10/13/announcing-cadence-oss-office-hours-and-community-sync-up.html @@ -3,8 +3,8 @@ -Announcing Cadence OSS office hours and community sync up | Cadence - +Announcing Cadence OSS office hours and community sync up | Cadence + @@ -15,20 +15,20 @@ - - - + + + -

Announcing Cadence OSS office hours and community sync up

· 2 min read
Liang Mei
Engineering Manager @ Uber

Are you a current Cadence user, do you operate Cadence services, or are you interested in learning about workflow technologies and wonder what problems Cadence could solve for you? We would like to talk to you!

+

Announcing Cadence OSS office hours and community sync up

· 2 min read
Liang Mei
Engineering Manager @ Uber

Are you a current Cadence user, do you operate Cadence services, or are you interested in learning about workflow technologies and wonder what problems Cadence could solve for you? We would like to talk to you!

Our team has spent a significant amount of time working with users and partner teams at Uber to design, scale and operate their workflows. This helps our users understand the technology better, smooth their learning curve and ramp up experience, and at the same time allows us to get fast and direct feedback so we can improve the developer experience and close feature gaps. As our product and community grows, we would like to expand this practice to our users in the OSS community. For the first time ever, members of the Cadence team along with core contributors from the community will host bi-weekly office hours to answer any questions you have about Cadence, or workflow technology in general. We can also dedicate future sessions to specific topics that have a common interest. Please don’t hesitate to let us know your thoughts.

Please join a session if you would like to talk about any of the following topics:

  1. Understand what Cadence is and why it might be useful for you and your company
  2. Guidance about running Cadence services and workers in production
  3. Workflow design and operation consultation
  4. Product update, future roadmaps as well as collaboration opportunities

Building and maintaining a healthy and growing community is the key to the success of Cadence, and one of the top priorities for our team. We would like to use the office hours as an opportunity to understand and help our customers, seek feedback, and forge partnerships. We look forward to seeing you in one of the meetings.

Upcoming Office Hours

As we have a geo-distributed userbase, we are still trying to figure out a time that works for most of the people. In the meanwhile, we will manually schedule the first few instances of the meeting until we settle on a fixed schedule. Our next office hours will take place on Thursday, October 21 2pm-3pm PT/5pm-6pm EST/9pm-10pm GMT. Please join via this zoom link.

-

The Uber Cadence team

+

The Uber Cadence team

\ No newline at end of file diff --git a/blog/2021/10/13/announcing-cadence-oss-office-hours-and-community-sync-up.html.html b/blog/2021/10/13/announcing-cadence-oss-office-hours-and-community-sync-up.html.html index 6b52d5f16..60ea75dd5 100644 --- a/blog/2021/10/13/announcing-cadence-oss-office-hours-and-community-sync-up.html.html +++ b/blog/2021/10/13/announcing-cadence-oss-office-hours-and-community-sync-up.html.html @@ -2,10 +2,10 @@ - - + + \ No newline at end of file diff --git a/blog/2021/10/19/2021-10-19-moving-to-grpc/moving-to-grpc.html b/blog/2021/10/19/2021-10-19-moving-to-grpc/moving-to-grpc.html index 0b4a15d13..2ef49a85a 100644 --- a/blog/2021/10/19/2021-10-19-moving-to-grpc/moving-to-grpc.html +++ b/blog/2021/10/19/2021-10-19-moving-to-grpc/moving-to-grpc.html @@ -3,8 +3,8 @@ -Moving to gRPC | Cadence - +Moving to gRPC | Cadence + @@ -15,14 +15,14 @@ - - - + + + -

Moving to gRPC

· 5 min read
Vytautas Karpavicius
Software Engineer @ Uber

Background

+

Moving to gRPC

· 5 min read
Vytautas Karpavicius
Software Engineer @ Uber

Background

Cadence historically has been using TChannel transport with Thrift encoding for both internal RPC calls and communication with client SDKs. gRPC is becoming a de-facto industry standard with much better adoption and community support. It offers features such as authentication and streaming that are very relevant for Cadence. Moreover, TChannel is being deprecated within Uber itself, pushing an effort for this migration. During the last year we’ve implemented multiple changes in server and SDK that allows users to use gRPC in Cadence, as well as to upgrade their existing Cadence cluster in a backward compatible way. This post tracks the completed work items and our future plans.

Our Approach

With ~500 services using Cadence at Uber and many more open source customers around the world, we had to think about the gRPC transition in a backwards compatible way. We couldn’t simply flip transport and encoding everywhere. Instead we needed to support both protocols as an intermediate step to ensure a smooth transition for our users.

@@ -30,7 +30,7 @@

Our ApproachThe next step - client migration. We have more users for the Go SDK at Uber, that is why we started with it. Current version of SDK exposes Thrift types via public API, therefore we can not remove them without breaking changes. While we have plans for revamped v2 SDK, current users are able to use gRPC as well - with the help of a translation adapter. Migration is underway starting with cadence canary service, and then onboarding user services one by one.

We plan to support TChannel for a few more releases and then eventually drop it in a future.

System overview

-

gRPC migration overview

+

gRPC migration overview

  1. The frontend of Cadence Server exposes two inbounds for both gRPC and TChannel starting v0.21.0 release. gRPC traffic is being served on a different port that can be configured here. For gRPC API we introduced proto IDL definitions. We will keep TChannel open on frontend for some time to allow gradual client migration.
  2. Starting with v0.21.0 internal components of Cadence Server (history & matching) also started accepting gRPC traffic. Sending traffic via gRPC is off by default and could be enabled with a flag in dynamic config. Planned for v0.24.0 it will be enabled by default, with an option to opt-out.
  3. @@ -66,6 +66,6 @@

    Status at Ube

    Do not hesitate to reach out to us (cadence-oss@googlegroups.com or slack) if you have any questions.

    -

    The Uber Cadence team

+

The Uber Cadence team

\ No newline at end of file diff --git a/blog/2021/10/19/2021-10-19-moving-to-grpc/moving-to-grpc.html.html b/blog/2021/10/19/2021-10-19-moving-to-grpc/moving-to-grpc.html.html index 1990339d5..3e92fc53a 100644 --- a/blog/2021/10/19/2021-10-19-moving-to-grpc/moving-to-grpc.html.html +++ b/blog/2021/10/19/2021-10-19-moving-to-grpc/moving-to-grpc.html.html @@ -2,10 +2,10 @@ - - + + \ No newline at end of file diff --git a/blog/2022/01/31/community-spotlight-january-2022.html b/blog/2022/01/31/community-spotlight-january-2022.html index d230d84b0..a4a42bca6 100644 --- a/blog/2022/01/31/community-spotlight-january-2022.html +++ b/blog/2022/01/31/community-spotlight-january-2022.html @@ -3,8 +3,8 @@ -Cadence Community Spotlight Update - January 2022 | Cadence - +Cadence Community Spotlight Update - January 2022 | Cadence + @@ -15,14 +15,14 @@ - - - + + + -

Cadence Community Spotlight Update - January 2022

· 3 min read
Sharan Foga
Director of Operations & Customer Success @ Encube Technologies

Welcome to our very first Cadence Community Spotlight update!

+

Cadence Community Spotlight Update - January 2022

· 3 min read
Sharan Foga
Director of Operations & Customer Success @ Encube Technologies

Welcome to our very first Cadence Community Spotlight update!

This monthly update focuses on news from the wider Cadence community and is all about what you have been doing with Cadence. Do you have an interesting project that uses Cadence? If so then we want to hear from you. Also if you have any news items, blogs, articles, videos or events where Cadence has been mentioned then that is good too. We want to showcase that our community is active and is doing exciting and interesting things.

Please see below for a short round up of things that have happened recently in the community.

@@ -44,6 +44,6 @@

Upcoming Eve -

If you have any news or topics you'd like us to include in our next update then please join our slack#community channel.

+

If you have any news or topics you'd like us to include in our next update then please join our slack#community channel.

\ No newline at end of file diff --git a/blog/2022/01/31/community-spotlight-january-2022.html.html b/blog/2022/01/31/community-spotlight-january-2022.html.html index 8ac53e63f..d4be0e0c8 100644 --- a/blog/2022/01/31/community-spotlight-january-2022.html.html +++ b/blog/2022/01/31/community-spotlight-january-2022.html.html @@ -2,10 +2,10 @@ - - + + \ No newline at end of file diff --git a/blog/2022/02/28/community-spotlight-february-2022.html b/blog/2022/02/28/community-spotlight-february-2022.html index b84a08dd5..74f9876c5 100644 --- a/blog/2022/02/28/community-spotlight-february-2022.html +++ b/blog/2022/02/28/community-spotlight-february-2022.html @@ -3,8 +3,8 @@ -Cadence Community Spotlight Update - February 2022 | Cadence - +Cadence Community Spotlight Update - February 2022 | Cadence + @@ -15,14 +15,14 @@ - - - + + + -

Cadence Community Spotlight Update - February 2022

· 3 min read
Sharan Foga
Director of Operations & Customer Success @ Encube Technologies

Welcome to the Cadence Community Spotlight update!

+

Cadence Community Spotlight Update - February 2022

· 3 min read
Sharan Foga
Director of Operations & Customer Success @ Encube Technologies

Welcome to the Cadence Community Spotlight update!

This is the second in our series of monthly updates focused on the Cadence community and news about what you have been doing with Cadence. We hope that you enjoyed last month's update and are keen to find out what has been happening.

Please see below for a short activity roundup of what has happened recently in the community.

Announcements

@@ -54,6 +54,6 @@

Upcoming Eve
  • Webinar : What is Cadence? And is it right for you? (APAC)
  • If you have any news or topics you'd like us to include in our next update then please join our Slack#community channel.

    -

    Please remember that this update is for you - so if you have any comments or feedback that could help us improve it then please share it with us in the #community Slack channel.

    +

    Please remember that this update is for you - so if you have any comments or feedback that could help us improve it then please share it with us in the #community Slack channel.

    \ No newline at end of file diff --git a/blog/2022/02/28/community-spotlight-february-2022.html.html b/blog/2022/02/28/community-spotlight-february-2022.html.html index f0ffa3530..18922e86b 100644 --- a/blog/2022/02/28/community-spotlight-february-2022.html.html +++ b/blog/2022/02/28/community-spotlight-february-2022.html.html @@ -2,10 +2,10 @@ - - + + \ No newline at end of file diff --git a/blog/2022/03/31/community-spotlight-update-march-2022.html b/blog/2022/03/31/community-spotlight-update-march-2022.html index 3b4cd82cb..3ef239353 100644 --- a/blog/2022/03/31/community-spotlight-update-march-2022.html +++ b/blog/2022/03/31/community-spotlight-update-march-2022.html @@ -3,8 +3,8 @@ -Cadence Community Spotlight Update - March 2022 | Cadence - +Cadence Community Spotlight Update - March 2022 | Cadence + @@ -15,14 +15,14 @@ - - - + + + -

    Cadence Community Spotlight Update - March 2022

    · 4 min read
    Sharan Foga
    Director of Operations & Customer Success @ Encube Technologies

    Welcome to our Cadence Community Spotlight update!

    +

    Cadence Community Spotlight Update - March 2022

    · 4 min read
    Sharan Foga
    Director of Operations & Customer Success @ Encube Technologies

    Welcome to our Cadence Community Spotlight update!

    This is the latest in our series of monthly blog posts focused on the Cadence community and news about what you have been doing with Cadence.

    Please see below for a short activity roundup of what has happened recently in the community.

    Updated Cadence Topology Diagram

    @@ -81,6 +81,6 @@

    Upcoming Eve

    If you have any news or topics you'd like us to include in our next update then please join our Slack#community channel.

    -

    Please remember that this update is for you - so if you have any comments or feedback that could help us improve it then please share it with us in the #community Slack channel.

    +

    Please remember that this update is for you - so if you have any comments or feedback that could help us improve it then please share it with us in the #community Slack channel.

    \ No newline at end of file diff --git a/blog/2022/03/31/community-spotlight-update-march-2022.html.html b/blog/2022/03/31/community-spotlight-update-march-2022.html.html index 8e20a6847..be246ad45 100644 --- a/blog/2022/03/31/community-spotlight-update-march-2022.html.html +++ b/blog/2022/03/31/community-spotlight-update-march-2022.html.html @@ -2,10 +2,10 @@ - - + + \ No newline at end of file diff --git a/blog/2022/04/30/community-spotlight-update-april-2022.html b/blog/2022/04/30/community-spotlight-update-april-2022.html index 27cf03078..cce66c361 100644 --- a/blog/2022/04/30/community-spotlight-update-april-2022.html +++ b/blog/2022/04/30/community-spotlight-update-april-2022.html @@ -3,8 +3,8 @@ -Cadence Community Spotlight Update - April 2022 | Cadence - +Cadence Community Spotlight Update - April 2022 | Cadence + @@ -15,14 +15,14 @@ - - - + + + -

    Cadence Community Spotlight Update - April 2022

    · 3 min read
    Sharan Foga
    Director of Operations & Customer Success @ Encube Technologies

    Welcome to our Cadence Community Spotlight update!

    +

    Cadence Community Spotlight Update - April 2022

    · 3 min read
    Sharan Foga
    Director of Operations & Customer Success @ Encube Technologies

    Welcome to our Cadence Community Spotlight update!

    This is our monthly blog post series focused on news from in and around the Cadence community.

    Please see below for a short activity roundup of what has happened recently in the community.

    SD Times Names Cadence Open Source Project of the Week

    @@ -56,6 +56,6 @@

    Upcoming Eve
  • Cadence Technical Office Hours - 30th May 2022 @ 9am PT
  • If you have any news or topics you'd like us to include in our next update then please join our Slack#community channel.

    -

    Please remember that this update is for you - so if you have any comments or feedback that could help us improve it then please share it with us in the #community Slack channel.

    +

    Please remember that this update is for you - so if you have any comments or feedback that could help us improve it then please share it with us in the #community Slack channel.

    \ No newline at end of file diff --git a/blog/2022/04/30/community-spotlight-update-april-2022.html.html b/blog/2022/04/30/community-spotlight-update-april-2022.html.html index 083360946..2aa9ed46b 100644 --- a/blog/2022/04/30/community-spotlight-update-april-2022.html.html +++ b/blog/2022/04/30/community-spotlight-update-april-2022.html.html @@ -2,10 +2,10 @@ - - + + \ No newline at end of file diff --git a/blog/2022/05/31/community-spotlight-update-may-2022.html b/blog/2022/05/31/community-spotlight-update-may-2022.html index 28c6d7e6e..a1661e2f7 100644 --- a/blog/2022/05/31/community-spotlight-update-may-2022.html +++ b/blog/2022/05/31/community-spotlight-update-may-2022.html @@ -3,8 +3,8 @@ -Cadence Community Spotlight Update - May 2022 | Cadence - +Cadence Community Spotlight Update - May 2022 | Cadence + @@ -15,14 +15,14 @@ - - - + + + -

    Cadence Community Spotlight Update - May 2022

    · 3 min read
    Sharan Foga
    Director of Operations & Customer Success @ Encube Technologies

    Welcome to our regular Cadence Community Spotlight update!

    +

    Cadence Community Spotlight Update - May 2022

    · 3 min read
    Sharan Foga
    Director of Operations & Customer Success @ Encube Technologies

    Welcome to our regular Cadence Community Spotlight update!

    This is our monthly blog post series focused on news from in and around the Cadence community.

    Please see below for a short activity roundup of what has happened recently in the community.

    Cadence Polling Cookbook

    @@ -65,6 +65,6 @@

    Upcoming Eve

    If you have any news or topics you'd like us to include in our next update then please join our Slack#community channel.

    -

    Please remember that this update is for you - so if you have any comments or feedback that could help us improve it then please share it with us in the #community Slack channel.

    +

    Please remember that this update is for you - so if you have any comments or feedback that could help us improve it then please share it with us in the #community Slack channel.

    \ No newline at end of file diff --git a/blog/2022/05/31/community-spotlight-update-may-2022.html.html b/blog/2022/05/31/community-spotlight-update-may-2022.html.html index f5c88a073..7aa985c5a 100644 --- a/blog/2022/05/31/community-spotlight-update-may-2022.html.html +++ b/blog/2022/05/31/community-spotlight-update-may-2022.html.html @@ -2,10 +2,10 @@ - - + + \ No newline at end of file diff --git a/blog/2022/06/30/community-spotlight-update-june-2022.html b/blog/2022/06/30/community-spotlight-update-june-2022.html index f52bf1eea..93aed0b38 100644 --- a/blog/2022/06/30/community-spotlight-update-june-2022.html +++ b/blog/2022/06/30/community-spotlight-update-june-2022.html @@ -3,8 +3,8 @@ -Cadence Community Spotlight Update - June 2022 | Cadence - +Cadence Community Spotlight Update - June 2022 | Cadence + @@ -15,14 +15,14 @@ - - - + + + -

    Cadence Community Spotlight Update - June 2022

    · 3 min read
    Sharan Foga
    Director of Operations & Customer Success @ Encube Technologies

    It’s time for our monthly Cadence Community Spotlight update with news from in and around the Cadence community!

    +

    Cadence Community Spotlight Update - June 2022

    · 3 min read
    Sharan Foga
    Director of Operations & Customer Success @ Encube Technologies

    It’s time for our monthly Cadence Community Spotlight update with news from in and around the Cadence community!

    Please see below for a roundup of the highlights:

    Knowledge Sharing and Support

    Our Slack #support channel has been busy this month with 13 questions asked this month by 12 different community members. Six community members took time to respond to those questions which clearly shows our community is growing, collaborating and keen to share knowledge.

    @@ -58,6 +58,6 @@

    Upcoming Eve

    If you have any news or topics you'd like us to include in our next update then please join our Slack#community channel.

    -

    Please remember that this update is for you - so if you have any comments or feedback that could help us improve it then please share it with us in the #community Slack channel.

    +

    Please remember that this update is for you - so if you have any comments or feedback that could help us improve it then please share it with us in the #community Slack channel.

    \ No newline at end of file diff --git a/blog/2022/06/30/community-spotlight-update-june-2022.html.html b/blog/2022/06/30/community-spotlight-update-june-2022.html.html index 7c0b50c2e..d0366b358 100644 --- a/blog/2022/06/30/community-spotlight-update-june-2022.html.html +++ b/blog/2022/06/30/community-spotlight-update-june-2022.html.html @@ -2,10 +2,10 @@ - - + + \ No newline at end of file diff --git a/blog/2022/07/31/community-spotlight-update-july-2022.html b/blog/2022/07/31/community-spotlight-update-july-2022.html index 9a16142f6..d7e84f933 100644 --- a/blog/2022/07/31/community-spotlight-update-july-2022.html +++ b/blog/2022/07/31/community-spotlight-update-july-2022.html @@ -3,8 +3,8 @@ -Cadence Community Spotlight Update - July 2022 | Cadence - +Cadence Community Spotlight Update - July 2022 | Cadence + @@ -15,14 +15,14 @@ - - - + + + -

    Cadence Community Spotlight Update - July 2022

    · 2 min read
    Sharan Foga
    Director of Operations & Customer Success @ Encube Technologies

    Here’s our monthly Community Spotlight update that gives you news from in and around the Cadence community!

    +

    Cadence Community Spotlight Update - July 2022

    · 2 min read
    Sharan Foga
    Director of Operations & Customer Success @ Encube Technologies

    Here’s our monthly Community Spotlight update that gives you news from in and around the Cadence community!

    Please see below for a roundup of the highlights:

    Flying Drones with Cadence

    Community member Paul Brebner has released another blog in the series of using Cadence to manage a drone delivery service. You can see a simulated view of it in action

    @@ -56,6 +56,6 @@

    Upcoming Eve

    If you have any news or topics you'd like us to include in our next update then please join our Slack#community channel.

    -

    Please remember that this update is for you - so if you have any comments or feedback that could help us improve it then please share it with us in the #community Slack channel.

    +

    Please remember that this update is for you - so if you have any comments or feedback that could help us improve it then please share it with us in the #community Slack channel.

    \ No newline at end of file diff --git a/blog/2022/07/31/community-spotlight-update-july-2022.html.html b/blog/2022/07/31/community-spotlight-update-july-2022.html.html index d1ba2107d..afb37d203 100644 --- a/blog/2022/07/31/community-spotlight-update-july-2022.html.html +++ b/blog/2022/07/31/community-spotlight-update-july-2022.html.html @@ -2,10 +2,10 @@ - - + + \ No newline at end of file diff --git a/blog/2022/08/31/community-spotlight-august-2022.html b/blog/2022/08/31/community-spotlight-august-2022.html index d70997a7e..843f184b4 100644 --- a/blog/2022/08/31/community-spotlight-august-2022.html +++ b/blog/2022/08/31/community-spotlight-august-2022.html @@ -3,8 +3,8 @@ -Cadence Community Spotlight Update - August 2022 | Cadence - +Cadence Community Spotlight Update - August 2022 | Cadence + @@ -15,14 +15,14 @@ - - - + + + -

    Cadence Community Spotlight Update - August 2022

    · 3 min read
    Sharan Foga
    Director of Operations & Customer Success @ Encube Technologies

    Here’s the latest in our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!

    +

    Cadence Community Spotlight Update - August 2022

    · 3 min read
    Sharan Foga
    Director of Operations & Customer Success @ Encube Technologies

    Here’s the latest in our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!

    Please see below for a roundup of the highlights:

    Community Survey

    We are working on putting together our first community survey to find out a bit more about our community. We would like to get your feedback about on a few things such as:

    @@ -64,6 +64,6 @@

    Upcoming Eve

    If you have any news or topics you'd like us to include in our next update then please join our Slack#community channel.

    -

    Please remember that this update is for you - so if you have any comments or feedback that could help us improve it then please share it with us in the #community Slack channel.

    +

    Please remember that this update is for you - so if you have any comments or feedback that could help us improve it then please share it with us in the #community Slack channel.

    \ No newline at end of file diff --git a/blog/2022/08/31/community-spotlight-august-2022.html.html b/blog/2022/08/31/community-spotlight-august-2022.html.html index 33352f352..a1f56d69d 100644 --- a/blog/2022/08/31/community-spotlight-august-2022.html.html +++ b/blog/2022/08/31/community-spotlight-august-2022.html.html @@ -2,10 +2,10 @@ - - + + \ No newline at end of file diff --git a/blog/2022/09/30/community-spotlight-september-2022.html b/blog/2022/09/30/community-spotlight-september-2022.html index 75ae4b673..316413d14 100644 --- a/blog/2022/09/30/community-spotlight-september-2022.html +++ b/blog/2022/09/30/community-spotlight-september-2022.html @@ -3,8 +3,8 @@ -Cadence Community Spotlight Update - September 2022 | Cadence - +Cadence Community Spotlight Update - September 2022 | Cadence + @@ -15,14 +15,14 @@ - - - + + + -

    Cadence Community Spotlight Update - September 2022

    · 2 min read
    Sharan Foga
    Director of Operations & Customer Success @ Encube Technologies

    Here’s the latest in our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!

    +

    Cadence Community Spotlight Update - September 2022

    · 2 min read
    Sharan Foga
    Director of Operations & Customer Success @ Encube Technologies

    Here’s the latest in our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!

    Please see below for a roundup of the highlights:

    A Cadence talk by Ender Demirkaya and Ben Slater has been accepted for Developer Week Enterprise.

    The talk is scheduled to for 16th November so please make a note in your calendars.

    @@ -59,6 +59,6 @@

    Upcoming Eve

    If you have any news or topics you'd like us to include in our next update then please join our Slack#community channel.

    -

    Please remember that this update is for you - so if you have any comments or feedback that could help us improve it then please share it with us in the #community Slack channel.

    +

    Please remember that this update is for you - so if you have any comments or feedback that could help us improve it then please share it with us in the #community Slack channel.

    \ No newline at end of file diff --git a/blog/2022/09/30/community-spotlight-september-2022.html.html b/blog/2022/09/30/community-spotlight-september-2022.html.html index 12e5a359b..fe72e4396 100644 --- a/blog/2022/09/30/community-spotlight-september-2022.html.html +++ b/blog/2022/09/30/community-spotlight-september-2022.html.html @@ -2,10 +2,10 @@ - - + + \ No newline at end of file diff --git a/blog/2022/10/31/community-spotlight-october-2022.html b/blog/2022/10/31/community-spotlight-october-2022.html index 5680419f1..9a605dfc5 100644 --- a/blog/2022/10/31/community-spotlight-october-2022.html +++ b/blog/2022/10/31/community-spotlight-october-2022.html @@ -3,8 +3,8 @@ -Cadence Community Spotlight Update - October 2022 | Cadence - +Cadence Community Spotlight Update - October 2022 | Cadence + @@ -15,14 +15,14 @@ - - - + + + -

    Cadence Community Spotlight Update - October 2022

    · 2 min read
    Sharan Foga
    Director of Operations & Customer Success @ Encube Technologies

    Here’s the latest in our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!

    +

    Cadence Community Spotlight Update - October 2022

    · 2 min read
    Sharan Foga
    Director of Operations & Customer Success @ Encube Technologies

    Here’s the latest in our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!

    Please see below for a roundup of the highlights:

    Cadence Meetup Postponed

    It's always great to get the community together and we had planned to run another Cadence Meetup in early November. Unfortunately we didn't have enough time to get things organised so we've decided to postpone it. So please watch out for an announcement for the new Cadence meetup date.

    @@ -56,6 +56,6 @@

    Upcoming Eve

    If you have any news or topics you'd like us to include in our next update then please join our Slack#community channel.

    -

    Please remember that this update is for you - so if you have any comments or feedback that could help us improve it then please share it with us in the #community Slack channel.

    +

    Please remember that this update is for you - so if you have any comments or feedback that could help us improve it then please share it with us in the #community Slack channel.

    \ No newline at end of file diff --git a/blog/2022/10/31/community-spotlight-october-2022.html.html b/blog/2022/10/31/community-spotlight-october-2022.html.html index a29272b2e..89a0a79c7 100644 --- a/blog/2022/10/31/community-spotlight-october-2022.html.html +++ b/blog/2022/10/31/community-spotlight-october-2022.html.html @@ -2,10 +2,10 @@ - - + + \ No newline at end of file diff --git a/blog/2022/11/30/community-spotlight-november-2022.html b/blog/2022/11/30/community-spotlight-november-2022.html index d69429baf..58ae63d8f 100644 --- a/blog/2022/11/30/community-spotlight-november-2022.html +++ b/blog/2022/11/30/community-spotlight-november-2022.html @@ -3,8 +3,8 @@ -Cadence Community Spotlight Update - November 2022 | Cadence - +Cadence Community Spotlight Update - November 2022 | Cadence + @@ -15,14 +15,14 @@ - - - + + + -

    Cadence Community Spotlight Update - November 2022

    · 2 min read
    Sharan Foga
    Director of Operations & Customer Success @ Encube Technologies

    Here’s the latest in our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!

    +

    Cadence Community Spotlight Update - November 2022

    · 2 min read
    Sharan Foga
    Director of Operations & Customer Success @ Encube Technologies

    Here’s the latest in our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!

    Please see below for a roundup of the highlights:

    Cadence @ Uber

    This month Uber Engineering published a really nice article on one of the ways they are using Cadence. The article is called How Uber Optimizes the Timing of Push Notifications using ML and Linear Programming.

    @@ -49,6 +49,6 @@

    Upcoming Eve
  • Cadence Technical Office Hours - 30th January 2023 @ 9am PT
  • If you have any news or topics you'd like us to include in our next update then please join our Slack#community channel.

    -

    Please remember that this update is for you - so if you have any comments or feedback that could help us improve it then please share it with us in the #community Slack channel.

    +

    Please remember that this update is for you - so if you have any comments or feedback that could help us improve it then please share it with us in the #community Slack channel.

    \ No newline at end of file diff --git a/blog/2022/11/30/community-spotlight-november-2022.html.html b/blog/2022/11/30/community-spotlight-november-2022.html.html index 11240b864..1b9d805b1 100644 --- a/blog/2022/11/30/community-spotlight-november-2022.html.html +++ b/blog/2022/11/30/community-spotlight-november-2022.html.html @@ -2,10 +2,10 @@ - - + + \ No newline at end of file diff --git a/blog/2022/12/23/community-spotlight-december-2022.html b/blog/2022/12/23/community-spotlight-december-2022.html index 7e7903bd2..b8637e1f6 100644 --- a/blog/2022/12/23/community-spotlight-december-2022.html +++ b/blog/2022/12/23/community-spotlight-december-2022.html @@ -3,8 +3,8 @@ -Cadence Community Spotlight Update - December 2022 | Cadence - +Cadence Community Spotlight Update - December 2022 | Cadence + @@ -15,14 +15,14 @@ - - - + + + -

    Cadence Community Spotlight Update - December 2022

    · 2 min read
    Sharan Foga
    Director of Operations & Customer Success @ Encube Technologies

    I know we are a little early this month as many people will be taking some time out for holidays.

    +

    Cadence Community Spotlight Update - December 2022

    · 2 min read
    Sharan Foga
    Director of Operations & Customer Success @ Encube Technologies

    I know we are a little early this month as many people will be taking some time out for holidays.

    Happy Holidays

    We'd like to wish everyone happy holidays and to thank you for being part of the Cadence community. It's been a busy year for Cadence as we have continued to build a strong, active community that works together to solve issues and generally support each other.

    Let's keep going!...This is a great way to build a sustainable community.

    @@ -45,6 +45,6 @@

    Upcoming Eve
  • Cadence Technical Office Hours - 30th January 2023 @ 9am PT
  • If you have any news or topics you'd like us to include in our next update then please join our Slack#community channel.

    -

    Please remember that this update is for you - so if you have any comments or feedback that could help us improve it then please share it with us in the #community Slack channel.

    +

    Please remember that this update is for you - so if you have any comments or feedback that could help us improve it then please share it with us in the #community Slack channel.

    \ No newline at end of file diff --git a/blog/2022/12/23/community-spotlight-december-2022.html.html b/blog/2022/12/23/community-spotlight-december-2022.html.html index 996fc40cf..4d11d77ce 100644 --- a/blog/2022/12/23/community-spotlight-december-2022.html.html +++ b/blog/2022/12/23/community-spotlight-december-2022.html.html @@ -2,10 +2,10 @@ - - + + \ No newline at end of file diff --git a/blog/2023/01/31/community-spotlight-january-2023.html b/blog/2023/01/31/community-spotlight-january-2023.html index 2edefc208..1eb4975f9 100644 --- a/blog/2023/01/31/community-spotlight-january-2023.html +++ b/blog/2023/01/31/community-spotlight-january-2023.html @@ -3,8 +3,8 @@ -Cadence Community Spotlight Update - January 2023 | Cadence - +Cadence Community Spotlight Update - January 2023 | Cadence + @@ -15,14 +15,14 @@ - - - + + + -

    Cadence Community Spotlight Update - January 2023

    · 3 min read
    Sharan Foga
    Director of Operations & Customer Success @ Encube Technologies

    Happy New Year everyone! Here’s the latest in our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!

    +

    Cadence Community Spotlight Update - January 2023

    · 3 min read
    Sharan Foga
    Director of Operations & Customer Success @ Encube Technologies

    Happy New Year everyone! Here’s the latest in our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!

    Please see below for a roundup of the highlights:

    Closing Down Cadence Office Hours

    We have been running Office Hours sessions every month since May last year. The aim was to give the community an opportunity to speak directly with some of the Cadence core developers and experts to answer questions on particular issues you may be having. We have found that the most preferred method for community questions has been the support Slack channel so have decided to stop this monthly call.

    @@ -48,6 +48,6 @@

    Cadence

    Upcoming Events

    No upcoming events at the moment.

    If you have any news or topics you'd like us to include in our next update then please join our Slack#community channel.

    -

    Please remember that this update is for you - so if you have any comments or feedback that could help us improve it then please share it with us in the #community Slack channel.

    +

    Please remember that this update is for you - so if you have any comments or feedback that could help us improve it then please share it with us in the #community Slack channel.

    \ No newline at end of file diff --git a/blog/2023/01/31/community-spotlight-january-2023.html.html b/blog/2023/01/31/community-spotlight-january-2023.html.html index e799deb7d..7bf930de3 100644 --- a/blog/2023/01/31/community-spotlight-january-2023.html.html +++ b/blog/2023/01/31/community-spotlight-january-2023.html.html @@ -2,10 +2,10 @@ - - + + \ No newline at end of file diff --git a/blog/2023/02/28/community-spotlight-february.html b/blog/2023/02/28/community-spotlight-february.html index 126d615db..aebcd348e 100644 --- a/blog/2023/02/28/community-spotlight-february.html +++ b/blog/2023/02/28/community-spotlight-february.html @@ -3,8 +3,8 @@ -Cadence Community Spotlight Update - February 2023 | Cadence - +Cadence Community Spotlight Update - February 2023 | Cadence + @@ -15,14 +15,14 @@ - - - + + + -

    Cadence Community Spotlight Update - February 2023

    · 2 min read
    Sharan Foga
    Director of Operations & Customer Success @ Encube Technologies

    Here’s the latest in our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!

    +

    Cadence Community Spotlight Update - February 2023

    · 2 min read
    Sharan Foga
    Director of Operations & Customer Success @ Encube Technologies

    Here’s the latest in our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!

    Please see below for a roundup of the highlights:

    Community Survey

    We've been talking about doing a community survey for a while and during February we sent it out. We are still collating the results so it's not too late to send in your response.

    @@ -50,6 +50,6 @@

    Upcoming Eve
  • On Demand Webinar: Spinning Your Drones with Cadence and Apache Kafka
  • If you have any news or topics you'd like us to include in our next update then please join our Slack#community channel.

    -

    Please remember that this update is for you - so if you have any comments or feedback that could help us improve it then please share it with us in the #community Slack channel.

    +

    Please remember that this update is for you - so if you have any comments or feedback that could help us improve it then please share it with us in the #community Slack channel.

    \ No newline at end of file diff --git a/blog/2023/02/28/community-spotlight-february.html.html b/blog/2023/02/28/community-spotlight-february.html.html index e06bcf1de..93bf14019 100644 --- a/blog/2023/02/28/community-spotlight-february.html.html +++ b/blog/2023/02/28/community-spotlight-february.html.html @@ -2,10 +2,10 @@ - - + + \ No newline at end of file diff --git a/blog/2023/03/31/community-spotlight-march-2023.html b/blog/2023/03/31/community-spotlight-march-2023.html index b925a9cd3..4e49116ef 100644 --- a/blog/2023/03/31/community-spotlight-march-2023.html +++ b/blog/2023/03/31/community-spotlight-march-2023.html @@ -3,8 +3,8 @@ -Cadence Community Spotlight Update - March 2023 | Cadence - +Cadence Community Spotlight Update - March 2023 | Cadence + @@ -15,14 +15,14 @@ - - - + + + -

    Cadence Community Spotlight Update - March 2023

    · 2 min read
    Sharan Foga
    Director of Operations & Customer Success @ Encube Technologies

    Welcome to the latest of our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!

    +

    Cadence Community Spotlight Update - March 2023

    · 2 min read
    Sharan Foga
    Director of Operations & Customer Success @ Encube Technologies

    Welcome to the latest of our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!

    Please see below for a roundup of the highlights:

    Cadence at Open Source Summit, North America

    We are very pleased to let you know that a talk on Cadence has been accepted for the Linux Foundation's Open Source Summit, North America in Vancouver on 10th - 12th May 2023.

    @@ -53,6 +53,6 @@

    Upcoming Eve
  • Webinar: Microservices - A Modern Orchestration Approach with Cadence
  • If you have any news or topics you'd like us to include in our next update then please join our Slack#community channel.

    -

    Please remember that this update is for you - so if you have any comments or feedback that could help us improve it then please share it with us in the #community Slack channel.

    +

    Please remember that this update is for you - so if you have any comments or feedback that could help us improve it then please share it with us in the #community Slack channel.

    \ No newline at end of file diff --git a/blog/2023/03/31/community-spotlight-march-2023.html.html b/blog/2023/03/31/community-spotlight-march-2023.html.html index 336ef8270..42a8231c8 100644 --- a/blog/2023/03/31/community-spotlight-march-2023.html.html +++ b/blog/2023/03/31/community-spotlight-march-2023.html.html @@ -2,10 +2,10 @@ - - + + \ No newline at end of file diff --git a/blog/2023/06/08/2023-06-08-survey-results/survey-results.html b/blog/2023/06/08/2023-06-08-survey-results/survey-results.html index a8489dc72..778ed4317 100644 --- a/blog/2023/06/08/2023-06-08-survey-results/survey-results.html +++ b/blog/2023/06/08/2023-06-08-survey-results/survey-results.html @@ -3,8 +3,8 @@ -2023 Cadence Community Survey Results | Cadence - +2023 Cadence Community Survey Results | Cadence + @@ -15,36 +15,36 @@ - - - + + + -

    2023 Cadence Community Survey Results

    · 4 min read
    Ender Demirkaya
    Senior Manager at Uber, Cadence. Author of the Software Engineering Handbook

    We released a user survey earlier this year to learn about who our users are, how they use Cadence, and how we can help them. It was shared from our Slack workspace, cadenceworkflow.io Blog and LinkedIn. After collecting the feedback, we wanted to share the results with our community. Thank you everyone for filling it out! Your feedback is invaluable and it helps us shape our roadmap for the future.

    +

    2023 Cadence Community Survey Results

    · 4 min read
    Ender Demirkaya
    Senior Manager at Uber, Cadence. Author of the Software Engineering Handbook

    We released a user survey earlier this year to learn about who our users are, how they use Cadence, and how we can help them. It was shared from our Slack workspace, cadenceworkflow.io Blog and LinkedIn. After collecting the feedback, we wanted to share the results with our community. Thank you everyone for filling it out! Your feedback is invaluable and it helps us shape our roadmap for the future.

    Here are some highlights in text and you can check out the visuals to get more details:

    -

    using.png

    -

    job_role.png

    +

    using.png

    +

    job_role.png

    Most of the people who replied to our survey were engineers who were already using Cadence, actively evaluating, or migrating from a similar technology. This was exciting to hear! Some of you have contacted us to learn more about benchmarks, scale, and ideal use cases. We will share more guidelines about this but until then, feel free to contact us over our Slack workspace for guidance.

    -

    scale.png

    +

    scale.png

    The scale our users operating Cadence varies from thousands to billions of workflows per month. It was exciting to see it being used in both small and large scale companies.

    -

    time_zone.png

    +

    time_zone.png

    Most survey responders were from Europe compared to any other place. This is in-line with the Cadence team growing its presence in Europe. Users from different places also contacted us to contribute to Cadence as a follow up to the survey. We will start putting up-for-grabs and new-starter tasks on Github. Several of them wanted to meet with a Zoom call and to discuss their use cases and best practices. As the Cadence team has presence in both the EU and the US, we welcome all our users to contact us anytime. Slack is the fastest way to reach us.

    -

    following.png

    -

    channels.png

    +

    following.png

    +

    channels.png

    Cadence is followed in Slack the most, then Github and LinkedIn. We are the most active in Slack and we plan to be more active in other mediums as well.

    -

    scenarios.png +

    scenarios.png All of our main use cases were used across the board. While we mentioned the most common cases, several others were mentioned as a comment: enhanced timers, leader election etc.

    We found out that Cadence has been used in several science communities. Some of them were using community built clients and were asking if we are going to support more languages. We are planning to take ownership of the Python and Javascript/Typescript clients and support them officially.

    -

    improvement.png

    +

    improvement.png

    Documentation is by far what our users wanted improvements on. We are revamping our documentation soon and there will be major changes on our website soon.

    -

    help_stage.png

    +

    help_stage.png

    Other requests were about observability, debuggability, operability, and usability. These areas have been our main focus this year and we are planning to release updates and blogs about them.

    -

    support.png

    +

    support.png

    We noticed most of our users need help once a month or more. While we welcome questions and discussions over the mediums mentioned above, we plan to make more public posts about the common issues using our blog, StackOverflow, LinkedIn, or Twitter.

    Many users wanted to hear more from Cadence about the roadmap and its growth. Our posts about these will be released soon. Expect more posts about upcoming features, investments, scale, and community updates. Follow us at LinkedIn for such updates.

    Our users are interested in learning more about guidelines, capacity expectations in on-prem and in managed solutions. While we have been providing feedback per user basis before, we plan to release more generic guidelines with our observability updates mentioned above.

    -

    We also would like to thank our community for the increased interest and engagement with us! Cadence has been more active in different mediums (LinkedIn, Slack, blog, etc.) this year. In the first quarter, we observed that our user base and activities has almost doubled (+96% and +90% respectively) through both new and returning users. Based on such immediate positive reactions, we will keep increasing our community investments in different channels.

    +

    We also would like to thank our community for the increased interest and engagement with us! Cadence has been more active in different mediums (LinkedIn, Slack, blog, etc.) this year. In the first quarter, we observed that our user base and activities has almost doubled (+96% and +90% respectively) through both new and returning users. Based on such immediate positive reactions, we will keep increasing our community investments in different channels.

    \ No newline at end of file diff --git a/blog/2023/06/08/2023-06-08-survey-results/survey-results.html.html b/blog/2023/06/08/2023-06-08-survey-results/survey-results.html.html index e8331ff3c..a4b4bc5e0 100644 --- a/blog/2023/06/08/2023-06-08-survey-results/survey-results.html.html +++ b/blog/2023/06/08/2023-06-08-survey-results/survey-results.html.html @@ -2,10 +2,10 @@ - - + + \ No newline at end of file diff --git a/blog/2023/06/28/components-of-cadence-application-setup.html b/blog/2023/06/28/components-of-cadence-application-setup.html index a2e03821c..accdf0b1a 100644 --- a/blog/2023/06/28/components-of-cadence-application-setup.html +++ b/blog/2023/06/28/components-of-cadence-application-setup.html @@ -3,8 +3,8 @@ -Understanding components of Cadence application | Cadence - +Understanding components of Cadence application | Cadence + @@ -15,14 +15,14 @@ - - - + + + -

    Understanding components of Cadence application

    · 2 min read
    Chris Qin
    Applications Developer @ Uber

    Cadence is a powerful, scalable, and fault-tolerant workflow orchestration framework that helps developers implement and manage complex workflow tasks. In most cases, developers contribute activities and workflows directly to their codebases, and they may not have a full understanding of the components behind a running Cadence application. We receive numerous inquiries about setting up Cadence in a local environment from scratch for testing. Therefore, in this article, we will explore the components that power a Cadence cluster.

    +

    Understanding components of Cadence application

    · 2 min read
    Chris Qin
    Applications Developer @ Uber

    Cadence is a powerful, scalable, and fault-tolerant workflow orchestration framework that helps developers implement and manage complex workflow tasks. In most cases, developers contribute activities and workflows directly to their codebases, and they may not have a full understanding of the components behind a running Cadence application. We receive numerous inquiries about setting up Cadence in a local environment from scratch for testing. Therefore, in this article, we will explore the components that power a Cadence cluster.

    There are three critical components that are essential for any Cadence application:

    1. A running Cadence backend server.
    2. @@ -30,9 +30,9 @@
    3. A running Cadence worker that registers all workflows and activities.

    Let's go over these components in more details.

    -

    The Cadence backend serves as the heart of your Cadence application. It is responsible for processing and scheduling your workflows and activities. While the backend relies on various dependencies, our team has conveniently packaged them into a single Docker image. You can follow the instructions provided here.

    +

    The Cadence backend serves as the heart of your Cadence application. It is responsible for processing and scheduling your workflows and activities. While the backend relies on various dependencies, our team has conveniently packaged them into a single Docker image. You can follow the instructions provided here.

    The Cadence domain functions as the namespace for your Cadence workflows. It helps segregate your workflows into manageable groups. When running workflows, you must specify the domain on which you want to execute them.

    The Cadence worker, also known as the worker service, is a separate binary process that you need to implement in order to host your workflows and activities. When developing a worker, ensure that all your workflows and activities are properly registered with it. The worker is an actively running application, and you have the freedom to choose the hosting technologies that best suit your needs, such as a simple HTTP or gRPC application.

    -

    Ultimately, you will need to set up two running processes on your local machine: the Cadence server and the worker. Additionally, you must register the Cadence domain as a resource. Our team has packaged all these components into user-friendly tools, which you can find on our website.

    +

    Ultimately, you will need to set up two running processes on your local machine: the Cadence server and the worker. Additionally, you must register the Cadence domain as a resource. Our team has packaged all these components into user-friendly tools, which you can find on our website.

    \ No newline at end of file diff --git a/blog/2023/06/28/components-of-cadence-application-setup.html.html b/blog/2023/06/28/components-of-cadence-application-setup.html.html index c354a931c..2aa032fc4 100644 --- a/blog/2023/06/28/components-of-cadence-application-setup.html.html +++ b/blog/2023/06/28/components-of-cadence-application-setup.html.html @@ -2,10 +2,10 @@ - - + + \ No newline at end of file diff --git a/blog/2023/06/30/community-spotlight-june-2023.html b/blog/2023/06/30/community-spotlight-june-2023.html index d3fe3f978..6afcd6fa5 100644 --- a/blog/2023/06/30/community-spotlight-june-2023.html +++ b/blog/2023/06/30/community-spotlight-june-2023.html @@ -3,8 +3,8 @@ -Cadence Community Spotlight Update - June 2023 | Cadence - +Cadence Community Spotlight Update - June 2023 | Cadence + @@ -15,14 +15,14 @@ - - - + + + -

    Cadence Community Spotlight Update - June 2023

    · 3 min read
    Sharan Foga
    Director of Operations & Customer Success @ Encube Technologies

    We've had a short break but now we are back. Welcome to the latest of our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!

    +

    Cadence Community Spotlight Update - June 2023

    · 3 min read
    Sharan Foga
    Director of Operations & Customer Success @ Encube Technologies

    We've had a short break but now we are back. Welcome to the latest of our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!

    Please see below for a roundup of the highlights:

    Cadence Release 1.0

    Just in case you missed it - at the end of April Cadence v1.0 was officially released. This release is a significant milestone for the project and the community. It indicates that we are confident in the stability of the code that we can recommend it and promote it widely to more users. Kudos to everyone that worked together to make this release happen.

    @@ -76,6 +76,6 @@

    Upcoming Eve
  • None
  • If you have any news or topics you'd like us to include in our next update then please join our Slack#community channel.

    -

    Please remember that this update is for you - so if you have any comments or feedback that could help us improve it then please share it with us in the #community Slack channel.

    +

    Please remember that this update is for you - so if you have any comments or feedback that could help us improve it then please share it with us in the #community Slack channel.

    \ No newline at end of file diff --git a/blog/2023/06/30/community-spotlight-june-2023.html.html b/blog/2023/06/30/community-spotlight-june-2023.html.html index 955729879..93bcb5449 100644 --- a/blog/2023/06/30/community-spotlight-june-2023.html.html +++ b/blog/2023/06/30/community-spotlight-june-2023.html.html @@ -2,10 +2,10 @@ - - + + \ No newline at end of file diff --git a/blog/2023/07/05/implement-cadence-worker-from-scratch.html b/blog/2023/07/05/implement-cadence-worker-from-scratch.html index dd3c5ac65..763e9b451 100644 --- a/blog/2023/07/05/implement-cadence-worker-from-scratch.html +++ b/blog/2023/07/05/implement-cadence-worker-from-scratch.html @@ -3,8 +3,8 @@ -Implement a Cadence worker service from scratch | Cadence - +Implement a Cadence worker service from scratch | Cadence + @@ -15,14 +15,14 @@ - - - + + + -

    Implement a Cadence worker service from scratch

    · 4 min read
    Chris Qin
    Applications Developer @ Uber

    In the previous blog, we have introduced three critical components for a Cadence application: the Cadence backend, domain, and worker. Among these, the worker service is the most crucial focus for developers as it hosts the activities and workflows of a Cadence application. In this blog, I will provide a short tutorial on how to implement a simple worker service from scratch in Go.

    +

    Implement a Cadence worker service from scratch

    · 4 min read
    Chris Qin
    Applications Developer @ Uber

    In the previous blog, we have introduced three critical components for a Cadence application: the Cadence backend, domain, and worker. Among these, the worker service is the most crucial focus for developers as it hosts the activities and workflows of a Cadence application. In this blog, I will provide a short tutorial on how to implement a simple worker service from scratch in Go.

    To finish this tutorial, there are two prerequisites you need to finish first

    1. Register a Cadence domain for your worker. For this tutorial, I've already registered a domain named test-domain
    2. @@ -43,6 +43,6 @@
      import (
      "net/http"
      "go.uber.org/cadence/.gen/go/cadence/workflowserviceclient"
      "go.uber.org/cadence/compatibility"
      "go.uber.org/cadence/worker"

      apiv1 "github.com/cadence-workflow/cadence-idl/go/proto/api/v1"
      "github.com/uber-go/tally"
      "go.uber.org/zap"
      "go.uber.org/zap/zapcore"
      "go.uber.org/yarpc"
      "go.uber.org/yarpc/transport/grpc"
      )

      var HostPort = "127.0.0.1:7933"
      var Domain = "test-domain"
      var TaskListName = "test-worker"
      var ClientName = "test-worker"
      var CadenceService = "cadence-frontend"

      func main() {
      startWorker(buildLogger(), buildCadenceClient())
      http.ListenAndServe(":3000", nil)
      }

      func buildLogger() *zap.Logger {
      config := zap.NewDevelopmentConfig()
      config.Level.SetLevel(zapcore.InfoLevel)

      var err error
      logger, err := config.Build()
      if err != nil {
      panic("Failed to setup logger")
      }

      return logger
      }

      func buildCadenceClient() workflowserviceclient.Interface {
      dispatcher := yarpc.NewDispatcher(yarpc.Config{
      Name: ClientName,
      Outbounds: yarpc.Outbounds{
      CadenceService: {Unary: grpc.NewTransport().NewSingleOutbound(HostPort)},
      },
      })
      if err := dispatcher.Start(); err != nil {
      panic("Failed to start dispatcher")
      }

      clientConfig := dispatcher.ClientConfig(CadenceService)

      return compatibility.NewThrift2ProtoAdapter(
      apiv1.NewDomainAPIYARPCClient(clientConfig),
      apiv1.NewWorkflowAPIYARPCClient(clientConfig),
      apiv1.NewWorkerAPIYARPCClient(clientConfig),
      apiv1.NewVisibilityAPIYARPCClient(clientConfig),
      )
      }

      func startWorker(logger *zap.Logger, service workflowserviceclient.Interface) {
      // TaskListName identifies set of client workflows, activities, and workers.
      // It could be your group or client or application name.
      workerOptions := worker.Options{
      Logger: logger,
      MetricsScope: tally.NewTestScope(TaskListName, map[string]string{}),
      }

      worker := worker.New(
      service,
      Domain,
      TaskListName,
      workerOptions)
      err := worker.Start()
      if err != nil {
      panic("Failed to start worker")
      }

      logger.Info("Started Worker.", zap.String("worker", TaskListName))
      }

      Open a new terminal and start this server, you should see logs like

      2023-07-03T11:46:46.266-0700    INFO    internal/internal_worker.go:826 Worker has no workflows registered, so workflow worker will not be started.     {"Domain": "test-domain", "TaskList": "test-worker", "WorkerID": "35987@uber-C02F18EQMD6R@test-worker@90c0260e-ba5c-4652-9f10-c6d1f9e29c1d"}
      2023-07-03T11:46:46.267-0700 INFO internal/internal_worker.go:834 Started Workflow Worker {"Domain": "test-domain", "TaskList": "test-worker", "WorkerID": "35987@uber-C02F18EQMD6R@test-worker@90c0260e-ba5c-4652-9f10-c6d1f9e29c1d"}
      2023-07-03T11:46:46.267-0700 INFO internal/internal_worker.go:838 Worker has no activities registered, so activity worker will not be started. {"Domain": "test-domain", "TaskList": "test-worker", "WorkerID": "35987@uber-C02F18EQMD6R@test-worker@90c0260e-ba5c-4652-9f10-c6d1f9e29c1d"}
      2023-07-03T11:46:46.267-0700 INFO cadence-worker/main.go:75 Started Worker. {"worker": "test-worker"}
      -

      You may see these logs because your worker is successfully running but we haven't registered any workflows or activities to the worker. In the next tutorial, we will learn how to write a simple hello world workflow for your Cadence application.

    +

    You may see these logs because your worker is successfully running but we haven't registered any workflows or activities to the worker. In the next tutorial, we will learn how to write a simple hello world workflow for your Cadence application.

    \ No newline at end of file diff --git a/blog/2023/07/05/implement-cadence-worker-from-scratch.html.html b/blog/2023/07/05/implement-cadence-worker-from-scratch.html.html index 2fc66d5ed..141025c30 100644 --- a/blog/2023/07/05/implement-cadence-worker-from-scratch.html.html +++ b/blog/2023/07/05/implement-cadence-worker-from-scratch.html.html @@ -2,10 +2,10 @@ - - + + \ No newline at end of file diff --git a/blog/2023/07/10/cadence-bad-practices-part-1.html b/blog/2023/07/10/cadence-bad-practices-part-1.html index 30edcc6c7..9360a6d2f 100644 --- a/blog/2023/07/10/cadence-bad-practices-part-1.html +++ b/blog/2023/07/10/cadence-bad-practices-part-1.html @@ -3,8 +3,8 @@ -Bad practices and Anti-patterns with Cadence (Part 1) | Cadence - +Bad practices and Anti-patterns with Cadence (Part 1) | Cadence + @@ -15,14 +15,14 @@ - - - + + + -

    Bad practices and Anti-patterns with Cadence (Part 1)

    · 3 min read
    Chris Qin
    Applications Developer @ Uber

    In the upcoming blog series, we will delve into a discussion about common bad practices and anti-patterns related to Cadence. As diverse teams often encounter distinct business use cases, it becomes imperative to address the most frequently reported issues in Cadence workflows. To provide valuable insights and guidance, the Cadence team has meticulously compiled these common challenges based on customer feedback.

    +

    Bad practices and Anti-patterns with Cadence (Part 1)

    · 3 min read
    Chris Qin
    Applications Developer @ Uber

    In the upcoming blog series, we will delve into a discussion about common bad practices and anti-patterns related to Cadence. As diverse teams often encounter distinct business use cases, it becomes imperative to address the most frequently reported issues in Cadence workflows. To provide valuable insights and guidance, the Cadence team has meticulously compiled these common challenges based on customer feedback.

    • Reusing the same workflow ID for very active/continuous running workflows
    @@ -35,6 +35,6 @@

    Cadence has the capability to handle a large number of concurrent tasks initiated simultaneously, but tampering with this feature can lead to issues within the Cadence system. Consider a scenario where millions of jobs are scheduled to start at the same time and are expected to finish within a specific time interval. Cadence faces the challenge of understanding the desired behavior of customers in such cases. It is uncertain whether the intention is to complete all jobs simultaneously, provide progressive updates in parallel, or finish all jobs before a given deadline. This ambiguity arises due to the independent nature of each job and the difficulty in predicting their outcomes.

    Moreover, Cadence workers utilize a sticky cache by default to optimize the runtime of workflows. However, when an overwhelming number of parallel workflows cannot fit into the cache, it can result in cache thrashing. This, in turn, leads to a quadratic increase in runtime complexity, specifically O(n^2), exacerbating the overall performance of the system.

    Solution: -There are multiple ways to address this issue. Customers can either run jobs in a smaller batch or use start workflow jitter to randomly distribute timers within certain timeframe.

    +There are multiple ways to address this issue. Customers can either run jobs in a smaller batch or use start workflow jitter to randomly distribute timers within certain timeframe.

    \ No newline at end of file diff --git a/blog/2023/07/10/cadence-bad-practices-part-1.html.html b/blog/2023/07/10/cadence-bad-practices-part-1.html.html index 950e687d8..e21ebdc44 100644 --- a/blog/2023/07/10/cadence-bad-practices-part-1.html.html +++ b/blog/2023/07/10/cadence-bad-practices-part-1.html.html @@ -2,10 +2,10 @@ - - + + \ No newline at end of file diff --git a/blog/2023/07/16/2023-07-16-write-your-first-workflow-with-cadence/write-your-first-workflow-with-cadence.html b/blog/2023/07/16/2023-07-16-write-your-first-workflow-with-cadence/write-your-first-workflow-with-cadence.html index 63c3a1bb4..f693354f1 100644 --- a/blog/2023/07/16/2023-07-16-write-your-first-workflow-with-cadence/write-your-first-workflow-with-cadence.html +++ b/blog/2023/07/16/2023-07-16-write-your-first-workflow-with-cadence/write-your-first-workflow-with-cadence.html @@ -3,8 +3,8 @@ -Write your first workflow with Cadence | Cadence - +Write your first workflow with Cadence | Cadence + @@ -15,14 +15,14 @@ - - - + + + -

    Write your first workflow with Cadence

    · 3 min read
    Chris Qin
    Applications Developer @ Uber

    We have covered basic components of Cadence and how to implement a Cadence worker on local environment in previous blogs. In this blog, let's write your very first HelloWorld workflow with Cadence. I've started the Cadence backend server in background and registered a domain named test-domain. You may use the code snippet for the worker service in this blog Let's first write a activity, which takes a single string argument and print a log in the console.

    +

    Write your first workflow with Cadence

    · 3 min read
    Chris Qin
    Applications Developer @ Uber

    We have covered basic components of Cadence and how to implement a Cadence worker on local environment in previous blogs. In this blog, let's write your very first HelloWorld workflow with Cadence. I've started the Cadence backend server in background and registered a domain named test-domain. You may use the code snippet for the worker service in this blog Let's first write a activity, which takes a single string argument and print a log in the console.

    func helloWorldActivity(ctx context.Context, name string) (string, error) {
    logger := activity.GetLogger(ctx)
    logger.Info("helloworld activity started")
    return "Hello " + name + "!", nil
    }

    Then let's write a workflow that invokes this activity

    func helloWorldWorkflow(ctx workflow.Context, name string) error {
    ao := workflow.ActivityOptions{
    ScheduleToStartTimeout: time.Minute,
    StartToCloseTimeout: time.Minute,
    HeartbeatTimeout: time.Second * 20,
    }
    ctx = workflow.WithActivityOptions(ctx, ao)

    logger := workflow.GetLogger(ctx)
    logger.Info("helloworld workflow started")
    var helloworldResult string
    err := workflow.ExecuteActivity(ctx, helloWorldActivity, name).Get(ctx, &helloworldResult)
    if err != nil {
    logger.Error("Activity failed.", zap.Error(err))
    return err
    }

    logger.Info("Workflow completed.", zap.String("Result", helloworldResult))

    return nil
    }
    @@ -36,9 +36,9 @@
    2023-07-16T12:09:11.858-0700    INFO    cadence-worker/code.go:104      Workflow completed. {"Domain": "test-domain", "TaskList": "test-worker", "WorkerID": "13585@uber-C02F18EQMD6R@test-worker@42f8a76f-cc42-4a0d-a001-7f7959d5d623", "WorkflowType": "main.helloWorldWorkflow", "WorkflowID": "8cb7fb2a-243b-43f8-82d9-48d758c9d62f", "RunID": "3c070007-89c3-4e00-a039-19a86b2f9224", "Result": "Hello World!"}

    Congratulations, you have successfully run your very first Cadence workflow.

    For a bonus point, the Cadence team has also developed a demonstrative web dashboard to visualize the history of all workflows you have run when you start the Cadence server. Check http://localhost:8088 to see the dashboard like this.

    -

    cadencde-ui

    +

    cadencde-ui

    This web portal persists all historical workflow you have run recently. Search for the domain you used for this tutorial. In our case, type test-domain and hit enter. You may see a list of workflows with detailed information. Feel free to explore the web UI and raise your suggestions to our Github repo.

    -

    cadence-ui-detailed

    -

    For the incoming blogs, we will cover more advanced topics and use cases with Cadence.

    +

    cadence-ui-detailed

    +

    For the incoming blogs, we will cover more advanced topics and use cases with Cadence.

    \ No newline at end of file diff --git a/blog/2023/07/16/2023-07-16-write-your-first-workflow-with-cadence/write-your-first-workflow-with-cadence.html.html b/blog/2023/07/16/2023-07-16-write-your-first-workflow-with-cadence/write-your-first-workflow-with-cadence.html.html index 002c30428..d31a7f86f 100644 --- a/blog/2023/07/16/2023-07-16-write-your-first-workflow-with-cadence/write-your-first-workflow-with-cadence.html.html +++ b/blog/2023/07/16/2023-07-16-write-your-first-workflow-with-cadence/write-your-first-workflow-with-cadence.html.html @@ -2,10 +2,10 @@ - - + + \ No newline at end of file diff --git a/blog/2023/07/31/community-spotlight-july-2023.html b/blog/2023/07/31/community-spotlight-july-2023.html index 68195ed6c..b3caa047a 100644 --- a/blog/2023/07/31/community-spotlight-july-2023.html +++ b/blog/2023/07/31/community-spotlight-july-2023.html @@ -3,8 +3,8 @@ -Cadence Community Spotlight Update - July 2023 | Cadence - +Cadence Community Spotlight Update - July 2023 | Cadence + @@ -15,14 +15,14 @@ - - - + + + -

    Cadence Community Spotlight Update - July 2023

    · 3 min read
    Sharan Foga
    Director of Operations & Customer Success @ Encube Technologies

    Welcome to the latest of our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!

    +

    Cadence Community Spotlight Update - July 2023

    · 3 min read
    Sharan Foga
    Director of Operations & Customer Success @ Encube Technologies

    Welcome to the latest of our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!

    Please see below for a roundup of the highlights:

    Getting Started with Cadence

    Are you new to Cadence and want to understand the basic concepts and architecture? Well we have some great information for you!

    @@ -45,6 +45,6 @@

    Upcoming Eve
  • None
  • If you have any news or topics you'd like us to include in our next update then please join our Slack #community channel.

    -

    Please remember that this update is for you - so if you have any comments or feedback that could help us improve it then please share it with us in the #community Slack channel.

    +

    Please remember that this update is for you - so if you have any comments or feedback that could help us improve it then please share it with us in the #community Slack channel.

    \ No newline at end of file diff --git a/blog/2023/07/31/community-spotlight-july-2023.html.html b/blog/2023/07/31/community-spotlight-july-2023.html.html index 4c18c692c..c552dee77 100644 --- a/blog/2023/07/31/community-spotlight-july-2023.html.html +++ b/blog/2023/07/31/community-spotlight-july-2023.html.html @@ -2,10 +2,10 @@ - - + + \ No newline at end of file diff --git a/blog/2023/08/28/nondeterministic-errors-replayers-shadowers.html b/blog/2023/08/28/nondeterministic-errors-replayers-shadowers.html index d98f6a760..a16e92775 100644 --- a/blog/2023/08/28/nondeterministic-errors-replayers-shadowers.html +++ b/blog/2023/08/28/nondeterministic-errors-replayers-shadowers.html @@ -3,8 +3,8 @@ -Non-deterministic errors, replayers and shadowers | Cadence - +Non-deterministic errors, replayers and shadowers | Cadence + @@ -15,14 +15,14 @@ - - - + + + -

    Non-deterministic errors, replayers and shadowers

    · 3 min read
    Chris Qin
    Applications Developer @ Uber

    It is conceivable that developers constantly update their Cadence workflow code based upon new business use cases and needs. However, +

    Non-deterministic errors, replayers and shadowers

    · 3 min read
    Chris Qin
    Applications Developer @ Uber

    It is conceivable that developers constantly update their Cadence workflow code based upon new business use cases and needs. However, the definition of a Cadence workflow must be deterministic because behind the scenes cadence uses event sourcing to construct the workflow state by replaying the historical events stored for this specific workflow. Introducing components that are not compatible with an existing running workflow will yield to non-deterministic errors and sometimes developers find it tricky to debug. Consider the @@ -32,6 +32,6 @@

    Cadence workflow replayer is a testing component for replaying existing workflow histories against a workflow definition. You may think of replayer as a mock which will rerun your workflow with exactly the same history as your real workflow. The replaying logic is the same as the one used for processing workflow tasks. If it detects any incompatible changes, the replay test will fail. Workflow Replayer works well when verifying the compatibility against a small number of workflow histories. If there are lots of workflows in production that need to be verified, dumping all histories manually clearly won't work. Directly fetching histories from the cadence server might be a solution, but the time to replay all workflow histories might be too long for a test.

    Workflow Shadower is built on top of Workflow Replayer to address this problem. The basic idea of shadowing is: scan workflows based on the filters you defined, fetch history for each workflow in the scan result from Cadence server and run the replay test. It can be run either as a test to serve local development purposes or as a workflow in your worker to continuously replay production workflows.

    -

    You may find detailed instructions on how to use replayers and shadowers on our website. We will introduce versioning in the next coming blogs.

    +

    You may find detailed instructions on how to use replayers and shadowers on our website. We will introduce versioning in the next coming blogs.

    \ No newline at end of file diff --git a/blog/2023/08/28/nondeterministic-errors-replayers-shadowers.html.html b/blog/2023/08/28/nondeterministic-errors-replayers-shadowers.html.html index 355a441ad..420b5d11a 100644 --- a/blog/2023/08/28/nondeterministic-errors-replayers-shadowers.html.html +++ b/blog/2023/08/28/nondeterministic-errors-replayers-shadowers.html.html @@ -2,10 +2,10 @@ - - + + \ No newline at end of file diff --git a/blog/2023/08/31/community-spotlight-august-2023.html b/blog/2023/08/31/community-spotlight-august-2023.html index cf07da6cf..d0531841c 100644 --- a/blog/2023/08/31/community-spotlight-august-2023.html +++ b/blog/2023/08/31/community-spotlight-august-2023.html @@ -3,8 +3,8 @@ -Cadence Community Spotlight Update - August 2023 | Cadence - +Cadence Community Spotlight Update - August 2023 | Cadence + @@ -15,14 +15,14 @@ - - - + + + -

    Cadence Community Spotlight Update - August 2023

    · 3 min read
    Sharan Foga
    Director of Operations & Customer Success @ Encube Technologies

    Welcome to the latest of our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!

    +

    Cadence Community Spotlight Update - August 2023

    · 3 min read
    Sharan Foga
    Director of Operations & Customer Success @ Encube Technologies

    Welcome to the latest of our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!

    Please see below for a roundup of the highlights:

    More Cadence How To's

    You might have noticed that we have had a few more contributions to our blog from Chris Qin. Chris has been busy sharing insights, and tips on a few important Cadence topics. The objective is to help the community with any potential problems.

    @@ -84,6 +84,6 @@

    Upcoming Eve

    If you have any news or topics you'd like us to include in our next update then please join our Slack #community channel.

    -

    Please remember that this update is for you - so if you have any comments or feedback that could help us improve it then please share it with us in the #community Slack channel.

    +

    Please remember that this update is for you - so if you have any comments or feedback that could help us improve it then please share it with us in the #community Slack channel.

    \ No newline at end of file diff --git a/blog/2023/08/31/community-spotlight-august-2023.html.html b/blog/2023/08/31/community-spotlight-august-2023.html.html index ce1f39a7f..867bc5e0c 100644 --- a/blog/2023/08/31/community-spotlight-august-2023.html.html +++ b/blog/2023/08/31/community-spotlight-august-2023.html.html @@ -2,10 +2,10 @@ - - + + \ No newline at end of file diff --git a/blog/2023/11/30/community-spotlight-update-november-2023.html b/blog/2023/11/30/community-spotlight-update-november-2023.html index 60a907bde..6c08c3ca2 100644 --- a/blog/2023/11/30/community-spotlight-update-november-2023.html +++ b/blog/2023/11/30/community-spotlight-update-november-2023.html @@ -3,8 +3,8 @@ -Cadence Community Spotlight Update - November 2023 | Cadence - +Cadence Community Spotlight Update - November 2023 | Cadence + @@ -15,14 +15,14 @@ - - - + + + -

    Cadence Community Spotlight Update - November 2023

    · 4 min read
    Sharan Foga
    Director of Operations & Customer Success @ Encube Technologies

    Welcome to the latest of our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!

    +

    Cadence Community Spotlight Update - November 2023

    · 4 min read
    Sharan Foga
    Director of Operations & Customer Success @ Encube Technologies

    Welcome to the latest of our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!

    It's been a couple of months since our last update so we have a lot of updates to share with you.

    Please see below for a roundup of the highlights:

    Proposal for Cadence Native Authentication

    @@ -84,6 +84,6 @@

    Upcoming Eve
  • On Demand Webinar: Building With Cadence:Quantifiable Efficiency
  • If you have any news or topics you'd like us to include in our next update then please join our Slack #community channel.

    -

    Please remember that this update is for you - so if you have any comments or feedback that could help us improve it then please share it with us in the #community Slack channel.

    +

    Please remember that this update is for you - so if you have any comments or feedback that could help us improve it then please share it with us in the #community Slack channel.

    \ No newline at end of file diff --git a/blog/2023/11/30/community-spotlight-update-november-2023.html.html b/blog/2023/11/30/community-spotlight-update-november-2023.html.html index 3dad0673d..a6a148b73 100644 --- a/blog/2023/11/30/community-spotlight-update-november-2023.html.html +++ b/blog/2023/11/30/community-spotlight-update-november-2023.html.html @@ -2,10 +2,10 @@ - - + + \ No newline at end of file diff --git a/blog/2024/02/15/cadence-non-deterministic-common-qa.html b/blog/2024/02/15/cadence-non-deterministic-common-qa.html index 347d537f0..3f8913e2c 100644 --- a/blog/2024/02/15/cadence-non-deterministic-common-qa.html +++ b/blog/2024/02/15/cadence-non-deterministic-common-qa.html @@ -3,8 +3,8 @@ -Cadence non-derministic errors common question Q&A (part 1) | Cadence - +Cadence non-derministic errors common question Q&A (part 1) | Cadence + @@ -15,14 +15,14 @@ - - - + + + -

    Cadence non-derministic errors common question Q&A (part 1)

    · 3 min read
    Chris Qin
    Applications Developer @ Uber

    If I change code logic inside an Cadence activity (for example, my activity is calling database A but now I want it to call database B), will it trigger an non-deterministic error?

    +

    Cadence non-derministic errors common question Q&A (part 1)

    · 3 min read
    Chris Qin
    Applications Developer @ Uber

    If I change code logic inside an Cadence activity (for example, my activity is calling database A but now I want it to call database B), will it trigger an non-deterministic error?

    NO. This change will not trigger non-deterministic error.

    An Activity is the smallest unit of execution for Cadence and what happens inside activities are not recorded as historical events and therefore will not be replayed. In short, this change is deterministic and it is fine to modify logic inside activities.

    Does changing the workflow definition trigger non-determinstic errors?

    @@ -69,6 +69,6 @@

    If I have new business requirement and really need to change the definition of a workflow, what should I do?

    You may introduce a new workflow registered to your worker and divert traffic to it or use versioning for your workflow. Check out Cadence website for more information about versioning.

    Does changes to local activities' definition trigger non-deterministic errors?

    -

    Yes. Local activities are recorded and therefore replayed by Cadence. Imcompatible changes on local activity definitions will yield to non-deterministic errors.

    +

    Yes. Local activities are recorded and therefore replayed by Cadence. Imcompatible changes on local activity definitions will yield to non-deterministic errors.

    \ No newline at end of file diff --git a/blog/2024/02/15/cadence-non-deterministic-common-qa.html.html b/blog/2024/02/15/cadence-non-deterministic-common-qa.html.html index 8cbf74a93..e79f0f686 100644 --- a/blog/2024/02/15/cadence-non-deterministic-common-qa.html.html +++ b/blog/2024/02/15/cadence-non-deterministic-common-qa.html.html @@ -2,10 +2,10 @@ - - + + \ No newline at end of file diff --git a/blog/2024/07/11/2024-07-11-yearly-roadmap-update/yearly-roadmap-update.html b/blog/2024/07/11/2024-07-11-yearly-roadmap-update/yearly-roadmap-update.html index ae1affe7b..e58277afa 100644 --- a/blog/2024/07/11/2024-07-11-yearly-roadmap-update/yearly-roadmap-update.html +++ b/blog/2024/07/11/2024-07-11-yearly-roadmap-update/yearly-roadmap-update.html @@ -3,8 +3,8 @@ -2024 Cadence Yearly Roadmap Update | Cadence - +2024 Cadence Yearly Roadmap Update | Cadence + @@ -15,14 +15,14 @@ - - - + + + -

    2024 Cadence Yearly Roadmap Update

    · 17 min read
    Ender Demirkaya
    Senior Manager at Uber, Cadence. Author of the Software Engineering Handbook

    Introduction

    +

    2024 Cadence Yearly Roadmap Update

    · 17 min read
    Ender Demirkaya
    Senior Manager at Uber, Cadence. Author of the Software Engineering Handbook

    Introduction

    If you haven’t heard about Cadence, this section is for you. In a short description, Cadence is a code-driven workflow orchestration engine. The definition itself may not tell enough, so it would help splitting it into three parts:

    • What’s a workflow? (everyone has a different definition)
    • @@ -30,7 +30,7 @@
    • Benefits of Cadence

    What is a Workflow?

    -

    workflow.png

    +

    workflow.png

    In the simplest definition, it is “a multi-step execution”. Step here represents individual operations that are a little heavier than small in-process function calls. Although they are not limited to those: it could be a separate service call, processing a large dataset, map-reduce, thread sleep, scheduling next run, waiting for an external input, starting a sub workflow etc. It’s anything a user thinks as a single unit of logic in their code. Those steps often have dependencies among themselves. Some steps, including the very first step, might require external triggers (e.g. button click) or schedules. In the more broader meaning, any multi-step function or service is a workflow in principle.

    While the above is a more correct way to define workflows, specialized workflows are more widely known: such as data pipelines, directed acyclic graphs, state machines, cron jobs, (micro)service orchestration, etc. This is why typically everyone has a different workflow meaning in mind. Specialized workflows also have simplified interfaces such as UI, configs or a DSL (domain specific language) to make it easy to express the workflow definition.

    Code-Driven Workflows

    @@ -38,7 +38,7 @@

    Code-D

    What happens here is users love the seamless way of creating workflow applications and try to fit more scenarios into it. Natural user tendency is to be able to write any program with such simplicity and confidence.

    Given this natural evolution of workflow requirements, it’s better to have a code-driven workflow orchestration engine that can meet any future needs with its powerful expressiveness. On top of this, it is ideal if the interface is seamless, where engineers learn as little as possible and change almost nothing in their local code to write a distributed and durable workflow code. This would virtually remove any limitation and enable implementing any service as a workflow. This is what Cadence aims for.

    Benefits

    -

    cadence-benefits.png

    +

    cadence-benefits.png

    With Cadence, many overheads that need to be built for any well-supported service come for free. Here are some highlights (see cadenceworkflow.io):

    • Disaster recovery is supported by default through data replication and failovers
    • @@ -136,6 +136,6 @@

      CommunitySlack: https://uber-cadence.slack.com/

      Github: https://github.com/cadence-workflow/cadence

      Since last year, we have been contacted by various companies to take on bigger projects on the Cadence project. As we have been investing in code coverage and refactoring Cadence for a cleaner codebase, this will be a lot easier now. Let us know if you have project ideas to contribute or if you’d like to pick something we already planned.

      -

      Our monthly community meetings are still ongoing, too. That is the best place to get heard and be involved in our decision-making process. Let us know so we can send you an invite. We are also working on a broader governing model to open up this project to more people. Stay tuned for updates on this topic!

    +

    Our monthly community meetings are still ongoing, too. That is the best place to get heard and be involved in our decision-making process. Let us know so we can send you an invite. We are also working on a broader governing model to open up this project to more people. Stay tuned for updates on this topic!

    \ No newline at end of file diff --git a/blog/2024/07/11/2024-07-11-yearly-roadmap-update/yearly-roadmap-update.html.html b/blog/2024/07/11/2024-07-11-yearly-roadmap-update/yearly-roadmap-update.html.html index 5cb8c3e1b..3afdf1d78 100644 --- a/blog/2024/07/11/2024-07-11-yearly-roadmap-update/yearly-roadmap-update.html.html +++ b/blog/2024/07/11/2024-07-11-yearly-roadmap-update/yearly-roadmap-update.html.html @@ -2,10 +2,10 @@ - - + + \ No newline at end of file diff --git a/blog/2024/09/05/workflow-specific-rate-limits.html b/blog/2024/09/05/workflow-specific-rate-limits.html index 4c2a19f0f..8f91e9058 100644 --- a/blog/2024/09/05/workflow-specific-rate-limits.html +++ b/blog/2024/09/05/workflow-specific-rate-limits.html @@ -3,8 +3,8 @@ -Minimizing blast radius in Cadence: Introducing Workflow ID-based Rate Limits | Cadence - +Minimizing blast radius in Cadence: Introducing Workflow ID-based Rate Limits | Cadence + @@ -15,14 +15,14 @@ - - - + + + -

    Minimizing blast radius in Cadence: Introducing Workflow ID-based Rate Limits

    · 7 min read
    Jakob Haahr Taankvist
    Software Engineer II @ Uber

    At Uber, we run several big multitenant Cadence clusters with hundreds of domains in each. The clusters being multi-tenant means potential noisy neighbor effects between domains.

    +

    Minimizing blast radius in Cadence: Introducing Workflow ID-based Rate Limits

    · 7 min read
    Jakob Haahr Taankvist
    Software Engineer II @ Uber

    At Uber, we run several big multitenant Cadence clusters with hundreds of domains in each. The clusters being multi-tenant means potential noisy neighbor effects between domains.

    An essential aspect of avoiding this is managing how workflows interact with our infrastructure to prevent any single workflow from causing instability for the whole cluster. To this end, we are excited to introduce Workflow ID-based rate limits — a new feature designed to protect our clusters from problematic workflows and ensure stability across the board.

    Why Workflow ID-based Rate Limits?

    We already have rate limits for how many requests can be sent to a domain. However, since Cadence is sharded on the workflow ID, a user-provided input, an overused workflow with a particular id might overwhelm a shard by making too many requests. There are two main ways this happens:

    @@ -99,6 +99,6 @@

    {
    "level":"info",
    "ts":"2024-09-02T08:47:12.843Z",
    "msg":"Rate limiting workflowID",
    "service":"cadence-history",
    "request-type":"external",
    "wf-domain-id":"fc0c7fcb-5796-4c80-b0d7-10bbbc66614e",
    "wf-domain-name":"samples-domain",
    "wf-id":"test",
    "logging-call-at":"cache.go:175"
    }

    Conclusion

    Implementing these rate limits highly improves the reliability of a Cadence cluster, as users now cannot send too many requests to a single shard. This fine-grained control helps in maintaining optimal performance and enhances the ability to forecast and mitigate potential issues before they impact the service.

    -

    Workflow ID-based rate limits are a significant step forward in our ongoing effort to provide a robust and efficient workflow management service. By preventing hot shards and ensuring equitable resource distribution, we can offer more reliable performance, even under peak loads. We encourage all Cadence users to familiarize themselves with these new limits and adjust their workflow configurations to achieve optimal results.

    +

    Workflow ID-based rate limits are a significant step forward in our ongoing effort to provide a robust and efficient workflow management service. By preventing hot shards and ensuring equitable resource distribution, we can offer more reliable performance, even under peak loads. We encourage all Cadence users to familiarize themselves with these new limits and adjust their workflow configurations to achieve optimal results.

    \ No newline at end of file diff --git a/blog/2024/09/05/workflow-specific-rate-limits.html.html b/blog/2024/09/05/workflow-specific-rate-limits.html.html index 97adb4597..99784f929 100644 --- a/blog/2024/09/05/workflow-specific-rate-limits.html.html +++ b/blog/2024/09/05/workflow-specific-rate-limits.html.html @@ -2,10 +2,10 @@ - - + + \ No newline at end of file diff --git a/blog/2024/10/01/announcing-cadence-helm-charts-v0.html b/blog/2024/10/01/announcing-cadence-helm-charts-v0.html index ace27f6bd..f9f3681af 100644 --- a/blog/2024/10/01/announcing-cadence-helm-charts-v0.html +++ b/blog/2024/10/01/announcing-cadence-helm-charts-v0.html @@ -3,8 +3,8 @@ -Announcement: Cadence Helm Charts v0 Release | Cadence - +Announcement: Cadence Helm Charts v0 Release | Cadence + @@ -15,14 +15,14 @@ - - - + + + -

    Announcement: Cadence Helm Charts v0 Release

    · 3 min read
    Taylan Isikdemir
    Sr. Staff Software Engineer @ Uber

    We’ve heard your feedback: deploying Cadence has been a challenge, especially with limited documentation on operational aspects. So far, we’ve only provided a few docker compose files to help you get started on a development machine. However, deploying and managing Cadence at scale requires a deep understanding of underlying services, configurations and their dependencies.

    +

    Announcement: Cadence Helm Charts v0 Release

    · 3 min read
    Taylan Isikdemir
    Sr. Staff Software Engineer @ Uber

    We’ve heard your feedback: deploying Cadence has been a challenge, especially with limited documentation on operational aspects. So far, we’ve only provided a few docker compose files to help you get started on a development machine. However, deploying and managing Cadence at scale requires a deep understanding of underlying services, configurations and their dependencies.

    To address these challenges, we’re launching several initiatives to make it easier to deploy and operate Cadence clusters. These include deployment specs for common scenarios, monitoring dashboards, alerts, runbooks, and more comprehensive documentation.

    Introducing Cadence Kubernetes Helm Chart v0

    Today, we are happy to announce the release of Cadence Kubernetes Helm Chart v0. This will be the starting point for standardizing Cadence deployments on Kubernetes. We chose Kubernetes because it's the leading compute platform, but Cadence remains flexible and can run on any infrastructure.

    @@ -58,6 +58,6 @@

    C

    Next Steps

    Since this is an early release, we would love to hear from you. Feel free to start discussions or report issues.

    Also check out the contribution guideline if you are interested to contribute. Don't hesitate to send a PR and ping us over slack if we miss it.

    -

    P.S. Huge thanks to our summer intern Nikita Bhardwaj for kickstarting the Cadence Helm charts initiative.

    +

    P.S. Huge thanks to our summer intern Nikita Bhardwaj for kickstarting the Cadence Helm charts initiative.

    \ No newline at end of file diff --git a/blog/2024/10/01/announcing-cadence-helm-charts-v0.html.html b/blog/2024/10/01/announcing-cadence-helm-charts-v0.html.html index 6c8955135..1cacbd39e 100644 --- a/blog/2024/10/01/announcing-cadence-helm-charts-v0.html.html +++ b/blog/2024/10/01/announcing-cadence-helm-charts-v0.html.html @@ -2,10 +2,10 @@ - - + + \ No newline at end of file diff --git a/blog/2024/11/18/cadence-workflows-github-organization.html b/blog/2024/11/18/cadence-workflows-github-organization.html index 79eb99f48..5d8096b52 100644 --- a/blog/2024/11/18/cadence-workflows-github-organization.html +++ b/blog/2024/11/18/cadence-workflows-github-organization.html @@ -3,8 +3,8 @@ -Cadence Repositories Have Moved! | Cadence - +Cadence Repositories Have Moved! | Cadence + @@ -15,14 +15,14 @@ - - - + + + -

    Cadence Repositories Have Moved!

    · One min read
    Josué Alexander Ibarra
    Developer Advocate @ Uber

    We’re excited to announce that all Cadence GitHub repositories have been consolidated under the cadence-workflow organization! 🎉

    +

    Cadence Repositories Have Moved!

    · One min read
    Josué Alexander Ibarra
    Developer Advocate @ Uber

    We’re excited to announce that all Cadence GitHub repositories have been consolidated under the cadence-workflow organization! 🎉

    Previously, Cadence repositories were distributed across multiple organizations at Uber: uber, uber-go, uber-common. To improve developer cohesiveness and simplify access, the Cadence Core team has migrated all open-source repositories to the cadence-workflow organization.

    For example, our main repository has moved from:

    👉 uber/cadence

    @@ -30,6 +30,6 @@

    👉 cadence-workflow/cadence

    You can find the full list of Cadence repositories here 👉 orgs/cadence-workflow/repositories

    This move reflects our continued commitment to growing the Cadence community and making the project even more accessible to contributors and users. Please update your bookmarks and links accordingly.

    -

    Thank you for being part of the Cadence journey! 🚀

    +

    Thank you for being part of the Cadence journey! 🚀

    \ No newline at end of file diff --git a/blog/2024/11/18/cadence-workflows-github-organization.html.html b/blog/2024/11/18/cadence-workflows-github-organization.html.html index c5a07ad93..eb50018a8 100644 --- a/blog/2024/11/18/cadence-workflows-github-organization.html.html +++ b/blog/2024/11/18/cadence-workflows-github-organization.html.html @@ -2,10 +2,10 @@ - - + + \ No newline at end of file diff --git a/blog/2024/3/11/community-spotlight-update-march-2024.html b/blog/2024/3/11/community-spotlight-update-march-2024.html index bede02b1c..58ab0a1dd 100644 --- a/blog/2024/3/11/community-spotlight-update-march-2024.html +++ b/blog/2024/3/11/community-spotlight-update-march-2024.html @@ -3,8 +3,8 @@ -Cadence Community Spotlight Update - March 2024 | Cadence - +Cadence Community Spotlight Update - March 2024 | Cadence + @@ -15,14 +15,14 @@ - - - + + + -

    Cadence Community Spotlight Update - March 2024

    · 3 min read
    Kevin Corbett
    Open Source Community Manager | @instaclustr @NetApp

    Welcome back to the latest in our regular Cadence community spotlight updates where we aim to deliver you news from in and around the Cadence community! +

    Cadence Community Spotlight Update - March 2024

    · 3 min read
    Kevin Corbett
    Open Source Community Manager | @instaclustr @NetApp

    Welcome back to the latest in our regular Cadence community spotlight updates where we aim to deliver you news from in and around the Cadence community! It’s been a few months since our last update, so I have a bunch of exciting updates to share.

    Let’s get started!

    Proposal for Cadence Plugin System

    @@ -60,6 +60,6 @@

    Recent Events< That’s all for this month!

    Your engagement and contributions are what make the Cadence community thrive. Whether you have innovative ideas, insightful feedback, or just want to chat about Cadence, we encourage you to join our Slack #community channel.

    We're committed to making this update as useful and informative as possible, so please share any feedback or suggestions you might have. Let’s keep building a vibrant and collaborative Cadence community together!

    -

    Looking forward to sharing more exciting updates next month!

    +

    Looking forward to sharing more exciting updates next month!

    \ No newline at end of file diff --git a/blog/2024/3/11/community-spotlight-update-march-2024.html.html b/blog/2024/3/11/community-spotlight-update-march-2024.html.html index af517b83a..24485eab5 100644 --- a/blog/2024/3/11/community-spotlight-update-march-2024.html.html +++ b/blog/2024/3/11/community-spotlight-update-march-2024.html.html @@ -2,10 +2,10 @@ - - + + \ No newline at end of file diff --git a/blog/archive.html b/blog/archive.html index f98344b7a..3a8111a33 100644 --- a/blog/archive.html +++ b/blog/archive.html @@ -3,8 +3,8 @@ -Archive | Cadence - +Archive | Cadence + @@ -15,13 +15,13 @@ - - - + + + -

    Archive

    Archive

    +

    Archive

    Archive

    \ No newline at end of file diff --git a/blog/archive.html.html b/blog/archive.html.html index 32fce0472..8fdf698b5 100644 --- a/blog/archive.html.html +++ b/blog/archive.html.html @@ -2,10 +2,10 @@ - - + + \ No newline at end of file diff --git a/blog/atom.xml b/blog/atom.xml index 49a149bff..643f9d5ec 100644 --- a/blog/atom.xml +++ b/blog/atom.xml @@ -1,16 +1,16 @@ - https://cadenceworkflow.io/blog + https://cadenceworkflow.io/Cadence-Docs/blog Cadence Blog 2024-11-18T14:00:00.000Z https://github.com/jpmonette/feed - + Cadence Blog - https://cadenceworkflow.io/img/favicon.ico + https://cadenceworkflow.io/Cadence-Docs/img/favicon.ico <![CDATA[Cadence Repositories Have Moved!]]> - https://cadenceworkflow.io/blog/2024/11/18/cadence-workflows-github-organization - + https://cadenceworkflow.io/Cadence-Docs/blog/2024/11/18/cadence-workflows-github-organization + 2024-11-18T14:00:00.000Z We’re excited to announce that all Cadence GitHub repositories have been consolidated under the cadence-workflow organization! 🎉

    @@ -30,12 +30,12 @@
    <![CDATA[Zonal Isolation for Cadence Workflows]]> - https://cadenceworkflow.io/blog/zonal-isolation-v1/zonal-isolation-v1 - + https://cadenceworkflow.io/Cadence-Docs/blog/zonal-isolation-v1/zonal-isolation-v1 + 2024-10-14T00:00:00.000Z At Uber, we want to achieve regional resilience such that losing a zone within a region can be tolerated without requiring a cross-region failover. We also want to make sure that losing a zone only affects a subset of workload, at most, rather than everything. However, in Cadence-based systems, the workload in a region is distributed randomly across all workers in the region at a “task-level granularity”, which means a workflow may be worked on by any worker in the region where the domain is active. To achieve this goal, we introduced Zonal Isolation for Cadence Workflows - a feature designed to pin workflows to the zone they are started in, so that zonal isolation can be achieved at a workflow-level.

    -

    What is Zonal Isolation for Cadence Workflows?

    +

    What is Zonal Isolation for Cadence Workflows?

    At high-level, Zonal Isolation for Cadence Workflows can be thought in 2 levels:

    1. Task-level isolation: All decision tasks and activity tasks of a workflow are only processed by workers from the zone where the workflow was started
    2. @@ -43,13 +43,13 @@

    Infrastructure-level isolation is quite challenging to implement as it requires significant changes to the core design of the Cadence server. Due to the complexity involved, support for this feature is not planned for the foreseeable future.

    As a result, the focus remains on achieving task-level zonal isolation outside the Cadence server, which offers a more practical and immediate way to improve system resilience. It provides the capability of ensuring that an unhealthy zone (i.e. bad deployment of workers) only affect a subset of workflows (started from a certain zone) rather than every workflow in a Cadence domain.

    -

    How Zonal Isolation Works in Cadence?

    -

    Architecture

    +

    How Zonal Isolation Works in Cadence?

    +

    Architecture

    Here is what the architecture of a zonally isolated Cadence-based system looks like: -zonal isolation overview +zonal isolation overview

    Fig: Workflows started in one zone are only dispatched to workers from the same zone. Colors to emphasize pinning.

    -

    Implementation

    -

    Determine the zone of a workflow and workers

    +

    Implementation

    +

    Determine the zone of a workflow and workers

    To ensure that tasks are dispatched to workers in the same zone as the workflows, we must identify the origin zone of both. The zone of a workflow is determined by the origin zone of the StartWorkflowExecution request, while the zone of workers is determined by the origin zone of the PollForDecisionTask and PollForActivityTask requests. There are three possible ways to determine the origin zone for these requests:

    • Uber's Approach: Let Cadence SDK set the origin zone in the headers of the requests before sending the request to Cadence.
    • @@ -57,27 +57,27 @@
    • Determine the origin zone of the requests from the zone of the cadence-frontend instance receiving the request, if the network layer has already achieved zonal isolation.

    The 2nd approach is the ideal one, but Uber's network infrastructure doesn't provide such headers and the network layer is not ready for zonal isolation. As a result, we adopt the 1st approach. At Uber, we have internal libraries in Go and Java acting as wrappers around Cadence SDK injecting necessary configurations. These libraries have been updated to include the origin zone in the request headers using a header called cadence-client-isolation-group.

    -

    How to dispatch tasks to workers from the same zone?

    +

    How to dispatch tasks to workers from the same zone?

    To implement task-level isolation, we introduce a new dimension to the tasklist — isolation group. When a workflow is initiated, the origin zone of the workflow is stored in the database. Each time a decision or activity task is dispatched to cadence-matching, the workflow's origin zone is used as the isolation group for that task.

    When a worker sends a PollForDecisionTask or PollForActivityTask request to cadence-matching, the request is labeled with the worker's isolation group (i.e., the worker's zone). Tasks are then dispatched only to poller requests that have the same isolation group, ensuring that tasks are processed by workers in the same zone as the workflow's origin.

    -

    How to handle workflows from a drained zone?

    +

    How to handle workflows from a drained zone?

    In the event of an outage, such as a bad deployment, customers may want to drain workers from a specific zone to mitigate the impact. There are two types of drains that can occur:

    1. Implicit drain: Workers from a zone completely stop operating, either due to failures or manual shutdowns.
    2. Explicit drain: Customers explicitly mark workers from a zone as drained.

    Within cadence-matching, a list of pollers is maintained for each tasklist, tracking the zone from which the pollers originate. An implicit drain can be detected by checking whether there are any active pollers from a particular zone. If a zone is drained (either explicitly or implicitly), workflows that were started in that zone will be reassigned and spread to workers in the remaining healthy zones.

    -
    How to drain a zone explicitly?
    +
    How to drain a zone explicitly?

    Explicitly draining a zone can be done at two levels:

    1. Domain-level drain: This applies to a specific domain, allowing the zone to be drained only for workflows within that domain.
    2. Cluster-level drain: This applies to the entire Cadence cluster, draining the zone for all domains and workflows within the cluster.

    For domain-level drain, the draining status is stored in domains table. For cluster-level drain, the status is stored in cluster_config table.

    -

    How to enable Zonal Isolation?

    -

    Server Update

    +

    How to enable Zonal Isolation?

    +

    Server Update

    In order to enable this feature, please upgrade Cadence server to v1.2.1 or later.

    -

    NOTE: If you're not using the provided main binary located in cmd/server, you must adopt this middleware. Depends on the appoach to determine the origin zone of requests, you can adopt this middleware or build your own middleware using partition.ContextWithConfig function to inject origin zone into the context.

    +

    NOTE: If you're not using the provided main binary located in cmd/server, you must adopt this middleware. Depends on the appoach to determine the origin zone of requests, you can adopt this middleware or build your own middleware using partition.ContextWithConfig function to inject origin zone into the context.

    This feature is controlled by 2 dynamic config properties.

    • system.allIsolationGroups: This property provides the list of available zones within a region.
    • @@ -87,8 +87,8 @@ It’s important to note that any update to the system.allIsolationGroups<

      An example configuration using the file based dynamic configuration could look like this:

      system.allIsolationGroups:
      - value: []
      constraints: {}
      - value: ["dca1", "dca2", "dca3"]
      constraints:
      clusterName: prod-dca
      - value: ["phx1", "phx2", "phx3"]
      constraints:
      clusterName: prod-phx
      system.enableTasklistIsolation:
      - value: false
      constraints: {}
      - value: true
      constraints:
      domainName: samples-domain

      In this example, the Cadence cluster spans two regions, each containing three zones: dca1, dca2, dca3 in the dca region and phx1, phx2, phx3 in the phx region. Zonal isolation is enabled only for the samples-domain, while it remains disabled for other domains.

      -

      SDK Update

      -

      NOTE: This update is only necessary if you're using the 1st approach to determine the origin zone of requests.

      +

      SDK Update

      +

      NOTE: This update is only necessary if you're using the 1st approach to determine the origin zone of requests.

      To support Zonal Isolation, please upgrade your SDK versions:

      • Go SDK: Upgrade to v1.0.2 or later.
      • @@ -96,17 +96,17 @@ It’s important to note that any update to the system.allIsolationGroups<

      For Java SDK users, set the isolationGroup field to the zone of the instance when creating serviceClient.

      For Go SDK users, set the isolationGroup field to the zone of the instance when creating Worker. Additionally, you need to use this method to wrap workflowserviceclient.Interface.

      -

      How to drain a zone explicitly?

      +

      How to drain a zone explicitly?

      Drains can be done via the Admin APIs of cadence-frontend or CLI.

      You can check the help message for the CLI by running:

      cadence admin isolation-groups -h
      -

      Monitoring

      +

      Monitoring

      A new metric is introduced to help detect the leakage of tasks and skewness of traffic.

      isolation_task_matches_per_tl: This is a counter that counts the number of tasks polled by workers. The metric is tagged with the domain, tasklist name, tasklist type, the origin zone of the workflow and the origin zone of the worker polling the task.

      This metric can be used in the following ways:

      Detecting task leakage: By grouping tasks based on the origin zones of both the workflows and workers, you can identify tasks that have leaked, i.e., tasks assigned to workers in zones different from the workflow's origin zone.

      Identifying traffic skewness: By grouping tasks based solely on the origin zones of workflows, you can determine if traffic is disproportionately distributed among the zones, helping to detect any uneven load or traffic imbalance across zones.

      -

      Status at Uber

      +

      Status at Uber

      • We launched this feature at Uber in July 2023. More than 100 domains have Zonal Isolation enabled.
      • However, as of 2024, the rollout of Zonal Isolation is paused due to a traffic skewness issue: @@ -115,7 +115,7 @@ It’s important to note that any update to the system.allIsolationGroups<
    -

    Next Step

    +

    Next Step

    Currently, Zonal Isolation is implemented as hard isolation, where tasks are strictly limited to the same zone as the originating workflow. To address the traffic skewness issue, we are working on iterating this feature to introduce soft isolation. This relaxed version will allow for some task leakage between zones if traffic skewness is detected, ensuring better worker utilization and reducing latency.

    This enhancement is one of our major ongoing projects, and we plan to share more details in a future blog post once it is launched.

    ]]>
    @@ -127,15 +127,15 @@ It’s important to note that any update to the system.allIsolationGroups<
    <![CDATA[Announcement: Cadence Helm Charts v0 Release]]> - https://cadenceworkflow.io/blog/2024/10/01/announcing-cadence-helm-charts-v0 - + https://cadenceworkflow.io/Cadence-Docs/blog/2024/10/01/announcing-cadence-helm-charts-v0 + 2024-10-01T00:00:00.000Z We’ve heard your feedback: deploying Cadence has been a challenge, especially with limited documentation on operational aspects. So far, we’ve only provided a few docker compose files to help you get started on a development machine. However, deploying and managing Cadence at scale requires a deep understanding of underlying services, configurations and their dependencies.

    To address these challenges, we’re launching several initiatives to make it easier to deploy and operate Cadence clusters. These include deployment specs for common scenarios, monitoring dashboards, alerts, runbooks, and more comprehensive documentation.

    -

    Introducing Cadence Kubernetes Helm Chart v0

    +

    Introducing Cadence Kubernetes Helm Chart v0

    Today, we are happy to announce the release of Cadence Kubernetes Helm Chart v0. This will be the starting point for standardizing Cadence deployments on Kubernetes. We chose Kubernetes because it's the leading compute platform, but Cadence remains flexible and can run on any infrastructure.

    -

    How to Get Started

    +

    How to Get Started

    Helm must be installed to use the charts. Please refer to Helm's documentation to get started.

    Once Helm has been set up correctly, add the repo as follows:

    helm repo add cadence https://uber.github.io/cadence-charts
    @@ -145,7 +145,7 @@ It’s important to note that any update to the system.allIsolationGroups<

    To uninstall the chart:

    helm delete my-cadence

    See CONTRIBUTING.md for details on how to validate the deployment by running sample workflows.

    -

    Current State of the Chart

    +

    Current State of the Chart

    There were a few community-created Cadence Helm charts but they were not actively maintained and had a few glitches that Cadence team @Uber wasn't able to provide support for. With the introduction of the new official Cadence Helm chart, our team is committed to provide support and evolve it with input from community.

    The v0 chart contains only the basics at the moment:

      @@ -164,7 +164,7 @@ It’s important to note that any update to the system.allIsolationGroups<
    • Custom annotations/lables/tolerations etc.
    • Support for ingress
    -

    Next Steps

    +

    Next Steps

    Since this is an early release, we would love to hear from you. Feel free to start discussions or report issues.

    Also check out the contribution guideline if you are interested to contribute. Don't hesitate to send a PR and ping us over slack if we miss it.

    P.S. Huge thanks to our summer intern Nikita Bhardwaj for kickstarting the Cadence Helm charts initiative.

    ]]>
    @@ -176,13 +176,13 @@ It’s important to note that any update to the system.allIsolationGroups<
    <![CDATA[Minimizing blast radius in Cadence: Introducing Workflow ID-based Rate Limits]]> - https://cadenceworkflow.io/blog/2024/09/05/workflow-specific-rate-limits - + https://cadenceworkflow.io/Cadence-Docs/blog/2024/09/05/workflow-specific-rate-limits + 2024-09-05T00:00:00.000Z At Uber, we run several big multitenant Cadence clusters with hundreds of domains in each. The clusters being multi-tenant means potential noisy neighbor effects between domains.

    An essential aspect of avoiding this is managing how workflows interact with our infrastructure to prevent any single workflow from causing instability for the whole cluster. To this end, we are excited to introduce Workflow ID-based rate limits — a new feature designed to protect our clusters from problematic workflows and ensure stability across the board.

    -

    Why Workflow ID-based Rate Limits?

    +

    Why Workflow ID-based Rate Limits?

    We already have rate limits for how many requests can be sent to a domain. However, since Cadence is sharded on the workflow ID, a user-provided input, an overused workflow with a particular id might overwhelm a shard by making too many requests. There are two main ways this happens:

    1. A user starts, or signals the same workflow ID too aggressively,
    2. @@ -192,7 +192,7 @@ It’s important to note that any update to the system.allIsolationGroups<
      func Workflow(ctx workflow.Context, input sampleInput) (string, error) {
      ...
      for _, elem := range longList {
      err := workflow.ExecuteActivity(ctx, QuickActivity, elem).Get(ctx, nil)
      }
      ...
      }

      This heavy load creates what we call hot shards. Hot shards degrade performance not just for the workflow causing the issue, but for all workflows that interact with the affected shard. This can grow to a point where the whole cluster becomes unstable.

      Now, with Workflow ID-based rate limits, we limit the number of external calls and actions per second for each individual workflow, reducing the blast radius (impact on the cluster) of a badly behaved workflow to an absolute minimum where only the offending workflow is impacted.

      -

      Why not Shard Rate Limits?

      +

      Why not Shard Rate Limits?

      An obvious question is “why don’t we rate limit the requests to the shard?”. After all, the shard is what we want to protect. We have several reasons for choosing to rate limit the workflow ID instead of the shard:

      • Hashing The workflow ID to shard is random. This means that rate limiting a workflow is a good proxy for rate limiting a shard. The likelihood that many requests from different workflows hit the same shard is very low.
      • @@ -200,7 +200,7 @@ It’s important to note that any update to the system.allIsolationGroups<
      • Noisy neighbors Shards are shared across the different domains in a Cadence cluster. If a user is sending too many requests to a shard, we would choose to rate limit requests to that shard. Since other users in other domains are also using the shard, they will also be rate limited. Rate limiting users of a healthy domain because of requests from a completely different domain goes against the isolation the domains are meant to ensure.
      -

      How Does It Work?

      +

      How Does It Work?

      Workflow ID-based rate limits are set for all workflow IDs in a domain. If the external limit for a domain is e.g. set to 100 it means that any single workflow ID in that domain can at most be signaled 100 times a second. The rate limits are implemented in two main areas:

      1. @@ -210,7 +210,7 @@ Rate limiting users of a healthy domain because of requests from a completely di

        Actions Within a Workflow This limit controls the number of tasks processed per second within a workflow, focusing on managing decision tasks and activity tasks. When these limits are reached, Cadence slows down task processing without requiring any intervention from the user, though they might notice an increase in task execution time, eventually causing timeouts.

      -

      How do I Enable It?

      +

      How do I Enable It?

      The limits are controlled using six dynamic config properties, three for the internal limits, and a corresponding three for the external limits, all with a domain filter, so the limits can be controlled for each domain.

      • history.workflowIDCacheInternalEnabled
        @@ -236,7 +236,7 @@ Rate limiting users of a healthy domain because of requests from a completely di
        history.workflowIDCacheExternalEnabled:
        - value: true
        constraints: {}
        history.workflowIDExternalRateLimitEnabled:
        - value: false
        constraints:
        domainName: samples-domain
        - value: true
        constraints: {}
        history.workflowIDExternalRPS:
        - value: 100
        constraints: {}

        Here only the external rate limits are enabled. The internal rate limits have the same structure. We see that ‌the rate limiting is enabled for all domains, with a max RPS of 100. The domain samples-domain is however running in shadow mode, so its requests are not rate limited, but metrics and logs are still emitted.

        The exact RPS to set for a specific domain and cluster, depends on many things, such as the number of shards, the selected persistent layer, the general load on the cluster etc.

        -

        Monitoring and Troubleshooting

        +

        Monitoring and Troubleshooting

        The new feature introduces both new metrics and new logs. The new logs help us find workflows that are being rate limited, while the new metrics let us see if domains are being rate limited, and how close to being rate limited they are.

        There are four new metrics, two for internal limits and two corresponding metrics for external limits, all emitted from history.

          @@ -255,7 +255,7 @@ Rate limiting users of a healthy domain because of requests from a completely di

        These metrics let us monitor and alert on the new rate limits. Additionally, when breaking a rate limit, the history service will emit an info log with the message “Rate limiting workflowID”, these logs are tagged with the workflowID that is being limited, so it is easy to find the offending workflow. An example log would look like this:

        {
        "level":"info",
        "ts":"2024-09-02T08:47:12.843Z",
        "msg":"Rate limiting workflowID",
        "service":"cadence-history",
        "request-type":"external",
        "wf-domain-id":"fc0c7fcb-5796-4c80-b0d7-10bbbc66614e",
        "wf-domain-name":"samples-domain",
        "wf-id":"test",
        "logging-call-at":"cache.go:175"
        }
        -

        Conclusion

        +

        Conclusion

        Implementing these rate limits highly improves the reliability of a Cadence cluster, as users now cannot send too many requests to a single shard. This fine-grained control helps in maintaining optimal performance and enhances the ability to forecast and mitigate potential issues before they impact the service.

        Workflow ID-based rate limits are a significant step forward in our ongoing effort to provide a robust and efficient workflow management service. By preventing hot shards and ensuring equitable resource distribution, we can offer more reliable performance, even under peak loads. We encourage all Cadence users to familiarize themselves with these new limits and adjust their workflow configurations to achieve optimal results.

        ]]> @@ -266,27 +266,27 @@ Rate limiting users of a healthy domain because of requests from a completely di <![CDATA[2024 Cadence Yearly Roadmap Update]]> - https://cadenceworkflow.io/blog/2024/07/11/2024-07-11-yearly-roadmap-update/yearly-roadmap-update - + https://cadenceworkflow.io/Cadence-Docs/blog/2024/07/11/2024-07-11-yearly-roadmap-update/yearly-roadmap-update + 2024-07-11T00:00:00.000Z - Introduction + Introduction

        If you haven’t heard about Cadence, this section is for you. In a short description, Cadence is a code-driven workflow orchestration engine. The definition itself may not tell enough, so it would help splitting it into three parts:

        • What’s a workflow? (everyone has a different definition)
        • Why does it matter to be code-driven?
        • Benefits of Cadence
        -

        What is a Workflow?

        -

        workflow.png

        +

        What is a Workflow?

        +

        workflow.png

        In the simplest definition, it is “a multi-step execution”. Step here represents individual operations that are a little heavier than small in-process function calls. Although they are not limited to those: it could be a separate service call, processing a large dataset, map-reduce, thread sleep, scheduling next run, waiting for an external input, starting a sub workflow etc. It’s anything a user thinks as a single unit of logic in their code. Those steps often have dependencies among themselves. Some steps, including the very first step, might require external triggers (e.g. button click) or schedules. In the more broader meaning, any multi-step function or service is a workflow in principle.

        While the above is a more correct way to define workflows, specialized workflows are more widely known: such as data pipelines, directed acyclic graphs, state machines, cron jobs, (micro)service orchestration, etc. This is why typically everyone has a different workflow meaning in mind. Specialized workflows also have simplified interfaces such as UI, configs or a DSL (domain specific language) to make it easy to express the workflow definition.

        -

        Code-Driven Workflows

        +

        Code-Driven Workflows

        Over time, any workflow interface evolves to support more scenarios. For any non-code (UI, config, DSL) technology, this means more APIs, concepts and tooling. However, eventually, the technology’s capabilities will be limited by its interface itself. Otherwise the interface will get more complicated to operate.

        What happens here is users love the seamless way of creating workflow applications and try to fit more scenarios into it. Natural user tendency is to be able to write any program with such simplicity and confidence.

        Given this natural evolution of workflow requirements, it’s better to have a code-driven workflow orchestration engine that can meet any future needs with its powerful expressiveness. On top of this, it is ideal if the interface is seamless, where engineers learn as little as possible and change almost nothing in their local code to write a distributed and durable workflow code. This would virtually remove any limitation and enable implementing any service as a workflow. This is what Cadence aims for.

        -

        Benefits

        -

        cadence-benefits.png

        +

        Benefits

        +

        cadence-benefits.png

        With Cadence, many overheads that need to be built for any well-supported service come for free. Here are some highlights (see cadenceworkflow.io):

        • Disaster recovery is supported by default through data replication and failovers
        • @@ -301,85 +301,85 @@ Rate limiting users of a healthy domain because of requests from a completely di
        • With Cadence testing capabilities, they can write unit tests or test against production data to prevent backward incompatibility issues.
        -

        Project Support

        -

        Team

        +

        Project Support

        +

        Team

        Today the Cadence team comprises 26 people. We have people working from Uber’s US offices (Seattle, San Francisco and Sunnyvale) as well as Europe offices (Aarhus-DK and Amsterdam-NL).

        -

        Community

        +

        Community

        Cadence is an actively built open source project. We invest in both our internal and open source community (Slack, Github), responding to new features and enhancements.

        -

        Scale

        +

        Scale

        It’s one of the most popular platforms at Uber executing ~100K workflow updates per second. There are about 30 different Cadence clusters, several of which serve hundreds of domains. There are ~1000 domains (use cases) varying from tier 0 (most critical) to tier 5 scenarios.

        -

        Managed Solutions

        +

        Managed Solutions

        While Uber doesn’t officially sell a managed Cadence solution, there are companies (e.g. Instaclustr) in our community that we work closely with selling Managed Cadence. Due to efficiency investments and other factors, it’s significantly cheaper than its competitors. It can be run in users’ on-prem machines or their cloud service of choice. Pricing is defined based on allocated hosts instead of number of requests so users can get more with the same resources by utilizing multi-tenant clusters.

        -

        After V1 Release

        +

        After V1 Release

        Last year, around this time we announced Cadence V1 and shared our roadmap. In this section we will talk about updates since then. At a high level, you will notice that we continue investing in high reliability and efficiency while also developing new features.

        -

        Frequent Releases

        +

        Frequent Releases

        We announced plans to make more frequent releases last year and started making more frequent releases. Today we aim to release biweekly and sometimes release as frequently as weekly. About the format, we listened to our community and heard about having too frequent releases potentially being painful. Therefore, we decided to increment the patch version with releases while incrementing the minor version close to quarterly. This helped us ship much more robust releases and improved our reliability. Here are some highlights:

        -

        Zonal Isolation

        +

        Zonal Isolation

        Cadence clusters have already been regionally isolated until this change. However, in the cloud, inter-zone communications matter as they are more expensive and their latencies are higher. Zones can individually have problems without impacting other cloud zones. In a regional architecture, a single zone problem might impact every request; however, with zonal isolation traffic from a zone with issues can easily be failed over to other zones, eliminating its impact on the whole cluster. Therefore, we implemented zonal isolation keeping domain traffic inside a single zone to help improve efficiency and reliability.

        -

        Narrowing Blast Radius

        +

        Narrowing Blast Radius

        When there are issues in a Cadence cluster, it’s often from a single misbehaving workflow. When this happens the whole domain or the cluster could have had issues until the specific workflow is addressed. With this change, we are able to contain the issue only to the offending workflow without impacting others. This is the narrowest blast radius possible.

        -

        Async APIs

        +

        Async APIs

        At Uber, there are many batch work streams that run a high number of workflows (thousands to millions) at the same time causing bottlenecks for Cadence clusters, causing noisy neighbor issues. This is because StartWorkflow and SignalWorkflow APIs are synchronous, which means when Cadence acks the user requests are successfully saved in their workflow history.

        Even after successful initiations, users would then need to deal with high concurrency. This often means constant worker cache thrashing, followed by history rebuilds at every update, increasing workflow execution complexity to O(n^2) from O(n). Alternatively, they would need to quickly scale out and down their service hosts in a very short amount of time to avoid this.

        When we took a step back and analyzed such scenarios, we realized that users simply wanted to “complete N workflows (jobs) in K time”. The guarantees around starts and signals were not really important for their use cases. Therefore, we implemented async versions of our sync API, by which we can control the consumption rate, guaranteeing the fastest execution with no disruption in the cluster.

        Later this year, we plan to expand this feature to cron workflows and timers as well.

        -

        Pinot as Visibility Store

        +

        Pinot as Visibility Store

        Apache Pinot is becoming popular due to its cost efficient nature. Several teams reported significant savings by changing their observability storage to Pinot. Cadence now has a Pinot plugin for its visibility store. We are still rolling out this change. Latencies and cost savings will be shared later.

        -

        Code Coverage

        +

        Code Coverage

        We have received many requests from our community to actively contribute to our codebase, especially after our V1 release. While we have been already collaborating with some companies, this is a challenge with individuals who are just learning about Cadence. One of the main reasons was to avoid bugs that can be introduced.

        While Cadence has many integration tests, its unit test coverage was lower than desired. With better unit test coverage we can catch changes that break previous logic and prevent them getting into the main branch. Our team covered additional 50K+ lines in various Cadence repos. We hope to bring our code coverage to 85%+ by the end of year so we can welcome such inquiries a lot easier.

        -

        Replayer Improvements

        +

        Replayer Improvements

        This is still an ongoing project. As mentioned in our V1 release, we are revisiting some core parts of Cadence where less-than-ideal architectural decisions were made in the past. Replayer/shadower is one of such parts. We have been working on improving its precision, eliminating false negatives and positives.

        -

        Global Rate Limiters

        +

        Global Rate Limiters

        Cadence rate limiters are equally distributed across zones and hosts. However, when the user's traffic is skewed, rate limits can get activated even though the user has more capacity. To avoid this, we built global rate limiters. This will make rate limits much more predictable and capacity management a lot easier.

        -

        Regular Failover Drills

        +

        Regular Failover Drills

        Cadence has been performing monthly regional and zonal failover drills to ensure its failover operations are working properly in case we need it. We are failing over hundreds of domains at the same time to validate the scale of this operation, capacity elasticity and correctness of workflows.

        -

        Cadence Web v4

        +

        Cadence Web v4

        We are migrating Cadence web from Vue.js to React.js to use a more modern infrastructure and to have better feature velocity. We are about 70% complete with this migration and hope to release the new version of it soon.

        -

        Code Review Time Non-determinism Checks

        +

        Code Review Time Non-determinism Checks

        (This is an internal-only feature that we hope to release soon) Cadence non-determinism errors and versioning were common pain points for our customers. There are available tools but they require ongoing effort to validate. We have built a tool that generates a shadower test with a single line command (one time only operation) and continuously validates any code change against production data.

        This feature reduced the detect-and-fix time from days/weeks to minutes. Just by launching this feature to the domains with the most non-determinism errors, the number of related incidents reduced by 40%. We have already blocked 500+ diffs that would potentially impact production negatively. This boosted our users’ confidence in using Cadence.

        -

        Domain Reports

        +

        Domain Reports

        (This is an internal-only feature that we hope to release soon) We are able to detect potential issues (bugs, antipatterns, inefficiencies, failures) with domains upon manual investigation. We have automated this process and now generate reports for each domain. This information can be accessed historically (to see the progression over time) and on-demand (to see the current state). This has already driven domain reliability and efficiency improvements.

        This feature and above are at MVP level where we plan to generalize, expand and release for open source soon. In the V1 release, we have mentioned that we would build certain features internally first to be able to have enough velocity, to see where they are going and to make breaking changes until it’s mature.

        -

        Client Based Migrations

        +

        Client Based Migrations

        With 30 clusters and ~1000 domains in production, migrating a domain from a cluster to another became a somewhat frequent operation for Cadence. While this feature is mostly automated, we would like to fully automate it to a level that this would be a single click or command operation. Client based migrations (as opposed to server based ones) give us big flexibility that we can have migrations from many to many environments at the same time. Each migration happens in isolation without impacting any other domain or the cluster.

        This is an ongoing project where remaining parts are migrating long running workflows faster and seamless technology to technology migrations even if the “from-technology” is not Cadence in the first place. There are many users that migrated from Cadence-like or different technologies to Cadence so we hope to remove the repeating overhead for such users.

        -

        Roadmap (Next Year)

        +

        Roadmap (Next Year)

        Our priorities for next year look similar with reliability, efficiency, and new features as our focus. We have seen significant improvements especially in our users’ reliability and efficiency on top of the improvements in our servers. This both reduces operational load on our users and makes Cadence one step closer to being a standard way to build services. Here is a short list of what's coming over the next 12 months:

        -

        Database efficiency

        +

        Database efficiency

        We are increasing our investment in improving Cadence’s database usage. Even though Cadence’s cost looks a lot better compared to the same family of technologies, it can still be significantly improved by eliminating certain bottlenecks coming from its original design.

        -

        Helm Charts

        +

        Helm Charts

        We are grateful to the Cadence community for introducing and maintaining our Helm charts for operating Cadence clusters. We are taking its ownership so it can be officially released and tested. We expect to release this in 2024.

        -

        Dashboard Templates

        +

        Dashboard Templates

        During our tech talks, demos and user talks, we have received inquiries about what metrics care about. We plan to release templates for our dashboards so our community would look at a similar picture.

        -

        Client V2 Modernization

        +

        Client V2 Modernization

        As we announced last year that we plan to make breaking changes to significantly improve our interfaces, we are working on modernizing our client interface.

        -

        Higher Parallelization and Prioritization in Task Processing

        +

        Higher Parallelization and Prioritization in Task Processing

        In an effort to have better domain prioritization in multitenant Cadence clusters, we are improving our task processing with higher parallelization and better prioritization. This is a lot better model than just having domains with defined limits. We expect to provide more resources to high priority domains during their peak hours while allowing low priority domains to consume much bigger resources than allocated during quiet times.

        -

        Timer and Cron Burst Handling

        +

        Timer and Cron Burst Handling

        After addressing start and signal burst scenarios, we are continuing with bursty timers and cron jobs. Many users set their schedules and timers for the same second with the intention of being able to finish N jobs within a certain amount of time. Current scheduling design isn’t friendly for such intents and high loads can cause temporary starvation in the cluster. By introducing better batch scheduling support, clusters can continue with no disruption while timers are processed in the most efficient way.

        -

        High zonal skew handling

        +

        High zonal skew handling

        For users operating in their own cloud and having multiple independent zones in every region, zonal skews can be a problem and can create unnecessary bottlenecks when Zonal Isolation feature is enabled. We are working on addressing such issues to improve task matching across zones when skew is detected.

        -

        Tasklist Improvements

        +

        Tasklist Improvements

        When a user scenario grows, there are many knobs that need to be manually adjusted. We would like to automatically partition and smartly forward tasks to improve tasklist efficiency significantly to avoid backlogs, timeouts and hot shards.

        -

        Shard Movement/Assignment Improvements

        +

        Shard Movement/Assignment Improvements

        Cadence shard movements are based on consistent hash and this can be a limiting factor for many different reasons. Certain hosts can end up getting unlucky by having many shards, or having heavy shards. During deployments we might observe a much higher number of shard movements than desired, which reduces the availability. With improved shard movements and assignments we can have more homogenous load among hosts while also having a minimum amount of shard movements during deployments with much better availability.

        -

        Worker Heartbeats

        +

        Worker Heartbeats

        Today, there’s no worker liveliness tracking in Cadence. Instead, task or activity heartbeat timeouts are used to reassign tasks to different workers. For latency sensitive users this can become a big disruption. For long activities without heartbeats, this can cause big delays. This feature is to eliminate depending on manual timeout or heartbeat configs to reassign tasks by tracking if workers are still healthy. This feature will also enable so many other new efficiency and reliability features we would like to get to in the future.

        -

        Domain and Workflow Diagnostics

        +

        Domain and Workflow Diagnostics

        Probably the two most common user questions are “What’s wrong with my domain?” and “What’s wrong with my workflow?”. Today, diagnosing what happened and what could be wrong isn’t that easy apart from some basic cases. We are working on tools that would run diagnostics on workflows and domains to point out things that might potentially be wrong with public runbook links attached. This feature will not only help diagnose what is wrong with our workflows and domains but will also help fix them.

        -

        Self Serve Operations

        +

        Self Serve Operations

        Certain Cadence operations are performed through admin CLI operations. However, these should be able to be done via Cadence UI by users. Admins shouldn’t need to be involved in every step or the checks they validate should be able to be automated. This is what the initiative is about including domain registration, auth/authz onboarding or adding new search attributes but it’s not limited to these operations.

        -

        Cost Estimation

        +

        Cost Estimation

        One big question we receive when users are onboarding to Cadence is “How much will this cost me?”. This is not an easy question to answer since data and traffic load can be quite different. We plan to automate this process to help users understand how much resources they will need. Especially in multi-tenant clusters, this will help users understand how much room they still have in their clusters and how much the new scenario will consume.

        -

        Domain Reports (continue)

        +

        Domain Reports (continue)

        We plan to release this internal feature to open source as soon as possible. On top of presenting this data on built-in Cadence surfaces (web, CLI. etc.) we will create APIs to make it integratable with deployment systems, user service UIs, periodic reports and any other service that would like to consume.

        -

        Non-determinism Detection Improvements (continue)

        +

        Non-determinism Detection Improvements (continue)

        We have seen great reliability improvements and reduction in incidents with this feature on the user side last year. We continue to invest in this feature and make it available in open source as soon as possible.

        -

        Domain Migrations (continue)

        +

        Domain Migrations (continue)

        In the next year, we plan to finish our seamless client based migration to be able to safely migrate domains from one cluster to another, one technology (even if it’s not Cadence) to another and one cloud solution to another. There are only a few features left to achieve this.

        -

        Community

        +

        Community

        Do you want to hear more about Cadence? Do you need help with your set-up or usage? Are you evaluating your options? Do you want to contribute? Feel free to join our community and reach out to us.

        Slack: https://uber-cadence.slack.com/

        Github: https://github.com/cadence-workflow/cadence

        @@ -394,14 +394,14 @@ Rate limiting users of a healthy domain because of requests from a completely di
        <![CDATA[Cadence non-derministic errors common question Q&A (part 1)]]> - https://cadenceworkflow.io/blog/2024/02/15/cadence-non-deterministic-common-qa - + https://cadenceworkflow.io/Cadence-Docs/blog/2024/02/15/cadence-non-deterministic-common-qa + 2024-03-10T00:00:00.000Z - If I change code logic inside an Cadence activity (for example, my activity is calling database A but now I want it to call database B), will it trigger an non-deterministic error? + If I change code logic inside an Cadence activity (for example, my activity is calling database A but now I want it to call database B), will it trigger an non-deterministic error?

        NO. This change will not trigger non-deterministic error.

        An Activity is the smallest unit of execution for Cadence and what happens inside activities are not recorded as historical events and therefore will not be replayed. In short, this change is deterministic and it is fine to modify logic inside activities.

        -

        Does changing the workflow definition trigger non-determinstic errors?

        +

        Does changing the workflow definition trigger non-determinstic errors?

        YES. This is a very typical non-deterministic error.

        When a new workflow code change is deployed, Cadence will find if it is compatible with Cadence history. Changes to workflow definition will fail the replay process of Cadence @@ -418,7 +418,7 @@ trigger non-deterministic errors.

      • Changes of workflow return values
      • Changing workflow parameter names as they are just positional
      -

      Does changing activity definitions trigger non-determinstic errors?

      +

      Does changing activity definitions trigger non-determinstic errors?

      YES. Similar to workflow definition change, this is also a very typical non-deterministic error.

      Activities are also recorded and replayed by Cadence. Therefore, changes to activity must also be compatible with Cadence history. The following changes are common ones that trigger non-deterministic errors.

        @@ -432,7 +432,7 @@ trigger non-deterministic errors.

      • Changing activity parameter names

      Activity return values inside workflows are not recorded and replayed.

      -

      What changes inside workflows may potentially trigger non-deterministic errors?

      +

      What changes inside workflows may potentially trigger non-deterministic errors?

      Cadence records each execution of a workflow and activity execution inside each of them.Therefore, new changes must be compatible with execution orders inside the workflow. The following changes will fail the non-deterministic check.

      • Append another activity
      • @@ -440,11 +440,11 @@ trigger non-deterministic errors.

      • Reordering activities

      If you really need to change the activity implementation based on new business requirements, you may consider using versioning your workflow.

      -

      Are Cadence signals replayed? If definition of signal is changed, will it trigger non-deterministic errors?

      +

      Are Cadence signals replayed? If definition of signal is changed, will it trigger non-deterministic errors?

      Yes. If a signal is used in a workflow, it becomes a critical component of your workflow. Because signals also involve I/O to your workflow, it is also recorded and replayed. Modifications on signal definitions or usage may yield to non-deterministic errors, for instance, changing return type of a signal.

      -

      If I have new business requirement and really need to change the definition of a workflow, what should I do?

      +

      If I have new business requirement and really need to change the definition of a workflow, what should I do?

      You may introduce a new workflow registered to your worker and divert traffic to it or use versioning for your workflow. Check out Cadence website for more information about versioning.

      -

      Does changes to local activities' definition trigger non-deterministic errors?

      +

      Does changes to local activities' definition trigger non-deterministic errors?

      Yes. Local activities are recorded and therefore replayed by Cadence. Imcompatible changes on local activity definitions will yield to non-deterministic errors.

      ]]> Chris Qin @@ -454,20 +454,20 @@ trigger non-deterministic errors.

      <![CDATA[Cadence Community Spotlight Update - November 2023]]> - https://cadenceworkflow.io/blog/2023/11/30/community-spotlight-update-november-2023 - + https://cadenceworkflow.io/Cadence-Docs/blog/2023/11/30/community-spotlight-update-november-2023 + 2023-11-30T00:00:00.000Z Welcome to the latest of our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!

      It's been a couple of months since our last update so we have a lot of updates to share with you.

      Please see below for a roundup of the highlights:

      -

      Proposal for Cadence Native Authentication

      +

      Proposal for Cadence Native Authentication

      Community member Mantas Sidlauskas has drafted a proposal around Cadence native authentication and is asking for community feedback. If you are interested in reviewing the current proposal and providing comments or feedback then please find the proposal details at the link below:

      This is a great example of how we can focus on collaborating together to find a collective solution. A big thank you to Mantas for initiating this work and we hope to see the results of the community input soon!

      -

      iWF Deep Dive and More!

      +

      iWF Deep Dive and More!

      During the last few months community member Quanzheng Long has continued to share his thoughts about iWF, a layer implemented on top of Cadence. Since our last update iWF now has aPython SDK. Long has been busy writing articles to share iWF tips and tricks as well as some general ideas about workflows and processes. Links to Long's articles can be found below:

      -

      New Go Samples for Cadence

      +

      New Go Samples for Cadence

      The Cadence core team is deprecating the old samples for Go and replacing them with new version 2 (V2) samples. They have received a lot of feedback from the community that people are having trouble with old samples, so are in the process of publishing a completely new set of samples for Go.

      Here are some major changes to the new samples:

      Note that the old samples will be removed once the new samples are fully refreshed.

      -

      Cadence Retrospective

      +

      Cadence Retrospective

      We are nearly at the end of another year and yes it has gone so fast! Over this year Cadence and the community have evolved and grown. This is a good time to reflect about all the things that have happened in the project over the year and think about a possible roadmap for the future.

      If you have any feedback, or comments about the project or ideas about what features you'd like to see in the roadmap then please feel free to begin a discussion in the #community Slack channel.

      -

      Cadence in the News!

      +

      Cadence in the News!

      Below are a selection of Cadence related articles, blogs and whitepapers. Please take a look and feel free to share via your own social media channels.

      -

      Upcoming Events

      +

      Upcoming Events

      @@ -530,13 +530,13 @@ Please take a look and feel free to share via your own social media channels.

      <![CDATA[Cadence Community Spotlight Update - August 2023]]> - https://cadenceworkflow.io/blog/2023/08/31/community-spotlight-august-2023 - + https://cadenceworkflow.io/Cadence-Docs/blog/2023/08/31/community-spotlight-august-2023 + 2023-08-31T00:00:00.000Z Welcome to the latest of our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!

      Please see below for a roundup of the highlights:

      -

      More Cadence How To's

      +

      More Cadence How To's

      You might have noticed that we have had a few more contributions to our blog from Chris Qin. Chris has been busy sharing insights, and tips on a few important Cadence topics. The objective is to help the community with any potential problems.

      Here are the latest topics:

    \ No newline at end of file diff --git a/blog/authors/jakobht.html.html b/blog/authors/jakobht.html.html index c22812255..4c18d8a6b 100644 --- a/blog/authors/jakobht.html.html +++ b/blog/authors/jakobht.html.html @@ -2,10 +2,10 @@ - - + + \ No newline at end of file diff --git a/blog/authors/kcorbett-netapp.html b/blog/authors/kcorbett-netapp.html index c40528e31..f5f916e04 100644 --- a/blog/authors/kcorbett-netapp.html +++ b/blog/authors/kcorbett-netapp.html @@ -3,8 +3,8 @@ -Kevin Corbett - One post | Cadence - +Kevin Corbett - One post | Cadence + @@ -15,14 +15,14 @@ - - - + + + -
    Kevin Corbett
    Open Source Community Manager | @instaclustr @NetApp
    View all authors

    Cadence Community Spotlight Update - March 2024

    · 3 min read
    Kevin Corbett
    Open Source Community Manager | @instaclustr @NetApp

    Welcome back to the latest in our regular Cadence community spotlight updates where we aim to deliver you news from in and around the Cadence community! +

    Kevin Corbett
    Open Source Community Manager | @instaclustr @NetApp
    View all authors

    Cadence Community Spotlight Update - March 2024

    · 3 min read
    Kevin Corbett
    Open Source Community Manager | @instaclustr @NetApp

    Welcome back to the latest in our regular Cadence community spotlight updates where we aim to deliver you news from in and around the Cadence community! It’s been a few months since our last update, so I have a bunch of exciting updates to share.

    Let’s get started!

    Proposal for Cadence Plugin System

    @@ -30,6 +30,6 @@

    Cadence Plugin System Proposal -

    A huge thank you to Mantas for initiating this work. This is an excellent example of how we can collaborate together to bring about new features that benefit us all.

    +

    A huge thank you to Mantas for initiating this work. This is an excellent example of how we can collaborate together to bring about new features that benefit us all.

    \ No newline at end of file diff --git a/blog/authors/kcorbett-netapp.html.html b/blog/authors/kcorbett-netapp.html.html index 2c2038763..871fb8661 100644 --- a/blog/authors/kcorbett-netapp.html.html +++ b/blog/authors/kcorbett-netapp.html.html @@ -2,10 +2,10 @@ - - + + \ No newline at end of file diff --git a/blog/authors/meiliang-86.html b/blog/authors/meiliang-86.html index 9107e5248..16cd7b678 100644 --- a/blog/authors/meiliang-86.html +++ b/blog/authors/meiliang-86.html @@ -3,8 +3,8 @@ -Liang Mei - 2 posts | Cadence - +Liang Mei - 2 posts | Cadence + @@ -15,21 +15,21 @@ - - - + + + -
    Liang Mei
    Engineering Manager @ Uber
    View all authors

    Announcing Cadence OSS office hours and community sync up

    · 2 min read
    Liang Mei
    Engineering Manager @ Uber

    Are you a current Cadence user, do you operate Cadence services, or are you interested in learning about workflow technologies and wonder what problems Cadence could solve for you? We would like to talk to you!

    +
    Liang Mei
    Engineering Manager @ Uber
    View all authors

    Announcing Cadence OSS office hours and community sync up

    · 2 min read
    Liang Mei
    Engineering Manager @ Uber

    Are you a current Cadence user, do you operate Cadence services, or are you interested in learning about workflow technologies and wonder what problems Cadence could solve for you? We would like to talk to you!

    Our team has spent a significant amount of time working with users and partner teams at Uber to design, scale and operate their workflows. This helps our users understand the technology better, smooth their learning curve and ramp up experience, and at the same time allows us to get fast and direct feedback so we can improve the developer experience and close feature gaps. As our product and community grows, we would like to expand this practice to our users in the OSS community. For the first time ever, members of the Cadence team along with core contributors from the community will host bi-weekly office hours to answer any questions you have about Cadence, or workflow technology in general. We can also dedicate future sessions to specific topics that have a common interest. Please don’t hesitate to let us know your thoughts.

    Please join a session if you would like to talk about any of the following topics:

    1. Understand what Cadence is and why it might be useful for you and your company
    2. Guidance about running Cadence services and workers in production
    3. Workflow design and operation consultation
    4. Product update, future roadmaps as well as collaboration opportunities

    Building and maintaining a healthy and growing community is the key to the success of Cadence, and one of the top priorities for our team. We would like to use the office hours as an opportunity to understand and help our customers, seek feedback, and forge partnerships. We look forward to seeing you in one of the meetings.

    Upcoming Office Hours

    -

    As we have a geo-distributed userbase, we are still trying to figure out a time that works for most of the people. In the meanwhile, we will manually schedule the first few instances of the meeting until we settle on a fixed schedule. Our next office hours will take place on Thursday, October 21 2pm-3pm PT/5pm-6pm EST/9pm-10pm GMT. Please join via this zoom link.

    Long-term commitment and support for the Cadence project, and its community

    · 3 min read
    Liang Mei
    Engineering Manager @ Uber

    Dear valued Cadence users and developers,

    +

    As we have a geo-distributed userbase, we are still trying to figure out a time that works for most of the people. In the meanwhile, we will manually schedule the first few instances of the meeting until we settle on a fixed schedule. Our next office hours will take place on Thursday, October 21 2pm-3pm PT/5pm-6pm EST/9pm-10pm GMT. Please join via this zoom link.

    Long-term commitment and support for the Cadence project, and its community

    · 3 min read
    Liang Mei
    Engineering Manager @ Uber

    Dear valued Cadence users and developers,

    Some of you might have read Temporal’s recent announcement about their decision to drop the support for the Cadence project. This message caused some confusion in the community, so we would like to take this opportunity to clear things out.

    -

    First of all, Uber is committed to the long-term success of the Cadence project. Since its inception 5 years ago, use cases built on Cadence and their scale have grown significantly at Uber. Today, Cadence powers a variety of our most business-critical use cases (some public stories are available here and here). At the same time, the Cadence development team at Uber has enjoyed rapid growth with the product and has been driving innovations of workflow technology across the board, from new features (e.g. graceful failover, workflow shadowing, UI improvements) to better engineering foundations (e.g. gRPC support, multi-tenancy support), all in a backwards compatible manner. Neither Uber’s use nor support of Cadence is going to change with Temporal’s announcement. We have a long list of features and exciting roadmaps ahead of us, and we will share more details in our next meetup in November ‘21. As always we will continue to push the boundaries of scale and reliability as our usage within Uber grows.

    +

    First of all, Uber is committed to the long-term success of the Cadence project. Since its inception 5 years ago, use cases built on Cadence and their scale have grown significantly at Uber. Today, Cadence powers a variety of our most business-critical use cases (some public stories are available here and here). At the same time, the Cadence development team at Uber has enjoyed rapid growth with the product and has been driving innovations of workflow technology across the board, from new features (e.g. graceful failover, workflow shadowing, UI improvements) to better engineering foundations (e.g. gRPC support, multi-tenancy support), all in a backwards compatible manner. Neither Uber’s use nor support of Cadence is going to change with Temporal’s announcement. We have a long list of features and exciting roadmaps ahead of us, and we will share more details in our next meetup in November ‘21. As always we will continue to push the boundaries of scale and reliability as our usage within Uber grows.

    \ No newline at end of file diff --git a/blog/authors/meiliang-86.html.html b/blog/authors/meiliang-86.html.html index b8c6a61e1..5ee44f1ca 100644 --- a/blog/authors/meiliang-86.html.html +++ b/blog/authors/meiliang-86.html.html @@ -2,10 +2,10 @@ - - + + \ No newline at end of file diff --git a/blog/authors/shaddoll.html b/blog/authors/shaddoll.html index 954857b69..b5d254095 100644 --- a/blog/authors/shaddoll.html +++ b/blog/authors/shaddoll.html @@ -3,8 +3,8 @@ -Zijian Chen - One post | Cadence - +Zijian Chen - One post | Cadence + @@ -15,14 +15,14 @@ - - - + + + -
    Zijian Chen
    Software Engineer @ Uber
    View all authors

    Zonal Isolation for Cadence Workflows

    · 8 min read
    Zijian Chen
    Software Engineer @ Uber

    At Uber, we want to achieve regional resilience such that losing a zone within a region can be tolerated without requiring a cross-region failover. We also want to make sure that losing a zone only affects a subset of workload, at most, rather than everything. However, in Cadence-based systems, the workload in a region is distributed randomly across all workers in the region at a “task-level granularity”, which means a workflow may be worked on by any worker in the region where the domain is active. To achieve this goal, we introduced Zonal Isolation for Cadence Workflows - a feature designed to pin workflows to the zone they are started in, so that zonal isolation can be achieved at a workflow-level.

    +
    Zijian Chen
    Software Engineer @ Uber
    View all authors

    Zonal Isolation for Cadence Workflows

    · 8 min read
    Zijian Chen
    Software Engineer @ Uber

    At Uber, we want to achieve regional resilience such that losing a zone within a region can be tolerated without requiring a cross-region failover. We also want to make sure that losing a zone only affects a subset of workload, at most, rather than everything. However, in Cadence-based systems, the workload in a region is distributed randomly across all workers in the region at a “task-level granularity”, which means a workflow may be worked on by any worker in the region where the domain is active. To achieve this goal, we introduced Zonal Isolation for Cadence Workflows - a feature designed to pin workflows to the zone they are started in, so that zonal isolation can be achieved at a workflow-level.

    What is Zonal Isolation for Cadence Workflows?

    At high-level, Zonal Isolation for Cadence Workflows can be thought in 2 levels:

      @@ -30,6 +30,6 @@

    +

    As a result, the focus remains on achieving task-level zonal isolation outside the Cadence server, which offers a more practical and immediate way to improve system resilience. It provides the capability of ensuring that an unhealthy zone (i.e. bad deployment of workers) only affect a subset of workflows (started from a certain zone) rather than every workflow in a Cadence domain.

    \ No newline at end of file diff --git a/blog/authors/shaddoll.html.html b/blog/authors/shaddoll.html.html index 6c343b94c..7d7607fea 100644 --- a/blog/authors/shaddoll.html.html +++ b/blog/authors/shaddoll.html.html @@ -2,10 +2,10 @@ - - + + \ No newline at end of file diff --git a/blog/authors/sharanf.html b/blog/authors/sharanf.html index 697b593a8..54e9173df 100644 --- a/blog/authors/sharanf.html +++ b/blog/authors/sharanf.html @@ -3,8 +3,8 @@ -Sharan Foga - 19 posts | Cadence - +Sharan Foga - 19 posts | Cadence + @@ -15,16 +15,16 @@ - - - + + + -
    Sharan Foga
    Director of Operations & Customer Success @ Encube Technologies
    View all authors

    Cadence Community Spotlight Update - November 2023

    · 4 min read
    Sharan Foga
    Director of Operations & Customer Success @ Encube Technologies

    Welcome to the latest of our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!

    +
    Sharan Foga
    Director of Operations & Customer Success @ Encube Technologies
    View all authors

    Cadence Community Spotlight Update - August 2023

    · 3 min read
    Sharan Foga
    Director of Operations & Customer Success @ Encube Technologies

    Welcome to the latest of our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!

    Please see below for a roundup of the highlights:

    More Cadence How To's

    You might have noticed that we have had a few more contributions to our blog from Chris Qin. Chris has been busy sharing insights, and tips on a few important Cadence topics. The objective is to help the community with any potential problems.

    @@ -39,7 +39,7 @@

    More Ca

    Even if you have not encountered these use cases - it is good to be prepared and have a solution ready.Please take a look and let us have your feedback.

    Chris is also going to take a look at the Cadence Samples to make sure they are all working and if not - he's going to re-write them so that they do!

    -

    Thanks very much Chris for all the work you are doing to help improve the project!

    Cadence Community Spotlight Update - July 2023

    · 3 min read
    Sharan Foga
    Director of Operations & Customer Success @ Encube Technologies

    Welcome to the latest of our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!

    Please see below for a roundup of the highlights:

    Getting Started with Cadence

    Are you new to Cadence and want to understand the basic concepts and architecture? Well we have some great information for you!

    @@ -47,11 +47,11 @@

    Thanks Chris for sharing your knowledge and helping others to get started.

    Cadence Go Client v1.0 Released

    This month saw the release of v1.0 of the Cadence Go Client. Note that the work done on this release was as a result of community feedback asking for it - so we are listening and responding to community needs.

    -

    Thanks very much to everyone who worked hard to get this release out!

    Cadence Community Spotlight Update - June 2023

    · 3 min read
    Sharan Foga
    Director of Operations & Customer Success @ Encube Technologies

    We've had a short break but now we are back. Welcome to the latest of our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!

    Please see below for a roundup of the highlights:

    Cadence Release 1.0

    Just in case you missed it - at the end of April Cadence v1.0 was officially released. This release is a significant milestone for the project and the community. It indicates that we are confident in the stability of the code that we can recommend it and promote it widely to more users. Kudos to everyone that worked together to make this release happen.

    -

    And the Uber team also gave Cadence a writeup on the Uber Engineering Blog so please take a look.

    Cadence Community Spotlight Update - March 2023

    · 2 min read
    Sharan Foga
    Director of Operations & Customer Success @ Encube Technologies

    Welcome to the latest of our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!

    Please see below for a roundup of the highlights:

    Cadence at Open Source Summit, North America

    We are very pleased to let you know that a talk on Cadence has been accepted for the Linux Foundation's Open Source Summit, North America in Vancouver on 10th - 12th May 2023.

    @@ -62,18 +62,18 @@

    Community
  • February 2023 : 16 questions asked
  • March 2023 : 12 questions asked
  • -

    All of these questions are being answered collaboratively by the community. Thanks everyone for sharing your knowledge and we are looking forward to receiving more of your questions!

    Cadence Community Spotlight Update - February 2023

    · 2 min read
    Sharan Foga
    Director of Operations & Customer Success @ Encube Technologies

    Here’s the latest in our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!

    +

    All of these questions are being answered collaboratively by the community. Thanks everyone for sharing your knowledge and we are looking forward to receiving more of your questions!

    Cadence Community Spotlight Update - February 2023

    · 2 min read
    Sharan Foga
    Director of Operations & Customer Success @ Encube Technologies

    Here’s the latest in our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!

    Please see below for a roundup of the highlights:

    Community Survey

    We've been talking about doing a community survey for a while and during February we sent it out. We are still collating the results so it's not too late to send in your response.

    The survey takes 5 minutes and is your opportunity to provide feedback to the project and highlight areas you think we need to focus on.

    Use this Survey Link

    -

    Please take a few minutes to give us your opinion.

    Cadence Community Spotlight Update - January 2023

    · 3 min read
    Sharan Foga
    Director of Operations & Customer Success @ Encube Technologies

    Happy New Year everyone! Here’s the latest in our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!

    Please see below for a roundup of the highlights:

    Closing Down Cadence Office Hours

    We have been running Office Hours sessions every month since May last year. The aim was to give the community an opportunity to speak directly with some of the Cadence core developers and experts to answer questions on particular issues you may be having. We have found that the most preferred method for community questions has been the support Slack channel so have decided to stop this monthly call.

    Thanks very much to Ender Demirkayaand the Uber team for making themselves available for these sessions.

    -

    Please remember that if you have question about Cadence or are facing a specific issue then you can post your question in our #support Slack channel. If you also post the details on StackOverflow with the cadence workflow tag then there will be a searchable history for others who encounter the same issue to find a solution.

    Cadence Community Spotlight Update - December 2022

    · 2 min read
    Sharan Foga
    Director of Operations & Customer Success @ Encube Technologies

    I know we are a little early this month as many people will be taking some time out for holidays.

    +

    Please remember that if you have question about Cadence or are facing a specific issue then you can post your question in our #support Slack channel. If you also post the details on StackOverflow with the cadence workflow tag then there will be a searchable history for others who encounter the same issue to find a solution.

    Cadence Community Spotlight Update - December 2022

    · 2 min read
    Sharan Foga
    Director of Operations & Customer Success @ Encube Technologies

    I know we are a little early this month as many people will be taking some time out for holidays.

    Happy Holidays

    We'd like to wish everyone happy holidays and to thank you for being part of the Cadence community. It's been a busy year for Cadence as we have continued to build a strong, active community that works together to solve issues and generally support each other.

    Let's keep going!...This is a great way to build a sustainable community.

    @@ -90,20 +90,20 @@

    Cadence
  • Cadence Connection Examples Using TLS

  • -

    Cadence Community Spotlight Update - November 2022

    · 2 min read
    Sharan Foga
    Director of Operations & Customer Success @ Encube Technologies

    Here’s the latest in our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!

    Please see below for a roundup of the highlights:

    Cadence @ Uber

    This month Uber Engineering published a really nice article on one of the ways they are using Cadence. The article is called How Uber Optimizes the Timing of Push Notifications using ML and Linear Programming.

    The Uber team take you through the details of the problem that they are looking to solve, so you can understand the scope limitations and depedencies - so please take a look.

    Cadence @ DeveloperWeek Enterprise

    DevNetwork run a series of conferences and during November Cadence was featured in at DeveloperWeek Enterprise. Ender Demirkaya and Ben Slater presented a talk called Espress Complex Business Logic as Code with Open Source Cadence!.

    -

    It is good to see that we are finding new channels for us to present the benefits of using Cadence. Huge hanks to Ben and Ender for the presentation and to everyone that attended.

    Cadence Community Spotlight Update - October 2022

    · 2 min read
    Sharan Foga
    Director of Operations & Customer Success @ Encube Technologies

    Here’s the latest in our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!

    +

    It is good to see that we are finding new channels for us to present the benefits of using Cadence. Huge hanks to Ben and Ender for the presentation and to everyone that attended.

    Cadence Community Spotlight Update - October 2022

    · 2 min read
    Sharan Foga
    Director of Operations & Customer Success @ Encube Technologies

    Here’s the latest in our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!

    Please see below for a roundup of the highlights:

    Cadence Meetup Postponed

    It's always great to get the community together and we had planned to run another Cadence Meetup in early November. Unfortunately we didn't have enough time to get things organised so we've decided to postpone it. So please watch out for an announcement for the new Cadence meetup date.

    Doordash Technnical Showcase Featuring Cadence

    We have had some great feedback from people who attended Technical Showcase that was run this month by Doordash. It featured their financial products but also highlighted some of the key technologies they use...and guess what Cadence is one of them!

    If you missed the session then you will be happy to know that it was recorded and we've inlcuded a link to the the recording on Youtube.

    -

    Thanks to the Doordash team for running the session and helping support Cadence by sharing their knowledge.

    +

    Thanks to the Doordash team for running the session and helping support Cadence by sharing their knowledge.

    \ No newline at end of file diff --git a/blog/authors/sharanf.html.html b/blog/authors/sharanf.html.html index b91e6b4f8..4ecdd4cd8 100644 --- a/blog/authors/sharanf.html.html +++ b/blog/authors/sharanf.html.html @@ -2,10 +2,10 @@ - - + + \ No newline at end of file diff --git a/blog/authors/sharanf/authors/2.html b/blog/authors/sharanf/authors/2.html index e830b0c08..a27569a9a 100644 --- a/blog/authors/sharanf/authors/2.html +++ b/blog/authors/sharanf/authors/2.html @@ -3,8 +3,8 @@ -Sharan Foga - 19 posts | Cadence - +Sharan Foga - 19 posts | Cadence + @@ -15,20 +15,20 @@ - - - + + + -
    Sharan Foga
    Director of Operations & Customer Success @ Encube Technologies
    View all authors

    Cadence Community Spotlight Update - September 2022

    · 2 min read
    Sharan Foga
    Director of Operations & Customer Success @ Encube Technologies

    Here’s the latest in our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!

    +
    Sharan Foga
    Director of Operations & Customer Success @ Encube Technologies
    View all authors

    Cadence Community Spotlight Update - September 2022

    · 2 min read
    Sharan Foga
    Director of Operations & Customer Success @ Encube Technologies

    Here’s the latest in our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!

    Please see below for a roundup of the highlights:

    A Cadence talk by Ender Demirkaya and Ben Slater has been accepted for Developer Week Enterprise.

    The talk is scheduled to for 16th November so please make a note in your calendars.

    Sharing Knowledge

    Over the last few months we have had a continual stream of Cadence questions in our Slack #support channel or on StackOverflow. As a result of the increased interest some members from the Cadence core team have decided to spend some time each day responding to your questions.

    -

    Remember that if you have received a response that has solved your problem especially on StackOverflow then please don't forget to accept answer!

    Cadence Community Spotlight Update - August 2022

    · 3 min read
    Sharan Foga
    Director of Operations & Customer Success @ Encube Technologies

    Here’s the latest in our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!

    +

    Remember that if you have received a response that has solved your problem especially on StackOverflow then please don't forget to accept answer!

    Cadence Community Spotlight Update - August 2022

    · 3 min read
    Sharan Foga
    Director of Operations & Customer Success @ Encube Technologies

    Here’s the latest in our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!

    Please see below for a roundup of the highlights:

    Community Survey

    We are working on putting together our first community survey to find out a bit more about our community. We would like to get your feedback about on a few things such as:

    @@ -38,46 +38,46 @@

    Community S
  • any special use cases not yet covered
  • and of course whatever other feedback you'd like to give us
  • -

    So please watch out for the survey which will be coming out to you via the Slack channel soon!

    Cadence Community Spotlight Update - July 2022

    · 2 min read
    Sharan Foga
    Director of Operations & Customer Success @ Encube Technologies

    Here’s our monthly Community Spotlight update that gives you news from in and around the Cadence community!

    Please see below for a roundup of the highlights:

    Flying Drones with Cadence

    Community member Paul Brebner has released another blog in the series of using Cadence to manage a drone delivery service. You can see a simulated view of it in action

    Don’t forget to try out the code yourself and remember if you have used Cadence to do something interesting then please let us know so we can feature it in our next update.

    GitHub Statistics

    During July the main Cadence branch had 28 pull requests (PRs) merged. There were 214 files changed by 11 different authors. You can find more details here

    -

    The Cadence documentation repository was not as busy with only 2 PRs merged in July, 5 commits and 3 authors active. More details can be found here

    Cadence Community Spotlight Update - June 2022

    · 3 min read
    Sharan Foga
    Director of Operations & Customer Success @ Encube Technologies

    It’s time for our monthly Cadence Community Spotlight update with news from in and around the Cadence community!

    Please see below for a roundup of the highlights:

    Knowledge Sharing and Support

    Our Slack #support channel has been busy this month with 13 questions asked this month by 12 different community members. Six community members took time to respond to those questions which clearly shows our community is growing, collaborating and keen to share knowledge.

    Please don’t forget that we encourage everyone to post questions on StackOverflow using the cadence-workflow and uber-cadence tags so that others with similar questions or issues can easily search for and find an answer.

    Improving Technical Office Hours

    Over the last few months we have been holding regular monthly Office Hours meetings but they have not attracted as many participants as we would like. We would like to understand if there is something preventing people from attending (e.g perhaps the timing or dates are not convenient) so we are planning to send out a short community survey.

    -

    If you have any ideas or comments about how we can improve our community office hours sessions then please include this in your feedback or contact us in the #community Slack channel.

    Cadence Community Spotlight Update - May 2022

    · 3 min read
    Sharan Foga
    Director of Operations & Customer Success @ Encube Technologies

    Welcome to our regular Cadence Community Spotlight update!

    +

    If you have any ideas or comments about how we can improve our community office hours sessions then please include this in your feedback or contact us in the #community Slack channel.

    Cadence Community Spotlight Update - May 2022

    · 3 min read
    Sharan Foga
    Director of Operations & Customer Success @ Encube Technologies

    Welcome to our regular Cadence Community Spotlight update!

    This is our monthly blog post series focused on news from in and around the Cadence community.

    Please see below for a short activity roundup of what has happened recently in the community.

    Cadence Polling Cookbook

    Do you want to understand polling work and have an example of how to set it up in Cadence? Well a brand new Cadence Polling cookbook is now available that gives you all the details you need. The cookbook was created by several members of the Instaclustr team and they are keen to share it with the community. The pdf version of the cookbook can found on the Cadence website under the Polling an external API for a specific resource to become available section of the Polling Use cases.

    A Github repository has also been created with the sample cookbook code for you to try out for yourself.

    -

    So please go ahead and try out the cookbook and don’t forget to let us have your feedback.

    Cadence Community Spotlight Update - April 2022

    · 3 min read
    Sharan Foga
    Director of Operations & Customer Success @ Encube Technologies

    Welcome to our Cadence Community Spotlight update!

    This is our monthly blog post series focused on news from in and around the Cadence community.

    Please see below for a short activity roundup of what has happened recently in the community.

    SD Times Names Cadence Open Source Project of the Week

    In April Cadence was named as open source project of the week by the SD Times. Being named gives the project some great publicity and means the project is getting noticed. You can find a link to the article in the Cadence in the News section below.

    Follow Us on LinkedIn and Twitter!

    We have now set up Cadence accounts on LinkedIn and Twitter where you can keep up to date with what is happening in the community. We will be using these social media accounts to share news, articles, stories and links related to Cadence - so please follow us!

    -

    And don’t forget to share your news with us. We are looking forward to receiving your feedback and comments. The more we interact - the more we build our community!

    Cadence Community Spotlight Update - March 2022

    · 4 min read
    Sharan Foga
    Director of Operations & Customer Success @ Encube Technologies

    Welcome to our Cadence Community Spotlight update!

    This is the latest in our series of monthly blog posts focused on the Cadence community and news about what you have been doing with Cadence.

    Please see below for a short activity roundup of what has happened recently in the community.

    Updated Cadence Topology Diagram

    Did you know that we have an updated Cadence Service diagram on the website? Well we do - and you can find it on our Deployment Topology page. We are always looking for information that helps makes it easier for people to understand how Cadence works.

    -

    Special thanks to Ben Slater for updating the diagram and also to Ender, Emrah and Long for helping review it.

    Cadence Community Spotlight Update - February 2022

    · 3 min read
    Sharan Foga
    Director of Operations & Customer Success @ Encube Technologies

    Welcome to the Cadence Community Spotlight update!

    This is the second in our series of monthly updates focused on the Cadence community and news about what you have been doing with Cadence. We hope that you enjoyed last month's update and are keen to find out what has been happening.

    Please see below for a short activity roundup of what has happened recently in the community.

    Announcements

    Just in case you missed it the alpha version of the Cadence notification service has been released. Details can be found at the following link: Cadence Notification Service

    -

    Thanks very much to everyone that worked on this!

    Cadence Community Spotlight Update - January 2022

    · 3 min read
    Sharan Foga
    Director of Operations & Customer Success @ Encube Technologies

    Welcome to our very first Cadence Community Spotlight update!

    This monthly update focuses on news from the wider Cadence community and is all about what you have been doing with Cadence. Do you have an interesting project that uses Cadence? If so then we want to hear from you. Also if you have any news items, blogs, articles, videos or events where Cadence has been mentioned then that is good too. We want to showcase that our community is active and is doing exciting and interesting things.

    -

    Please see below for a short round up of things that have happened recently in the community.

    +

    Please see below for a short round up of things that have happened recently in the community.

    \ No newline at end of file diff --git a/blog/authors/sharanf/authors/2.html.html b/blog/authors/sharanf/authors/2.html.html index 3cbde6f05..6c53193e0 100644 --- a/blog/authors/sharanf/authors/2.html.html +++ b/blog/authors/sharanf/authors/2.html.html @@ -2,10 +2,10 @@ - - + + \ No newline at end of file diff --git a/blog/authors/taylanisikdemir.html b/blog/authors/taylanisikdemir.html index 3eb74ea20..c987669a8 100644 --- a/blog/authors/taylanisikdemir.html +++ b/blog/authors/taylanisikdemir.html @@ -3,8 +3,8 @@ -Taylan Isikdemir - One post | Cadence - +Taylan Isikdemir - One post | Cadence + @@ -15,14 +15,14 @@ - - - + + + -
    Taylan Isikdemir
    Sr. Staff Software Engineer @ Uber
    View all authors

    Announcement: Cadence Helm Charts v0 Release

    · 3 min read
    Taylan Isikdemir
    Sr. Staff Software Engineer @ Uber

    We’ve heard your feedback: deploying Cadence has been a challenge, especially with limited documentation on operational aspects. So far, we’ve only provided a few docker compose files to help you get started on a development machine. However, deploying and managing Cadence at scale requires a deep understanding of underlying services, configurations and their dependencies.

    -

    To address these challenges, we’re launching several initiatives to make it easier to deploy and operate Cadence clusters. These include deployment specs for common scenarios, monitoring dashboards, alerts, runbooks, and more comprehensive documentation.

    +
    Taylan Isikdemir
    Sr. Staff Software Engineer @ Uber
    View all authors

    Announcement: Cadence Helm Charts v0 Release

    · 3 min read
    Taylan Isikdemir
    Sr. Staff Software Engineer @ Uber

    We’ve heard your feedback: deploying Cadence has been a challenge, especially with limited documentation on operational aspects. So far, we’ve only provided a few docker compose files to help you get started on a development machine. However, deploying and managing Cadence at scale requires a deep understanding of underlying services, configurations and their dependencies.

    +

    To address these challenges, we’re launching several initiatives to make it easier to deploy and operate Cadence clusters. These include deployment specs for common scenarios, monitoring dashboards, alerts, runbooks, and more comprehensive documentation.

    \ No newline at end of file diff --git a/blog/authors/taylanisikdemir.html.html b/blog/authors/taylanisikdemir.html.html index 73a49af3c..4500b5c8a 100644 --- a/blog/authors/taylanisikdemir.html.html +++ b/blog/authors/taylanisikdemir.html.html @@ -2,10 +2,10 @@ - - + + \ No newline at end of file diff --git a/blog/authors/vytautas-karpavicius.html b/blog/authors/vytautas-karpavicius.html index 0acc29bae..3045db2f1 100644 --- a/blog/authors/vytautas-karpavicius.html +++ b/blog/authors/vytautas-karpavicius.html @@ -3,8 +3,8 @@ -Vytautas Karpavicius - One post | Cadence - +Vytautas Karpavicius - One post | Cadence + @@ -15,17 +15,17 @@ - - - + + + -
    Vytautas Karpavicius
    Software Engineer @ Uber
    View all authors

    Moving to gRPC

    · 5 min read
    Vytautas Karpavicius
    Software Engineer @ Uber

    Background

    +
    Vytautas Karpavicius
    Software Engineer @ Uber
    View all authors

    Moving to gRPC

    · 5 min read
    Vytautas Karpavicius
    Software Engineer @ Uber

    Background

    Cadence historically has been using TChannel transport with Thrift encoding for both internal RPC calls and communication with client SDKs. gRPC is becoming a de-facto industry standard with much better adoption and community support. It offers features such as authentication and streaming that are very relevant for Cadence. Moreover, TChannel is being deprecated within Uber itself, pushing an effort for this migration. During the last year we’ve implemented multiple changes in server and SDK that allows users to use gRPC in Cadence, as well as to upgrade their existing Cadence cluster in a backward compatible way. This post tracks the completed work items and our future plans.

    Our Approach

    With ~500 services using Cadence at Uber and many more open source customers around the world, we had to think about the gRPC transition in a backwards compatible way. We couldn’t simply flip transport and encoding everywhere. Instead we needed to support both protocols as an intermediate step to ensure a smooth transition for our users.

    -

    Cadence was using Thrift/TChannel not just for the API with client SDKs. They were also used for RPC calls between internal Cadence server components and also between different data centers. When starting this migration we had a choice of either starting with public APIs first or all the internal things within the server. We chose the latter one, so that we could gain experience and iterate faster within the server without disruption to the clients. With server side done and listening for both protocols, dynamic config flag was exposed to switch traffic internally. It allowed gradual deployment and provided an option to rollback if needed.

    +

    Cadence was using Thrift/TChannel not just for the API with client SDKs. They were also used for RPC calls between internal Cadence server components and also between different data centers. When starting this migration we had a choice of either starting with public APIs first or all the internal things within the server. We chose the latter one, so that we could gain experience and iterate faster within the server without disruption to the clients. With server side done and listening for both protocols, dynamic config flag was exposed to switch traffic internally. It allowed gradual deployment and provided an option to rollback if needed.

    \ No newline at end of file diff --git a/blog/authors/vytautas-karpavicius.html.html b/blog/authors/vytautas-karpavicius.html.html index fce5523b7..4568b9424 100644 --- a/blog/authors/vytautas-karpavicius.html.html +++ b/blog/authors/vytautas-karpavicius.html.html @@ -2,10 +2,10 @@ - - + + \ No newline at end of file diff --git a/blog/page/2.html b/blog/page/2.html index 2e7484b30..659c95785 100644 --- a/blog/page/2.html +++ b/blog/page/2.html @@ -3,8 +3,8 @@ -Cadence Blog | Cadence - +Cadence Blog | Cadence + @@ -15,43 +15,43 @@ - - - + + + -

    Write your first workflow with Cadence

    · 3 min read
    Chris Qin
    Applications Developer @ Uber

    We have covered basic components of Cadence and how to implement a Cadence worker on local environment in previous blogs. In this blog, let's write your very first HelloWorld workflow with Cadence. I've started the Cadence backend server in background and registered a domain named test-domain. You may use the code snippet for the worker service in this blog Let's first write a activity, which takes a single string argument and print a log in the console.

    -
    func helloWorldActivity(ctx context.Context, name string) (string, error) {
    logger := activity.GetLogger(ctx)
    logger.Info("helloworld activity started")
    return "Hello " + name + "!", nil
    }

    Bad practices and Anti-patterns with Cadence (Part 1)

    · 3 min read
    Chris Qin
    Applications Developer @ Uber

    In the upcoming blog series, we will delve into a discussion about common bad practices and anti-patterns related to Cadence. As diverse teams often encounter distinct business use cases, it becomes imperative to address the most frequently reported issues in Cadence workflows. To provide valuable insights and guidance, the Cadence team has meticulously compiled these common challenges based on customer feedback.

    +

    Write your first workflow with Cadence

    · 3 min read
    Chris Qin
    Applications Developer @ Uber

    We have covered basic components of Cadence and how to implement a Cadence worker on local environment in previous blogs. In this blog, let's write your very first HelloWorld workflow with Cadence. I've started the Cadence backend server in background and registered a domain named test-domain. You may use the code snippet for the worker service in this blog Let's first write a activity, which takes a single string argument and print a log in the console.

    +
    func helloWorldActivity(ctx context.Context, name string) (string, error) {
    logger := activity.GetLogger(ctx)
    logger.Info("helloworld activity started")
    return "Hello " + name + "!", nil
    }

    Bad practices and Anti-patterns with Cadence (Part 1)

    · 3 min read
    Chris Qin
    Applications Developer @ Uber

    In the upcoming blog series, we will delve into a discussion about common bad practices and anti-patterns related to Cadence. As diverse teams often encounter distinct business use cases, it becomes imperative to address the most frequently reported issues in Cadence workflows. To provide valuable insights and guidance, the Cadence team has meticulously compiled these common challenges based on customer feedback.

    • Reusing the same workflow ID for very active/continuous running workflows

    Cadence organizes workflows based on their unique IDs, using a process called partitioning. If a workflow receives a large number of updates in a short period of time or frequently starts new runs using the continueAsNew function, all these updates will be directed to the same shard. Unfortunately, the Cadence backend is not equipped to handle this concentrated workload efficiently. As a result, a situation known as a "hot shard" arises, overloading the Cadence backend and worsening the problem.

    Solution: -Well, the best way to avoid this is simply just design your workflow in the way such that each workflow owns a uniformly distributed workflow ID across your Cadence domain. This will make sure that Cadence backend is able to evenly distribute the traffic with proper partition on your workflowIDs.

    Implement a Cadence worker service from scratch

    · 4 min read
    Chris Qin
    Applications Developer @ Uber

    In the previous blog, we have introduced three critical components for a Cadence application: the Cadence backend, domain, and worker. Among these, the worker service is the most crucial focus for developers as it hosts the activities and workflows of a Cadence application. In this blog, I will provide a short tutorial on how to implement a simple worker service from scratch in Go.

    +Well, the best way to avoid this is simply just design your workflow in the way such that each workflow owns a uniformly distributed workflow ID across your Cadence domain. This will make sure that Cadence backend is able to evenly distribute the traffic with proper partition on your workflowIDs.

    Implement a Cadence worker service from scratch

    · 4 min read
    Chris Qin
    Applications Developer @ Uber

    In the previous blog, we have introduced three critical components for a Cadence application: the Cadence backend, domain, and worker. Among these, the worker service is the most crucial focus for developers as it hosts the activities and workflows of a Cadence application. In this blog, I will provide a short tutorial on how to implement a simple worker service from scratch in Go.

    To finish this tutorial, there are two prerequisites you need to finish first

    1. Register a Cadence domain for your worker. For this tutorial, I've already registered a domain named test-domain
    2. Start the Cadence backend server in background.

    To get started, let's simply use the native HTTP package built in Go to start a process listening to port 3000. You may customize the port for your worker, but the port you choose should not conflict with existing port for your Cadence backend.

    -
    package main

    import (
    "fmt"
    "net/http"
    )

    func main(){
    fmt.Println("Cadence worker started at port 3000")
    http.ListenAndServe(":3000", nil)
    }

    Understanding components of Cadence application

    · 2 min read
    Chris Qin
    Applications Developer @ Uber

    Cadence is a powerful, scalable, and fault-tolerant workflow orchestration framework that helps developers implement and manage complex workflow tasks. In most cases, developers contribute activities and workflows directly to their codebases, and they may not have a full understanding of the components behind a running Cadence application. We receive numerous inquiries about setting up Cadence in a local environment from scratch for testing. Therefore, in this article, we will explore the components that power a Cadence cluster.

    +
    package main

    import (
    "fmt"
    "net/http"
    )

    func main(){
    fmt.Println("Cadence worker started at port 3000")
    http.ListenAndServe(":3000", nil)
    }

    Understanding components of Cadence application

    · 2 min read
    Chris Qin
    Applications Developer @ Uber

    Cadence is a powerful, scalable, and fault-tolerant workflow orchestration framework that helps developers implement and manage complex workflow tasks. In most cases, developers contribute activities and workflows directly to their codebases, and they may not have a full understanding of the components behind a running Cadence application. We receive numerous inquiries about setting up Cadence in a local environment from scratch for testing. Therefore, in this article, we will explore the components that power a Cadence cluster.

    There are three critical components that are essential for any Cadence application:

    1. A running Cadence backend server.
    2. A registered Cadence domain.
    3. A running Cadence worker that registers all workflows and activities.
    -

    Let's go over these components in more details.

    Cadence Community Spotlight Update - June 2023

    · 3 min read
    Sharan Foga
    Director of Operations & Customer Success @ Encube Technologies

    We've had a short break but now we are back. Welcome to the latest of our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!

    Please see below for a roundup of the highlights:

    Cadence Release 1.0

    Just in case you missed it - at the end of April Cadence v1.0 was officially released. This release is a significant milestone for the project and the community. It indicates that we are confident in the stability of the code that we can recommend it and promote it widely to more users. Kudos to everyone that worked together to make this release happen.

    -

    And the Uber team also gave Cadence a writeup on the Uber Engineering Blog so please take a look.

    2023 Cadence Community Survey Results

    · 4 min read
    Ender Demirkaya
    Senior Manager at Uber, Cadence. Author of the Software Engineering Handbook

    We released a user survey earlier this year to learn about who our users are, how they use Cadence, and how we can help them. It was shared from our Slack workspace, cadenceworkflow.io Blog and LinkedIn. After collecting the feedback, we wanted to share the results with our community. Thank you everyone for filling it out! Your feedback is invaluable and it helps us shape our roadmap for the future.

    +

    And the Uber team also gave Cadence a writeup on the Uber Engineering Blog so please take a look.

    2023 Cadence Community Survey Results

    · 4 min read
    Ender Demirkaya
    Senior Manager at Uber, Cadence. Author of the Software Engineering Handbook

    We released a user survey earlier this year to learn about who our users are, how they use Cadence, and how we can help them. It was shared from our Slack workspace, cadenceworkflow.io Blog and LinkedIn. After collecting the feedback, we wanted to share the results with our community. Thank you everyone for filling it out! Your feedback is invaluable and it helps us shape our roadmap for the future.

    Here are some highlights in text and you can check out the visuals to get more details:

    -

    using.png

    -

    job_role.png

    -

    Most of the people who replied to our survey were engineers who were already using Cadence, actively evaluating, or migrating from a similar technology. This was exciting to hear! Some of you have contacted us to learn more about benchmarks, scale, and ideal use cases. We will share more guidelines about this but until then, feel free to contact us over our Slack workspace for guidance.

    Cadence Community Spotlight Update - March 2023

    · 2 min read
    Sharan Foga
    Director of Operations & Customer Success @ Encube Technologies

    Welcome to the latest of our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!

    +

    using.png

    +

    job_role.png

    +

    Most of the people who replied to our survey were engineers who were already using Cadence, actively evaluating, or migrating from a similar technology. This was exciting to hear! Some of you have contacted us to learn more about benchmarks, scale, and ideal use cases. We will share more guidelines about this but until then, feel free to contact us over our Slack workspace for guidance.

    Cadence Community Spotlight Update - March 2023

    · 2 min read
    Sharan Foga
    Director of Operations & Customer Success @ Encube Technologies

    Welcome to the latest of our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!

    Please see below for a roundup of the highlights:

    Cadence at Open Source Summit, North America

    We are very pleased to let you know that a talk on Cadence has been accepted for the Linux Foundation's Open Source Summit, North America in Vancouver on 10th - 12th May 2023.

    @@ -62,7 +62,7 @@

    Community
  • February 2023 : 16 questions asked
  • March 2023 : 12 questions asked
  • -

    All of these questions are being answered collaboratively by the community. Thanks everyone for sharing your knowledge and we are looking forward to receiving more of your questions!

    Cadence Community Spotlight Update - March 2024

    · 3 min read
    Kevin Corbett
    Open Source Community Manager | @instaclustr @NetApp

    Welcome back to the latest in our regular Cadence community spotlight updates where we aim to deliver you news from in and around the Cadence community! +

    All of these questions are being answered collaboratively by the community. Thanks everyone for sharing your knowledge and we are looking forward to receiving more of your questions!

    Cadence Community Spotlight Update - March 2024

    · 3 min read
    Kevin Corbett
    Open Source Community Manager | @instaclustr @NetApp

    Welcome back to the latest in our regular Cadence community spotlight updates where we aim to deliver you news from in and around the Cadence community! It’s been a few months since our last update, so I have a bunch of exciting updates to share.

    Let’s get started!

    Proposal for Cadence Plugin System

    @@ -70,17 +70,17 @@

    Cadence Plugin System Proposal -

    A huge thank you to Mantas for initiating this work. This is an excellent example of how we can collaborate together to bring about new features that benefit us all.

    Cadence Community Spotlight Update - February 2023

    · 2 min read
    Sharan Foga
    Director of Operations & Customer Success @ Encube Technologies

    Here’s the latest in our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!

    +

    A huge thank you to Mantas for initiating this work. This is an excellent example of how we can collaborate together to bring about new features that benefit us all.

    Cadence Community Spotlight Update - February 2023

    · 2 min read
    Sharan Foga
    Director of Operations & Customer Success @ Encube Technologies

    Here’s the latest in our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!

    Please see below for a roundup of the highlights:

    Community Survey

    We've been talking about doing a community survey for a while and during February we sent it out. We are still collating the results so it's not too late to send in your response.

    The survey takes 5 minutes and is your opportunity to provide feedback to the project and highlight areas you think we need to focus on.

    Use this Survey Link

    -

    Please take a few minutes to give us your opinion.

    Cadence Community Spotlight Update - January 2023

    · 3 min read
    Sharan Foga
    Director of Operations & Customer Success @ Encube Technologies

    Happy New Year everyone! Here’s the latest in our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!

    Please see below for a roundup of the highlights:

    Closing Down Cadence Office Hours

    We have been running Office Hours sessions every month since May last year. The aim was to give the community an opportunity to speak directly with some of the Cadence core developers and experts to answer questions on particular issues you may be having. We have found that the most preferred method for community questions has been the support Slack channel so have decided to stop this monthly call.

    Thanks very much to Ender Demirkayaand the Uber team for making themselves available for these sessions.

    -

    Please remember that if you have question about Cadence or are facing a specific issue then you can post your question in our #support Slack channel. If you also post the details on StackOverflow with the cadence workflow tag then there will be a searchable history for others who encounter the same issue to find a solution.

    +

    Please remember that if you have question about Cadence or are facing a specific issue then you can post your question in our #support Slack channel. If you also post the details on StackOverflow with the cadence workflow tag then there will be a searchable history for others who encounter the same issue to find a solution.

    \ No newline at end of file diff --git a/blog/page/2.html.html b/blog/page/2.html.html index dfecd03d2..3d66e6643 100644 --- a/blog/page/2.html.html +++ b/blog/page/2.html.html @@ -2,10 +2,10 @@ - - + + \ No newline at end of file diff --git a/blog/page/3.html b/blog/page/3.html index cf85a0f0f..71c848021 100644 --- a/blog/page/3.html +++ b/blog/page/3.html @@ -3,8 +3,8 @@ -Cadence Blog | Cadence - +Cadence Blog | Cadence + @@ -15,14 +15,14 @@ - - - + + + -

    Cadence Community Spotlight Update - December 2022

    · 2 min read
    Sharan Foga
    Director of Operations & Customer Success @ Encube Technologies

    I know we are a little early this month as many people will be taking some time out for holidays.

    +

    Cadence Community Spotlight Update - December 2022

    · 2 min read
    Sharan Foga
    Director of Operations & Customer Success @ Encube Technologies

    I know we are a little early this month as many people will be taking some time out for holidays.

    Happy Holidays

    We'd like to wish everyone happy holidays and to thank you for being part of the Cadence community. It's been a busy year for Cadence as we have continued to build a strong, active community that works together to solve issues and generally support each other.

    Let's keep going!...This is a great way to build a sustainable community.

    @@ -39,27 +39,27 @@

    Cadence
  • Cadence Connection Examples Using TLS

  • -

    Cadence Community Spotlight Update - November 2022

    · 2 min read
    Sharan Foga
    Director of Operations & Customer Success @ Encube Technologies

    Here’s the latest in our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!

    Please see below for a roundup of the highlights:

    Cadence @ Uber

    This month Uber Engineering published a really nice article on one of the ways they are using Cadence. The article is called How Uber Optimizes the Timing of Push Notifications using ML and Linear Programming.

    The Uber team take you through the details of the problem that they are looking to solve, so you can understand the scope limitations and depedencies - so please take a look.

    Cadence @ DeveloperWeek Enterprise

    DevNetwork run a series of conferences and during November Cadence was featured in at DeveloperWeek Enterprise. Ender Demirkaya and Ben Slater presented a talk called Espress Complex Business Logic as Code with Open Source Cadence!.

    -

    It is good to see that we are finding new channels for us to present the benefits of using Cadence. Huge hanks to Ben and Ender for the presentation and to everyone that attended.

    Cadence Community Spotlight Update - October 2022

    · 2 min read
    Sharan Foga
    Director of Operations & Customer Success @ Encube Technologies

    Here’s the latest in our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!

    +

    It is good to see that we are finding new channels for us to present the benefits of using Cadence. Huge hanks to Ben and Ender for the presentation and to everyone that attended.

    Cadence Community Spotlight Update - October 2022

    · 2 min read
    Sharan Foga
    Director of Operations & Customer Success @ Encube Technologies

    Here’s the latest in our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!

    Please see below for a roundup of the highlights:

    Cadence Meetup Postponed

    It's always great to get the community together and we had planned to run another Cadence Meetup in early November. Unfortunately we didn't have enough time to get things organised so we've decided to postpone it. So please watch out for an announcement for the new Cadence meetup date.

    Doordash Technnical Showcase Featuring Cadence

    We have had some great feedback from people who attended Technical Showcase that was run this month by Doordash. It featured their financial products but also highlighted some of the key technologies they use...and guess what Cadence is one of them!

    If you missed the session then you will be happy to know that it was recorded and we've inlcuded a link to the the recording on Youtube.

    -

    Thanks to the Doordash team for running the session and helping support Cadence by sharing their knowledge.

    Cadence Community Spotlight Update - September 2022

    · 2 min read
    Sharan Foga
    Director of Operations & Customer Success @ Encube Technologies

    Here’s the latest in our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!

    Please see below for a roundup of the highlights:

    A Cadence talk by Ender Demirkaya and Ben Slater has been accepted for Developer Week Enterprise.

    The talk is scheduled to for 16th November so please make a note in your calendars.

    Sharing Knowledge

    Over the last few months we have had a continual stream of Cadence questions in our Slack #support channel or on StackOverflow. As a result of the increased interest some members from the Cadence core team have decided to spend some time each day responding to your questions.

    -

    Remember that if you have received a response that has solved your problem especially on StackOverflow then please don't forget to accept answer!

    Cadence Community Spotlight Update - August 2022

    · 3 min read
    Sharan Foga
    Director of Operations & Customer Success @ Encube Technologies

    Here’s the latest in our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!

    +

    Remember that if you have received a response that has solved your problem especially on StackOverflow then please don't forget to accept answer!

    Cadence Community Spotlight Update - August 2022

    · 3 min read
    Sharan Foga
    Director of Operations & Customer Success @ Encube Technologies

    Here’s the latest in our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!

    Please see below for a roundup of the highlights:

    Community Survey

    We are working on putting together our first community survey to find out a bit more about our community. We would like to get your feedback about on a few things such as:

    @@ -69,38 +69,38 @@

    Community S
  • any special use cases not yet covered
  • and of course whatever other feedback you'd like to give us
  • -

    So please watch out for the survey which will be coming out to you via the Slack channel soon!

    Cadence Community Spotlight Update - July 2022

    · 2 min read
    Sharan Foga
    Director of Operations & Customer Success @ Encube Technologies

    Here’s our monthly Community Spotlight update that gives you news from in and around the Cadence community!

    Please see below for a roundup of the highlights:

    Flying Drones with Cadence

    Community member Paul Brebner has released another blog in the series of using Cadence to manage a drone delivery service. You can see a simulated view of it in action

    Don’t forget to try out the code yourself and remember if you have used Cadence to do something interesting then please let us know so we can feature it in our next update.

    GitHub Statistics

    During July the main Cadence branch had 28 pull requests (PRs) merged. There were 214 files changed by 11 different authors. You can find more details here

    -

    The Cadence documentation repository was not as busy with only 2 PRs merged in July, 5 commits and 3 authors active. More details can be found here

    Cadence Community Spotlight Update - June 2022

    · 3 min read
    Sharan Foga
    Director of Operations & Customer Success @ Encube Technologies

    It’s time for our monthly Cadence Community Spotlight update with news from in and around the Cadence community!

    Please see below for a roundup of the highlights:

    Knowledge Sharing and Support

    Our Slack #support channel has been busy this month with 13 questions asked this month by 12 different community members. Six community members took time to respond to those questions which clearly shows our community is growing, collaborating and keen to share knowledge.

    Please don’t forget that we encourage everyone to post questions on StackOverflow using the cadence-workflow and uber-cadence tags so that others with similar questions or issues can easily search for and find an answer.

    Improving Technical Office Hours

    Over the last few months we have been holding regular monthly Office Hours meetings but they have not attracted as many participants as we would like. We would like to understand if there is something preventing people from attending (e.g perhaps the timing or dates are not convenient) so we are planning to send out a short community survey.

    -

    If you have any ideas or comments about how we can improve our community office hours sessions then please include this in your feedback or contact us in the #community Slack channel.

    Cadence Community Spotlight Update - May 2022

    · 3 min read
    Sharan Foga
    Director of Operations & Customer Success @ Encube Technologies

    Welcome to our regular Cadence Community Spotlight update!

    +

    If you have any ideas or comments about how we can improve our community office hours sessions then please include this in your feedback or contact us in the #community Slack channel.

    Cadence Community Spotlight Update - May 2022

    · 3 min read
    Sharan Foga
    Director of Operations & Customer Success @ Encube Technologies

    Welcome to our regular Cadence Community Spotlight update!

    This is our monthly blog post series focused on news from in and around the Cadence community.

    Please see below for a short activity roundup of what has happened recently in the community.

    Cadence Polling Cookbook

    Do you want to understand polling work and have an example of how to set it up in Cadence? Well a brand new Cadence Polling cookbook is now available that gives you all the details you need. The cookbook was created by several members of the Instaclustr team and they are keen to share it with the community. The pdf version of the cookbook can found on the Cadence website under the Polling an external API for a specific resource to become available section of the Polling Use cases.

    A Github repository has also been created with the sample cookbook code for you to try out for yourself.

    -

    So please go ahead and try out the cookbook and don’t forget to let us have your feedback.

    Cadence Community Spotlight Update - April 2022

    · 3 min read
    Sharan Foga
    Director of Operations & Customer Success @ Encube Technologies

    Welcome to our Cadence Community Spotlight update!

    This is our monthly blog post series focused on news from in and around the Cadence community.

    Please see below for a short activity roundup of what has happened recently in the community.

    SD Times Names Cadence Open Source Project of the Week

    In April Cadence was named as open source project of the week by the SD Times. Being named gives the project some great publicity and means the project is getting noticed. You can find a link to the article in the Cadence in the News section below.

    Follow Us on LinkedIn and Twitter!

    We have now set up Cadence accounts on LinkedIn and Twitter where you can keep up to date with what is happening in the community. We will be using these social media accounts to share news, articles, stories and links related to Cadence - so please follow us!

    -

    And don’t forget to share your news with us. We are looking forward to receiving your feedback and comments. The more we interact - the more we build our community!

    Cadence Community Spotlight Update - March 2022

    · 4 min read
    Sharan Foga
    Director of Operations & Customer Success @ Encube Technologies

    Welcome to our Cadence Community Spotlight update!

    This is the latest in our series of monthly blog posts focused on the Cadence community and news about what you have been doing with Cadence.

    Please see below for a short activity roundup of what has happened recently in the community.

    Updated Cadence Topology Diagram

    Did you know that we have an updated Cadence Service diagram on the website? Well we do - and you can find it on our Deployment Topology page. We are always looking for information that helps makes it easier for people to understand how Cadence works.

    -

    Special thanks to Ben Slater for updating the diagram and also to Ender, Emrah and Long for helping review it.

    +

    Special thanks to Ben Slater for updating the diagram and also to Ender, Emrah and Long for helping review it.

    \ No newline at end of file diff --git a/blog/page/3.html.html b/blog/page/3.html.html index 374a94ac5..6344e1695 100644 --- a/blog/page/3.html.html +++ b/blog/page/3.html.html @@ -2,10 +2,10 @@ - - + + \ No newline at end of file diff --git a/blog/page/4.html b/blog/page/4.html index bbf206666..7702f74c7 100644 --- a/blog/page/4.html +++ b/blog/page/4.html @@ -3,8 +3,8 @@ -Cadence Blog | Cadence - +Cadence Blog | Cadence + @@ -15,33 +15,33 @@ - - - + + + -

    Cadence Community Spotlight Update - February 2022

    · 3 min read
    Sharan Foga
    Director of Operations & Customer Success @ Encube Technologies

    Welcome to the Cadence Community Spotlight update!

    +

    Cadence Community Spotlight Update - February 2022

    · 3 min read
    Sharan Foga
    Director of Operations & Customer Success @ Encube Technologies

    Welcome to the Cadence Community Spotlight update!

    This is the second in our series of monthly updates focused on the Cadence community and news about what you have been doing with Cadence. We hope that you enjoyed last month's update and are keen to find out what has been happening.

    Please see below for a short activity roundup of what has happened recently in the community.

    Announcements

    Just in case you missed it the alpha version of the Cadence notification service has been released. Details can be found at the following link: Cadence Notification Service

    -

    Thanks very much to everyone that worked on this!

    Cadence Community Spotlight Update - January 2022

    · 3 min read
    Sharan Foga
    Director of Operations & Customer Success @ Encube Technologies

    Welcome to our very first Cadence Community Spotlight update!

    This monthly update focuses on news from the wider Cadence community and is all about what you have been doing with Cadence. Do you have an interesting project that uses Cadence? If so then we want to hear from you. Also if you have any news items, blogs, articles, videos or events where Cadence has been mentioned then that is good too. We want to showcase that our community is active and is doing exciting and interesting things.

    -

    Please see below for a short round up of things that have happened recently in the community.

    Moving to gRPC

    · 5 min read
    Vytautas Karpavicius
    Software Engineer @ Uber

    Background

    Cadence historically has been using TChannel transport with Thrift encoding for both internal RPC calls and communication with client SDKs. gRPC is becoming a de-facto industry standard with much better adoption and community support. It offers features such as authentication and streaming that are very relevant for Cadence. Moreover, TChannel is being deprecated within Uber itself, pushing an effort for this migration. During the last year we’ve implemented multiple changes in server and SDK that allows users to use gRPC in Cadence, as well as to upgrade their existing Cadence cluster in a backward compatible way. This post tracks the completed work items and our future plans.

    Our Approach

    With ~500 services using Cadence at Uber and many more open source customers around the world, we had to think about the gRPC transition in a backwards compatible way. We couldn’t simply flip transport and encoding everywhere. Instead we needed to support both protocols as an intermediate step to ensure a smooth transition for our users.

    -

    Cadence was using Thrift/TChannel not just for the API with client SDKs. They were also used for RPC calls between internal Cadence server components and also between different data centers. When starting this migration we had a choice of either starting with public APIs first or all the internal things within the server. We chose the latter one, so that we could gain experience and iterate faster within the server without disruption to the clients. With server side done and listening for both protocols, dynamic config flag was exposed to switch traffic internally. It allowed gradual deployment and provided an option to rollback if needed.

    Announcing Cadence OSS office hours and community sync up

    · 2 min read
    Liang Mei
    Engineering Manager @ Uber

    Are you a current Cadence user, do you operate Cadence services, or are you interested in learning about workflow technologies and wonder what problems Cadence could solve for you? We would like to talk to you!

    +

    Cadence was using Thrift/TChannel not just for the API with client SDKs. They were also used for RPC calls between internal Cadence server components and also between different data centers. When starting this migration we had a choice of either starting with public APIs first or all the internal things within the server. We chose the latter one, so that we could gain experience and iterate faster within the server without disruption to the clients. With server side done and listening for both protocols, dynamic config flag was exposed to switch traffic internally. It allowed gradual deployment and provided an option to rollback if needed.

    Announcing Cadence OSS office hours and community sync up

    · 2 min read
    Liang Mei
    Engineering Manager @ Uber

    Are you a current Cadence user, do you operate Cadence services, or are you interested in learning about workflow technologies and wonder what problems Cadence could solve for you? We would like to talk to you!

    Our team has spent a significant amount of time working with users and partner teams at Uber to design, scale and operate their workflows. This helps our users understand the technology better, smooth their learning curve and ramp up experience, and at the same time allows us to get fast and direct feedback so we can improve the developer experience and close feature gaps. As our product and community grows, we would like to expand this practice to our users in the OSS community. For the first time ever, members of the Cadence team along with core contributors from the community will host bi-weekly office hours to answer any questions you have about Cadence, or workflow technology in general. We can also dedicate future sessions to specific topics that have a common interest. Please don’t hesitate to let us know your thoughts.

    Please join a session if you would like to talk about any of the following topics:

    1. Understand what Cadence is and why it might be useful for you and your company
    2. Guidance about running Cadence services and workers in production
    3. Workflow design and operation consultation
    4. Product update, future roadmaps as well as collaboration opportunities

    Building and maintaining a healthy and growing community is the key to the success of Cadence, and one of the top priorities for our team. We would like to use the office hours as an opportunity to understand and help our customers, seek feedback, and forge partnerships. We look forward to seeing you in one of the meetings.

    Upcoming Office Hours

    -

    As we have a geo-distributed userbase, we are still trying to figure out a time that works for most of the people. In the meanwhile, we will manually schedule the first few instances of the meeting until we settle on a fixed schedule. Our next office hours will take place on Thursday, October 21 2pm-3pm PT/5pm-6pm EST/9pm-10pm GMT. Please join via this zoom link.

    Long-term commitment and support for the Cadence project, and its community

    · 3 min read
    Liang Mei
    Engineering Manager @ Uber

    Dear valued Cadence users and developers,

    +

    As we have a geo-distributed userbase, we are still trying to figure out a time that works for most of the people. In the meanwhile, we will manually schedule the first few instances of the meeting until we settle on a fixed schedule. Our next office hours will take place on Thursday, October 21 2pm-3pm PT/5pm-6pm EST/9pm-10pm GMT. Please join via this zoom link.

    Long-term commitment and support for the Cadence project, and its community

    · 3 min read
    Liang Mei
    Engineering Manager @ Uber

    Dear valued Cadence users and developers,

    Some of you might have read Temporal’s recent announcement about their decision to drop the support for the Cadence project. This message caused some confusion in the community, so we would like to take this opportunity to clear things out.

    -

    First of all, Uber is committed to the long-term success of the Cadence project. Since its inception 5 years ago, use cases built on Cadence and their scale have grown significantly at Uber. Today, Cadence powers a variety of our most business-critical use cases (some public stories are available here and here). At the same time, the Cadence development team at Uber has enjoyed rapid growth with the product and has been driving innovations of workflow technology across the board, from new features (e.g. graceful failover, workflow shadowing, UI improvements) to better engineering foundations (e.g. gRPC support, multi-tenancy support), all in a backwards compatible manner. Neither Uber’s use nor support of Cadence is going to change with Temporal’s announcement. We have a long list of features and exciting roadmaps ahead of us, and we will share more details in our next meetup in November ‘21. As always we will continue to push the boundaries of scale and reliability as our usage within Uber grows.

    +

    First of all, Uber is committed to the long-term success of the Cadence project. Since its inception 5 years ago, use cases built on Cadence and their scale have grown significantly at Uber. Today, Cadence powers a variety of our most business-critical use cases (some public stories are available here and here). At the same time, the Cadence development team at Uber has enjoyed rapid growth with the product and has been driving innovations of workflow technology across the board, from new features (e.g. graceful failover, workflow shadowing, UI improvements) to better engineering foundations (e.g. gRPC support, multi-tenancy support), all in a backwards compatible manner. Neither Uber’s use nor support of Cadence is going to change with Temporal’s announcement. We have a long list of features and exciting roadmaps ahead of us, and we will share more details in our next meetup in November ‘21. As always we will continue to push the boundaries of scale and reliability as our usage within Uber grows.

    \ No newline at end of file diff --git a/blog/page/4.html.html b/blog/page/4.html.html index 32a833341..8bc2142d0 100644 --- a/blog/page/4.html.html +++ b/blog/page/4.html.html @@ -2,10 +2,10 @@ - - + + \ No newline at end of file diff --git a/blog/rss.xml b/blog/rss.xml index c120ce12c..9a77b5e6d 100644 --- a/blog/rss.xml +++ b/blog/rss.xml @@ -2,7 +2,7 @@ Cadence Blog - https://cadenceworkflow.io/blog + https://cadenceworkflow.io/Cadence-Docs/blog Cadence Blog Mon, 18 Nov 2024 14:00:00 GMT https://validator.w3.org/feed/docs/rss2.html @@ -10,8 +10,8 @@ en <![CDATA[Cadence Repositories Have Moved!]]> - https://cadenceworkflow.io/blog/2024/11/18/cadence-workflows-github-organization - https://cadenceworkflow.io/blog/2024/11/18/cadence-workflows-github-organization + https://cadenceworkflow.io/Cadence-Docs/blog/2024/11/18/cadence-workflows-github-organization + https://cadenceworkflow.io/Cadence-Docs/blog/2024/11/18/cadence-workflows-github-organization Mon, 18 Nov 2024 14:00:00 GMT We’re excited to announce that all Cadence GitHub repositories have been consolidated under the cadence-workflow organization! 🎉

    @@ -27,12 +27,12 @@
    <![CDATA[Zonal Isolation for Cadence Workflows]]> - https://cadenceworkflow.io/blog/zonal-isolation-v1/zonal-isolation-v1 - https://cadenceworkflow.io/blog/zonal-isolation-v1/zonal-isolation-v1 + https://cadenceworkflow.io/Cadence-Docs/blog/zonal-isolation-v1/zonal-isolation-v1 + https://cadenceworkflow.io/Cadence-Docs/blog/zonal-isolation-v1/zonal-isolation-v1 Mon, 14 Oct 2024 00:00:00 GMT At Uber, we want to achieve regional resilience such that losing a zone within a region can be tolerated without requiring a cross-region failover. We also want to make sure that losing a zone only affects a subset of workload, at most, rather than everything. However, in Cadence-based systems, the workload in a region is distributed randomly across all workers in the region at a “task-level granularity”, which means a workflow may be worked on by any worker in the region where the domain is active. To achieve this goal, we introduced Zonal Isolation for Cadence Workflows - a feature designed to pin workflows to the zone they are started in, so that zonal isolation can be achieved at a workflow-level.

    -

    What is Zonal Isolation for Cadence Workflows?

    +

    What is Zonal Isolation for Cadence Workflows?

    At high-level, Zonal Isolation for Cadence Workflows can be thought in 2 levels:

    1. Task-level isolation: All decision tasks and activity tasks of a workflow are only processed by workers from the zone where the workflow was started
    2. @@ -40,13 +40,13 @@

    Infrastructure-level isolation is quite challenging to implement as it requires significant changes to the core design of the Cadence server. Due to the complexity involved, support for this feature is not planned for the foreseeable future.

    As a result, the focus remains on achieving task-level zonal isolation outside the Cadence server, which offers a more practical and immediate way to improve system resilience. It provides the capability of ensuring that an unhealthy zone (i.e. bad deployment of workers) only affect a subset of workflows (started from a certain zone) rather than every workflow in a Cadence domain.

    -

    How Zonal Isolation Works in Cadence?

    -

    Architecture

    +

    How Zonal Isolation Works in Cadence?

    +

    Architecture

    Here is what the architecture of a zonally isolated Cadence-based system looks like: -zonal isolation overview +zonal isolation overview

    Fig: Workflows started in one zone are only dispatched to workers from the same zone. Colors to emphasize pinning.

    -

    Implementation

    -

    Determine the zone of a workflow and workers

    +

    Implementation

    +

    Determine the zone of a workflow and workers

    To ensure that tasks are dispatched to workers in the same zone as the workflows, we must identify the origin zone of both. The zone of a workflow is determined by the origin zone of the StartWorkflowExecution request, while the zone of workers is determined by the origin zone of the PollForDecisionTask and PollForActivityTask requests. There are three possible ways to determine the origin zone for these requests:

    • Uber's Approach: Let Cadence SDK set the origin zone in the headers of the requests before sending the request to Cadence.
    • @@ -54,27 +54,27 @@
    • Determine the origin zone of the requests from the zone of the cadence-frontend instance receiving the request, if the network layer has already achieved zonal isolation.

    The 2nd approach is the ideal one, but Uber's network infrastructure doesn't provide such headers and the network layer is not ready for zonal isolation. As a result, we adopt the 1st approach. At Uber, we have internal libraries in Go and Java acting as wrappers around Cadence SDK injecting necessary configurations. These libraries have been updated to include the origin zone in the request headers using a header called cadence-client-isolation-group.

    -

    How to dispatch tasks to workers from the same zone?

    +

    How to dispatch tasks to workers from the same zone?

    To implement task-level isolation, we introduce a new dimension to the tasklist — isolation group. When a workflow is initiated, the origin zone of the workflow is stored in the database. Each time a decision or activity task is dispatched to cadence-matching, the workflow's origin zone is used as the isolation group for that task.

    When a worker sends a PollForDecisionTask or PollForActivityTask request to cadence-matching, the request is labeled with the worker's isolation group (i.e., the worker's zone). Tasks are then dispatched only to poller requests that have the same isolation group, ensuring that tasks are processed by workers in the same zone as the workflow's origin.

    -

    How to handle workflows from a drained zone?

    +

    How to handle workflows from a drained zone?

    In the event of an outage, such as a bad deployment, customers may want to drain workers from a specific zone to mitigate the impact. There are two types of drains that can occur:

    1. Implicit drain: Workers from a zone completely stop operating, either due to failures or manual shutdowns.
    2. Explicit drain: Customers explicitly mark workers from a zone as drained.

    Within cadence-matching, a list of pollers is maintained for each tasklist, tracking the zone from which the pollers originate. An implicit drain can be detected by checking whether there are any active pollers from a particular zone. If a zone is drained (either explicitly or implicitly), workflows that were started in that zone will be reassigned and spread to workers in the remaining healthy zones.

    -
    How to drain a zone explicitly?
    +
    How to drain a zone explicitly?

    Explicitly draining a zone can be done at two levels:

    1. Domain-level drain: This applies to a specific domain, allowing the zone to be drained only for workflows within that domain.
    2. Cluster-level drain: This applies to the entire Cadence cluster, draining the zone for all domains and workflows within the cluster.

    For domain-level drain, the draining status is stored in domains table. For cluster-level drain, the status is stored in cluster_config table.

    -

    How to enable Zonal Isolation?

    -

    Server Update

    +

    How to enable Zonal Isolation?

    +

    Server Update

    In order to enable this feature, please upgrade Cadence server to v1.2.1 or later.

    -

    NOTE: If you're not using the provided main binary located in cmd/server, you must adopt this middleware. Depends on the appoach to determine the origin zone of requests, you can adopt this middleware or build your own middleware using partition.ContextWithConfig function to inject origin zone into the context.

    +

    NOTE: If you're not using the provided main binary located in cmd/server, you must adopt this middleware. Depends on the appoach to determine the origin zone of requests, you can adopt this middleware or build your own middleware using partition.ContextWithConfig function to inject origin zone into the context.

    This feature is controlled by 2 dynamic config properties.

    • system.allIsolationGroups: This property provides the list of available zones within a region.
    • @@ -84,8 +84,8 @@ It’s important to note that any update to the system.allIsolationGroups<

      An example configuration using the file based dynamic configuration could look like this:

      system.allIsolationGroups:
      - value: []
      constraints: {}
      - value: ["dca1", "dca2", "dca3"]
      constraints:
      clusterName: prod-dca
      - value: ["phx1", "phx2", "phx3"]
      constraints:
      clusterName: prod-phx
      system.enableTasklistIsolation:
      - value: false
      constraints: {}
      - value: true
      constraints:
      domainName: samples-domain

      In this example, the Cadence cluster spans two regions, each containing three zones: dca1, dca2, dca3 in the dca region and phx1, phx2, phx3 in the phx region. Zonal isolation is enabled only for the samples-domain, while it remains disabled for other domains.

      -

      SDK Update

      -

      NOTE: This update is only necessary if you're using the 1st approach to determine the origin zone of requests.

      +

      SDK Update

      +

      NOTE: This update is only necessary if you're using the 1st approach to determine the origin zone of requests.

      To support Zonal Isolation, please upgrade your SDK versions:

      • Go SDK: Upgrade to v1.0.2 or later.
      • @@ -93,17 +93,17 @@ It’s important to note that any update to the system.allIsolationGroups<

      For Java SDK users, set the isolationGroup field to the zone of the instance when creating serviceClient.

      For Go SDK users, set the isolationGroup field to the zone of the instance when creating Worker. Additionally, you need to use this method to wrap workflowserviceclient.Interface.

      -

      How to drain a zone explicitly?

      +

      How to drain a zone explicitly?

      Drains can be done via the Admin APIs of cadence-frontend or CLI.

      You can check the help message for the CLI by running:

      cadence admin isolation-groups -h
      -

      Monitoring

      +

      Monitoring

      A new metric is introduced to help detect the leakage of tasks and skewness of traffic.

      isolation_task_matches_per_tl: This is a counter that counts the number of tasks polled by workers. The metric is tagged with the domain, tasklist name, tasklist type, the origin zone of the workflow and the origin zone of the worker polling the task.

      This metric can be used in the following ways:

      Detecting task leakage: By grouping tasks based on the origin zones of both the workflows and workers, you can identify tasks that have leaked, i.e., tasks assigned to workers in zones different from the workflow's origin zone.

      Identifying traffic skewness: By grouping tasks based solely on the origin zones of workflows, you can determine if traffic is disproportionately distributed among the zones, helping to detect any uneven load or traffic imbalance across zones.

      -

      Status at Uber

      +

      Status at Uber

      • We launched this feature at Uber in July 2023. More than 100 domains have Zonal Isolation enabled.
      • However, as of 2024, the rollout of Zonal Isolation is paused due to a traffic skewness issue: @@ -112,7 +112,7 @@ It’s important to note that any update to the system.allIsolationGroups<
    -

    Next Step

    +

    Next Step

    Currently, Zonal Isolation is implemented as hard isolation, where tasks are strictly limited to the same zone as the originating workflow. To address the traffic skewness issue, we are working on iterating this feature to introduce soft isolation. This relaxed version will allow for some task leakage between zones if traffic skewness is detected, ensuring better worker utilization and reducing latency.

    This enhancement is one of our major ongoing projects, and we plan to share more details in a future blog post once it is launched.

    ]]>
    Deep Dives @@ -120,15 +120,15 @@ It’s important to note that any update to the system.allIsolationGroups<
    <![CDATA[Announcement: Cadence Helm Charts v0 Release]]> - https://cadenceworkflow.io/blog/2024/10/01/announcing-cadence-helm-charts-v0 - https://cadenceworkflow.io/blog/2024/10/01/announcing-cadence-helm-charts-v0 + https://cadenceworkflow.io/Cadence-Docs/blog/2024/10/01/announcing-cadence-helm-charts-v0 + https://cadenceworkflow.io/Cadence-Docs/blog/2024/10/01/announcing-cadence-helm-charts-v0 Tue, 01 Oct 2024 00:00:00 GMT We’ve heard your feedback: deploying Cadence has been a challenge, especially with limited documentation on operational aspects. So far, we’ve only provided a few docker compose files to help you get started on a development machine. However, deploying and managing Cadence at scale requires a deep understanding of underlying services, configurations and their dependencies.

    To address these challenges, we’re launching several initiatives to make it easier to deploy and operate Cadence clusters. These include deployment specs for common scenarios, monitoring dashboards, alerts, runbooks, and more comprehensive documentation.

    -

    Introducing Cadence Kubernetes Helm Chart v0

    +

    Introducing Cadence Kubernetes Helm Chart v0

    Today, we are happy to announce the release of Cadence Kubernetes Helm Chart v0. This will be the starting point for standardizing Cadence deployments on Kubernetes. We chose Kubernetes because it's the leading compute platform, but Cadence remains flexible and can run on any infrastructure.

    -

    How to Get Started

    +

    How to Get Started

    Helm must be installed to use the charts. Please refer to Helm's documentation to get started.

    Once Helm has been set up correctly, add the repo as follows:

    helm repo add cadence https://uber.github.io/cadence-charts
    @@ -138,7 +138,7 @@ It’s important to note that any update to the system.allIsolationGroups<

    To uninstall the chart:

    helm delete my-cadence

    See CONTRIBUTING.md for details on how to validate the deployment by running sample workflows.

    -

    Current State of the Chart

    +

    Current State of the Chart

    There were a few community-created Cadence Helm charts but they were not actively maintained and had a few glitches that Cadence team @Uber wasn't able to provide support for. With the introduction of the new official Cadence Helm chart, our team is committed to provide support and evolve it with input from community.

    The v0 chart contains only the basics at the moment:

      @@ -157,7 +157,7 @@ It’s important to note that any update to the system.allIsolationGroups<
    • Custom annotations/lables/tolerations etc.
    • Support for ingress
    -

    Next Steps

    +

    Next Steps

    Since this is an early release, we would love to hear from you. Feel free to start discussions or report issues.

    Also check out the contribution guideline if you are interested to contribute. Don't hesitate to send a PR and ping us over slack if we miss it.

    P.S. Huge thanks to our summer intern Nikita Bhardwaj for kickstarting the Cadence Helm charts initiative.

    ]]>
    @@ -165,13 +165,13 @@ It’s important to note that any update to the system.allIsolationGroups<
    <![CDATA[Minimizing blast radius in Cadence: Introducing Workflow ID-based Rate Limits]]> - https://cadenceworkflow.io/blog/2024/09/05/workflow-specific-rate-limits - https://cadenceworkflow.io/blog/2024/09/05/workflow-specific-rate-limits + https://cadenceworkflow.io/Cadence-Docs/blog/2024/09/05/workflow-specific-rate-limits + https://cadenceworkflow.io/Cadence-Docs/blog/2024/09/05/workflow-specific-rate-limits Thu, 05 Sep 2024 00:00:00 GMT At Uber, we run several big multitenant Cadence clusters with hundreds of domains in each. The clusters being multi-tenant means potential noisy neighbor effects between domains.

    An essential aspect of avoiding this is managing how workflows interact with our infrastructure to prevent any single workflow from causing instability for the whole cluster. To this end, we are excited to introduce Workflow ID-based rate limits — a new feature designed to protect our clusters from problematic workflows and ensure stability across the board.

    -

    Why Workflow ID-based Rate Limits?

    +

    Why Workflow ID-based Rate Limits?

    We already have rate limits for how many requests can be sent to a domain. However, since Cadence is sharded on the workflow ID, a user-provided input, an overused workflow with a particular id might overwhelm a shard by making too many requests. There are two main ways this happens:

    1. A user starts, or signals the same workflow ID too aggressively,
    2. @@ -181,7 +181,7 @@ It’s important to note that any update to the system.allIsolationGroups<
      func Workflow(ctx workflow.Context, input sampleInput) (string, error) {
      ...
      for _, elem := range longList {
      err := workflow.ExecuteActivity(ctx, QuickActivity, elem).Get(ctx, nil)
      }
      ...
      }

      This heavy load creates what we call hot shards. Hot shards degrade performance not just for the workflow causing the issue, but for all workflows that interact with the affected shard. This can grow to a point where the whole cluster becomes unstable.

      Now, with Workflow ID-based rate limits, we limit the number of external calls and actions per second for each individual workflow, reducing the blast radius (impact on the cluster) of a badly behaved workflow to an absolute minimum where only the offending workflow is impacted.

      -

      Why not Shard Rate Limits?

      +

      Why not Shard Rate Limits?

      An obvious question is “why don’t we rate limit the requests to the shard?”. After all, the shard is what we want to protect. We have several reasons for choosing to rate limit the workflow ID instead of the shard:

      • Hashing The workflow ID to shard is random. This means that rate limiting a workflow is a good proxy for rate limiting a shard. The likelihood that many requests from different workflows hit the same shard is very low.
      • @@ -189,7 +189,7 @@ It’s important to note that any update to the system.allIsolationGroups<
      • Noisy neighbors Shards are shared across the different domains in a Cadence cluster. If a user is sending too many requests to a shard, we would choose to rate limit requests to that shard. Since other users in other domains are also using the shard, they will also be rate limited. Rate limiting users of a healthy domain because of requests from a completely different domain goes against the isolation the domains are meant to ensure.
      -

      How Does It Work?

      +

      How Does It Work?

      Workflow ID-based rate limits are set for all workflow IDs in a domain. If the external limit for a domain is e.g. set to 100 it means that any single workflow ID in that domain can at most be signaled 100 times a second. The rate limits are implemented in two main areas:

      1. @@ -199,7 +199,7 @@ Rate limiting users of a healthy domain because of requests from a completely di

        Actions Within a Workflow This limit controls the number of tasks processed per second within a workflow, focusing on managing decision tasks and activity tasks. When these limits are reached, Cadence slows down task processing without requiring any intervention from the user, though they might notice an increase in task execution time, eventually causing timeouts.

      -

      How do I Enable It?

      +

      How do I Enable It?

      The limits are controlled using six dynamic config properties, three for the internal limits, and a corresponding three for the external limits, all with a domain filter, so the limits can be controlled for each domain.

      • history.workflowIDCacheInternalEnabled
        @@ -225,7 +225,7 @@ Rate limiting users of a healthy domain because of requests from a completely di
        history.workflowIDCacheExternalEnabled:
        - value: true
        constraints: {}
        history.workflowIDExternalRateLimitEnabled:
        - value: false
        constraints:
        domainName: samples-domain
        - value: true
        constraints: {}
        history.workflowIDExternalRPS:
        - value: 100
        constraints: {}

        Here only the external rate limits are enabled. The internal rate limits have the same structure. We see that ‌the rate limiting is enabled for all domains, with a max RPS of 100. The domain samples-domain is however running in shadow mode, so its requests are not rate limited, but metrics and logs are still emitted.

        The exact RPS to set for a specific domain and cluster, depends on many things, such as the number of shards, the selected persistent layer, the general load on the cluster etc.

        -

        Monitoring and Troubleshooting

        +

        Monitoring and Troubleshooting

        The new feature introduces both new metrics and new logs. The new logs help us find workflows that are being rate limited, while the new metrics let us see if domains are being rate limited, and how close to being rate limited they are.

        There are four new metrics, two for internal limits and two corresponding metrics for external limits, all emitted from history.

          @@ -244,34 +244,34 @@ Rate limiting users of a healthy domain because of requests from a completely di

        These metrics let us monitor and alert on the new rate limits. Additionally, when breaking a rate limit, the history service will emit an info log with the message “Rate limiting workflowID”, these logs are tagged with the workflowID that is being limited, so it is easy to find the offending workflow. An example log would look like this:

        {
        "level":"info",
        "ts":"2024-09-02T08:47:12.843Z",
        "msg":"Rate limiting workflowID",
        "service":"cadence-history",
        "request-type":"external",
        "wf-domain-id":"fc0c7fcb-5796-4c80-b0d7-10bbbc66614e",
        "wf-domain-name":"samples-domain",
        "wf-id":"test",
        "logging-call-at":"cache.go:175"
        }
        -

        Conclusion

        +

        Conclusion

        Implementing these rate limits highly improves the reliability of a Cadence cluster, as users now cannot send too many requests to a single shard. This fine-grained control helps in maintaining optimal performance and enhances the ability to forecast and mitigate potential issues before they impact the service.

        Workflow ID-based rate limits are a significant step forward in our ongoing effort to provide a robust and efficient workflow management service. By preventing hot shards and ensuring equitable resource distribution, we can offer more reliable performance, even under peak loads. We encourage all Cadence users to familiarize themselves with these new limits and adjust their workflow configurations to achieve optimal results.

        ]]> Deep Dives <![CDATA[2024 Cadence Yearly Roadmap Update]]> - https://cadenceworkflow.io/blog/2024/07/11/2024-07-11-yearly-roadmap-update/yearly-roadmap-update - https://cadenceworkflow.io/blog/2024/07/11/2024-07-11-yearly-roadmap-update/yearly-roadmap-update + https://cadenceworkflow.io/Cadence-Docs/blog/2024/07/11/2024-07-11-yearly-roadmap-update/yearly-roadmap-update + https://cadenceworkflow.io/Cadence-Docs/blog/2024/07/11/2024-07-11-yearly-roadmap-update/yearly-roadmap-update Thu, 11 Jul 2024 00:00:00 GMT - Introduction + Introduction

        If you haven’t heard about Cadence, this section is for you. In a short description, Cadence is a code-driven workflow orchestration engine. The definition itself may not tell enough, so it would help splitting it into three parts:

        • What’s a workflow? (everyone has a different definition)
        • Why does it matter to be code-driven?
        • Benefits of Cadence
        -

        What is a Workflow?

        -

        workflow.png

        +

        What is a Workflow?

        +

        workflow.png

        In the simplest definition, it is “a multi-step execution”. Step here represents individual operations that are a little heavier than small in-process function calls. Although they are not limited to those: it could be a separate service call, processing a large dataset, map-reduce, thread sleep, scheduling next run, waiting for an external input, starting a sub workflow etc. It’s anything a user thinks as a single unit of logic in their code. Those steps often have dependencies among themselves. Some steps, including the very first step, might require external triggers (e.g. button click) or schedules. In the more broader meaning, any multi-step function or service is a workflow in principle.

        While the above is a more correct way to define workflows, specialized workflows are more widely known: such as data pipelines, directed acyclic graphs, state machines, cron jobs, (micro)service orchestration, etc. This is why typically everyone has a different workflow meaning in mind. Specialized workflows also have simplified interfaces such as UI, configs or a DSL (domain specific language) to make it easy to express the workflow definition.

        -

        Code-Driven Workflows

        +

        Code-Driven Workflows

        Over time, any workflow interface evolves to support more scenarios. For any non-code (UI, config, DSL) technology, this means more APIs, concepts and tooling. However, eventually, the technology’s capabilities will be limited by its interface itself. Otherwise the interface will get more complicated to operate.

        What happens here is users love the seamless way of creating workflow applications and try to fit more scenarios into it. Natural user tendency is to be able to write any program with such simplicity and confidence.

        Given this natural evolution of workflow requirements, it’s better to have a code-driven workflow orchestration engine that can meet any future needs with its powerful expressiveness. On top of this, it is ideal if the interface is seamless, where engineers learn as little as possible and change almost nothing in their local code to write a distributed and durable workflow code. This would virtually remove any limitation and enable implementing any service as a workflow. This is what Cadence aims for.

        -

        Benefits

        -

        cadence-benefits.png

        +

        Benefits

        +

        cadence-benefits.png

        With Cadence, many overheads that need to be built for any well-supported service come for free. Here are some highlights (see cadenceworkflow.io):

        • Disaster recovery is supported by default through data replication and failovers
        • @@ -286,85 +286,85 @@ Rate limiting users of a healthy domain because of requests from a completely di
        • With Cadence testing capabilities, they can write unit tests or test against production data to prevent backward incompatibility issues.
        -

        Project Support

        -

        Team

        +

        Project Support

        +

        Team

        Today the Cadence team comprises 26 people. We have people working from Uber’s US offices (Seattle, San Francisco and Sunnyvale) as well as Europe offices (Aarhus-DK and Amsterdam-NL).

        -

        Community

        +

        Community

        Cadence is an actively built open source project. We invest in both our internal and open source community (Slack, Github), responding to new features and enhancements.

        -

        Scale

        +

        Scale

        It’s one of the most popular platforms at Uber executing ~100K workflow updates per second. There are about 30 different Cadence clusters, several of which serve hundreds of domains. There are ~1000 domains (use cases) varying from tier 0 (most critical) to tier 5 scenarios.

        -

        Managed Solutions

        +

        Managed Solutions

        While Uber doesn’t officially sell a managed Cadence solution, there are companies (e.g. Instaclustr) in our community that we work closely with selling Managed Cadence. Due to efficiency investments and other factors, it’s significantly cheaper than its competitors. It can be run in users’ on-prem machines or their cloud service of choice. Pricing is defined based on allocated hosts instead of number of requests so users can get more with the same resources by utilizing multi-tenant clusters.

        -

        After V1 Release

        +

        After V1 Release

        Last year, around this time we announced Cadence V1 and shared our roadmap. In this section we will talk about updates since then. At a high level, you will notice that we continue investing in high reliability and efficiency while also developing new features.

        -

        Frequent Releases

        +

        Frequent Releases

        We announced plans to make more frequent releases last year and started making more frequent releases. Today we aim to release biweekly and sometimes release as frequently as weekly. About the format, we listened to our community and heard about having too frequent releases potentially being painful. Therefore, we decided to increment the patch version with releases while incrementing the minor version close to quarterly. This helped us ship much more robust releases and improved our reliability. Here are some highlights:

        -

        Zonal Isolation

        +

        Zonal Isolation

        Cadence clusters have already been regionally isolated until this change. However, in the cloud, inter-zone communications matter as they are more expensive and their latencies are higher. Zones can individually have problems without impacting other cloud zones. In a regional architecture, a single zone problem might impact every request; however, with zonal isolation traffic from a zone with issues can easily be failed over to other zones, eliminating its impact on the whole cluster. Therefore, we implemented zonal isolation keeping domain traffic inside a single zone to help improve efficiency and reliability.

        -

        Narrowing Blast Radius

        +

        Narrowing Blast Radius

        When there are issues in a Cadence cluster, it’s often from a single misbehaving workflow. When this happens the whole domain or the cluster could have had issues until the specific workflow is addressed. With this change, we are able to contain the issue only to the offending workflow without impacting others. This is the narrowest blast radius possible.

        -

        Async APIs

        +

        Async APIs

        At Uber, there are many batch work streams that run a high number of workflows (thousands to millions) at the same time causing bottlenecks for Cadence clusters, causing noisy neighbor issues. This is because StartWorkflow and SignalWorkflow APIs are synchronous, which means when Cadence acks the user requests are successfully saved in their workflow history.

        Even after successful initiations, users would then need to deal with high concurrency. This often means constant worker cache thrashing, followed by history rebuilds at every update, increasing workflow execution complexity to O(n^2) from O(n). Alternatively, they would need to quickly scale out and down their service hosts in a very short amount of time to avoid this.

        When we took a step back and analyzed such scenarios, we realized that users simply wanted to “complete N workflows (jobs) in K time”. The guarantees around starts and signals were not really important for their use cases. Therefore, we implemented async versions of our sync API, by which we can control the consumption rate, guaranteeing the fastest execution with no disruption in the cluster.

        Later this year, we plan to expand this feature to cron workflows and timers as well.

        -

        Pinot as Visibility Store

        +

        Pinot as Visibility Store

        Apache Pinot is becoming popular due to its cost efficient nature. Several teams reported significant savings by changing their observability storage to Pinot. Cadence now has a Pinot plugin for its visibility store. We are still rolling out this change. Latencies and cost savings will be shared later.

        -

        Code Coverage

        +

        Code Coverage

        We have received many requests from our community to actively contribute to our codebase, especially after our V1 release. While we have been already collaborating with some companies, this is a challenge with individuals who are just learning about Cadence. One of the main reasons was to avoid bugs that can be introduced.

        While Cadence has many integration tests, its unit test coverage was lower than desired. With better unit test coverage we can catch changes that break previous logic and prevent them getting into the main branch. Our team covered additional 50K+ lines in various Cadence repos. We hope to bring our code coverage to 85%+ by the end of year so we can welcome such inquiries a lot easier.

        -

        Replayer Improvements

        +

        Replayer Improvements

        This is still an ongoing project. As mentioned in our V1 release, we are revisiting some core parts of Cadence where less-than-ideal architectural decisions were made in the past. Replayer/shadower is one of such parts. We have been working on improving its precision, eliminating false negatives and positives.

        -

        Global Rate Limiters

        +

        Global Rate Limiters

        Cadence rate limiters are equally distributed across zones and hosts. However, when the user's traffic is skewed, rate limits can get activated even though the user has more capacity. To avoid this, we built global rate limiters. This will make rate limits much more predictable and capacity management a lot easier.

        -

        Regular Failover Drills

        +

        Regular Failover Drills

        Cadence has been performing monthly regional and zonal failover drills to ensure its failover operations are working properly in case we need it. We are failing over hundreds of domains at the same time to validate the scale of this operation, capacity elasticity and correctness of workflows.

        -

        Cadence Web v4

        +

        Cadence Web v4

        We are migrating Cadence web from Vue.js to React.js to use a more modern infrastructure and to have better feature velocity. We are about 70% complete with this migration and hope to release the new version of it soon.

        -

        Code Review Time Non-determinism Checks

        +

        Code Review Time Non-determinism Checks

        (This is an internal-only feature that we hope to release soon) Cadence non-determinism errors and versioning were common pain points for our customers. There are available tools but they require ongoing effort to validate. We have built a tool that generates a shadower test with a single line command (one time only operation) and continuously validates any code change against production data.

        This feature reduced the detect-and-fix time from days/weeks to minutes. Just by launching this feature to the domains with the most non-determinism errors, the number of related incidents reduced by 40%. We have already blocked 500+ diffs that would potentially impact production negatively. This boosted our users’ confidence in using Cadence.

        -

        Domain Reports

        +

        Domain Reports

        (This is an internal-only feature that we hope to release soon) We are able to detect potential issues (bugs, antipatterns, inefficiencies, failures) with domains upon manual investigation. We have automated this process and now generate reports for each domain. This information can be accessed historically (to see the progression over time) and on-demand (to see the current state). This has already driven domain reliability and efficiency improvements.

        This feature and above are at MVP level where we plan to generalize, expand and release for open source soon. In the V1 release, we have mentioned that we would build certain features internally first to be able to have enough velocity, to see where they are going and to make breaking changes until it’s mature.

        -

        Client Based Migrations

        +

        Client Based Migrations

        With 30 clusters and ~1000 domains in production, migrating a domain from a cluster to another became a somewhat frequent operation for Cadence. While this feature is mostly automated, we would like to fully automate it to a level that this would be a single click or command operation. Client based migrations (as opposed to server based ones) give us big flexibility that we can have migrations from many to many environments at the same time. Each migration happens in isolation without impacting any other domain or the cluster.

        This is an ongoing project where remaining parts are migrating long running workflows faster and seamless technology to technology migrations even if the “from-technology” is not Cadence in the first place. There are many users that migrated from Cadence-like or different technologies to Cadence so we hope to remove the repeating overhead for such users.

        -

        Roadmap (Next Year)

        +

        Roadmap (Next Year)

        Our priorities for next year look similar with reliability, efficiency, and new features as our focus. We have seen significant improvements especially in our users’ reliability and efficiency on top of the improvements in our servers. This both reduces operational load on our users and makes Cadence one step closer to being a standard way to build services. Here is a short list of what's coming over the next 12 months:

        -

        Database efficiency

        +

        Database efficiency

        We are increasing our investment in improving Cadence’s database usage. Even though Cadence’s cost looks a lot better compared to the same family of technologies, it can still be significantly improved by eliminating certain bottlenecks coming from its original design.

        -

        Helm Charts

        +

        Helm Charts

        We are grateful to the Cadence community for introducing and maintaining our Helm charts for operating Cadence clusters. We are taking its ownership so it can be officially released and tested. We expect to release this in 2024.

        -

        Dashboard Templates

        +

        Dashboard Templates

        During our tech talks, demos and user talks, we have received inquiries about what metrics care about. We plan to release templates for our dashboards so our community would look at a similar picture.

        -

        Client V2 Modernization

        +

        Client V2 Modernization

        As we announced last year that we plan to make breaking changes to significantly improve our interfaces, we are working on modernizing our client interface.

        -

        Higher Parallelization and Prioritization in Task Processing

        +

        Higher Parallelization and Prioritization in Task Processing

        In an effort to have better domain prioritization in multitenant Cadence clusters, we are improving our task processing with higher parallelization and better prioritization. This is a lot better model than just having domains with defined limits. We expect to provide more resources to high priority domains during their peak hours while allowing low priority domains to consume much bigger resources than allocated during quiet times.

        -

        Timer and Cron Burst Handling

        +

        Timer and Cron Burst Handling

        After addressing start and signal burst scenarios, we are continuing with bursty timers and cron jobs. Many users set their schedules and timers for the same second with the intention of being able to finish N jobs within a certain amount of time. Current scheduling design isn’t friendly for such intents and high loads can cause temporary starvation in the cluster. By introducing better batch scheduling support, clusters can continue with no disruption while timers are processed in the most efficient way.

        -

        High zonal skew handling

        +

        High zonal skew handling

        For users operating in their own cloud and having multiple independent zones in every region, zonal skews can be a problem and can create unnecessary bottlenecks when Zonal Isolation feature is enabled. We are working on addressing such issues to improve task matching across zones when skew is detected.

        -

        Tasklist Improvements

        +

        Tasklist Improvements

        When a user scenario grows, there are many knobs that need to be manually adjusted. We would like to automatically partition and smartly forward tasks to improve tasklist efficiency significantly to avoid backlogs, timeouts and hot shards.

        -

        Shard Movement/Assignment Improvements

        +

        Shard Movement/Assignment Improvements

        Cadence shard movements are based on consistent hash and this can be a limiting factor for many different reasons. Certain hosts can end up getting unlucky by having many shards, or having heavy shards. During deployments we might observe a much higher number of shard movements than desired, which reduces the availability. With improved shard movements and assignments we can have more homogenous load among hosts while also having a minimum amount of shard movements during deployments with much better availability.

        -

        Worker Heartbeats

        +

        Worker Heartbeats

        Today, there’s no worker liveliness tracking in Cadence. Instead, task or activity heartbeat timeouts are used to reassign tasks to different workers. For latency sensitive users this can become a big disruption. For long activities without heartbeats, this can cause big delays. This feature is to eliminate depending on manual timeout or heartbeat configs to reassign tasks by tracking if workers are still healthy. This feature will also enable so many other new efficiency and reliability features we would like to get to in the future.

        -

        Domain and Workflow Diagnostics

        +

        Domain and Workflow Diagnostics

        Probably the two most common user questions are “What’s wrong with my domain?” and “What’s wrong with my workflow?”. Today, diagnosing what happened and what could be wrong isn’t that easy apart from some basic cases. We are working on tools that would run diagnostics on workflows and domains to point out things that might potentially be wrong with public runbook links attached. This feature will not only help diagnose what is wrong with our workflows and domains but will also help fix them.

        -

        Self Serve Operations

        +

        Self Serve Operations

        Certain Cadence operations are performed through admin CLI operations. However, these should be able to be done via Cadence UI by users. Admins shouldn’t need to be involved in every step or the checks they validate should be able to be automated. This is what the initiative is about including domain registration, auth/authz onboarding or adding new search attributes but it’s not limited to these operations.

        -

        Cost Estimation

        +

        Cost Estimation

        One big question we receive when users are onboarding to Cadence is “How much will this cost me?”. This is not an easy question to answer since data and traffic load can be quite different. We plan to automate this process to help users understand how much resources they will need. Especially in multi-tenant clusters, this will help users understand how much room they still have in their clusters and how much the new scenario will consume.

        -

        Domain Reports (continue)

        +

        Domain Reports (continue)

        We plan to release this internal feature to open source as soon as possible. On top of presenting this data on built-in Cadence surfaces (web, CLI. etc.) we will create APIs to make it integratable with deployment systems, user service UIs, periodic reports and any other service that would like to consume.

        -

        Non-determinism Detection Improvements (continue)

        +

        Non-determinism Detection Improvements (continue)

        We have seen great reliability improvements and reduction in incidents with this feature on the user side last year. We continue to invest in this feature and make it available in open source as soon as possible.

        -

        Domain Migrations (continue)

        +

        Domain Migrations (continue)

        In the next year, we plan to finish our seamless client based migration to be able to safely migrate domains from one cluster to another, one technology (even if it’s not Cadence) to another and one cloud solution to another. There are only a few features left to achieve this.

        -

        Community

        +

        Community

        Do you want to hear more about Cadence? Do you need help with your set-up or usage? Are you evaluating your options? Do you want to contribute? Feel free to join our community and reach out to us.

        Slack: https://uber-cadence.slack.com/

        Github: https://github.com/cadence-workflow/cadence

        @@ -375,14 +375,14 @@ Rate limiting users of a healthy domain because of requests from a completely di
        <![CDATA[Cadence non-derministic errors common question Q&A (part 1)]]> - https://cadenceworkflow.io/blog/2024/02/15/cadence-non-deterministic-common-qa - https://cadenceworkflow.io/blog/2024/02/15/cadence-non-deterministic-common-qa + https://cadenceworkflow.io/Cadence-Docs/blog/2024/02/15/cadence-non-deterministic-common-qa + https://cadenceworkflow.io/Cadence-Docs/blog/2024/02/15/cadence-non-deterministic-common-qa Sun, 10 Mar 2024 00:00:00 GMT - If I change code logic inside an Cadence activity (for example, my activity is calling database A but now I want it to call database B), will it trigger an non-deterministic error? + If I change code logic inside an Cadence activity (for example, my activity is calling database A but now I want it to call database B), will it trigger an non-deterministic error?

        NO. This change will not trigger non-deterministic error.

        An Activity is the smallest unit of execution for Cadence and what happens inside activities are not recorded as historical events and therefore will not be replayed. In short, this change is deterministic and it is fine to modify logic inside activities.

        -

        Does changing the workflow definition trigger non-determinstic errors?

        +

        Does changing the workflow definition trigger non-determinstic errors?

        YES. This is a very typical non-deterministic error.

        When a new workflow code change is deployed, Cadence will find if it is compatible with Cadence history. Changes to workflow definition will fail the replay process of Cadence @@ -399,7 +399,7 @@ trigger non-deterministic errors.

      • Changes of workflow return values
      • Changing workflow parameter names as they are just positional
      -

      Does changing activity definitions trigger non-determinstic errors?

      +

      Does changing activity definitions trigger non-determinstic errors?

      YES. Similar to workflow definition change, this is also a very typical non-deterministic error.

      Activities are also recorded and replayed by Cadence. Therefore, changes to activity must also be compatible with Cadence history. The following changes are common ones that trigger non-deterministic errors.

        @@ -413,7 +413,7 @@ trigger non-deterministic errors.

      • Changing activity parameter names

      Activity return values inside workflows are not recorded and replayed.

      -

      What changes inside workflows may potentially trigger non-deterministic errors?

      +

      What changes inside workflows may potentially trigger non-deterministic errors?

      Cadence records each execution of a workflow and activity execution inside each of them.Therefore, new changes must be compatible with execution orders inside the workflow. The following changes will fail the non-deterministic check.

      • Append another activity
      • @@ -421,30 +421,30 @@ trigger non-deterministic errors.

      • Reordering activities

      If you really need to change the activity implementation based on new business requirements, you may consider using versioning your workflow.

      -

      Are Cadence signals replayed? If definition of signal is changed, will it trigger non-deterministic errors?

      +

      Are Cadence signals replayed? If definition of signal is changed, will it trigger non-deterministic errors?

      Yes. If a signal is used in a workflow, it becomes a critical component of your workflow. Because signals also involve I/O to your workflow, it is also recorded and replayed. Modifications on signal definitions or usage may yield to non-deterministic errors, for instance, changing return type of a signal.

      -

      If I have new business requirement and really need to change the definition of a workflow, what should I do?

      +

      If I have new business requirement and really need to change the definition of a workflow, what should I do?

      You may introduce a new workflow registered to your worker and divert traffic to it or use versioning for your workflow. Check out Cadence website for more information about versioning.

      -

      Does changes to local activities' definition trigger non-deterministic errors?

      +

      Does changes to local activities' definition trigger non-deterministic errors?

      Yes. Local activities are recorded and therefore replayed by Cadence. Imcompatible changes on local activity definitions will yield to non-deterministic errors.

      ]]> Deep Dives <![CDATA[Cadence Community Spotlight Update - November 2023]]> - https://cadenceworkflow.io/blog/2023/11/30/community-spotlight-update-november-2023 - https://cadenceworkflow.io/blog/2023/11/30/community-spotlight-update-november-2023 + https://cadenceworkflow.io/Cadence-Docs/blog/2023/11/30/community-spotlight-update-november-2023 + https://cadenceworkflow.io/Cadence-Docs/blog/2023/11/30/community-spotlight-update-november-2023 Thu, 30 Nov 2023 00:00:00 GMT Welcome to the latest of our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!

      It's been a couple of months since our last update so we have a lot of updates to share with you.

      Please see below for a roundup of the highlights:

      -

      Proposal for Cadence Native Authentication

      +

      Proposal for Cadence Native Authentication

      Community member Mantas Sidlauskas has drafted a proposal around Cadence native authentication and is asking for community feedback. If you are interested in reviewing the current proposal and providing comments or feedback then please find the proposal details at the link below:

      This is a great example of how we can focus on collaborating together to find a collective solution. A big thank you to Mantas for initiating this work and we hope to see the results of the community input soon!

      -

      iWF Deep Dive and More!

      +

      iWF Deep Dive and More!

      During the last few months community member Quanzheng Long has continued to share his thoughts about iWF, a layer implemented on top of Cadence. Since our last update iWF now has aPython SDK. Long has been busy writing articles to share iWF tips and tricks as well as some general ideas about workflows and processes. Links to Long's articles can be found below:

      -

      New Go Samples for Cadence

      +

      New Go Samples for Cadence

      The Cadence core team is deprecating the old samples for Go and replacing them with new version 2 (V2) samples. They have received a lot of feedback from the community that people are having trouble with old samples, so are in the process of publishing a completely new set of samples for Go.

      Here are some major changes to the new samples:

      Note that the old samples will be removed once the new samples are fully refreshed.

      -

      Cadence Retrospective

      +

      Cadence Retrospective

      We are nearly at the end of another year and yes it has gone so fast! Over this year Cadence and the community have evolved and grown. This is a good time to reflect about all the things that have happened in the project over the year and think about a possible roadmap for the future.

      If you have any feedback, or comments about the project or ideas about what features you'd like to see in the roadmap then please feel free to begin a discussion in the #community Slack channel.

      -

      Cadence in the News!

      +

      Cadence in the News!

      Below are a selection of Cadence related articles, blogs and whitepapers. Please take a look and feel free to share via your own social media channels.

      -

      Upcoming Events

      +

      Upcoming Events

      @@ -503,13 +503,13 @@ Please take a look and feel free to share via your own social media channels.

      <![CDATA[Cadence Community Spotlight Update - August 2023]]> - https://cadenceworkflow.io/blog/2023/08/31/community-spotlight-august-2023 - https://cadenceworkflow.io/blog/2023/08/31/community-spotlight-august-2023 + https://cadenceworkflow.io/Cadence-Docs/blog/2023/08/31/community-spotlight-august-2023 + https://cadenceworkflow.io/Cadence-Docs/blog/2023/08/31/community-spotlight-august-2023 Thu, 31 Aug 2023 00:00:00 GMT Welcome to the latest of our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!

      Please see below for a roundup of the highlights:

      -

      More Cadence How To's

      +

      More Cadence How To's

      You might have noticed that we have had a few more contributions to our blog from Chris Qin. Chris has been busy sharing insights, and tips on a few important Cadence topics. The objective is to help the community with any potential problems.

      Here are the latest topics:

      -

      A huge thank you to Mantas for initiating this work. This is an excellent example of how we can collaborate together to bring about new features that benefit us all.

      Cadence Community Spotlight Update - February 2023

      · 2 min read
      Sharan Foga
      Director of Operations & Customer Success @ Encube Technologies

      Here’s the latest in our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!

      +

      A huge thank you to Mantas for initiating this work. This is an excellent example of how we can collaborate together to bring about new features that benefit us all.

      Cadence Community Spotlight Update - February 2023

      · 2 min read
      Sharan Foga
      Director of Operations & Customer Success @ Encube Technologies

      Here’s the latest in our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!

      Please see below for a roundup of the highlights:

      Community Survey

      We've been talking about doing a community survey for a while and during February we sent it out. We are still collating the results so it's not too late to send in your response.

      The survey takes 5 minutes and is your opportunity to provide feedback to the project and highlight areas you think we need to focus on.

      Use this Survey Link

      -

      Please take a few minutes to give us your opinion.

      Cadence Community Spotlight Update - January 2023

      · 3 min read
      Sharan Foga
      Director of Operations & Customer Success @ Encube Technologies

      Happy New Year everyone! Here’s the latest in our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!

      Please see below for a roundup of the highlights:

      Closing Down Cadence Office Hours

      We have been running Office Hours sessions every month since May last year. The aim was to give the community an opportunity to speak directly with some of the Cadence core developers and experts to answer questions on particular issues you may be having. We have found that the most preferred method for community questions has been the support Slack channel so have decided to stop this monthly call.

      Thanks very much to Ender Demirkayaand the Uber team for making themselves available for these sessions.

      -

      Please remember that if you have question about Cadence or are facing a specific issue then you can post your question in our #support Slack channel. If you also post the details on StackOverflow with the cadence workflow tag then there will be a searchable history for others who encounter the same issue to find a solution.

      Cadence Community Spotlight Update - December 2022

      · 2 min read
      Sharan Foga
      Director of Operations & Customer Success @ Encube Technologies

      I know we are a little early this month as many people will be taking some time out for holidays.

      +

      Please remember that if you have question about Cadence or are facing a specific issue then you can post your question in our #support Slack channel. If you also post the details on StackOverflow with the cadence workflow tag then there will be a searchable history for others who encounter the same issue to find a solution.

      Cadence Community Spotlight Update - December 2022

      · 2 min read
      Sharan Foga
      Director of Operations & Customer Success @ Encube Technologies

      I know we are a little early this month as many people will be taking some time out for holidays.

      Happy Holidays

      We'd like to wish everyone happy holidays and to thank you for being part of the Cadence community. It's been a busy year for Cadence as we have continued to build a strong, active community that works together to solve issues and generally support each other.

      Let's keep going!...This is a great way to build a sustainable community.

      @@ -98,13 +98,13 @@

      Cadence
    3. Cadence Connection Examples Using TLS

    4. -

      Cadence Community Spotlight Update - November 2022

      · 2 min read
      Sharan Foga
      Director of Operations & Customer Success @ Encube Technologies

      Here’s the latest in our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!

      Please see below for a roundup of the highlights:

      Cadence @ Uber

      This month Uber Engineering published a really nice article on one of the ways they are using Cadence. The article is called How Uber Optimizes the Timing of Push Notifications using ML and Linear Programming.

      The Uber team take you through the details of the problem that they are looking to solve, so you can understand the scope limitations and depedencies - so please take a look.

      Cadence @ DeveloperWeek Enterprise

      DevNetwork run a series of conferences and during November Cadence was featured in at DeveloperWeek Enterprise. Ender Demirkaya and Ben Slater presented a talk called Espress Complex Business Logic as Code with Open Source Cadence!.

      -

      It is good to see that we are finding new channels for us to present the benefits of using Cadence. Huge hanks to Ben and Ender for the presentation and to everyone that attended.

      +

      It is good to see that we are finding new channels for us to present the benefits of using Cadence. Huge hanks to Ben and Ender for the presentation and to everyone that attended.

      \ No newline at end of file diff --git a/blog/tags/community-spotlights.html.html b/blog/tags/community-spotlights.html.html index 47a8e517e..77b514c52 100644 --- a/blog/tags/community-spotlights.html.html +++ b/blog/tags/community-spotlights.html.html @@ -2,10 +2,10 @@ - - + + \ No newline at end of file diff --git a/blog/tags/community-spotlights/page/2.html b/blog/tags/community-spotlights/page/2.html index 518af995e..6623c171f 100644 --- a/blog/tags/community-spotlights/page/2.html +++ b/blog/tags/community-spotlights/page/2.html @@ -3,8 +3,8 @@ -20 posts tagged with "Community Spotlight" | Cadence - +20 posts tagged with "Community Spotlight" | Cadence + @@ -15,27 +15,27 @@ - - - + + + -

      20 posts tagged with "Community Spotlight"

      Community Spotlight tag description

      View All Tags

      Cadence Community Spotlight Update - October 2022

      · 2 min read
      Sharan Foga
      Director of Operations & Customer Success @ Encube Technologies

      Here’s the latest in our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!

      +

      20 posts tagged with "Community Spotlight"

      Community Spotlight tag description

      View All Tags

      Cadence Community Spotlight Update - October 2022

      · 2 min read
      Sharan Foga
      Director of Operations & Customer Success @ Encube Technologies

      Here’s the latest in our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!

      Please see below for a roundup of the highlights:

      Cadence Meetup Postponed

      It's always great to get the community together and we had planned to run another Cadence Meetup in early November. Unfortunately we didn't have enough time to get things organised so we've decided to postpone it. So please watch out for an announcement for the new Cadence meetup date.

      Doordash Technnical Showcase Featuring Cadence

      We have had some great feedback from people who attended Technical Showcase that was run this month by Doordash. It featured their financial products but also highlighted some of the key technologies they use...and guess what Cadence is one of them!

      If you missed the session then you will be happy to know that it was recorded and we've inlcuded a link to the the recording on Youtube.

      -

      Thanks to the Doordash team for running the session and helping support Cadence by sharing their knowledge.

      Cadence Community Spotlight Update - September 2022

      · 2 min read
      Sharan Foga
      Director of Operations & Customer Success @ Encube Technologies

      Here’s the latest in our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!

      Please see below for a roundup of the highlights:

      A Cadence talk by Ender Demirkaya and Ben Slater has been accepted for Developer Week Enterprise.

      The talk is scheduled to for 16th November so please make a note in your calendars.

      Sharing Knowledge

      Over the last few months we have had a continual stream of Cadence questions in our Slack #support channel or on StackOverflow. As a result of the increased interest some members from the Cadence core team have decided to spend some time each day responding to your questions.

      -

      Remember that if you have received a response that has solved your problem especially on StackOverflow then please don't forget to accept answer!

      Cadence Community Spotlight Update - August 2022

      · 3 min read
      Sharan Foga
      Director of Operations & Customer Success @ Encube Technologies

      Here’s the latest in our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!

      +

      Remember that if you have received a response that has solved your problem especially on StackOverflow then please don't forget to accept answer!

      Cadence Community Spotlight Update - August 2022

      · 3 min read
      Sharan Foga
      Director of Operations & Customer Success @ Encube Technologies

      Here’s the latest in our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!

      Please see below for a roundup of the highlights:

      Community Survey

      We are working on putting together our first community survey to find out a bit more about our community. We would like to get your feedback about on a few things such as:

      @@ -45,46 +45,46 @@

      Community S
    5. any special use cases not yet covered
    6. and of course whatever other feedback you'd like to give us
    7. -

      So please watch out for the survey which will be coming out to you via the Slack channel soon!

      Cadence Community Spotlight Update - July 2022

      · 2 min read
      Sharan Foga
      Director of Operations & Customer Success @ Encube Technologies

      Here’s our monthly Community Spotlight update that gives you news from in and around the Cadence community!

      Please see below for a roundup of the highlights:

      Flying Drones with Cadence

      Community member Paul Brebner has released another blog in the series of using Cadence to manage a drone delivery service. You can see a simulated view of it in action

      Don’t forget to try out the code yourself and remember if you have used Cadence to do something interesting then please let us know so we can feature it in our next update.

      GitHub Statistics

      During July the main Cadence branch had 28 pull requests (PRs) merged. There were 214 files changed by 11 different authors. You can find more details here

      -

      The Cadence documentation repository was not as busy with only 2 PRs merged in July, 5 commits and 3 authors active. More details can be found here

      Cadence Community Spotlight Update - June 2022

      · 3 min read
      Sharan Foga
      Director of Operations & Customer Success @ Encube Technologies

      It’s time for our monthly Cadence Community Spotlight update with news from in and around the Cadence community!

      Please see below for a roundup of the highlights:

      Knowledge Sharing and Support

      Our Slack #support channel has been busy this month with 13 questions asked this month by 12 different community members. Six community members took time to respond to those questions which clearly shows our community is growing, collaborating and keen to share knowledge.

      Please don’t forget that we encourage everyone to post questions on StackOverflow using the cadence-workflow and uber-cadence tags so that others with similar questions or issues can easily search for and find an answer.

      Improving Technical Office Hours

      Over the last few months we have been holding regular monthly Office Hours meetings but they have not attracted as many participants as we would like. We would like to understand if there is something preventing people from attending (e.g perhaps the timing or dates are not convenient) so we are planning to send out a short community survey.

      -

      If you have any ideas or comments about how we can improve our community office hours sessions then please include this in your feedback or contact us in the #community Slack channel.

      Cadence Community Spotlight Update - May 2022

      · 3 min read
      Sharan Foga
      Director of Operations & Customer Success @ Encube Technologies

      Welcome to our regular Cadence Community Spotlight update!

      +

      If you have any ideas or comments about how we can improve our community office hours sessions then please include this in your feedback or contact us in the #community Slack channel.

      Cadence Community Spotlight Update - May 2022

      · 3 min read
      Sharan Foga
      Director of Operations & Customer Success @ Encube Technologies

      Welcome to our regular Cadence Community Spotlight update!

      This is our monthly blog post series focused on news from in and around the Cadence community.

      Please see below for a short activity roundup of what has happened recently in the community.

      Cadence Polling Cookbook

      Do you want to understand polling work and have an example of how to set it up in Cadence? Well a brand new Cadence Polling cookbook is now available that gives you all the details you need. The cookbook was created by several members of the Instaclustr team and they are keen to share it with the community. The pdf version of the cookbook can found on the Cadence website under the Polling an external API for a specific resource to become available section of the Polling Use cases.

      A Github repository has also been created with the sample cookbook code for you to try out for yourself.

      -

      So please go ahead and try out the cookbook and don’t forget to let us have your feedback.

      Cadence Community Spotlight Update - April 2022

      · 3 min read
      Sharan Foga
      Director of Operations & Customer Success @ Encube Technologies

      Welcome to our Cadence Community Spotlight update!

      This is our monthly blog post series focused on news from in and around the Cadence community.

      Please see below for a short activity roundup of what has happened recently in the community.

      SD Times Names Cadence Open Source Project of the Week

      In April Cadence was named as open source project of the week by the SD Times. Being named gives the project some great publicity and means the project is getting noticed. You can find a link to the article in the Cadence in the News section below.

      Follow Us on LinkedIn and Twitter!

      We have now set up Cadence accounts on LinkedIn and Twitter where you can keep up to date with what is happening in the community. We will be using these social media accounts to share news, articles, stories and links related to Cadence - so please follow us!

      -

      And don’t forget to share your news with us. We are looking forward to receiving your feedback and comments. The more we interact - the more we build our community!

      Cadence Community Spotlight Update - March 2022

      · 4 min read
      Sharan Foga
      Director of Operations & Customer Success @ Encube Technologies

      Welcome to our Cadence Community Spotlight update!

      This is the latest in our series of monthly blog posts focused on the Cadence community and news about what you have been doing with Cadence.

      Please see below for a short activity roundup of what has happened recently in the community.

      Updated Cadence Topology Diagram

      Did you know that we have an updated Cadence Service diagram on the website? Well we do - and you can find it on our Deployment Topology page. We are always looking for information that helps makes it easier for people to understand how Cadence works.

      -

      Special thanks to Ben Slater for updating the diagram and also to Ender, Emrah and Long for helping review it.

      Cadence Community Spotlight Update - February 2022

      · 3 min read
      Sharan Foga
      Director of Operations & Customer Success @ Encube Technologies

      Welcome to the Cadence Community Spotlight update!

      This is the second in our series of monthly updates focused on the Cadence community and news about what you have been doing with Cadence. We hope that you enjoyed last month's update and are keen to find out what has been happening.

      Please see below for a short activity roundup of what has happened recently in the community.

      Announcements

      Just in case you missed it the alpha version of the Cadence notification service has been released. Details can be found at the following link: Cadence Notification Service

      -

      Thanks very much to everyone that worked on this!

      Cadence Community Spotlight Update - January 2022

      · 3 min read
      Sharan Foga
      Director of Operations & Customer Success @ Encube Technologies

      Welcome to our very first Cadence Community Spotlight update!

      This monthly update focuses on news from the wider Cadence community and is all about what you have been doing with Cadence. Do you have an interesting project that uses Cadence? If so then we want to hear from you. Also if you have any news items, blogs, articles, videos or events where Cadence has been mentioned then that is good too. We want to showcase that our community is active and is doing exciting and interesting things.

      -

      Please see below for a short round up of things that have happened recently in the community.

      +

      Please see below for a short round up of things that have happened recently in the community.

      \ No newline at end of file diff --git a/blog/tags/community-spotlights/page/2.html.html b/blog/tags/community-spotlights/page/2.html.html index 99563e4c1..884144ac4 100644 --- a/blog/tags/community-spotlights/page/2.html.html +++ b/blog/tags/community-spotlights/page/2.html.html @@ -2,10 +2,10 @@ - - + + \ No newline at end of file diff --git a/blog/tags/deep-dives.html b/blog/tags/deep-dives.html index 76c0fbb55..4779e9d3c 100644 --- a/blog/tags/deep-dives.html +++ b/blog/tags/deep-dives.html @@ -3,8 +3,8 @@ -10 posts tagged with "Deep Dives" | Cadence - +10 posts tagged with "Deep Dives" | Cadence + @@ -15,14 +15,14 @@ - - - + + + -

      10 posts tagged with "Deep Dives"

      Deep Dives tag description

      View All Tags

      Zonal Isolation for Cadence Workflows

      · 8 min read
      Zijian Chen
      Software Engineer @ Uber

      At Uber, we want to achieve regional resilience such that losing a zone within a region can be tolerated without requiring a cross-region failover. We also want to make sure that losing a zone only affects a subset of workload, at most, rather than everything. However, in Cadence-based systems, the workload in a region is distributed randomly across all workers in the region at a “task-level granularity”, which means a workflow may be worked on by any worker in the region where the domain is active. To achieve this goal, we introduced Zonal Isolation for Cadence Workflows - a feature designed to pin workflows to the zone they are started in, so that zonal isolation can be achieved at a workflow-level.

      +

      10 posts tagged with "Deep Dives"

      Deep Dives tag description

      View All Tags

      Zonal Isolation for Cadence Workflows

      · 8 min read
      Zijian Chen
      Software Engineer @ Uber

      At Uber, we want to achieve regional resilience such that losing a zone within a region can be tolerated without requiring a cross-region failover. We also want to make sure that losing a zone only affects a subset of workload, at most, rather than everything. However, in Cadence-based systems, the workload in a region is distributed randomly across all workers in the region at a “task-level granularity”, which means a workflow may be worked on by any worker in the region where the domain is active. To achieve this goal, we introduced Zonal Isolation for Cadence Workflows - a feature designed to pin workflows to the zone they are started in, so that zonal isolation can be achieved at a workflow-level.

      What is Zonal Isolation for Cadence Workflows?

      At high-level, Zonal Isolation for Cadence Workflows can be thought in 2 levels:

        @@ -30,14 +30,14 @@

      Minimizing blast radius in Cadence: Introducing Workflow ID-based Rate Limits

      · 7 min read
      Jakob Haahr Taankvist
      Software Engineer II @ Uber

      At Uber, we run several big multitenant Cadence clusters with hundreds of domains in each. The clusters being multi-tenant means potential noisy neighbor effects between domains.

      +

      As a result, the focus remains on achieving task-level zonal isolation outside the Cadence server, which offers a more practical and immediate way to improve system resilience. It provides the capability of ensuring that an unhealthy zone (i.e. bad deployment of workers) only affect a subset of workflows (started from a certain zone) rather than every workflow in a Cadence domain.

      Minimizing blast radius in Cadence: Introducing Workflow ID-based Rate Limits

      · 7 min read
      Jakob Haahr Taankvist
      Software Engineer II @ Uber

      At Uber, we run several big multitenant Cadence clusters with hundreds of domains in each. The clusters being multi-tenant means potential noisy neighbor effects between domains.

      An essential aspect of avoiding this is managing how workflows interact with our infrastructure to prevent any single workflow from causing instability for the whole cluster. To this end, we are excited to introduce Workflow ID-based rate limits — a new feature designed to protect our clusters from problematic workflows and ensure stability across the board.

      Why Workflow ID-based Rate Limits?

      We already have rate limits for how many requests can be sent to a domain. However, since Cadence is sharded on the workflow ID, a user-provided input, an overused workflow with a particular id might overwhelm a shard by making too many requests. There are two main ways this happens:

      1. A user starts, or signals the same workflow ID too aggressively,
      2. A workflow starts too many activities over a short period of time (e.g. thousands of activities in seconds).
      3. -

    2024 Cadence Yearly Roadmap Update

    · 17 min read
    Ender Demirkaya
    Senior Manager at Uber, Cadence. Author of the Software Engineering Handbook

    Introduction

    If you haven’t heard about Cadence, this section is for you. In a short description, Cadence is a code-driven workflow orchestration engine. The definition itself may not tell enough, so it would help splitting it into three parts:

    • What’s a workflow? (everyone has a different definition)
    • @@ -45,8 +45,8 @@

      What is a Workflow?

      -

      workflow.png

      -

      In the simplest definition, it is “a multi-step execution”. Step here represents individual operations that are a little heavier than small in-process function calls. Although they are not limited to those: it could be a separate service call, processing a large dataset, map-reduce, thread sleep, scheduling next run, waiting for an external input, starting a sub workflow etc. It’s anything a user thinks as a single unit of logic in their code. Those steps often have dependencies among themselves. Some steps, including the very first step, might require external triggers (e.g. button click) or schedules. In the more broader meaning, any multi-step function or service is a workflow in principle.

    Cadence non-derministic errors common question Q&A (part 1)

    · 3 min read
    Chris Qin
    Applications Developer @ Uber

    If I change code logic inside an Cadence activity (for example, my activity is calling database A but now I want it to call database B), will it trigger an non-deterministic error?

    +

    workflow.png

    +

    In the simplest definition, it is “a multi-step execution”. Step here represents individual operations that are a little heavier than small in-process function calls. Although they are not limited to those: it could be a separate service call, processing a large dataset, map-reduce, thread sleep, scheduling next run, waiting for an external input, starting a sub workflow etc. It’s anything a user thinks as a single unit of logic in their code. Those steps often have dependencies among themselves. Some steps, including the very first step, might require external triggers (e.g. button click) or schedules. In the more broader meaning, any multi-step function or service is a workflow in principle.

    Cadence non-derministic errors common question Q&A (part 1)

    · 3 min read
    Chris Qin
    Applications Developer @ Uber

    If I change code logic inside an Cadence activity (for example, my activity is calling database A but now I want it to call database B), will it trigger an non-deterministic error?

    NO. This change will not trigger non-deterministic error.

    An Activity is the smallest unit of execution for Cadence and what happens inside activities are not recorded as historical events and therefore will not be replayed. In short, this change is deterministic and it is fine to modify logic inside activities.

    Does changing the workflow definition trigger non-determinstic errors?

    @@ -65,36 +65,36 @@

    Non-deterministic errors, replayers and shadowers

    · 3 min read
    Chris Qin
    Applications Developer @ Uber

    It is conceivable that developers constantly update their Cadence workflow code based upon new business use cases and needs. However, the definition of a Cadence workflow must be deterministic because behind the scenes cadence uses event sourcing to construct the workflow state by replaying the historical events stored for this specific workflow. Introducing components that are not compatible with an existing running workflow will yield to non-deterministic errors and sometimes developers find it tricky to debug. Consider the following workflow that executes two activities.

    -
    func SampleWorkflow(ctx workflow.Context, data string) (string, error) {
    ao := workflow.ActivityOptions{
    ScheduleToStartTimeout: time.Minute,
    StartToCloseTimeout: time.Minute,
    }
    ctx = workflow.WithActivityOptions(ctx, ao)
    var result1 string
    err := workflow.ExecuteActivity(ctx, ActivityA, data).Get(ctx, &result1)
    if err != nil {
    return "", err
    }
    var result2 string
    err = workflow.ExecuteActivity(ctx, ActivityB, result1).Get(ctx, &result2)
    return result2, err
    }

    Write your first workflow with Cadence

    · 3 min read
    Chris Qin
    Applications Developer @ Uber

    We have covered basic components of Cadence and how to implement a Cadence worker on local environment in previous blogs. In this blog, let's write your very first HelloWorld workflow with Cadence. I've started the Cadence backend server in background and registered a domain named test-domain. You may use the code snippet for the worker service in this blog Let's first write a activity, which takes a single string argument and print a log in the console.

    -
    func helloWorldActivity(ctx context.Context, name string) (string, error) {
    logger := activity.GetLogger(ctx)
    logger.Info("helloworld activity started")
    return "Hello " + name + "!", nil
    }

    Bad practices and Anti-patterns with Cadence (Part 1)

    · 3 min read
    Chris Qin
    Applications Developer @ Uber

    In the upcoming blog series, we will delve into a discussion about common bad practices and anti-patterns related to Cadence. As diverse teams often encounter distinct business use cases, it becomes imperative to address the most frequently reported issues in Cadence workflows. To provide valuable insights and guidance, the Cadence team has meticulously compiled these common challenges based on customer feedback.

    +
    func SampleWorkflow(ctx workflow.Context, data string) (string, error) {
    ao := workflow.ActivityOptions{
    ScheduleToStartTimeout: time.Minute,
    StartToCloseTimeout: time.Minute,
    }
    ctx = workflow.WithActivityOptions(ctx, ao)
    var result1 string
    err := workflow.ExecuteActivity(ctx, ActivityA, data).Get(ctx, &result1)
    if err != nil {
    return "", err
    }
    var result2 string
    err = workflow.ExecuteActivity(ctx, ActivityB, result1).Get(ctx, &result2)
    return result2, err
    }

    Write your first workflow with Cadence

    · 3 min read
    Chris Qin
    Applications Developer @ Uber

    We have covered basic components of Cadence and how to implement a Cadence worker on local environment in previous blogs. In this blog, let's write your very first HelloWorld workflow with Cadence. I've started the Cadence backend server in background and registered a domain named test-domain. You may use the code snippet for the worker service in this blog Let's first write a activity, which takes a single string argument and print a log in the console.

    +
    func helloWorldActivity(ctx context.Context, name string) (string, error) {
    logger := activity.GetLogger(ctx)
    logger.Info("helloworld activity started")
    return "Hello " + name + "!", nil
    }

    Bad practices and Anti-patterns with Cadence (Part 1)

    · 3 min read
    Chris Qin
    Applications Developer @ Uber

    In the upcoming blog series, we will delve into a discussion about common bad practices and anti-patterns related to Cadence. As diverse teams often encounter distinct business use cases, it becomes imperative to address the most frequently reported issues in Cadence workflows. To provide valuable insights and guidance, the Cadence team has meticulously compiled these common challenges based on customer feedback.

    • Reusing the same workflow ID for very active/continuous running workflows

    Cadence organizes workflows based on their unique IDs, using a process called partitioning. If a workflow receives a large number of updates in a short period of time or frequently starts new runs using the continueAsNew function, all these updates will be directed to the same shard. Unfortunately, the Cadence backend is not equipped to handle this concentrated workload efficiently. As a result, a situation known as a "hot shard" arises, overloading the Cadence backend and worsening the problem.

    Solution: -Well, the best way to avoid this is simply just design your workflow in the way such that each workflow owns a uniformly distributed workflow ID across your Cadence domain. This will make sure that Cadence backend is able to evenly distribute the traffic with proper partition on your workflowIDs.

    Implement a Cadence worker service from scratch

    · 4 min read
    Chris Qin
    Applications Developer @ Uber

    In the previous blog, we have introduced three critical components for a Cadence application: the Cadence backend, domain, and worker. Among these, the worker service is the most crucial focus for developers as it hosts the activities and workflows of a Cadence application. In this blog, I will provide a short tutorial on how to implement a simple worker service from scratch in Go.

    +Well, the best way to avoid this is simply just design your workflow in the way such that each workflow owns a uniformly distributed workflow ID across your Cadence domain. This will make sure that Cadence backend is able to evenly distribute the traffic with proper partition on your workflowIDs.

    Implement a Cadence worker service from scratch

    · 4 min read
    Chris Qin
    Applications Developer @ Uber

    In the previous blog, we have introduced three critical components for a Cadence application: the Cadence backend, domain, and worker. Among these, the worker service is the most crucial focus for developers as it hosts the activities and workflows of a Cadence application. In this blog, I will provide a short tutorial on how to implement a simple worker service from scratch in Go.

    To finish this tutorial, there are two prerequisites you need to finish first

    1. Register a Cadence domain for your worker. For this tutorial, I've already registered a domain named test-domain
    2. Start the Cadence backend server in background.

    To get started, let's simply use the native HTTP package built in Go to start a process listening to port 3000. You may customize the port for your worker, but the port you choose should not conflict with existing port for your Cadence backend.

    -
    package main

    import (
    "fmt"
    "net/http"
    )

    func main(){
    fmt.Println("Cadence worker started at port 3000")
    http.ListenAndServe(":3000", nil)
    }

    Understanding components of Cadence application

    · 2 min read
    Chris Qin
    Applications Developer @ Uber

    Cadence is a powerful, scalable, and fault-tolerant workflow orchestration framework that helps developers implement and manage complex workflow tasks. In most cases, developers contribute activities and workflows directly to their codebases, and they may not have a full understanding of the components behind a running Cadence application. We receive numerous inquiries about setting up Cadence in a local environment from scratch for testing. Therefore, in this article, we will explore the components that power a Cadence cluster.

    +
    package main

    import (
    "fmt"
    "net/http"
    )

    func main(){
    fmt.Println("Cadence worker started at port 3000")
    http.ListenAndServe(":3000", nil)
    }

    Understanding components of Cadence application

    · 2 min read
    Chris Qin
    Applications Developer @ Uber

    Cadence is a powerful, scalable, and fault-tolerant workflow orchestration framework that helps developers implement and manage complex workflow tasks. In most cases, developers contribute activities and workflows directly to their codebases, and they may not have a full understanding of the components behind a running Cadence application. We receive numerous inquiries about setting up Cadence in a local environment from scratch for testing. Therefore, in this article, we will explore the components that power a Cadence cluster.

    There are three critical components that are essential for any Cadence application:

    1. A running Cadence backend server.
    2. A registered Cadence domain.
    3. A running Cadence worker that registers all workflows and activities.
    -

    Let's go over these components in more details.

    Moving to gRPC

    · 5 min read
    Vytautas Karpavicius
    Software Engineer @ Uber

    Background

    Cadence historically has been using TChannel transport with Thrift encoding for both internal RPC calls and communication with client SDKs. gRPC is becoming a de-facto industry standard with much better adoption and community support. It offers features such as authentication and streaming that are very relevant for Cadence. Moreover, TChannel is being deprecated within Uber itself, pushing an effort for this migration. During the last year we’ve implemented multiple changes in server and SDK that allows users to use gRPC in Cadence, as well as to upgrade their existing Cadence cluster in a backward compatible way. This post tracks the completed work items and our future plans.

    Our Approach

    With ~500 services using Cadence at Uber and many more open source customers around the world, we had to think about the gRPC transition in a backwards compatible way. We couldn’t simply flip transport and encoding everywhere. Instead we needed to support both protocols as an intermediate step to ensure a smooth transition for our users.

    -

    Cadence was using Thrift/TChannel not just for the API with client SDKs. They were also used for RPC calls between internal Cadence server components and also between different data centers. When starting this migration we had a choice of either starting with public APIs first or all the internal things within the server. We chose the latter one, so that we could gain experience and iterate faster within the server without disruption to the clients. With server side done and listening for both protocols, dynamic config flag was exposed to switch traffic internally. It allowed gradual deployment and provided an option to rollback if needed.

    +

    Cadence was using Thrift/TChannel not just for the API with client SDKs. They were also used for RPC calls between internal Cadence server components and also between different data centers. When starting this migration we had a choice of either starting with public APIs first or all the internal things within the server. We chose the latter one, so that we could gain experience and iterate faster within the server without disruption to the clients. With server side done and listening for both protocols, dynamic config flag was exposed to switch traffic internally. It allowed gradual deployment and provided an option to rollback if needed.

    \ No newline at end of file diff --git a/blog/tags/deep-dives.html.html b/blog/tags/deep-dives.html.html index 1ea3d9373..553fe1a34 100644 --- a/blog/tags/deep-dives.html.html +++ b/blog/tags/deep-dives.html.html @@ -2,10 +2,10 @@ - - + + \ No newline at end of file diff --git a/blog/tags/introduction-to-cadence.html b/blog/tags/introduction-to-cadence.html index f659098ed..da0c6d4f9 100644 --- a/blog/tags/introduction-to-cadence.html +++ b/blog/tags/introduction-to-cadence.html @@ -3,8 +3,8 @@ -5 posts tagged with "Introduction to Cadence" | Cadence - +5 posts tagged with "Introduction to Cadence" | Cadence + @@ -15,14 +15,14 @@ - - - + + + -

    5 posts tagged with "Introduction to Cadence"

    Introduction to Cadence tag description

    View All Tags

    Cadence Community Spotlight Update - August 2023

    · 3 min read
    Sharan Foga
    Director of Operations & Customer Success @ Encube Technologies

    Welcome to the latest of our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!

    +

    5 posts tagged with "Introduction to Cadence"

    Introduction to Cadence tag description

    View All Tags

    Cadence Community Spotlight Update - August 2023

    · 3 min read
    Sharan Foga
    Director of Operations & Customer Success @ Encube Technologies

    Welcome to the latest of our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!

    Please see below for a roundup of the highlights:

    More Cadence How To's

    You might have noticed that we have had a few more contributions to our blog from Chris Qin. Chris has been busy sharing insights, and tips on a few important Cadence topics. The objective is to help the community with any potential problems.

    @@ -37,27 +37,27 @@

    More Ca

    Even if you have not encountered these use cases - it is good to be prepared and have a solution ready.Please take a look and let us have your feedback.

    Chris is also going to take a look at the Cadence Samples to make sure they are all working and if not - he's going to re-write them so that they do!

    -

    Thanks very much Chris for all the work you are doing to help improve the project!

    Write your first workflow with Cadence

    · 3 min read
    Chris Qin
    Applications Developer @ Uber

    We have covered basic components of Cadence and how to implement a Cadence worker on local environment in previous blogs. In this blog, let's write your very first HelloWorld workflow with Cadence. I've started the Cadence backend server in background and registered a domain named test-domain. You may use the code snippet for the worker service in this blog Let's first write a activity, which takes a single string argument and print a log in the console.

    -
    func helloWorldActivity(ctx context.Context, name string) (string, error) {
    logger := activity.GetLogger(ctx)
    logger.Info("helloworld activity started")
    return "Hello " + name + "!", nil
    }

    Bad practices and Anti-patterns with Cadence (Part 1)

    · 3 min read
    Chris Qin
    Applications Developer @ Uber

    In the upcoming blog series, we will delve into a discussion about common bad practices and anti-patterns related to Cadence. As diverse teams often encounter distinct business use cases, it becomes imperative to address the most frequently reported issues in Cadence workflows. To provide valuable insights and guidance, the Cadence team has meticulously compiled these common challenges based on customer feedback.

    +

    Thanks very much Chris for all the work you are doing to help improve the project!

    Write your first workflow with Cadence

    · 3 min read
    Chris Qin
    Applications Developer @ Uber

    We have covered basic components of Cadence and how to implement a Cadence worker on local environment in previous blogs. In this blog, let's write your very first HelloWorld workflow with Cadence. I've started the Cadence backend server in background and registered a domain named test-domain. You may use the code snippet for the worker service in this blog Let's first write a activity, which takes a single string argument and print a log in the console.

    +
    func helloWorldActivity(ctx context.Context, name string) (string, error) {
    logger := activity.GetLogger(ctx)
    logger.Info("helloworld activity started")
    return "Hello " + name + "!", nil
    }

    Bad practices and Anti-patterns with Cadence (Part 1)

    · 3 min read
    Chris Qin
    Applications Developer @ Uber

    In the upcoming blog series, we will delve into a discussion about common bad practices and anti-patterns related to Cadence. As diverse teams often encounter distinct business use cases, it becomes imperative to address the most frequently reported issues in Cadence workflows. To provide valuable insights and guidance, the Cadence team has meticulously compiled these common challenges based on customer feedback.

    • Reusing the same workflow ID for very active/continuous running workflows

    Cadence organizes workflows based on their unique IDs, using a process called partitioning. If a workflow receives a large number of updates in a short period of time or frequently starts new runs using the continueAsNew function, all these updates will be directed to the same shard. Unfortunately, the Cadence backend is not equipped to handle this concentrated workload efficiently. As a result, a situation known as a "hot shard" arises, overloading the Cadence backend and worsening the problem.

    Solution: -Well, the best way to avoid this is simply just design your workflow in the way such that each workflow owns a uniformly distributed workflow ID across your Cadence domain. This will make sure that Cadence backend is able to evenly distribute the traffic with proper partition on your workflowIDs.

    Implement a Cadence worker service from scratch

    · 4 min read
    Chris Qin
    Applications Developer @ Uber

    In the previous blog, we have introduced three critical components for a Cadence application: the Cadence backend, domain, and worker. Among these, the worker service is the most crucial focus for developers as it hosts the activities and workflows of a Cadence application. In this blog, I will provide a short tutorial on how to implement a simple worker service from scratch in Go.

    +Well, the best way to avoid this is simply just design your workflow in the way such that each workflow owns a uniformly distributed workflow ID across your Cadence domain. This will make sure that Cadence backend is able to evenly distribute the traffic with proper partition on your workflowIDs.

    Implement a Cadence worker service from scratch

    · 4 min read
    Chris Qin
    Applications Developer @ Uber

    In the previous blog, we have introduced three critical components for a Cadence application: the Cadence backend, domain, and worker. Among these, the worker service is the most crucial focus for developers as it hosts the activities and workflows of a Cadence application. In this blog, I will provide a short tutorial on how to implement a simple worker service from scratch in Go.

    To finish this tutorial, there are two prerequisites you need to finish first

    1. Register a Cadence domain for your worker. For this tutorial, I've already registered a domain named test-domain
    2. Start the Cadence backend server in background.

    To get started, let's simply use the native HTTP package built in Go to start a process listening to port 3000. You may customize the port for your worker, but the port you choose should not conflict with existing port for your Cadence backend.

    -
    package main

    import (
    "fmt"
    "net/http"
    )

    func main(){
    fmt.Println("Cadence worker started at port 3000")
    http.ListenAndServe(":3000", nil)
    }

    Understanding components of Cadence application

    · 2 min read
    Chris Qin
    Applications Developer @ Uber

    Cadence is a powerful, scalable, and fault-tolerant workflow orchestration framework that helps developers implement and manage complex workflow tasks. In most cases, developers contribute activities and workflows directly to their codebases, and they may not have a full understanding of the components behind a running Cadence application. We receive numerous inquiries about setting up Cadence in a local environment from scratch for testing. Therefore, in this article, we will explore the components that power a Cadence cluster.

    +
    package main

    import (
    "fmt"
    "net/http"
    )

    func main(){
    fmt.Println("Cadence worker started at port 3000")
    http.ListenAndServe(":3000", nil)
    }

    Understanding components of Cadence application

    · 2 min read
    Chris Qin
    Applications Developer @ Uber

    Cadence is a powerful, scalable, and fault-tolerant workflow orchestration framework that helps developers implement and manage complex workflow tasks. In most cases, developers contribute activities and workflows directly to their codebases, and they may not have a full understanding of the components behind a running Cadence application. We receive numerous inquiries about setting up Cadence in a local environment from scratch for testing. Therefore, in this article, we will explore the components that power a Cadence cluster.

    There are three critical components that are essential for any Cadence application:

    1. A running Cadence backend server.
    2. A registered Cadence domain.
    3. A running Cadence worker that registers all workflows and activities.
    -

    Let's go over these components in more details.

    +

    Let's go over these components in more details.

    \ No newline at end of file diff --git a/blog/tags/introduction-to-cadence.html.html b/blog/tags/introduction-to-cadence.html.html index e940b6b74..08070211a 100644 --- a/blog/tags/introduction-to-cadence.html.html +++ b/blog/tags/introduction-to-cadence.html.html @@ -2,10 +2,10 @@ - - + + \ No newline at end of file diff --git a/blog/tags/releases.html b/blog/tags/releases.html index 6b68f00e1..574ca1485 100644 --- a/blog/tags/releases.html +++ b/blog/tags/releases.html @@ -3,8 +3,8 @@ -2 posts tagged with "Releases" | Cadence - +2 posts tagged with "Releases" | Cadence + @@ -15,14 +15,14 @@ - - - + + + -

    2 posts tagged with "Releases"

    Releases tag description

    View All Tags

    Cadence Community Spotlight Update - July 2023

    · 3 min read
    Sharan Foga
    Director of Operations & Customer Success @ Encube Technologies

    Welcome to the latest of our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!

    +

    2 posts tagged with "Releases"

    Releases tag description

    View All Tags

    Cadence Community Spotlight Update - July 2023

    · 3 min read
    Sharan Foga
    Director of Operations & Customer Success @ Encube Technologies

    Welcome to the latest of our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!

    Please see below for a roundup of the highlights:

    Getting Started with Cadence

    Are you new to Cadence and want to understand the basic concepts and architecture? Well we have some great information for you!

    @@ -30,10 +30,10 @@

    Thanks Chris for sharing your knowledge and helping others to get started.

    Cadence Go Client v1.0 Released

    This month saw the release of v1.0 of the Cadence Go Client. Note that the work done on this release was as a result of community feedback asking for it - so we are listening and responding to community needs.

    -

    Thanks very much to everyone who worked hard to get this release out!

    Cadence Community Spotlight Update - June 2023

    · 3 min read
    Sharan Foga
    Director of Operations & Customer Success @ Encube Technologies

    We've had a short break but now we are back. Welcome to the latest of our regular monthly Community Spotlight updates that gives you news from in and around the Cadence community!

    Please see below for a roundup of the highlights:

    Cadence Release 1.0

    Just in case you missed it - at the end of April Cadence v1.0 was officially released. This release is a significant milestone for the project and the community. It indicates that we are confident in the stability of the code that we can recommend it and promote it widely to more users. Kudos to everyone that worked together to make this release happen.

    -

    And the Uber team also gave Cadence a writeup on the Uber Engineering Blog so please take a look.

    +

    And the Uber team also gave Cadence a writeup on the Uber Engineering Blog so please take a look.

    \ No newline at end of file diff --git a/blog/tags/releases.html.html b/blog/tags/releases.html.html index 641c4888e..b66735ad9 100644 --- a/blog/tags/releases.html.html +++ b/blog/tags/releases.html.html @@ -2,10 +2,10 @@ - - + + \ No newline at end of file diff --git a/blog/tags/roadmap.html b/blog/tags/roadmap.html index 4f6ee1b14..1c2353984 100644 --- a/blog/tags/roadmap.html +++ b/blog/tags/roadmap.html @@ -3,8 +3,8 @@ -3 posts tagged with "Roadmap" | Cadence - +3 posts tagged with "Roadmap" | Cadence + @@ -15,14 +15,14 @@ - - - + + + -

    3 posts tagged with "Roadmap"

    Roadmap tag description

    View All Tags

    2024 Cadence Yearly Roadmap Update

    · 17 min read
    Ender Demirkaya
    Senior Manager at Uber, Cadence. Author of the Software Engineering Handbook

    Introduction

    +

    3 posts tagged with "Roadmap"

    Roadmap tag description

    View All Tags

    2024 Cadence Yearly Roadmap Update

    · 17 min read
    Ender Demirkaya
    Senior Manager at Uber, Cadence. Author of the Software Engineering Handbook

    Introduction

    If you haven’t heard about Cadence, this section is for you. In a short description, Cadence is a code-driven workflow orchestration engine. The definition itself may not tell enough, so it would help splitting it into three parts:

    • What’s a workflow? (everyone has a different definition)
    • @@ -30,15 +30,15 @@
    • Benefits of Cadence

    What is a Workflow?

    -

    workflow.png

    -

    In the simplest definition, it is “a multi-step execution”. Step here represents individual operations that are a little heavier than small in-process function calls. Although they are not limited to those: it could be a separate service call, processing a large dataset, map-reduce, thread sleep, scheduling next run, waiting for an external input, starting a sub workflow etc. It’s anything a user thinks as a single unit of logic in their code. Those steps often have dependencies among themselves. Some steps, including the very first step, might require external triggers (e.g. button click) or schedules. In the more broader meaning, any multi-step function or service is a workflow in principle.

    Cadence Community Spotlight Update - January 2022

    · 3 min read
    Sharan Foga
    Director of Operations & Customer Success @ Encube Technologies

    Welcome to our very first Cadence Community Spotlight update!

    +

    workflow.png

    +

    In the simplest definition, it is “a multi-step execution”. Step here represents individual operations that are a little heavier than small in-process function calls. Although they are not limited to those: it could be a separate service call, processing a large dataset, map-reduce, thread sleep, scheduling next run, waiting for an external input, starting a sub workflow etc. It’s anything a user thinks as a single unit of logic in their code. Those steps often have dependencies among themselves. Some steps, including the very first step, might require external triggers (e.g. button click) or schedules. In the more broader meaning, any multi-step function or service is a workflow in principle.

    Cadence Community Spotlight Update - January 2022

    · 3 min read
    Sharan Foga
    Director of Operations & Customer Success @ Encube Technologies

    Welcome to our very first Cadence Community Spotlight update!

    This monthly update focuses on news from the wider Cadence community and is all about what you have been doing with Cadence. Do you have an interesting project that uses Cadence? If so then we want to hear from you. Also if you have any news items, blogs, articles, videos or events where Cadence has been mentioned then that is good too. We want to showcase that our community is active and is doing exciting and interesting things.

    -

    Please see below for a short round up of things that have happened recently in the community.

    Announcing Cadence OSS office hours and community sync up

    · 2 min read
    Liang Mei
    Engineering Manager @ Uber

    Are you a current Cadence user, do you operate Cadence services, or are you interested in learning about workflow technologies and wonder what problems Cadence could solve for you? We would like to talk to you!

    Our team has spent a significant amount of time working with users and partner teams at Uber to design, scale and operate their workflows. This helps our users understand the technology better, smooth their learning curve and ramp up experience, and at the same time allows us to get fast and direct feedback so we can improve the developer experience and close feature gaps. As our product and community grows, we would like to expand this practice to our users in the OSS community. For the first time ever, members of the Cadence team along with core contributors from the community will host bi-weekly office hours to answer any questions you have about Cadence, or workflow technology in general. We can also dedicate future sessions to specific topics that have a common interest. Please don’t hesitate to let us know your thoughts.

    Please join a session if you would like to talk about any of the following topics:

    1. Understand what Cadence is and why it might be useful for you and your company
    2. Guidance about running Cadence services and workers in production
    3. Workflow design and operation consultation
    4. Product update, future roadmaps as well as collaboration opportunities

    Building and maintaining a healthy and growing community is the key to the success of Cadence, and one of the top priorities for our team. We would like to use the office hours as an opportunity to understand and help our customers, seek feedback, and forge partnerships. We look forward to seeing you in one of the meetings.

    Upcoming Office Hours

    -

    As we have a geo-distributed userbase, we are still trying to figure out a time that works for most of the people. In the meanwhile, we will manually schedule the first few instances of the meeting until we settle on a fixed schedule. Our next office hours will take place on Thursday, October 21 2pm-3pm PT/5pm-6pm EST/9pm-10pm GMT. Please join via this zoom link.

    +

    As we have a geo-distributed userbase, we are still trying to figure out a time that works for most of the people. In the meanwhile, we will manually schedule the first few instances of the meeting until we settle on a fixed schedule. Our next office hours will take place on Thursday, October 21 2pm-3pm PT/5pm-6pm EST/9pm-10pm GMT. Please join via this zoom link.

    \ No newline at end of file diff --git a/blog/tags/roadmap.html.html b/blog/tags/roadmap.html.html index aff3044b8..741f1fae6 100644 --- a/blog/tags/roadmap.html.html +++ b/blog/tags/roadmap.html.html @@ -2,10 +2,10 @@ - - + + \ No newline at end of file diff --git a/blog/tags/testing.html b/blog/tags/testing.html index 64cb79984..81c5903fa 100644 --- a/blog/tags/testing.html +++ b/blog/tags/testing.html @@ -3,8 +3,8 @@ -One post tagged with "Testing" | Cadence - +One post tagged with "Testing" | Cadence + @@ -15,18 +15,18 @@ - - - + + + -

    One post tagged with "Testing"

    Testing tag description

    View All Tags

    Non-deterministic errors, replayers and shadowers

    · 3 min read
    Chris Qin
    Applications Developer @ Uber

    It is conceivable that developers constantly update their Cadence workflow code based upon new business use cases and needs. However, +

    One post tagged with "Testing"

    Testing tag description

    View All Tags

    Non-deterministic errors, replayers and shadowers

    · 3 min read
    Chris Qin
    Applications Developer @ Uber

    It is conceivable that developers constantly update their Cadence workflow code based upon new business use cases and needs. However, the definition of a Cadence workflow must be deterministic because behind the scenes cadence uses event sourcing to construct the workflow state by replaying the historical events stored for this specific workflow. Introducing components that are not compatible with an existing running workflow will yield to non-deterministic errors and sometimes developers find it tricky to debug. Consider the following workflow that executes two activities.

    -
    func SampleWorkflow(ctx workflow.Context, data string) (string, error) {
    ao := workflow.ActivityOptions{
    ScheduleToStartTimeout: time.Minute,
    StartToCloseTimeout: time.Minute,
    }
    ctx = workflow.WithActivityOptions(ctx, ao)
    var result1 string
    err := workflow.ExecuteActivity(ctx, ActivityA, data).Get(ctx, &result1)
    if err != nil {
    return "", err
    }
    var result2 string
    err = workflow.ExecuteActivity(ctx, ActivityB, result1).Get(ctx, &result2)
    return result2, err
    }

    +
    func SampleWorkflow(ctx workflow.Context, data string) (string, error) {
    ao := workflow.ActivityOptions{
    ScheduleToStartTimeout: time.Minute,
    StartToCloseTimeout: time.Minute,
    }
    ctx = workflow.WithActivityOptions(ctx, ao)
    var result1 string
    err := workflow.ExecuteActivity(ctx, ActivityA, data).Get(ctx, &result1)
    if err != nil {
    return "", err
    }
    var result2 string
    err = workflow.ExecuteActivity(ctx, ActivityB, result1).Get(ctx, &result2)
    return result2, err
    }

    \ No newline at end of file diff --git a/blog/tags/testing.html.html b/blog/tags/testing.html.html index 9bf458b69..f78d287b8 100644 --- a/blog/tags/testing.html.html +++ b/blog/tags/testing.html.html @@ -2,10 +2,10 @@ - - + + \ No newline at end of file diff --git a/blog/zonal-isolation-v1/zonal-isolation-v1.html b/blog/zonal-isolation-v1/zonal-isolation-v1.html index a35741d8f..c38dd471c 100644 --- a/blog/zonal-isolation-v1/zonal-isolation-v1.html +++ b/blog/zonal-isolation-v1/zonal-isolation-v1.html @@ -3,8 +3,8 @@ -Zonal Isolation for Cadence Workflows | Cadence - +Zonal Isolation for Cadence Workflows | Cadence + @@ -15,14 +15,14 @@ - - - + + + -

    Zonal Isolation for Cadence Workflows

    · 8 min read
    Zijian Chen
    Software Engineer @ Uber

    At Uber, we want to achieve regional resilience such that losing a zone within a region can be tolerated without requiring a cross-region failover. We also want to make sure that losing a zone only affects a subset of workload, at most, rather than everything. However, in Cadence-based systems, the workload in a region is distributed randomly across all workers in the region at a “task-level granularity”, which means a workflow may be worked on by any worker in the region where the domain is active. To achieve this goal, we introduced Zonal Isolation for Cadence Workflows - a feature designed to pin workflows to the zone they are started in, so that zonal isolation can be achieved at a workflow-level.

    +

    Zonal Isolation for Cadence Workflows

    · 8 min read
    Zijian Chen
    Software Engineer @ Uber

    At Uber, we want to achieve regional resilience such that losing a zone within a region can be tolerated without requiring a cross-region failover. We also want to make sure that losing a zone only affects a subset of workload, at most, rather than everything. However, in Cadence-based systems, the workload in a region is distributed randomly across all workers in the region at a “task-level granularity”, which means a workflow may be worked on by any worker in the region where the domain is active. To achieve this goal, we introduced Zonal Isolation for Cadence Workflows - a feature designed to pin workflows to the zone they are started in, so that zonal isolation can be achieved at a workflow-level.

    What is Zonal Isolation for Cadence Workflows?

    At high-level, Zonal Isolation for Cadence Workflows can be thought in 2 levels:

      @@ -34,7 +34,7 @@

      How Zonal Isolation Works in Cadence?

      Architecture

      Here is what the architecture of a zonally isolated Cadence-based system looks like: -zonal isolation overview +zonal isolation overview

      Fig: Workflows started in one zone are only dispatched to workers from the same zone. Colors to emphasize pinning.

      Implementation

      Determine the zone of a workflow and workers

      @@ -105,6 +105,6 @@

      Status at Ube

      Next Step

      Currently, Zonal Isolation is implemented as hard isolation, where tasks are strictly limited to the same zone as the originating workflow. To address the traffic skewness issue, we are working on iterating this feature to introduce soft isolation. This relaxed version will allow for some task leakage between zones if traffic skewness is detected, ensuring better worker utilization and reducing latency.

      -

      This enhancement is one of our major ongoing projects, and we plan to share more details in a future blog post once it is launched.

    +

    This enhancement is one of our major ongoing projects, and we plan to share more details in a future blog post once it is launched.

    \ No newline at end of file diff --git a/blog/zonal-isolation-v1/zonal-isolation-v1.html.html b/blog/zonal-isolation-v1/zonal-isolation-v1.html.html index 40ce1385b..f2888ff03 100644 --- a/blog/zonal-isolation-v1/zonal-isolation-v1.html.html +++ b/blog/zonal-isolation-v1/zonal-isolation-v1.html.html @@ -2,10 +2,10 @@ - - + + \ No newline at end of file diff --git a/community/contributing.html b/community/contributing.html index 3e90bac8f..6982d0fad 100644 --- a/community/contributing.html +++ b/community/contributing.html @@ -3,8 +3,8 @@ -Contributing | Cadence - +Contributing | Cadence + @@ -15,13 +15,13 @@ - - - + + + - + \ No newline at end of file diff --git a/community/contributing.html.html b/community/contributing.html.html index 773ece9e5..7765fd62b 100644 --- a/community/contributing.html.html +++ b/community/contributing.html.html @@ -2,10 +2,10 @@ - - + + \ No newline at end of file diff --git a/community/resources.html b/community/resources.html index b09e87cef..c430dd316 100644 --- a/community/resources.html +++ b/community/resources.html @@ -3,8 +3,8 @@ -Resources | Cadence - +Resources | Cadence + @@ -15,17 +15,17 @@ - - - + + + -

    Resources

    +

    Resources

    Cadence documentation

      -
    • Official Documentation is available on this site
    • +
    • Official Documentation is available on this site
    info

    Videos

    @@ -42,6 +42,6 @@

    Enterprise
  • Hashicorp
  • Coinbase
  • DoorDash
  • -

    +
    \ No newline at end of file diff --git a/community/resources.html.html b/community/resources.html.html index 3308de34c..1d83d044c 100644 --- a/community/resources.html.html +++ b/community/resources.html.html @@ -2,10 +2,10 @@ - - + + \ No newline at end of file diff --git a/community/support.html b/community/support.html index d2e0a11fd..a99e272e8 100644 --- a/community/support.html +++ b/community/support.html @@ -3,8 +3,8 @@ -Support | Cadence - +Support | Cadence + @@ -15,14 +15,14 @@ - - - + + + -

    Support

    +

    Support

    On this page we've listed some Cadence-related communities that you can be a part of. You can look up other resources in this section for additional learning materials.

    Before participating in Cadence' communities, please read our Code of Conduct. We have adopted the Contributor Covenant and we expect that all community members adhere to the guidelines within.

    @@ -40,6 +40,6 @@

    Feature req

    Bug Reports

    You can report Cadence bugs by opening an issue on the most relevant repository, the primary being cadence-workflow/cadence

    News

    -

    For the latest news about Cadence, follow the official Cadence blog on this website, Cadence Workflow on LinkedIn and @cadenceworkflow on X

    +

    For the latest news about Cadence, follow the official Cadence blog on this website, Cadence Workflow on LinkedIn and @cadenceworkflow on X

    \ No newline at end of file diff --git a/community/support.html.html b/community/support.html.html index ae8781001..7e41f5ee7 100644 --- a/community/support.html.html +++ b/community/support.html.html @@ -2,10 +2,10 @@ - - + + \ No newline at end of file diff --git a/community/team.html b/community/team.html index 755034560..0b33060a7 100644 --- a/community/team.html +++ b/community/team.html @@ -3,8 +3,8 @@ -Team | Cadence - +Team | Cadence + @@ -15,20 +15,20 @@ - - - + + + -

    Team

    +

    Team

    Core Team

    The Cadence team develops and maintains the Cadence open source project as well as foundational services for Uber's Platform. Current members of the Cadence team are listed in alphabetical order below.

    -
    Abhishek Jha's avatar

    Abhishek Jha

    👋🏻 Abhishek Jha is a Software Developer for Cadence Workflows at Uber, specializing in developing robust distributed systems.
    He is passionate about leveraging emerging technologies, particularly Applied AI, to enhance system reliability and scalability.
    Outside of work, Abhishek enjoys hiking, singing/guitar, and playing various sports. He is always eager to discuss the future of technology, investments, and other intriguing topics. 🧑🏻‍💻🥾🎾🎶
    Adhitya Mamallan's avatar

    Adhitya Mamallan

    Andre Oliveira's avatar

    Andre Oliveira

    Assem Hafez's avatar

    Assem Hafez

    Bowen Xiao's avatar

    Bowen Xiao

    chopincode's avatar

    chopincode

    David Porter's avatar

    David Porter

    Ender Demirkaya's avatar

    Ender Demirkaya

    Ender joined the Cadence team as a tech lead and later transitioned into a management role.
    His career started with his own startup, followed with Microsoft, working for another startup and Meta.
    His prior work involves building Bing's/Azure's key value store (ObjectStore), distributed NAS, and search engines.
    He's into outdoors and endurance sports while not working.
    Felipe Imanishi's avatar

    Felipe Imanishi

    Felipe is a Software Engineer contributing to Cadence from San Francisco. He found CS later in his career, and he is glad he did. Felipe is always looking to learn more and Cadence is provides an endless source of topics. Outside of work, Felipe is probably doing something with his two sons.
    Gaziza Yestemirova's avatar

    Gaziza Yestemirova

    Ilya Ozherelyev's avatar

    Ilya Ozherelyev

    Jakob Haahr Taankvist's avatar

    Jakob Haahr Taankvist

    Jakob Haahr Taankvist is a Software Engineer, contributing to the Cadence project from Denmark. With a background in formal games and traffic optimization, he now explores workflow orchestration.
    Outside of work, Jakob is on a mission to evaluate how well Danish ice hockey arenas double as programming spots while cheering on his son's games. 🏒💻
    Jonathan Baker's avatar

    Jonathan Baker

    Josué Alexander Ibarra's avatar

    Josué Alexander Ibarra

    Josue Ibarra is a Developer Advocate for Cadence Workflows at Uber, based in Seattle.
    Passionate about building better systems with Cadence, he balances his love for coding with hobbies like motorcycles, sailing, and cooking. 🚀🍳🏍️
    Ketsia Mbaku's avatar

    Ketsia Mbaku

    Kisel Jan's avatar

    Kisel Jan

    Nate Mortensen's avatar

    Nate Mortensen

    Nate originally got into programming by modding Minecraft and has been contributing to open source software ever since. When he's not working on Cadence he's on a mission to try every pizza in Seattle.
    Neil Xie's avatar

    Neil Xie

    Neil is a Software Engineer contrinuting to Cadence based in Seattle. He is a camping enthusiast who enjoys exploring the outdoors with his two dogs.
    Sankari Gopalakrishnan's avatar

    Sankari Gopalakrishnan

    Sankari is a Software Engineer at Uber, working on Cadence from Denmark. With a career spanning multiple domains, she has mastered the art of connecting the dots. Outside her technical pursuits, she finds joy in therapeutic art, channeling her love for sugar, spices, and colors into creative expression.
    Shaddoll's avatar

    Shaddoll

    Shijie Sheng's avatar

    Shijie Sheng

    Steven L's avatar

    Steven L

    Taylan Isikdemir's avatar

    Taylan Isikdemir

    Taylan majored in CS and his software engineering journey includes working at Microsoft Azure, Google Cloud, and helping build an observability startup from ground up.
    Taylan is tech lead of Cadence team at Uber, based in Seattle.
    When he is not working, you'll probably find him playing basketball or kickboxing.
    Tim Li's avatar

    Tim Li

    tubignat's avatar

    tubignat

    Vinay Kumar Yadav's avatar

    Vinay Kumar Yadav

    Vsevolod Kaloshin's avatar

    Vsevolod Kaloshin

    +
    Abhishek Jha's avatar

    Abhishek Jha

    👋🏻 Abhishek Jha is a Software Developer for Cadence Workflows at Uber, specializing in developing robust distributed systems.
    He is passionate about leveraging emerging technologies, particularly Applied AI, to enhance system reliability and scalability.
    Outside of work, Abhishek enjoys hiking, singing/guitar, and playing various sports. He is always eager to discuss the future of technology, investments, and other intriguing topics. 🧑🏻‍💻🥾🎾🎶
    Adhitya Mamallan's avatar

    Adhitya Mamallan

    Andre Oliveira's avatar

    Andre Oliveira

    Assem Hafez's avatar

    Assem Hafez

    Bowen Xiao's avatar

    Bowen Xiao

    chopincode's avatar

    chopincode

    David Porter's avatar

    David Porter

    Ender Demirkaya's avatar

    Ender Demirkaya

    Ender joined the Cadence team as a tech lead and later transitioned into a management role.
    His career started with his own startup, followed with Microsoft, working for another startup and Meta.
    His prior work involves building Bing's/Azure's key value store (ObjectStore), distributed NAS, and search engines.
    He's into outdoors and endurance sports while not working.
    Felipe Imanishi's avatar

    Felipe Imanishi

    Felipe is a Software Engineer contributing to Cadence from San Francisco. He found CS later in his career, and he is glad he did. Felipe is always looking to learn more and Cadence is provides an endless source of topics. Outside of work, Felipe is probably doing something with his two sons.
    Gaziza Yestemirova's avatar

    Gaziza Yestemirova

    Ilya Ozherelyev's avatar

    Ilya Ozherelyev

    Jakob Haahr Taankvist's avatar

    Jakob Haahr Taankvist

    Jakob Haahr Taankvist is a Software Engineer, contributing to the Cadence project from Denmark. With a background in formal games and traffic optimization, he now explores workflow orchestration.
    Outside of work, Jakob is on a mission to evaluate how well Danish ice hockey arenas double as programming spots while cheering on his son's games. 🏒💻
    Jonathan Baker's avatar

    Jonathan Baker

    Josué Alexander Ibarra's avatar

    Josué Alexander Ibarra

    Josue Ibarra is a Developer Advocate for Cadence Workflows at Uber, based in Seattle.
    Passionate about building better systems with Cadence, he balances his love for coding with hobbies like motorcycles, sailing, and cooking. 🚀🍳🏍️
    Ketsia Mbaku's avatar

    Ketsia Mbaku

    Kisel Jan's avatar

    Kisel Jan

    Nate Mortensen's avatar

    Nate Mortensen

    Nate originally got into programming by modding Minecraft and has been contributing to open source software ever since. When he's not working on Cadence he's on a mission to try every pizza in Seattle.
    Neil Xie's avatar

    Neil Xie

    Neil is a Software Engineer contrinuting to Cadence based in Seattle. He is a camping enthusiast who enjoys exploring the outdoors with his two dogs.
    Sankari Gopalakrishnan's avatar

    Sankari Gopalakrishnan

    Sankari is a Software Engineer at Uber, working on Cadence from Denmark. With a career spanning multiple domains, she has mastered the art of connecting the dots. Outside her technical pursuits, she finds joy in therapeutic art, channeling her love for sugar, spices, and colors into creative expression.
    Shaddoll's avatar

    Shaddoll

    Shijie Sheng's avatar

    Shijie Sheng

    Steven L's avatar

    Steven L

    Taylan Isikdemir's avatar

    Taylan Isikdemir

    Taylan majored in CS and his software engineering journey includes working at Microsoft Azure, Google Cloud, and helping build an observability startup from ground up.
    Taylan is tech lead of Cadence team at Uber, based in Seattle.
    When he is not working, you'll probably find him playing basketball or kickboxing.
    Tim Li's avatar

    Tim Li

    tubignat's avatar

    tubignat

    Vinay Kumar Yadav's avatar

    Vinay Kumar Yadav

    Vsevolod Kaloshin's avatar

    Vsevolod Kaloshin

    \ No newline at end of file diff --git a/community/team.html.html b/community/team.html.html index 6e9a87742..29c379a88 100644 --- a/community/team.html.html +++ b/community/team.html.html @@ -2,10 +2,10 @@ - - + + \ No newline at end of file diff --git a/docs/about.html b/docs/about.html index 1de4263de..82f23bded 100644 --- a/docs/about.html +++ b/docs/about.html @@ -3,8 +3,8 @@ -Contact us | Cadence - +Contact us | Cadence + @@ -15,14 +15,14 @@ - - - + + + -

    Contact us

    +
    +
    \ No newline at end of file diff --git a/docs/about.html.html b/docs/about.html.html index 1b46f6859..0a5944fce 100644 --- a/docs/about.html.html +++ b/docs/about.html.html @@ -2,10 +2,10 @@ - - + + \ No newline at end of file diff --git a/docs/about/license.html b/docs/about/license.html index bb87c8bb1..24b1d97ac 100644 --- a/docs/about/license.html +++ b/docs/about/license.html @@ -3,8 +3,8 @@ -MIT License | Cadence - +MIT License | Cadence + @@ -15,14 +15,14 @@ - - - + + + -

    MIT License

    -
    Copyright (c) 2017 Uber Technologies, Inc.

    Permission is hereby granted, free of charge, to any person obtaining a copy
    of this software and associated documentation files (the "Software"), to deal
    in the Software without restriction, including without limitation the rights
    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    copies of the Software, and to permit persons to whom the Software is
    furnished to do so, subject to the following conditions:

    The above copyright notice and this permission notice shall be included in
    all copies or substantial portions of the Software.

    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    THE SOFTWARE.
    +

    MIT License

    +
    Copyright (c) 2017 Uber Technologies, Inc.

    Permission is hereby granted, free of charge, to any person obtaining a copy
    of this software and associated documentation files (the "Software"), to deal
    in the Software without restriction, including without limitation the rights
    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    copies of the Software, and to permit persons to whom the Software is
    furnished to do so, subject to the following conditions:

    The above copyright notice and this permission notice shall be included in
    all copies or substantial portions of the Software.

    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    THE SOFTWARE.
    \ No newline at end of file diff --git a/docs/about/license.html.html b/docs/about/license.html.html index 999fcbb14..b47ece32f 100644 --- a/docs/about/license.html.html +++ b/docs/about/license.html.html @@ -2,10 +2,10 @@ - - + + \ No newline at end of file diff --git a/docs/cli.html b/docs/cli.html index ab1056aaf..db04c46c4 100644 --- a/docs/cli.html +++ b/docs/cli.html @@ -3,8 +3,8 @@ -Introduction | Cadence - +Introduction | Cadence + @@ -15,14 +15,14 @@ - - - + + + -

    Command Line Interface

    +

    Command Line Interface

    The Cadence CLI is a command-line tool you can use to perform various tasks on a Cadence server. It can perform domain operations such as register, update, and describe as well as workflow operations like start workflow, show workflow history, and signal workflow.

    @@ -117,8 +117,8 @@
    Start a workflow with a memo

    Memos are immutable key/value pairs that can be attached to a workflow run when starting the workflow. These are visible when listing workflows. More information on memos can be found -here.

    -
    cadence wf start -tl helloWorldGroup -wt main.Workflow -et 60 -i '"cadence"' -memo_key ‘“Service” “Env” “Instance”’ -memo ‘“serverName1” “test” 5
    +here.

    +
    cadence wf start -tl helloWorldGroup -wt main.Workflow -et 60 -i '"cadence"' -memo_key ‘“Service” “Env” “Instance”’ -memo ‘“serverName1” “test” 5

    Show workflow history

    cadence workflow show -w 3ea6b242-b23c-4279-bb13-f215661b4717 -r 866ae14c-88cf-4f1e-980f-571e031d71b0
    # a shortcut of this is (without -w -r flag)
    cadence workflow showid 3ea6b242-b23c-4279-bb13-f215661b4717 866ae14c-88cf-4f1e-980f-571e031d71b0

    # if run_id is not provided, it will show the latest run history of that workflow_id
    cadence workflow show -w 3ea6b242-b23c-4279-bb13-f215661b4717
    # a shortcut of this is
    cadence workflow showid 3ea6b242-b23c-4279-bb13-f215661b4717

    Show workflow execution information

    @@ -178,6 +178,6 @@

    cadence wf desc -w <WorkflowID>  --reset_points_only
    +----------------------------------+--------------------------------+--------------------------------------+---------+
    | BINARY CHECKSUM | CREATE TIME | RUNID | EVENTID |
    +----------------------------------+--------------------------------+--------------------------------------+---------+
    | c84c5afa552613a83294793f4e664a7f | 2019-05-24 10:01:00.398455019 | 2dd29ab7-2dd8-4668-83e0-89cae261cfb1 | 4 |
    | aae748fdc557a3f873adbe1dd066713f | 2019-05-24 11:01:00.067691445 | d42d21b8-2adb-4313-b069-3837d44d6ce6 | 4 |
    ...
    ...

    Then use this command to tell Cadence to auto-reset all workflows impacted by the bad deployment. The command will store the bad binary checksum into domain info and trigger a process to reset all your workflows.

    cadence --do <YourDomainName> domain update --add_bad_binary aae748fdc557a3f873adbe1dd066713f  --reason "rollback bad deployment"
    -

    As you add the bad binary checksum to your domain, Cadence will not dispatch any decision_tasks to the bad binary. So make sure that you have rolled back to a good deployment(or roll out new bits with bug fixes). Otherwise your workflow can't make any progress after auto-reset.

    +

    As you add the bad binary checksum to your domain, Cadence will not dispatch any decision_tasks to the bad binary. So make sure that you have rolled back to a good deployment(or roll out new bits with bug fixes). Otherwise your workflow can't make any progress after auto-reset.

    \ No newline at end of file diff --git a/docs/cli.html.html b/docs/cli.html.html index 31f752e40..ebdf50b13 100644 --- a/docs/cli.html.html +++ b/docs/cli.html.html @@ -2,10 +2,10 @@ - - + + \ No newline at end of file diff --git a/docs/concepts.html b/docs/concepts.html index 7e2c11f9b..1f22a2570 100644 --- a/docs/concepts.html +++ b/docs/concepts.html @@ -3,8 +3,8 @@ -Introduction | Cadence - +Introduction | Cadence + @@ -15,17 +15,17 @@ - - - + + + -

    Concepts

    +

    Concepts

    Cadence is a new developer friendly way to develop distributed applications.

    -

    It borrows the core terminology from the workflow-automation space. So its concepts include workflows and activities. Workflows can react to events and return internal state through queries.

    -

    The deployment topology explains how all these concepts are mapped to deployable software components.

    -

    The HTTP API reference describes how to use HTTP API to interact with Cadence server.

    +

    It borrows the core terminology from the workflow-automation space. So its concepts include workflows and activities. Workflows can react to events and return internal state through queries.

    +

    The deployment topology explains how all these concepts are mapped to deployable software components.

    +

    The HTTP API reference describes how to use HTTP API to interact with Cadence server.

    \ No newline at end of file diff --git a/docs/concepts.html.html b/docs/concepts.html.html index 6ff017552..9dd543e4f 100644 --- a/docs/concepts.html.html +++ b/docs/concepts.html.html @@ -2,10 +2,10 @@ - - + + \ No newline at end of file diff --git a/docs/concepts/activities.html b/docs/concepts/activities.html index c316def87..7a34a5648 100644 --- a/docs/concepts/activities.html +++ b/docs/concepts/activities.html @@ -3,8 +3,8 @@ -Activities | Cadence - +Activities | Cadence + @@ -15,14 +15,14 @@ - - - + + + -

    Activities

    +

    Activities

    Fault-oblivious stateful workflow code is the core abstraction of Cadence. But, due to deterministic execution requirements, they are not allowed to call any external API directly. Instead they orchestrate execution of activities. In its simplest form, a Cadence activity is a function or an object method in one of the supported languages. Cadence does not recover activity state in case of failures. Therefore an activity function is allowed to contain any code without restrictions.

    @@ -92,6 +92,6 @@

    Local Activ
  • non business critical so that losing some debuggability is okay(e.g. logging, loading config)
  • when you really need optimization. For example, if there are many timers firing at the same time to invoke activities, it could overload Cadence's server. Using local activities can help save the server capacity.
  • -

    The main benefit of local_activities is that they are much more efficient in utilizing Cadence service resources and have much lower latency overhead comparing to the usual activity invocation.

    +

    The main benefit of local_activities is that they are much more efficient in utilizing Cadence service resources and have much lower latency overhead comparing to the usual activity invocation.

    \ No newline at end of file diff --git a/docs/concepts/activities.html.html b/docs/concepts/activities.html.html index 82ce2ab58..21a34860a 100644 --- a/docs/concepts/activities.html.html +++ b/docs/concepts/activities.html.html @@ -2,10 +2,10 @@ - - + + \ No newline at end of file diff --git a/docs/concepts/archival.html b/docs/concepts/archival.html index fb3d29be6..899a9b116 100644 --- a/docs/concepts/archival.html +++ b/docs/concepts/archival.html @@ -3,8 +3,8 @@ -Archival | Cadence - +Archival | Cadence + @@ -15,14 +15,14 @@ - - - + + + -

    Archival

    +

    Archival

    Archival is a feature that automatically moves workflow histories (history archival) and visibility records (visibility archival) from persistence to a secondary data store after the retention period, thus allowing users to keep workflow history and visibility records as long as necessary without overwhelming Cadence primary data store. There are two reasons you may consider turning on archival for your domain:

    1. Compliance: For legal reasons histories may need to be stored for a long period of time.
    2. @@ -89,6 +89,6 @@

      Planned
    3. Provide guarantee that no history or visibility record is deleted from primary persistence before being archived.
    4. Implement Paused state. In this state no archivals will occur but histories or visibility record also will not be deleted from persistence. Once enabled again from paused state, all skipped archivals will occur.
    5. -

    +
    \ No newline at end of file diff --git a/docs/concepts/archival.html.html b/docs/concepts/archival.html.html index ae2e606cd..a08334494 100644 --- a/docs/concepts/archival.html.html +++ b/docs/concepts/archival.html.html @@ -2,10 +2,10 @@ - - + + \ No newline at end of file diff --git a/docs/concepts/cross-dc-replication.html b/docs/concepts/cross-dc-replication.html index c60279f3e..2bb9257d0 100644 --- a/docs/concepts/cross-dc-replication.html +++ b/docs/concepts/cross-dc-replication.html @@ -3,8 +3,8 @@ -Cross DC replication | Cadence - +Cross DC replication | Cadence + @@ -15,14 +15,14 @@ - - - + + + -

    Cross-DC replication

    +

    Cross-DC replication

    The Cadence Global Domain feature provides clients with the capability to continue their workflow_execution from another cluster in the event of a datacenter failover. Although you can configure a Global Domain to be replicated to any number of clusters, it is only considered active in a single cluster.

    @@ -88,7 +88,7 @@

    Running Loca

    The best way is to use Cadence docker-compose: docker-compose -f docker-compose-multiclusters.yml up

    Running in Production

    -

    Enable global domain feature needs to be enabled in static config.

    +

    Enable global domain feature needs to be enabled in static config.

    Here we use clusterDCA and clusterDCB as an example. We pick clusterDCA as the primary(used to called "master") cluster. The only difference of being a primary cluster is that it is responsible for domain registration. Primary can be changed later but it needs to be the same across all clusters.

    The ClusterMeta config of clusterDCA should be

    @@ -108,6 +108,6 @@

    Runnin

    Then the domain should be failed over to clusterDCB. Now worklfows are read-only in clusterDCA. So your workers polling tasks from clusterDCA will become idle.

    Note 1: that even though clusterDCA is standy/read-only for this domain, it can be active for another domain. So being active/standy is per domain basis not per clusters. In other words, for example if you use XDC in case of DC failure of clusterDCA, you need to failover all domains from clusterDCA to clusterDCB.

    -

    Note 2: even though a domain is standy/read-only in a cluster, say clusterDCA, sending write requests(startWF, signalWF, etc) could still work because there is a forwarding component in the Frontend service. It will try to re-route the requests to an active cluster for the domain.

    +

    Note 2: even though a domain is standy/read-only in a cluster, say clusterDCA, sending write requests(startWF, signalWF, etc) could still work because there is a forwarding component in the Frontend service. It will try to re-route the requests to an active cluster for the domain.

    \ No newline at end of file diff --git a/docs/concepts/cross-dc-replication.html.html b/docs/concepts/cross-dc-replication.html.html index 64a406978..e64281d75 100644 --- a/docs/concepts/cross-dc-replication.html.html +++ b/docs/concepts/cross-dc-replication.html.html @@ -2,10 +2,10 @@ - - + + \ No newline at end of file diff --git a/docs/concepts/events.html b/docs/concepts/events.html index 2a781c26f..eab246672 100644 --- a/docs/concepts/events.html +++ b/docs/concepts/events.html @@ -3,8 +3,8 @@ -Event handling | Cadence - +Event handling | Cadence + @@ -15,14 +15,14 @@ - - - + + + -

    Event handling

    +

    Event handling

    Fault-oblivious stateful workflows can be signalled about an external event. A signal is always point to point destined to a specific workflow instance. Signals are always processed in the order in which they are received.

    There are multiple scenarios for which signals are useful.

    Event Aggregation and Correlation

    @@ -36,6 +36,6 @@

    Some business processes should change their behavior if some external event has happened. For example, while executing an order shipment workflow, any change in item quantity could be delivered in a form of a signal.

    Another example is a service deployment workflow. While rolling out new software version to a Kubernetes cluster some problem was identified. A signal can be used to ask the workflow to pause while the problem is investigated. Then either a continue or a rollback signal can be used to execute the appropriate action.

    Synchronization

    -

    Cadence workflows are strongly consistent so they can be used as a synchronization point for executing actions. For example, there is a requirement that all messages for a single user are processed sequentially but the underlying messaging infrastructure can deliver them in parallel. The Cadence solution would be to have a workflow per user and signal it when an event is received. Then the workflow would buffer all signals in an internal data structure and then call an activity for every signal received. See the following Stack Overflow answer for an example.

    +

    Cadence workflows are strongly consistent so they can be used as a synchronization point for executing actions. For example, there is a requirement that all messages for a single user are processed sequentially but the underlying messaging infrastructure can deliver them in parallel. The Cadence solution would be to have a workflow per user and signal it when an event is received. Then the workflow would buffer all signals in an internal data structure and then call an activity for every signal received. See the following Stack Overflow answer for an example.

    \ No newline at end of file diff --git a/docs/concepts/events.html.html b/docs/concepts/events.html.html index 85862b6aa..78ae7c684 100644 --- a/docs/concepts/events.html.html +++ b/docs/concepts/events.html.html @@ -2,10 +2,10 @@ - - + + \ No newline at end of file diff --git a/docs/concepts/http-api.html b/docs/concepts/http-api.html index 3f91c4025..b1d27910d 100644 --- a/docs/concepts/http-api.html +++ b/docs/concepts/http-api.html @@ -3,8 +3,8 @@ -HTTP API | Cadence - +HTTP API | Cadence + @@ -15,14 +15,14 @@ - - - + + + -

    Using HTTP API

    +

    Using HTTP API

    Introduction

    From version 1.2.0 onwards, Cadence has introduced HTTP API support, which allows you to interact with the Cadence server using the HTTP protocol. To put this into perspective, HTTP/JSON communication is a flexible method for server interaction. @@ -112,6 +112,6 @@

    Workflow APIPOST uber.cadence.api.v1.WorkflowAPIStartWorkflowExecution

    Start a new workflow execution

    Headers
    nameexample
    context-ttl-ms2000
    rpc-callercurl-client
    rpc-servicecadence-frontend
    rpc-encodingjson
    rpc-procedureuber.cadence.api.v1.WorkflowAPIStartWorkflowExecution
    Example payload
    {
    "domain": "sample-domain",
    "workflow_id": "sample-workflow-id",
    "execution_start_to_close_timeout": "61s",
    "task_start_to_close_timeout": "60s",
    "workflow_type": {
    "name": "sample-workflow-type"
    },
    "task_list": {
    "name": "sample-task-list"
    },
    "identity": "client-name-visible-in-history",
    "request_id": "8049B932-6C2F-415A-9BB2-241DCF4CFC9C",
    "input": {
    "data": "IkN1cmwhIg=="
    }
    }
    Example cURL
    curl -X POST http://0.0.0.0:8800 \
    -H 'context-ttl-ms: 2000' \
    -H 'rpc-caller: curl-client' \
    -H 'rpc-service: cadence-frontend' \
    -H 'rpc-encoding: json' \
    -H 'rpc-procedure: uber.cadence.api.v1.WorkflowAPI::StartWorkflowExecution' \
    -d \
    '{
    "domain": "sample-domain",
    "workflow_id": "sample-workflow-id",
    "execution_start_to_close_timeout": "61s",
    "task_start_to_close_timeout": "60s",
    "workflow_type": {
    "name": "sample-workflow-type"
    },
    "task_list": {
    "name": "sample-task-list"
    },
    "identity": "client-name-visible-in-history",
    "request_id": "8049B932-6C2F-415A-9BB2-241DCF4CFC9C",
    "input": {
    "data": "IkN1cmwhIg=="
    }
    }'
    Example successful response

    HTTP code: 200

    {
    "runId": "cc09d5dd-b2fa-46d8-b426-54c96b12d18f"
    }

    POST uber.cadence.api.v1.WorkflowAPITerminateWorkflowExecution

    Terminate a new workflow execution

    Headers
    nameexample
    context-ttl-ms2000
    rpc-callercurl-client
    rpc-servicecadence-frontend
    rpc-encodingjson
    rpc-procedureuber.cadence.api.v1.WorkflowAPITerminateWorkflowExecution
    Example payloads
    {
    "domain": "sample-domain",
    "workflow_execution": {
    "workflow_id": "sample-workflow-id"
    }
    }
    {
    "domain": "sample-domain",
    "workflow_execution": {
    "workflow_id": "sample-workflow-id",
    "run_id": "0f95ad5b-03bc-4c6b-8cf0-1f3ea08eb86a"
    },
    "reason": "dummy",
    "identity": "client-name-visible-in-history",
    "first_execution_run_id": "0f95ad5b-03bc-4c6b-8cf0-1f3ea08eb86a"
    }
    Example cURL
    curl -X POST http://0.0.0.0:8800 \
    -H 'context-ttl-ms: 2000' \
    -H 'rpc-caller: curl-client' \
    -H 'rpc-service: cadence-frontend' \
    -H 'rpc-encoding: json' \
    -H 'rpc-procedure: uber.cadence.api.v1.WorkflowAPI::TerminateWorkflowExecution' \
    -d \
    '{
    "domain": "sample-domain",
    "workflow_execution": {
    "workflow_id": "sample-workflow-id"
    }
    }'
    Example successful response

    HTTP code: 200

    {}
    -

    +
    \ No newline at end of file diff --git a/docs/concepts/http-api.html.html b/docs/concepts/http-api.html.html index f5d10e35a..f78c720b5 100644 --- a/docs/concepts/http-api.html.html +++ b/docs/concepts/http-api.html.html @@ -2,10 +2,10 @@ - - + + \ No newline at end of file diff --git a/docs/concepts/queries.html b/docs/concepts/queries.html index 314f3f8de..89c006bbc 100644 --- a/docs/concepts/queries.html +++ b/docs/concepts/queries.html @@ -3,8 +3,8 @@ -Synchronous query | Cadence - +Synchronous query | Cadence + @@ -15,14 +15,14 @@ - - - + + + -

    Synchronous query

    +

    Synchronous query

    Workflow code is stateful with the Cadence framework preserving it over various software and hardware failures. The state is constantly mutated during workflow_execution. To expose this internal state to the external world Cadence provides a synchronous query feature. From the workflow implementer point of view the query is exposed as a synchronous callback that is invoked by external entities. Multiple such callbacks can be provided per workflow type exposing different information to different external systems.

    To execute a query an external client calls a synchronous Cadence API providing domain, workflowID, query name and optional query arguments.

    Query callbacks must be read-only not mutating the workflow state in any way. The other limitation is that the query callback cannot contain any blocking code. Both above limitations rule out ability to invoke activities from the query handlers.

    @@ -30,6 +30,6 @@

    Stack Trace Query

    The Cadence client libraries expose some predefined queries out of the box. Currently the only supported built-in query is stack_trace. This query returns stacks of all workflow owned threads. This is a great way to troubleshoot any workflow in production.

    Example

    -
    $ cadence --do samples-domain wf query -w <workflowID> -qt __stack_trace

    "coroutine 1 [blocked on selector-1.Select]:\nmain.sampleSignalCounterWorkflow(0x1a99ae8, 0xc00009d700, 0x0, 0x0, 0x0)\n\t/Users/qlong/indeed/cadence-samples/cmd/samples/recipes/signalcounter/signal_counter_workflow.go:38 +0x1be\nreflect.Value.call(0x1852ac0, 0x19cb608, 0x13, 0x1979180, 0x4, 0xc00045aa80, 0x2, 0x2, 0x2, 0x18, ...)\n\t/usr/local/Cellar/go/1.16.3/libexec/src/reflect/value.go:476 +0x8e7\nreflect.Value.Call(0x1852ac0, 0x19cb608, 0x13, 0xc00045aa80, 0x2, 0x2, 0x1, 0x2, 0xc00045a720)\n\t/usr/local/Cellar/go/1.16.3/libexec/src/reflect/value.go:337 +0xb9\ngo.uber.org/cadence/internal.(*workflowEnvironmentInterceptor).ExecuteWorkflow(0xc00045a720, 0x1a99ae8, 0xc00009d700, 0xc0001ca820, 0x20, 0xc00007fad0, 0x1, 0x1, 0x1, 0x1, ...)\n\t/Users/qlong/go/pkg/mod/go.uber.org/cadence@v0.17.1-0.20210708064625-c4a7e032cc13/internal/workflow.go:372 +0x2cb\ngo.uber.org/cadence/internal.(*workflowExecutor).Execute(0xc000098d80, 0x1a99ae8, 0xc00009d700, 0xc0001b127e, 0x2, 0x2, 0xc00044cb01, 0xc000070101, 0xc000073738, 0x1729f25, ...)\n\t/Users/qlong/go/pkg/mod/go.uber.org/cadence@v0.17.1-0.20210708064625-c4a7e032cc13/internal/internal_worker.go:699 +0x28d\ngo.uber.org/cadence/internal.(*syncWorkflowDefinition).Execute.func1(0x1a99ce0, 0xc00045a9f0)\n\t/Users/qlong/go/pkg/mod/go.uber.org/cadence@v0.17.1-0.20210708064625-c4a7e032cc13/internal/internal_workflow.go:466 +0x106"
    +
    $ cadence --do samples-domain wf query -w <workflowID> -qt __stack_trace

    "coroutine 1 [blocked on selector-1.Select]:\nmain.sampleSignalCounterWorkflow(0x1a99ae8, 0xc00009d700, 0x0, 0x0, 0x0)\n\t/Users/qlong/indeed/cadence-samples/cmd/samples/recipes/signalcounter/signal_counter_workflow.go:38 +0x1be\nreflect.Value.call(0x1852ac0, 0x19cb608, 0x13, 0x1979180, 0x4, 0xc00045aa80, 0x2, 0x2, 0x2, 0x18, ...)\n\t/usr/local/Cellar/go/1.16.3/libexec/src/reflect/value.go:476 +0x8e7\nreflect.Value.Call(0x1852ac0, 0x19cb608, 0x13, 0xc00045aa80, 0x2, 0x2, 0x1, 0x2, 0xc00045a720)\n\t/usr/local/Cellar/go/1.16.3/libexec/src/reflect/value.go:337 +0xb9\ngo.uber.org/cadence/internal.(*workflowEnvironmentInterceptor).ExecuteWorkflow(0xc00045a720, 0x1a99ae8, 0xc00009d700, 0xc0001ca820, 0x20, 0xc00007fad0, 0x1, 0x1, 0x1, 0x1, ...)\n\t/Users/qlong/go/pkg/mod/go.uber.org/cadence@v0.17.1-0.20210708064625-c4a7e032cc13/internal/workflow.go:372 +0x2cb\ngo.uber.org/cadence/internal.(*workflowExecutor).Execute(0xc000098d80, 0x1a99ae8, 0xc00009d700, 0xc0001b127e, 0x2, 0x2, 0xc00044cb01, 0xc000070101, 0xc000073738, 0x1729f25, ...)\n\t/Users/qlong/go/pkg/mod/go.uber.org/cadence@v0.17.1-0.20210708064625-c4a7e032cc13/internal/internal_worker.go:699 +0x28d\ngo.uber.org/cadence/internal.(*syncWorkflowDefinition).Execute.func1(0x1a99ce0, 0xc00045a9f0)\n\t/Users/qlong/go/pkg/mod/go.uber.org/cadence@v0.17.1-0.20210708064625-c4a7e032cc13/internal/internal_workflow.go:466 +0x106"
    \ No newline at end of file diff --git a/docs/concepts/queries.html.html b/docs/concepts/queries.html.html index 498ccab7a..aa4e0dde4 100644 --- a/docs/concepts/queries.html.html +++ b/docs/concepts/queries.html.html @@ -2,10 +2,10 @@ - - + + \ No newline at end of file diff --git a/docs/concepts/search-workflows.html b/docs/concepts/search-workflows.html index b3e6f1750..ce597d518 100644 --- a/docs/concepts/search-workflows.html +++ b/docs/concepts/search-workflows.html @@ -3,8 +3,8 @@ -Search workflows(Advanced visibility) | Cadence - +Search workflows(Advanced visibility) | Cadence + @@ -15,17 +15,17 @@ - - - + + + -

    Searching Workflows(Advanced visibility)

    +

    Searching Workflows(Advanced visibility)

    Introduction

    Cadence supports creating workflows with customized key-value pairs, updating the information within the workflow code, and then listing/searching workflows with a SQL-like query. For example, you can create workflows with keys city and age, then search all workflows with city = seattle and age > 22.

    -

    Also note that normal workflow properties like start time and workflow type can be queried as well. For example, the following query could be specified when listing workflows from the CLI or using the list APIs (Go, Java):

    +

    Also note that normal workflow properties like start time and workflow type can be queried as well. For example, the following query could be specified when listing workflows from the CLI or using the list APIs (Go, Java):

    WorkflowType = "main.Workflow" AND CloseStatus != "completed" AND (StartTime >
    "2019-06-07T16:46:34-08:00" OR CloseTime > "2019-06-07T16:46:34-08:00")
    ORDER BY StartTime DESC

    In other places, this is also called as advanced visibility. While basic visibility is referred to basic listing without being able to search.

    Memo vs Search Attributes

    @@ -103,9 +103,9 @@ -

    When performing a ContinueAsNew or using Cron, search attributes (and memo) will be carried over to the new run by default.

    +

    When performing a ContinueAsNew or using Cron, search attributes (and memo) will be carried over to the new run by default.

    Query Capabilities

    -

    Query workflows by using a SQL-like where clause when listing workflows from the CLI or using the list APIs (Go, Java).

    +

    Query workflows by using a SQL-like where clause when listing workflows from the CLI or using the list APIs (Go, Java).

    Note that you will only see workflows from one domain when querying.

    Supported Operators

      @@ -197,7 +197,7 @@

      Runnin

  • Configure Cadence for ElasticSearch + Kafka like this documentation -Based on the full static config, you may add some other fields like AuthN. +Based on the full static config, you may add some other fields like AuthN. Similarly for Kafka.
  • To add new search attributes:

    @@ -205,6 +205,6 @@

    Runnin
  • Add the key to ElasticSearch cadence --do domain adm cl asa --search_attr_key NewKey --search_attr_type 1
  • Update the dynamic configuration to allowlist the new attribute
  • -

    Note: starting a workflow with search attributes but without advanced visibility feature will succeed as normal, but will not be searchable and will not be shown in list results.

    +

    Note: starting a workflow with search attributes but without advanced visibility feature will succeed as normal, but will not be searchable and will not be shown in list results.

    \ No newline at end of file diff --git a/docs/concepts/search-workflows.html.html b/docs/concepts/search-workflows.html.html index 838619b10..8c7611b41 100644 --- a/docs/concepts/search-workflows.html.html +++ b/docs/concepts/search-workflows.html.html @@ -2,10 +2,10 @@ - - + + \ No newline at end of file diff --git a/docs/concepts/task-lists.html b/docs/concepts/task-lists.html index 80308e3bb..a3ee07863 100644 --- a/docs/concepts/task-lists.html +++ b/docs/concepts/task-lists.html @@ -3,8 +3,8 @@ -Task lists | Cadence - +Task lists | Cadence + @@ -15,14 +15,14 @@ - - - + + + -

    Task lists

    +

    Task lists

    When a workflow invokes an activity, it sends the ScheduleActivityTask decision to the Cadence service. As a result, the service updates the workflow state and dispatches an activity_task to a worker that implements the activity. @@ -44,6 +44,6 @@

  • Automatic load balancing across a large number of workers.
  • Task_lists support server side throttling. This allows you to limit the task dispatch rate to the pool of workers and still supports adding a task with a higher rate when spikes happen.
  • Task_lists can be used to route a request to specific pools of workers or even a specific process.
  • -
    +
    \ No newline at end of file diff --git a/docs/concepts/task-lists.html.html b/docs/concepts/task-lists.html.html index b03f83b9e..b9e539e4b 100644 --- a/docs/concepts/task-lists.html.html +++ b/docs/concepts/task-lists.html.html @@ -2,10 +2,10 @@ - - + + \ No newline at end of file diff --git a/docs/concepts/topology.html b/docs/concepts/topology.html index dee25f966..b97e3d36f 100644 --- a/docs/concepts/topology.html +++ b/docs/concepts/topology.html @@ -3,8 +3,8 @@ -Deployment topology | Cadence - +Deployment topology | Cadence + @@ -15,14 +15,14 @@ - - - + + + -

    Deployment topology

    +

    Deployment topology

    Overview

    Cadence is a highly scalable fault-oblivious stateful code platform. The fault-oblivious code is a next level of abstraction over commonly used techniques to achieve fault tolerance and durability.

    A common Cadence-based application consists of a Cadence service, workflow and activity_workers, and external clients. @@ -58,6 +58,6 @@

    External Cl
  • synchronously wait for a workflow completion
  • cancel, terminate, restart, and reset workflows
  • search for specific workflows using list API
  • -

    +
    \ No newline at end of file diff --git a/docs/concepts/topology.html.html b/docs/concepts/topology.html.html index f7dd4438b..68c2f3e0b 100644 --- a/docs/concepts/topology.html.html +++ b/docs/concepts/topology.html.html @@ -2,10 +2,10 @@ - - + + \ No newline at end of file diff --git a/docs/concepts/workflows.html b/docs/concepts/workflows.html index 57dab6e9e..92869f9fd 100644 --- a/docs/concepts/workflows.html +++ b/docs/concepts/workflows.html @@ -3,8 +3,8 @@ -Workflows | Cadence - +Workflows | Cadence + @@ -15,14 +15,14 @@ - - - + + + -

    Fault-oblivious stateful workflow code

    +

    Fault-oblivious stateful workflow code

    Overview

    Cadence core abstraction is a fault-oblivious stateful workflow. The state of the workflow code, including local variables and threads it creates, is immune to process and Cadence service failures. This is a very powerful concept as it encapsulates state, processing threads, durable timers and event handlers.

    @@ -78,6 +78,6 @@

    Workflow Re
  • NonRetryableErrorReasons allows to specify errors that shouldn't be retried. For example, retrying invalid arguments error doesn't make sense in some scenarios.
  • How does workflow run

    -

    You may wonder how it works. Behind the scenes, workflow decision is driving the whole workflow running. It's the internal entities for client and server to run your workflows. If this is interesting to you, read this stack Overflow QA.

    +

    You may wonder how it works. Behind the scenes, workflow decision is driving the whole workflow running. It's the internal entities for client and server to run your workflows. If this is interesting to you, read this stack Overflow QA.

    \ No newline at end of file diff --git a/docs/concepts/workflows.html.html b/docs/concepts/workflows.html.html index bb4bbe016..23ff97dc6 100644 --- a/docs/concepts/workflows.html.html +++ b/docs/concepts/workflows.html.html @@ -2,10 +2,10 @@ - - + + \ No newline at end of file diff --git a/docs/get-started.html b/docs/get-started.html index 9e1c845af..12d2c613a 100644 --- a/docs/get-started.html +++ b/docs/get-started.html @@ -3,8 +3,8 @@ -Overview | Cadence - +Overview | Cadence + @@ -15,20 +15,20 @@ - - - + + + -

    Overview

    +

    Overview

    A large number of use cases span beyond a single request-reply, require tracking of a complex state, respond to asynchronous events, and communicate to external unreliable dependencies. The usual approach to building such applications is a hodgepodge of stateless services, databases, cron jobs, and queuing systems. This negatively impacts the developer productivity as most of the code is dedicated to plumbing, obscuring the actual business logic behind a myriad of low-level details. Such systems frequently have availability problems as it is hard to keep all the components healthy.

    -

    The Cadence solution is a fault-oblivious stateful programming model that obscures most of the complexities of building scalable distributed applications. In essence, Cadence provides a durable virtual memory that is not +

    The Cadence solution is a fault-oblivious stateful programming model that obscures most of the complexities of building scalable distributed applications. In essence, Cadence provides a durable virtual memory that is not linked to a specific process, and preserves the full application state, including function stacks, with local variables across all sorts of host and software failures. This allows you to write code using the full power of a programming language while Cadence takes care of durability, availability, and scalability of the application.

    Cadence consists of a programming framework (or client library) and a managed service (or backend). @@ -40,12 +40,12 @@

    The Cadence backend service is stateless and relies on a persistent store. Currently, Cassandra and MySQL/Postgres storages are supported. An adapter to any other database that provides multi-row single shard transactions can be added. There are different service deployment models. At Uber, our team operates multitenant clusters -that are shared by hundreds of applications. See service topology to understand the overall architecture. The GitHub repo for the Cadence server is cadence-workflow/cadence. The docker +that are shared by hundreds of applications. See service topology to understand the overall architecture. The GitHub repo for the Cadence server is cadence-workflow/cadence. The docker image for the Cadence server is available on Docker Hub at ubercadence/server.

    What's Next

    Let's try with some sample workflows. -To start with, go to server installation to install cadence locally, and run a HelloWorld sample with Java or Golang.

    -

    When you have any trouble with the instructions, you can watch the video tutorials, and reach out to us on Slack Channel, or raise any question on StackOverflow or open an Github issue.

    +To start with, go to server installation to install cadence locally, and run a HelloWorld sample with Java or Golang.

    +

    When you have any trouble with the instructions, you can watch the video tutorials, and reach out to us on Slack Channel, or raise any question on StackOverflow or open an Github issue.

    \ No newline at end of file diff --git a/docs/get-started.html.html b/docs/get-started.html.html index be5233406..6d824bd8b 100644 --- a/docs/get-started.html.html +++ b/docs/get-started.html.html @@ -2,10 +2,10 @@ - - + + \ No newline at end of file diff --git a/docs/get-started/golang-hello-world.html b/docs/get-started/golang-hello-world.html index 429d9bb32..5e3d8f523 100644 --- a/docs/get-started/golang-hello-world.html +++ b/docs/get-started/golang-hello-world.html @@ -3,8 +3,8 @@ -Golang hello world | Cadence - +Golang hello world | Cadence + @@ -15,14 +15,14 @@ - - - + + + -

    Golang Hello World

    +

    Golang Hello World

    This section provides step-by-step instructions on how to write and run a HelloWorld workflow in Cadence with Golang. You will learn two critical building blocks of Cadence: activities and workflows. First, you will write an activity function that prints a "Hello World!" message in the log. Then, you will write a workflow function that executes this activity.

    Prerequisite

    To successfully run this hello world sample, follow this checklist of setting up Cadence environment

    @@ -31,7 +31,7 @@

    PrerequisiteYour Cadence server is running (check your background docker container process)
  • You have successfully registered a domain for this workflow
  • -

    You must finish part 2 and 3 by following the first section to proceed the next steps. +

    You must finish part 2 and 3 by following the first section to proceed the next steps. We are using domain called test-domain for this tutorial project.

    Step 1. Implement A Cadence Worker Service

    Create a new main.go file in your local directory and paste the basic worker service layout.

    @@ -56,12 +56,12 @@

    http://localhost:8088

    You may see a dashboard below -cadence-ui

    +cadence-ui

    Type the domain you used for the tutorial, in this case, we type test-domain and hit enter. Then you can see a complete history of the workflows you have triggered associated to this domain. -cadence-ui-detailed

    +cadence-ui-detailed

    What is Next

    -

    Now you have completed the tutorials. You can continue to explore the key concepts in Cadence, and also how to use them with Go Client

    +

    Now you have completed the tutorials. You can continue to explore the key concepts in Cadence, and also how to use them with Go Client

    For complete, ready to build samples covering all the key Cadence concepts go to Cadence-Samples for more examples.

    -

    You can also review Cadence-Client and go-docs for more documentation.

    +

    You can also review Cadence-Client and go-docs for more documentation.

    \ No newline at end of file diff --git a/docs/get-started/golang-hello-world.html.html b/docs/get-started/golang-hello-world.html.html index d6591974c..4bab37729 100644 --- a/docs/get-started/golang-hello-world.html.html +++ b/docs/get-started/golang-hello-world.html.html @@ -2,10 +2,10 @@ - - + + \ No newline at end of file diff --git a/docs/get-started/java-hello-world.html b/docs/get-started/java-hello-world.html index ebcf7feff..f12524e0f 100644 --- a/docs/get-started/java-hello-world.html +++ b/docs/get-started/java-hello-world.html @@ -3,8 +3,8 @@ -Java hello world | Cadence - +Java hello world | Cadence + @@ -15,17 +15,17 @@ - - - + + + -

    Java Hello World

    +

    Java Hello World

    This section provides step by step instructions on how to write and run a HelloWorld with Java.

    For complete, ready to build samples covering all the key Cadence concepts go to Cadence-Java-Samples.

    -

    You can also review Java-Client and java-docs for more documentation.

    +

    You can also review Java-Client and java-docs for more documentation.

    Include Cadence Java Client Dependency

    Go to the Maven Repository Uber Cadence Java Client Page and find the latest version of the library. Include it as a dependency into your Java project. For example if you @@ -65,6 +65,6 @@

    $ docker run --network=host --rm ubercadence/cli:master --do test-domain workflow showid 1965109f-607f-4b14-a5f2-24399a7b8fa7
    1 WorkflowExecutionStarted {WorkflowType:{Name:HelloWorld::sayHello},
    TaskList:{Name:HelloWorldTaskList},
    Input:["World"],
    ExecutionStartToCloseTimeoutSeconds:3600,
    TaskStartToCloseTimeoutSeconds:10,
    ContinuedFailureDetails:[],
    LastCompletionResult:[],
    Identity:cadence-cli@linuxkit-025000000001,
    Attempt:0,
    FirstDecisionTaskBackoffSeconds:0}
    2 DecisionTaskScheduled {TaskList:{Name:HelloWorldTaskList},
    StartToCloseTimeoutSeconds:10,
    Attempt:0}
    3 DecisionTaskStarted {ScheduledEventId:2,
    Identity:45937@maxim-C02XD0AAJGH6,
    RequestId:481a14e5-67a4-436e-9a23-7f7fb7f87ef3}
    4 DecisionTaskCompleted {ExecutionContext:[],
    ScheduledEventId:2,
    StartedEventId:3,
    Identity:45937@maxim-C02XD0AAJGH6}
    5 WorkflowExecutionCompleted {Result:[],
    DecisionTaskCompletedEventId:4}

    Even for such a trivial workflow, the history gives a lot of useful information. For complex workflows this is a really useful tool for production and development troubleshooting. History can be automatically archived to a long-term blob store (for example Amazon S3) upon workflow completion for compliance, analytical, and troubleshooting purposes.

    What is Next

    -

    Now you have completed the tutorials. You can continue to explore the key concepts in Cadence, and also how to use them with Java Client

    +

    Now you have completed the tutorials. You can continue to explore the key concepts in Cadence, and also how to use them with Java Client

    \ No newline at end of file diff --git a/docs/get-started/java-hello-world.html.html b/docs/get-started/java-hello-world.html.html index f2e0248ee..6e4c2ec74 100644 --- a/docs/get-started/java-hello-world.html.html +++ b/docs/get-started/java-hello-world.html.html @@ -2,10 +2,10 @@ - - + + \ No newline at end of file diff --git a/docs/get-started/server-installation.html b/docs/get-started/server-installation.html index 2f6a3de3e..c228cde0d 100644 --- a/docs/get-started/server-installation.html +++ b/docs/get-started/server-installation.html @@ -3,8 +3,8 @@ -Server Installation | Cadence - +Server Installation | Cadence + @@ -15,14 +15,14 @@ - - - + + + -

    Install Cadence Service Locally

    +

    Install Cadence Service Locally

    To get started with Cadence, you need to set up three components successfully.

    • A Cadence server hosting dependencies that Cadence relies on such as Cassandra, Elastic Search, etc
    • @@ -45,7 +45,7 @@

      What's Next

      So far you've successfully finished two prerequisites to your Cadence application. The next steps are to implement a simple worker service that hosts your workflows and to run your very first hello world Cadence workflow.

      -

      Go to Java HelloWorld or Golang HelloWorld.

      +

      Go to Java HelloWorld or Golang HelloWorld.

      Troubleshooting

      There can be various reasons that docker-compose up cannot succeed:

        @@ -59,6 +59,6 @@

        Troubleshoot

    -

    If the above is still not working, open an issue in Server(main) repo.

    +

    If the above is still not working, open an issue in Server(main) repo.

    \ No newline at end of file diff --git a/docs/get-started/server-installation.html.html b/docs/get-started/server-installation.html.html index 2613ffd2e..4c62ab931 100644 --- a/docs/get-started/server-installation.html.html +++ b/docs/get-started/server-installation.html.html @@ -2,10 +2,10 @@ - - + + \ No newline at end of file diff --git a/docs/get-started/video-tutorials.html b/docs/get-started/video-tutorials.html index 8846b11ab..a65140d54 100644 --- a/docs/get-started/video-tutorials.html +++ b/docs/get-started/video-tutorials.html @@ -3,8 +3,8 @@ -Video Tutorials | Cadence - +Video Tutorials | Cadence + @@ -15,18 +15,18 @@ - - - + + + -

    Overview

    + +
    \ No newline at end of file diff --git a/docs/get-started/video-tutorials.html.html b/docs/get-started/video-tutorials.html.html index f11d0f5ee..b2e394d2c 100644 --- a/docs/get-started/video-tutorials.html.html +++ b/docs/get-started/video-tutorials.html.html @@ -2,10 +2,10 @@ - - + + \ No newline at end of file diff --git a/docs/glossary.html b/docs/glossary.html index 1108a4a2c..cc80881f3 100644 --- a/docs/glossary.html +++ b/docs/glossary.html @@ -3,8 +3,8 @@ -Glossary | Cadence - +Glossary | Cadence + @@ -15,14 +15,14 @@ - - - + + + - + \ No newline at end of file diff --git a/docs/glossary.html.html b/docs/glossary.html.html index ea298b717..1c5398d6b 100644 --- a/docs/glossary.html.html +++ b/docs/glossary.html.html @@ -2,10 +2,10 @@ - - + + \ No newline at end of file diff --git a/docs/go-client.html b/docs/go-client.html index 6603bb206..35a575d50 100644 --- a/docs/go-client.html +++ b/docs/go-client.html @@ -3,8 +3,8 @@ -Introduction | Cadence - +Introduction | Cadence + @@ -15,24 +15,24 @@ - - - + + + -

    Go client

    +

    Go client

    Overview

    Go client attempts to follow Go language conventions. The conversion of a Go program to the fault-oblivious workflow function is expected to be pretty mechanical.

    Cadence requires determinism of the workflow code. It supports deterministic execution of the multithreaded code and constructs like select that are non-deterministic by Go design. The Cadence solution is to provide corresponding constructs in the form of interfaces that have similar capability but support deterministic execution.

    For example, instead of native Go channels, workflow code must use the workflow.Channel interface. Instead of select, the workflow.Selector interface must be used.

    -

    For more information, see Creating Workflows.

    +

    For more information, see Creating Workflows.

    +
    \ No newline at end of file diff --git a/docs/go-client.html.html b/docs/go-client.html.html index a7982c7b0..19af7f70a 100644 --- a/docs/go-client.html.html +++ b/docs/go-client.html.html @@ -2,10 +2,10 @@ - - + + \ No newline at end of file diff --git a/docs/go-client/02.5-starting-workflows.html b/docs/go-client/02.5-starting-workflows.html index 1adfb5773..1e01c0d96 100644 --- a/docs/go-client/02.5-starting-workflows.html +++ b/docs/go-client/02.5-starting-workflows.html @@ -3,8 +3,8 @@ -Starting workflows | Cadence - +Starting workflows | Cadence + @@ -15,24 +15,24 @@ - - - + + + -

    Starting workflows

    +

    Starting workflows

    Starting workflows can be done from any service that can send requests to the Cadence server. There is no requirement for workflows to be started from the worker services.

    Generally workflows can either be started using a direct reference to the workflow code, or by referring to the registered name of the function. In -Workflow Registration we show +Workflow Registration we show how to register the workflows.

    Starting a workflow

    -

    After creating a workflow we can start it. -This can be done from the cli, but typically +

    After creating a workflow we can start it. +This can be done from the cli, but typically we want to start workflow programmatically e.g. from an http handler. We can do this using the client.StartWorkflow @@ -73,6 +73,6 @@

    StartWo specifies the two mandatory options; TaskList and ExecutionStartToCloseTimeout, all the options are described in the inline documentation:

    -
    type StartWorkflowOptions struct {
    // ID - The business identifier of the workflow execution.
    // Optional: defaulted to a uuid.
    ID string

    // TaskList - The decisions of the workflow are scheduled on this queue.
    // This is also the default task list on which activities are scheduled. The workflow author can choose
    // to override this using activity options.
    // Mandatory: No default.
    TaskList string

    // ExecutionStartToCloseTimeout - The timeout for duration of workflow execution.
    // The resolution is seconds.
    // Mandatory: No default.
    ExecutionStartToCloseTimeout time.Duration

    // DecisionTaskStartToCloseTimeout - The timeout for processing decision task from the time the worker
    // pulled this task. If a decision task is lost, it is retried after this timeout.
    // The resolution is seconds.
    // Optional: defaulted to 10 secs.
    DecisionTaskStartToCloseTimeout time.Duration

    // WorkflowIDReusePolicy - Whether server allow reuse of workflow ID, can be useful
    // for dedup logic if set to WorkflowIdReusePolicyRejectDuplicate.
    // Optional: defaulted to WorkflowIDReusePolicyAllowDuplicateFailedOnly.
    WorkflowIDReusePolicy WorkflowIDReusePolicy

    // RetryPolicy - Optional retry policy for workflow. If a retry policy is specified, in case of workflow failure
    // server will start new workflow execution if needed based on the retry policy.
    RetryPolicy *RetryPolicy

    // CronSchedule - Optional cron schedule for workflow. If a cron schedule is specified, the workflow will run
    // as a cron based on the schedule. The scheduling will be based on UTC time. Schedule for next run only happen
    // after the current run is completed/failed/timeout. If a RetryPolicy is also supplied, and the workflow failed
    // or timeout, the workflow will be retried based on the retry policy. While the workflow is retrying, it won't
    // schedule its next run. If next schedule is due while workflow is running (or retrying), then it will skip that
    // schedule. Cron workflow will not stop until it is terminated or cancelled (by returning cadence.CanceledError).
    // The cron spec is as following:
    // ┌───────────── minute (0 - 59)
    // │ ┌───────────── hour (0 - 23)
    // │ │ ┌───────────── day of the month (1 - 31)
    // │ │ │ ┌───────────── month (1 - 12)
    // │ │ │ │ ┌───────────── day of the week (0 - 6) (Sunday to Saturday)
    // │ │ │ │ │
    // │ │ │ │ │
    // * * * * *
    CronSchedule string

    // Memo - Optional non-indexed info that will be shown in list workflow.
    Memo map[string]interface{}

    // SearchAttributes - Optional indexed info that can be used in query of List/Scan/Count workflow APIs (only
    // supported when Cadence server is using ElasticSearch). The key and value type must be registered on Cadence server side.
    // Use GetSearchAttributes API to get valid key and corresponding value type.
    SearchAttributes map[string]interface{}

    // DelayStartSeconds - Seconds to delay the workflow start
    // The resolution is seconds.
    // Optional: defaulted to 0 seconds
    DelayStart time.Duration

    // JitterStart - Seconds to jitter the workflow start. For example, if set to 10, the workflow will start some time between 0-10 seconds.
    // This works with CronSchedule and with DelayStart.
    // Optional: defaulted to 0 seconds
    JitterStart time.Duration
    }

    +
    type StartWorkflowOptions struct {
    // ID - The business identifier of the workflow execution.
    // Optional: defaulted to a uuid.
    ID string

    // TaskList - The decisions of the workflow are scheduled on this queue.
    // This is also the default task list on which activities are scheduled. The workflow author can choose
    // to override this using activity options.
    // Mandatory: No default.
    TaskList string

    // ExecutionStartToCloseTimeout - The timeout for duration of workflow execution.
    // The resolution is seconds.
    // Mandatory: No default.
    ExecutionStartToCloseTimeout time.Duration

    // DecisionTaskStartToCloseTimeout - The timeout for processing decision task from the time the worker
    // pulled this task. If a decision task is lost, it is retried after this timeout.
    // The resolution is seconds.
    // Optional: defaulted to 10 secs.
    DecisionTaskStartToCloseTimeout time.Duration

    // WorkflowIDReusePolicy - Whether server allow reuse of workflow ID, can be useful
    // for dedup logic if set to WorkflowIdReusePolicyRejectDuplicate.
    // Optional: defaulted to WorkflowIDReusePolicyAllowDuplicateFailedOnly.
    WorkflowIDReusePolicy WorkflowIDReusePolicy

    // RetryPolicy - Optional retry policy for workflow. If a retry policy is specified, in case of workflow failure
    // server will start new workflow execution if needed based on the retry policy.
    RetryPolicy *RetryPolicy

    // CronSchedule - Optional cron schedule for workflow. If a cron schedule is specified, the workflow will run
    // as a cron based on the schedule. The scheduling will be based on UTC time. Schedule for next run only happen
    // after the current run is completed/failed/timeout. If a RetryPolicy is also supplied, and the workflow failed
    // or timeout, the workflow will be retried based on the retry policy. While the workflow is retrying, it won't
    // schedule its next run. If next schedule is due while workflow is running (or retrying), then it will skip that
    // schedule. Cron workflow will not stop until it is terminated or cancelled (by returning cadence.CanceledError).
    // The cron spec is as following:
    // ┌───────────── minute (0 - 59)
    // │ ┌───────────── hour (0 - 23)
    // │ │ ┌───────────── day of the month (1 - 31)
    // │ │ │ ┌───────────── month (1 - 12)
    // │ │ │ │ ┌───────────── day of the week (0 - 6) (Sunday to Saturday)
    // │ │ │ │ │
    // │ │ │ │ │
    // * * * * *
    CronSchedule string

    // Memo - Optional non-indexed info that will be shown in list workflow.
    Memo map[string]interface{}

    // SearchAttributes - Optional indexed info that can be used in query of List/Scan/Count workflow APIs (only
    // supported when Cadence server is using ElasticSearch). The key and value type must be registered on Cadence server side.
    // Use GetSearchAttributes API to get valid key and corresponding value type.
    SearchAttributes map[string]interface{}

    // DelayStartSeconds - Seconds to delay the workflow start
    // The resolution is seconds.
    // Optional: defaulted to 0 seconds
    DelayStart time.Duration

    // JitterStart - Seconds to jitter the workflow start. For example, if set to 10, the workflow will start some time between 0-10 seconds.
    // This works with CronSchedule and with DelayStart.
    // Optional: defaulted to 0 seconds
    JitterStart time.Duration
    }
    \ No newline at end of file diff --git a/docs/go-client/02.5-starting-workflows.html.html b/docs/go-client/02.5-starting-workflows.html.html index 64d798a67..77802099d 100644 --- a/docs/go-client/02.5-starting-workflows.html.html +++ b/docs/go-client/02.5-starting-workflows.html.html @@ -2,10 +2,10 @@ - - + + \ No newline at end of file diff --git a/docs/go-client/activities.html b/docs/go-client/activities.html index aca342b6b..3a88b3c07 100644 --- a/docs/go-client/activities.html +++ b/docs/go-client/activities.html @@ -3,8 +3,8 @@ -Activity overview | Cadence - +Activity overview | Cadence + @@ -15,14 +15,14 @@ - - - + + + -

    Activity overview

    + +

    To mark an activity as failed, the activity function must return an error via the error return value.

    \ No newline at end of file diff --git a/docs/go-client/activities.html.html b/docs/go-client/activities.html.html index ca7c67e50..27ef809f9 100644 --- a/docs/go-client/activities.html.html +++ b/docs/go-client/activities.html.html @@ -2,10 +2,10 @@ - - + + \ No newline at end of file diff --git a/docs/go-client/activity-async-completion.html b/docs/go-client/activity-async-completion.html index 8c1654ddb..476e4d114 100644 --- a/docs/go-client/activity-async-completion.html +++ b/docs/go-client/activity-async-completion.html @@ -3,8 +3,8 @@ -Async activity completion | Cadence - +Async activity completion | Cadence + @@ -15,14 +15,14 @@ - - - + + + -

    Asynchronous activity completion

    +

    Asynchronous activity completion

    There are certain scenarios when completing an activity upon completion of its function is not possible or desirable. For example, you might have an application that requires user input in order to complete the activity. You could implement the activity with a polling mechanism, but a simpler and less @@ -47,6 +47,6 @@ of the return value declared by the activity function.

  • err: The error code to return if the activity terminates with an error.
  • -

    If error is not null, the value of the result field is ignored.

    +

    If error is not null, the value of the result field is ignored.

    \ No newline at end of file diff --git a/docs/go-client/activity-async-completion.html.html b/docs/go-client/activity-async-completion.html.html index 666d46fdb..73fbfcb3b 100644 --- a/docs/go-client/activity-async-completion.html.html +++ b/docs/go-client/activity-async-completion.html.html @@ -2,10 +2,10 @@ - - + + \ No newline at end of file diff --git a/docs/go-client/child-workflows.html b/docs/go-client/child-workflows.html index d70966f07..1827dea75 100644 --- a/docs/go-client/child-workflows.html +++ b/docs/go-client/child-workflows.html @@ -3,8 +3,8 @@ -Child workflows | Cadence - +Child workflows | Cadence + @@ -15,14 +15,14 @@ - - - + + + -

    Child workflows

    +

    Child workflows

    workflow.ExecuteChildWorkflow enables the scheduling of other workflows from within a workflow's implementation. The parent workflow has the ability to monitor and impact the lifecycle of the child workflow, similar to the way it does for an activity that it invoked.

    @@ -53,6 +53,6 @@ patterns described for using workflow.ExecuteActivity() apply to the workflow.ExecuteChildWorkflow() function as well.

    When a parent workflow is cancelled by the user, the child workflow can be cancelled or abandoned -based on a configurable child policy.

    +based on a configurable child policy.

    \ No newline at end of file diff --git a/docs/go-client/child-workflows.html.html b/docs/go-client/child-workflows.html.html index ea3284b91..c4550a902 100644 --- a/docs/go-client/child-workflows.html.html +++ b/docs/go-client/child-workflows.html.html @@ -2,10 +2,10 @@ - - + + \ No newline at end of file diff --git a/docs/go-client/continue-as-new.html b/docs/go-client/continue-as-new.html index c89979d8f..0e1d5fe31 100644 --- a/docs/go-client/continue-as-new.html +++ b/docs/go-client/continue-as-new.html @@ -3,8 +3,8 @@ -Continue as new | Cadence - +Continue as new | Cadence + @@ -15,14 +15,14 @@ - - - + + + -

    Continue as new

    +

    Continue as new

    Workflows that need to rerun periodically could naively be implemented as a big for loop with a sleep where the entire logic of the workflow is inside the body of the for loop. The problem with this approach is that the history for that workflow will keep growing to a point where it @@ -32,6 +32,6 @@ a new execution of the workflow with the same workflow_ID. The new execution will not carry over any history from the old execution. To trigger this behavior, the workflow function should terminate by returning the special ContinueAsNewError error:

    -
    func SimpleWorkflow(workflow.Context ctx, value string) error {
    ...
    return workflow.NewContinueAsNewError(ctx, SimpleWorkflow, value)
    }
    +
    func SimpleWorkflow(workflow.Context ctx, value string) error {
    ...
    return workflow.NewContinueAsNewError(ctx, SimpleWorkflow, value)
    }
    \ No newline at end of file diff --git a/docs/go-client/continue-as-new.html.html b/docs/go-client/continue-as-new.html.html index 2fd8c3a48..1b564755e 100644 --- a/docs/go-client/continue-as-new.html.html +++ b/docs/go-client/continue-as-new.html.html @@ -2,10 +2,10 @@ - - + + \ No newline at end of file diff --git a/docs/go-client/create-workflows.html b/docs/go-client/create-workflows.html index 10dd863a9..4634575e3 100644 --- a/docs/go-client/create-workflows.html +++ b/docs/go-client/create-workflows.html @@ -3,8 +3,8 @@ -Creating workflows | Cadence - +Creating workflows | Cadence + @@ -15,14 +15,14 @@ - - - + + + -

    Creating workflows

    +
    +fail that task. However, the failure of the task will not cause the entire workflow to fail.

    \ No newline at end of file diff --git a/docs/go-client/create-workflows.html.html b/docs/go-client/create-workflows.html.html index 1e118361f..887b40fc4 100644 --- a/docs/go-client/create-workflows.html.html +++ b/docs/go-client/create-workflows.html.html @@ -2,10 +2,10 @@ - - + + \ No newline at end of file diff --git a/docs/go-client/distributed-cron.html b/docs/go-client/distributed-cron.html index 25d09deef..189450b03 100644 --- a/docs/go-client/distributed-cron.html +++ b/docs/go-client/distributed-cron.html @@ -3,8 +3,8 @@ -Distributed CRON | Cadence - +Distributed CRON | Cadence + @@ -15,14 +15,14 @@ - - - + + + -

    Distributed CRON

    +

    Distributed CRON

    It is relatively straightforward to turn any Cadence workflow into a Cron workflow. All you need is to supply a cron schedule when starting the workflow using the CronSchedule parameter of @@ -42,7 +42,7 @@

  • Cron workflows will not stop until they are terminated or cancelled.
  • Cadence supports the standard cron spec:

    -
    // CronSchedule - Optional cron schedule for workflow. If a cron schedule is specified, the workflow will run
    // as a cron based on the schedule. The scheduling will be based on UTC time. The schedule for next run only happen
    // after the current run is completed/failed/timeout. If a RetryPolicy is also supplied, and the workflow failed
    // or timed out, the workflow will be retried based on the retry policy. While the workflow is retrying, it won't
    // schedule its next run. If next schedule is due while the workflow is running (or retrying), then it will skip that
    // schedule. Cron workflow will not stop until it is terminated or cancelled (by returning cadence.CanceledError).
    // The cron spec is as following:
    // ┌───────────── minute (0 - 59)
    // │ ┌───────────── hour (0 - 23)
    // │ │ ┌───────────── day of the month (1 - 31)
    // │ │ │ ┌───────────── month (1 - 12)
    // │ │ │ │ ┌───────────── day of the week (0 - 6) (Sunday to Saturday)
    // │ │ │ │ │
    // │ │ │ │ │
    // * * * * *
    CronSchedule string
    +
    // CronSchedule - Optional cron schedule for workflow. If a cron schedule is specified, the workflow will run
    // as a cron based on the schedule. The scheduling will be based on UTC time. The schedule for next run only happen
    // after the current run is completed/failed/timeout. If a RetryPolicy is also supplied, and the workflow failed
    // or timed out, the workflow will be retried based on the retry policy. While the workflow is retrying, it won't
    // schedule its next run. If next schedule is due while the workflow is running (or retrying), then it will skip that
    // schedule. Cron workflow will not stop until it is terminated or cancelled (by returning cadence.CanceledError).
    // The cron spec is as following:
    // ┌───────────── minute (0 - 59)
    // │ ┌───────────── hour (0 - 23)
    // │ │ ┌───────────── day of the month (1 - 31)
    // │ │ │ ┌───────────── month (1 - 12)
    // │ │ │ │ ┌───────────── day of the week (0 - 6) (Sunday to Saturday)
    // │ │ │ │ │
    // │ │ │ │ │
    // * * * * *
    CronSchedule string

    Cadence also supports more advanced cron expressions.

    The crontab guru site is useful for testing your cron expressions.

    Convert existing cron workflow

    @@ -63,6 +63,6 @@

    +the result from first day's run using these APIs.

    \ No newline at end of file diff --git a/docs/go-client/distributed-cron.html.html b/docs/go-client/distributed-cron.html.html index a393565b8..5f46d52a1 100644 --- a/docs/go-client/distributed-cron.html.html +++ b/docs/go-client/distributed-cron.html.html @@ -2,10 +2,10 @@ - - + + \ No newline at end of file diff --git a/docs/go-client/error-handling.html b/docs/go-client/error-handling.html index 9b7a5809f..92adedd83 100644 --- a/docs/go-client/error-handling.html +++ b/docs/go-client/error-handling.html @@ -3,8 +3,8 @@ -Error handling | Cadence - +Error handling | Cadence + @@ -15,20 +15,20 @@ - - - + + + -

    Error handling

    +

    Error handling

    An activity, or child workflow, might fail and you could handle errors differently based on different error cases. If the activity returns an error as errors.New() or fmt.Errorf(), those errors will be converted to workflow.GenericError. If the activity returns an error as cadence.NewCustomError(“err-reason”, details), that error will be converted to *cadence.CustomError. There are other types of errors such as workflow.TimeoutError, workflow.CanceledError and workflow.PanicError. Following is an example of what your error code might look like:

    -
    err := workflow.ExecuteActivity(ctx, YourActivityFunc).Get(ctx, nil)
    switch err := err.(type) {
    case *cadence.CustomError:
    switch err.Reason() {
    case "err-reason-a":
    // Handle error-reason-a.
    var details YourErrorDetailsType
    err.Details(&details)
    // Deal with details.
    case "err-reason-b":
    // Handle error-reason-b.
    default:
    // Handle all other error reasons.
    }
    case *workflow.GenericError:
    switch err.Error() {
    case "err-msg-1":
    // Handle error with message "err-msg-1".
    case "err-msg-2":
    // Handle error with message "err-msg-2".
    default:
    // Handle all other generic errors.
    }
    case *workflow.TimeoutError:
    switch err.TimeoutType() {
    case shared.TimeoutTypeScheduleToStart:
    // Handle ScheduleToStart timeout.
    case shared.TimeoutTypeStartToClose:
    // Handle StartToClose timeout.
    case shared.TimeoutTypeHeartbeat:
    // Handle heartbeat timeout.
    default:
    }
    case *workflow.PanicError:
    // Handle panic error.
    case *cadence.CanceledError:
    // Handle canceled error.
    default:
    // All other cases (ideally, this should not happen).
    }
    +
    err := workflow.ExecuteActivity(ctx, YourActivityFunc).Get(ctx, nil)
    switch err := err.(type) {
    case *cadence.CustomError:
    switch err.Reason() {
    case "err-reason-a":
    // Handle error-reason-a.
    var details YourErrorDetailsType
    err.Details(&details)
    // Deal with details.
    case "err-reason-b":
    // Handle error-reason-b.
    default:
    // Handle all other error reasons.
    }
    case *workflow.GenericError:
    switch err.Error() {
    case "err-msg-1":
    // Handle error with message "err-msg-1".
    case "err-msg-2":
    // Handle error with message "err-msg-2".
    default:
    // Handle all other generic errors.
    }
    case *workflow.TimeoutError:
    switch err.TimeoutType() {
    case shared.TimeoutTypeScheduleToStart:
    // Handle ScheduleToStart timeout.
    case shared.TimeoutTypeStartToClose:
    // Handle StartToClose timeout.
    case shared.TimeoutTypeHeartbeat:
    // Handle heartbeat timeout.
    default:
    }
    case *workflow.PanicError:
    // Handle panic error.
    case *cadence.CanceledError:
    // Handle canceled error.
    default:
    // All other cases (ideally, this should not happen).
    }
    \ No newline at end of file diff --git a/docs/go-client/error-handling.html.html b/docs/go-client/error-handling.html.html index 53e9f27be..ba5e76bd1 100644 --- a/docs/go-client/error-handling.html.html +++ b/docs/go-client/error-handling.html.html @@ -2,10 +2,10 @@ - - + + \ No newline at end of file diff --git a/docs/go-client/execute-activity.html b/docs/go-client/execute-activity.html index f630ff8b5..41818ee14 100644 --- a/docs/go-client/execute-activity.html +++ b/docs/go-client/execute-activity.html @@ -3,8 +3,8 @@ -Executing activities | Cadence - +Executing activities | Cadence + @@ -15,14 +15,14 @@ - - - + + + -

    Executing activities

    +

    Executing activities

    The primary responsibility of a workflow implementation is to schedule activities for execution. The most straightforward way to do this is via the library method workflow.ExecuteActivity. The following sample code demonstrates making this call:

    @@ -63,6 +63,6 @@

    Execute However, this is not necessary. If you want to execute multiple activities in parallel, you can repeatedly call workflow.ExecuteActivity(), store the returned futures, and then wait for all activities to complete by calling the Get() methods of the future at a later time.

    -

    To implement more complex wait conditions on returned future objects, use the cadence.Selector class.

    +

    To implement more complex wait conditions on returned future objects, use the cadence.Selector class.

    \ No newline at end of file diff --git a/docs/go-client/execute-activity.html.html b/docs/go-client/execute-activity.html.html index 8a7577a0c..108384d29 100644 --- a/docs/go-client/execute-activity.html.html +++ b/docs/go-client/execute-activity.html.html @@ -2,10 +2,10 @@ - - + + \ No newline at end of file diff --git a/docs/go-client/queries.html b/docs/go-client/queries.html index 7ea1df09a..bc8f643dc 100644 --- a/docs/go-client/queries.html +++ b/docs/go-client/queries.html @@ -3,8 +3,8 @@ -Queries | Cadence - +Queries | Cadence + @@ -15,14 +15,14 @@ - - - + + + -

    Queries

    +

    Queries

    If a workflow_execution has been stuck at a state for longer than an expected period of time, you might want to query the current call stack. You can use the Cadence CLI to perform this query. For example:

    @@ -59,6 +59,6 @@

    Consistent

    cadence-cli --domain samples-domain workflow query -w my_workflow_id -r my_run_id -qt current_state --qcl strong

    In order to run a query using the go client do the following:

    resp, err := cadenceClient.QueryWorkflowWithOptions(ctx, &client.QueryWorkflowWithOptionsRequest{
    WorkflowID: workflowID,
    RunID: runID,
    QueryType: queryType,
    QueryConsistencyLevel: shared.QueryConsistencyLevelStrong.Ptr(),
    })
    -

    When using strongly consistent query you should expect higher latency than eventually consistent query.

    +

    When using strongly consistent query you should expect higher latency than eventually consistent query.

    \ No newline at end of file diff --git a/docs/go-client/queries.html.html b/docs/go-client/queries.html.html index 2b4c57be7..14f0f46d5 100644 --- a/docs/go-client/queries.html.html +++ b/docs/go-client/queries.html.html @@ -2,10 +2,10 @@ - - + + \ No newline at end of file diff --git a/docs/go-client/retries.html b/docs/go-client/retries.html index 699f7d8a3..a2bd98cdc 100644 --- a/docs/go-client/retries.html +++ b/docs/go-client/retries.html @@ -3,8 +3,8 @@ -Activity and workflow retries | Cadence - +Activity and workflow retries | Cadence + @@ -15,14 +15,14 @@ - - - + + + -

    Activity and workflow retries

    +

    Activity and workflow retries

    Activities and workflows can fail due to various intermediate conditions. In those cases, we want to retry the failed activity or child workflow or even the parent workflow. This can be achieved by supplying an optional retry policy. A retry policy looks like the following:

    @@ -52,6 +52,6 @@ will have the ContinueAsNewInitiator set to RetryPolicy and the new RunID for the next retry attempt.
  • The new attempt will be created immediately. But the first decision_task won't be scheduled until the backoff duration which is also recorded in the new run's WorkflowExecutionStartedEventAttributes event as firstDecisionTaskBackoffSeconds.
  • -
    +
    \ No newline at end of file diff --git a/docs/go-client/retries.html.html b/docs/go-client/retries.html.html index f8184218a..48a7b0d62 100644 --- a/docs/go-client/retries.html.html +++ b/docs/go-client/retries.html.html @@ -2,10 +2,10 @@ - - + + \ No newline at end of file diff --git a/docs/go-client/sessions.html b/docs/go-client/sessions.html index bc5ec1149..fb5e4f945 100644 --- a/docs/go-client/sessions.html +++ b/docs/go-client/sessions.html @@ -3,8 +3,8 @@ -Sessions | Cadence - +Sessions | Cadence + @@ -15,14 +15,14 @@ - - - + + + -

    Sessions

    +

    Sessions

    The session framework provides a straightforward interface for scheduling multiple activities on a single worker without requiring you to manually specify the task_list name. It also includes features like concurrent session limitation and worker failure detection.

    Use Cases

      @@ -73,6 +73,6 @@

      Future WorkSupport fine-grained concurrent session limitation The current implementation assumes that all sessions are consuming the same type of resource and there's only one global limitation. Our plan is to allow you to specify what type of resource your session will consume and enforce different limitations on different types of resources.

      -

    +
    \ No newline at end of file diff --git a/docs/go-client/sessions.html.html b/docs/go-client/sessions.html.html index c17b2cf10..e250421ca 100644 --- a/docs/go-client/sessions.html.html +++ b/docs/go-client/sessions.html.html @@ -2,10 +2,10 @@ - - + + \ No newline at end of file diff --git a/docs/go-client/side-effect.html b/docs/go-client/side-effect.html index 17b36aae0..c03a7ed92 100644 --- a/docs/go-client/side-effect.html +++ b/docs/go-client/side-effect.html @@ -3,8 +3,8 @@ -Side effect | Cadence - +Side effect | Cadence + @@ -15,14 +15,14 @@ - - - + + + -

    Side effect

    +

    Side effect

    workflow.SideEffect is useful for short, nondeterministic code snippets, such as getting a random value or generating a UUID. It executes the provided function once and records its result into the workflow history. workflow.SideEffect does not re-execute upon replay, but instead returns the @@ -34,6 +34,6 @@ timeout, Cadence reschedules and then re-executes the decision_task, giving SideEffect another chance to succeed. Do not return any data from SideEffect other than through its recorded return value.

    The following sample demonstrates how to use SideEffect:

    -
    encodedRandom := SideEffect(func(ctx cadence.Context) interface{} {
    return rand.Intn(100)
    })

    var random int
    encodedRandom.Get(&random)
    if random < 50 {
    ...
    } else {
    ...
    }
    +
    encodedRandom := SideEffect(func(ctx cadence.Context) interface{} {
    return rand.Intn(100)
    })

    var random int
    encodedRandom.Get(&random)
    if random < 50 {
    ...
    } else {
    ...
    }
    \ No newline at end of file diff --git a/docs/go-client/side-effect.html.html b/docs/go-client/side-effect.html.html index ed29e06e1..0dc60ca95 100644 --- a/docs/go-client/side-effect.html.html +++ b/docs/go-client/side-effect.html.html @@ -2,10 +2,10 @@ - - + + \ No newline at end of file diff --git a/docs/go-client/signals.html b/docs/go-client/signals.html index c9b584631..16f5a764e 100644 --- a/docs/go-client/signals.html +++ b/docs/go-client/signals.html @@ -3,8 +3,8 @@ -Signals | Cadence - +Signals | Cadence + @@ -15,14 +15,14 @@ - - - + + + -

    Signals

    + +parameter.

    \ No newline at end of file diff --git a/docs/go-client/signals.html.html b/docs/go-client/signals.html.html index c68e905aa..73b468005 100644 --- a/docs/go-client/signals.html.html +++ b/docs/go-client/signals.html.html @@ -2,10 +2,10 @@ - - + + \ No newline at end of file diff --git a/docs/go-client/tracing.html b/docs/go-client/tracing.html index 5f346b5ab..7288e29e6 100644 --- a/docs/go-client/tracing.html +++ b/docs/go-client/tracing.html @@ -3,8 +3,8 @@ -Tracing and context propagation | Cadence - +Tracing and context propagation | Cadence + @@ -15,14 +15,14 @@ - - - + + + -

    Tracing and context propagation

    +

    Tracing and context propagation

    Tracing

    The Go client provides distributed tracing support through OpenTracing. Tracing can be configured by providing an opentracing.Tracer @@ -69,6 +69,6 @@

    The context propagation sample configures a custom context propagator and shows context propagation of custom keys across a workflow and an activity.

    Can I configure multiple context propagators?

    -

    Yes, we recommended that you configure multiple context propagators with each propagator meant to propagate a particular type of context.

    +

    Yes, we recommended that you configure multiple context propagators with each propagator meant to propagate a particular type of context.

    \ No newline at end of file diff --git a/docs/go-client/tracing.html.html b/docs/go-client/tracing.html.html index de1268f55..d41ec44b3 100644 --- a/docs/go-client/tracing.html.html +++ b/docs/go-client/tracing.html.html @@ -2,10 +2,10 @@ - - + + \ No newline at end of file diff --git a/docs/go-client/workers.html b/docs/go-client/workers.html index 477d1a295..c15f2c17e 100644 --- a/docs/go-client/workers.html +++ b/docs/go-client/workers.html @@ -3,8 +3,8 @@ -Worker service | Cadence - +Worker service | Cadence + @@ -15,14 +15,14 @@ - - - + + + -

    Worker service

    +

    Worker service

    A worker or worker service is a service that hosts the workflow and activity implementations. The worker polls the Cadence service for tasks, performs those tasks, and communicates task execution results back to the Cadence service. Worker services are developed, deployed, and operated by Cadence customers.

    You can run a Cadence worker in a new or an existing service. Use the framework APIs to start the Cadence worker and link in all activity and workflow implementations that you require the service to execute.

    The following is an example worker service utilising tchannel, one of the two transport protocols supported by Cadence.

    @@ -31,6 +31,6 @@

    import (

    "go.uber.org/cadence/.gen/go/cadence"
    "go.uber.org/cadence/.gen/go/cadence/workflowserviceclient"
    "go.uber.org/cadence/compatibility"
    "go.uber.org/cadence/worker"

    apiv1 "github.com/cadence-workflow/cadence-idl/go/proto/api/v1"
    "github.com/uber-go/tally"
    "go.uber.org/zap"
    "go.uber.org/zap/zapcore"
    "go.uber.org/yarpc"
    "go.uber.org/yarpc/transport/grpc"
    )

    .
    .
    .

    func buildCadenceClient() workflowserviceclient.Interface {

    dispatcher := yarpc.NewDispatcher(yarpc.Config{
    Name: ClientName,
    Outbounds: yarpc.Outbounds{
    CadenceService: {Unary: grpc.NewTransport().NewSingleOutbound(HostPort)},
    },
    })
    if err := dispatcher.Start(); err != nil {
    panic("Failed to start dispatcher")
    }

    clientConfig := dispatcher.ClientConfig(CadenceService)

    return compatibility.NewThrift2ProtoAdapter(
    apiv1.NewDomainAPIYARPCClient(clientConfig),
    apiv1.NewWorkflowAPIYARPCClient(clientConfig),
    apiv1.NewWorkerAPIYARPCClient(clientConfig),
    apiv1.NewVisibilityAPIYARPCClient(clientConfig),
    )
    }

    Note also that the HostPort variable must be changed to target the gRPC listener port of the Cadence cluster (typically, 7833).

    Finally, gRPC can also support TLS connections between Go clients and the Cadence server. This requires the following alterations to the imported packages, and the buildCadenceClient function. Note that this also requires you replace "path/to/cert/file" in the function with a path to a valid certificate file matching the TLS configuration of the Cadence server.

    -

    import (

    "fmt"

    "go.uber.org/cadence/.gen/go/cadence"
    "go.uber.org/cadence/.gen/go/cadence/workflowserviceclient"
    "go.uber.org/cadence/compatibility"
    "go.uber.org/cadence/worker"

    apiv1 "github.com/cadence-workflow/cadence-idl/go/proto/api/v1"
    "github.com/uber-go/tally"
    "go.uber.org/zap"
    "go.uber.org/zap/zapcore"
    "go.uber.org/yarpc"
    "go.uber.org/yarpc/transport/grpc"
    "go.uber.org/yarpc/peer"
    "go.uber.org/yarpc/peer/hostport"

    "crypto/tls"
    "crypto/x509"
    "io/ioutil"

    "google.golang.org/grpc/credentials"
    )

    .
    .
    .

    func buildCadenceClient() workflowserviceclient.Interface {
    grpcTransport := grpc.NewTransport()
    var dialOptions []grpc.DialOption

    caCert, err := ioutil.ReadFile("/path/to/cert/file")
    if err != nil {
    fmt.Printf("Failed to load server CA certificate: %v", zap.Error(err))
    }

    caCertPool := x509.NewCertPool()
    if !caCertPool.AppendCertsFromPEM(caCert) {
    fmt.Errorf("Failed to add server CA's certificate")
    }

    tlsConfig := tls.Config{
    RootCAs: caCertPool,
    }

    creds := credentials.NewTLS(&tlsConfig)
    dialOptions = append(dialOptions, grpc.DialerCredentials(creds))

    dialer := grpcTransport.NewDialer(dialOptions...)
    outbound := grpcTransport.NewOutbound(
    peer.NewSingle(hostport.PeerIdentifier(HostPort), dialer)
    )

    dispatcher := yarpc.NewDispatcher(yarpc.Config{
    Name: ClientName,
    Outbounds: yarpc.Outbounds{
    CadenceService: {Unary: outbound},
    },
    })
    if err := dispatcher.Start(); err != nil {
    panic("Failed to start dispatcher")
    }

    clientConfig := dispatcher.ClientConfig(CadenceService)

    return compatibility.NewThrift2ProtoAdapter(
    apiv1.NewDomainAPIYARPCClient(clientConfig),
    apiv1.NewWorkflowAPIYARPCClient(clientConfig),
    apiv1.NewWorkerAPIYARPCClient(clientConfig),
    apiv1.NewVisibilityAPIYARPCClient(clientConfig),
    )
    }
    +

    import (

    "fmt"

    "go.uber.org/cadence/.gen/go/cadence"
    "go.uber.org/cadence/.gen/go/cadence/workflowserviceclient"
    "go.uber.org/cadence/compatibility"
    "go.uber.org/cadence/worker"

    apiv1 "github.com/cadence-workflow/cadence-idl/go/proto/api/v1"
    "github.com/uber-go/tally"
    "go.uber.org/zap"
    "go.uber.org/zap/zapcore"
    "go.uber.org/yarpc"
    "go.uber.org/yarpc/transport/grpc"
    "go.uber.org/yarpc/peer"
    "go.uber.org/yarpc/peer/hostport"

    "crypto/tls"
    "crypto/x509"
    "io/ioutil"

    "google.golang.org/grpc/credentials"
    )

    .
    .
    .

    func buildCadenceClient() workflowserviceclient.Interface {
    grpcTransport := grpc.NewTransport()
    var dialOptions []grpc.DialOption

    caCert, err := ioutil.ReadFile("/path/to/cert/file")
    if err != nil {
    fmt.Printf("Failed to load server CA certificate: %v", zap.Error(err))
    }

    caCertPool := x509.NewCertPool()
    if !caCertPool.AppendCertsFromPEM(caCert) {
    fmt.Errorf("Failed to add server CA's certificate")
    }

    tlsConfig := tls.Config{
    RootCAs: caCertPool,
    }

    creds := credentials.NewTLS(&tlsConfig)
    dialOptions = append(dialOptions, grpc.DialerCredentials(creds))

    dialer := grpcTransport.NewDialer(dialOptions...)
    outbound := grpcTransport.NewOutbound(
    peer.NewSingle(hostport.PeerIdentifier(HostPort), dialer)
    )

    dispatcher := yarpc.NewDispatcher(yarpc.Config{
    Name: ClientName,
    Outbounds: yarpc.Outbounds{
    CadenceService: {Unary: outbound},
    },
    })
    if err := dispatcher.Start(); err != nil {
    panic("Failed to start dispatcher")
    }

    clientConfig := dispatcher.ClientConfig(CadenceService)

    return compatibility.NewThrift2ProtoAdapter(
    apiv1.NewDomainAPIYARPCClient(clientConfig),
    apiv1.NewWorkflowAPIYARPCClient(clientConfig),
    apiv1.NewWorkerAPIYARPCClient(clientConfig),
    apiv1.NewVisibilityAPIYARPCClient(clientConfig),
    )
    }
    \ No newline at end of file diff --git a/docs/go-client/workers.html.html b/docs/go-client/workers.html.html index 45d9dbc77..f7b4a5112 100644 --- a/docs/go-client/workers.html.html +++ b/docs/go-client/workers.html.html @@ -2,10 +2,10 @@ - - + + \ No newline at end of file diff --git a/docs/go-client/workflow-non-deterministic-error.html b/docs/go-client/workflow-non-deterministic-error.html index 9f7405d4d..db3edf2b9 100644 --- a/docs/go-client/workflow-non-deterministic-error.html +++ b/docs/go-client/workflow-non-deterministic-error.html @@ -3,8 +3,8 @@ -Workflow Non-deterministic errors | Cadence - +Workflow Non-deterministic errors | Cadence + @@ -15,19 +15,19 @@ - - - + + + -

    Workflow Non-deterministic errors

    +

    Workflow Non-deterministic errors

    Root cause of non-deterministic errors

    Cadence workflows are designed as long-running operations, and therefore the workflow code you write must be deterministic so that no matter how many time it is executed it always produce the same results.

    In production environment, your workflow code will run on a distributed system orchestrated by clusters of machines. However, machine failures are inevitable and can happen anytime to your workflow host. If you have a workflow running for long period of time, maybe months even years, and it fails due to loss of a host, it will be resumed on another machine and continue the rest of its execution.

    Consider the following diagram where Workflow A is running on Host A but suddenly it crashes.

    -

    change-workflow-ownership

    +

    change-workflow-ownership

    Workflow A then will be picked up by Host B and continues its execution. This process is called change of workflow ownership. However, after Host B gains ownership of the Workflow A, it does not have any information about its historical executions. For example, Workflow A may have executed many activities and it fails. Host B needs to redo all its history until the moment of failure. The process of reconstructing history of a workflow is called history replay.

    In general, any errors occurs during the replay process are called non-deterministic errors. We will explore different types of non-deterministic errors in sections below but first let's try to understand how Cadence is able to perform the replay of workflow in case of failure.

    Decision tasks of workflow

    @@ -87,6 +87,6 @@

    I want to check if my code change will produce non-deterministic errors, how can I debug?

    -

    Cadence provides replayer test, which functions as an unit test on your local machine to replay your workflow history comparing to your potential code change. If you introduce a non-deterministic change and your history triggers it, the test should fail. Check out this page for more details.

    +

    Cadence provides replayer test, which functions as an unit test on your local machine to replay your workflow history comparing to your potential code change. If you introduce a non-deterministic change and your history triggers it, the test should fail. Check out this page for more details.

    \ No newline at end of file diff --git a/docs/go-client/workflow-non-deterministic-error.html.html b/docs/go-client/workflow-non-deterministic-error.html.html index c82dd1b03..79949c8fd 100644 --- a/docs/go-client/workflow-non-deterministic-error.html.html +++ b/docs/go-client/workflow-non-deterministic-error.html.html @@ -2,10 +2,10 @@ - - + + \ No newline at end of file diff --git a/docs/go-client/workflow-replay-shadowing.html b/docs/go-client/workflow-replay-shadowing.html index 3fad2f871..870ee6de5 100644 --- a/docs/go-client/workflow-replay-shadowing.html +++ b/docs/go-client/workflow-replay-shadowing.html @@ -3,8 +3,8 @@ -Workflow Replay and Shadowing | Cadence - +Workflow Replay and Shadowing | Cadence + @@ -15,14 +15,14 @@ - - - + + + -

    Workflow Replay and Shadowing

    +

    Workflow Replay and Shadowing

    In the Versioning section, we mentioned that incompatible changes to workflow definition code could cause non-deterministic issues when processing workflow tasks if versioning is not done correctly. However, it may be hard for you to tell if a particular change is incompatible or not and whether versioning logic is needed. To help you identify incompatible changes and catch them before production traffic is impacted, we implemented Workflow Replayer and Workflow Shadower.

    Workflow Replayer

    Workflow Replayer is a testing component for replaying existing workflow histories against a workflow definition. The replaying logic is the same as the one used for processing workflow tasks, so if there's any incompatible changes in the workflow definition, the replay test will fail.

    @@ -90,6 +90,6 @@

    Shadowing W

    Replay succeed, skipped and failed metrics will be emitted by your worker when executing the shadow workflow and you can monitor those metrics to see if there's any incompatible changes.

    To enable the shadow mode, the only change needed is setting the EnableShadowWorker field in worker.Options to true, and then specify the ShadowOptions.

    Registered workflows will be forwarded to the underlying WorkflowReplayer. DataConverter, WorkflowInterceptorChainFactories, ContextPropagators, and Tracer specified in the worker.Options will also be used as ReplayOptions. Since all shadow workflows are running in one system domain, to avoid conflict, the actual task list name used will be domain-tasklist.

    -

    A sample setup can be found here.

    +

    A sample setup can be found here.

    \ No newline at end of file diff --git a/docs/go-client/workflow-replay-shadowing.html.html b/docs/go-client/workflow-replay-shadowing.html.html index 6cd777d7e..5b86806ca 100644 --- a/docs/go-client/workflow-replay-shadowing.html.html +++ b/docs/go-client/workflow-replay-shadowing.html.html @@ -2,10 +2,10 @@ - - + + \ No newline at end of file diff --git a/docs/go-client/workflow-testing.html b/docs/go-client/workflow-testing.html index 1b389e2eb..e35fd85f8 100644 --- a/docs/go-client/workflow-testing.html +++ b/docs/go-client/workflow-testing.html @@ -3,8 +3,8 @@ -Testing | Cadence - +Testing | Cadence + @@ -15,14 +15,14 @@ - - - + + + -

    Testing

    +

    Testing

    The Cadence Go client library provides a test framework to facilitate testing workflow implementations. The framework is suited for implementing unit tests as well as functional tests of the workflow logic.

    The following code implements unit tests for the SimpleWorkflow sample:

    @@ -92,6 +92,6 @@

    Testing sign
    func (s *UnitTestSuite) Test_SimpleWorkflow_Signal() {
    // Send the signal
    s.env.RegisterDelayedCallback(func() {
    s.env.SignalWorkflow(signalName, signalData)
    }, time.Minute*10)

    // Execute the workflow
    s.env.ExecuteWorkflow(SimpleWorkflow, "test_success")

    s.True(s.env.IsWorkflowCompleted())
    s.NoError(s.env.GetWorkflowError())
    }

    Note that the s.env.RegisterDelayedCallback function does not actually wait 10 minutes in the unit test instead the cadence test framework uses an internal clock which knows which event is the next, and executes it -immediately.

    +immediately.

    \ No newline at end of file diff --git a/docs/go-client/workflow-testing.html.html b/docs/go-client/workflow-testing.html.html index 6497692e9..418e52365 100644 --- a/docs/go-client/workflow-testing.html.html +++ b/docs/go-client/workflow-testing.html.html @@ -2,10 +2,10 @@ - - + + \ No newline at end of file diff --git a/docs/go-client/workflow-versioning.html b/docs/go-client/workflow-versioning.html index 605542102..513f65d64 100644 --- a/docs/go-client/workflow-versioning.html +++ b/docs/go-client/workflow-versioning.html @@ -3,8 +3,8 @@ -Versioning | Cadence - +Versioning | Cadence + @@ -15,14 +15,14 @@ - - - + + + -

    Versioning

    +

    Versioning

    The definition code of a Cadence workflow must be deterministic because Cadence uses event sourcing to reconstruct the workflow state by replaying the saved history event data on the workflow definition code. This means that any incompatible update to the workflow definition code could cause @@ -104,6 +104,6 @@

    Sanity check too restricted and harder to maintain the workflow code. For example, if you move your activity code from one package to another package, that changes the ActivityType, which technically becomes a different activity. But, we don't want to fail on that change, so we only check the function name part of the -ActivityType.

    +ActivityType.

    \ No newline at end of file diff --git a/docs/go-client/workflow-versioning.html.html b/docs/go-client/workflow-versioning.html.html index cb4598954..3e483d123 100644 --- a/docs/go-client/workflow-versioning.html.html +++ b/docs/go-client/workflow-versioning.html.html @@ -2,10 +2,10 @@ - - + + \ No newline at end of file diff --git a/docs/java-client.html b/docs/java-client.html index bfa710c6d..d40b835bb 100644 --- a/docs/java-client.html +++ b/docs/java-client.html @@ -3,8 +3,8 @@ -Introduction | Cadence - +Introduction | Cadence + @@ -15,14 +15,14 @@ - - - + + + -

    Java client Java Client Release

    +

    Java client Java Client Release

    The following are important links for the Cadence Java client:

    • GitHub project: https://github.com/cadence-workflow/cadence-java-client
    • @@ -35,6 +35,6 @@
          dependencies {
      implementation group: 'com.uber.cadence', name: 'cadence-client', version: 'LATEST.RELEASE.VERSION'
      }

      If you are using gradle 6.9 or older, you can use compile group

          dependencies {
      compile group: 'com.uber.cadence', name: 'cadence-client', version: 'LATEST.RELEASE.VERSION'
      }
      -

      Release versions are available in the release page

    +

    Release versions are available in the release page

    \ No newline at end of file diff --git a/docs/java-client.html.html b/docs/java-client.html.html index b9e20bb14..17a1c91e3 100644 --- a/docs/java-client.html.html +++ b/docs/java-client.html.html @@ -2,10 +2,10 @@ - - + + \ No newline at end of file diff --git a/docs/java-client/activity-interface.html b/docs/java-client/activity-interface.html index 9bba77466..099f00baf 100644 --- a/docs/java-client/activity-interface.html +++ b/docs/java-client/activity-interface.html @@ -3,8 +3,8 @@ -Activity interface | Cadence - +Activity interface | Cadence + @@ -15,14 +15,14 @@ - - - + + + -

    Activity interface

    +

    Activity interface

    An activity is a manifestation of a particular task in the business logic.

    Activities are defined as methods of a plain Java interface. Each method defines a single activity type. A single workflow can use more than one activity interface and call more than one activity method from the same interface. @@ -34,6 +34,6 @@

    We recommend to use a single value type argument for activity methods. In this way, adding new arguments as fields to the value type is a backwards-compatible change.

    An optional @ActivityMethod annotation can be used to specify activity options like timeouts or a task_list. Required options -that are not specified through the annotation must be specified at runtime.

    +that are not specified through the annotation must be specified at runtime.

    \ No newline at end of file diff --git a/docs/java-client/activity-interface.html.html b/docs/java-client/activity-interface.html.html index 793cc9ef5..80c16d253 100644 --- a/docs/java-client/activity-interface.html.html +++ b/docs/java-client/activity-interface.html.html @@ -2,10 +2,10 @@ - - + + \ No newline at end of file diff --git a/docs/java-client/child-workflows.html b/docs/java-client/child-workflows.html index ae954b3ba..21d345910 100644 --- a/docs/java-client/child-workflows.html +++ b/docs/java-client/child-workflows.html @@ -3,8 +3,8 @@ -Child workflows | Cadence - +Child workflows | Cadence + @@ -15,14 +15,14 @@ - - - + + + -

    Child workflows

    +

    Child workflows

    Besides activities, a workflow can also orchestrate other workflows.

    workflow.ExecuteChildWorkflow enables the scheduling of other workflows from within a workflow's implementation. The parent workflow has the ability to monitor and impact the lifecycle of the child @@ -41,6 +41,6 @@

    public static class GreetingWorkflowImpl implements GreetingWorkflow {

    @Override
    public String getGreeting(String name) {

    // Workflows are stateful, so a new stub must be created for each new child.
    GreetingChild child1 = Workflow.newChildWorkflowStub(GreetingChild.class);
    Promise<String> greeting1 = Async.function(child1::composeGreeting, "Hello", name);

    // Both children will run concurrently.
    GreetingChild child2 = Workflow.newChildWorkflowStub(GreetingChild.class);
    Promise<String> greeting2 = Async.function(child2::composeGreeting, "Bye", name);

    // Do something else here.
    ...
    return "First: " + greeting1.get() + ", second: " + greeting2.get();
    }
    }

    To send a signal to a child, call a method annotated with @SignalMethod:

    public interface GreetingChild {
    @WorkflowMethod
    String composeGreeting(String greeting, String name);

    @SignalMethod
    void updateName(String name);
    }

    public static class GreetingWorkflowImpl implements GreetingWorkflow {

    @Override
    public String getGreeting(String name) {
    GreetingChild child = Workflow.newChildWorkflowStub(GreetingChild.class);
    Promise<String> greeting = Async.function(child::composeGreeting, "Hello", name);
    child.updateName("Cadence");
    return greeting.get();
    }
    }
    -

    Calling methods annotated with @QueryMethod is not allowed from within workflow code.

    +

    Calling methods annotated with @QueryMethod is not allowed from within workflow code.

    \ No newline at end of file diff --git a/docs/java-client/child-workflows.html.html b/docs/java-client/child-workflows.html.html index 4dfaf1078..fa1b0936b 100644 --- a/docs/java-client/child-workflows.html.html +++ b/docs/java-client/child-workflows.html.html @@ -2,10 +2,10 @@ - - + + \ No newline at end of file diff --git a/docs/java-client/client-overview.html b/docs/java-client/client-overview.html index f34abb121..5a3f12566 100644 --- a/docs/java-client/client-overview.html +++ b/docs/java-client/client-overview.html @@ -3,8 +3,8 @@ -Client SDK Overview | Cadence - +Client SDK Overview | Cadence + @@ -15,14 +15,14 @@ - - - + + + -

    Client SDK Overview

    + +it. This assumes that FileProcessingWorker has a worker running on the same task list.

    \ No newline at end of file diff --git a/docs/java-client/client-overview.html.html b/docs/java-client/client-overview.html.html index 32f7f4812..a77974d8c 100644 --- a/docs/java-client/client-overview.html.html +++ b/docs/java-client/client-overview.html.html @@ -2,10 +2,10 @@ - - + + \ No newline at end of file diff --git a/docs/java-client/continue-as-new.html b/docs/java-client/continue-as-new.html index 2e905b0d5..39ee63566 100644 --- a/docs/java-client/continue-as-new.html +++ b/docs/java-client/continue-as-new.html @@ -3,8 +3,8 @@ -Continue As New | Cadence - +Continue As New | Cadence + @@ -15,14 +15,14 @@ - - - + + + -

    Continue as new

    +

    Continue as new

    Workflows that need to rerun periodically could naively be implemented as a big for loop with a sleep where the entire logic of the workflow is inside the body of the for loop. The problem with this approach is that the history for that workflow will keep growing to a point where it @@ -32,6 +32,6 @@ risk of failures down the road. The operation atomically completes the current execution and starts a new execution of the workflow with the same workflow_ID. The new execution will not carry over any history from the old execution.

    -
    @Override
    public void greet(String name) {
    activities.greet("Hello " + name + "!");
    Workflow.continueAsNew(name);
    }

    +
    @Override
    public void greet(String name) {
    activities.greet("Hello " + name + "!");
    Workflow.continueAsNew(name);
    }

    \ No newline at end of file diff --git a/docs/java-client/continue-as-new.html.html b/docs/java-client/continue-as-new.html.html index c1cf4c085..e57b194a2 100644 --- a/docs/java-client/continue-as-new.html.html +++ b/docs/java-client/continue-as-new.html.html @@ -2,10 +2,10 @@ - - + + \ No newline at end of file diff --git a/docs/java-client/distributed-cron.html b/docs/java-client/distributed-cron.html index 6f92db680..c5ef14622 100644 --- a/docs/java-client/distributed-cron.html +++ b/docs/java-client/distributed-cron.html @@ -3,8 +3,8 @@ -Distributed CRON | Cadence - +Distributed CRON | Cadence + @@ -15,14 +15,14 @@ - - - + + + -

    Distributed CRON

    + +the result from first day's run using these APIs.

    \ No newline at end of file diff --git a/docs/java-client/distributed-cron.html.html b/docs/java-client/distributed-cron.html.html index ab6a13460..29d46c07a 100644 --- a/docs/java-client/distributed-cron.html.html +++ b/docs/java-client/distributed-cron.html.html @@ -2,10 +2,10 @@ - - + + \ No newline at end of file diff --git a/docs/java-client/exception-handling.html b/docs/java-client/exception-handling.html index ceddb7305..289371fac 100644 --- a/docs/java-client/exception-handling.html +++ b/docs/java-client/exception-handling.html @@ -3,8 +3,8 @@ -Exception Handling | Cadence - +Exception Handling | Cadence + @@ -15,14 +15,14 @@ - - - + + + -

    Exception Handling

    +

    Exception Handling

    By default, Exceptions thrown by an activity are received by the workflow wrapped into an com.uber.cadence.workflow.ActivityFailureException,

    Exceptions thrown by a child workflow are received by a parent workflow wrapped into a com.uber.cadence.workflow.ChildWorkflowFailureException

    Exceptions thrown by a workflow are received by a workflow client wrapped into com.uber.cadence.client.WorkflowFailureException.

    @@ -40,6 +40,6 @@ besides being wrapped when rethrown.

    public class HelloException {

    static final String TASK_LIST = "HelloException";

    public interface GreetingWorkflow {
    @WorkflowMethod
    String getGreeting(String name);
    }

    public interface GreetingChild {
    @WorkflowMethod
    String composeGreeting(String greeting, String name);
    }

    public interface GreetingActivities {
    String composeGreeting(String greeting, String name);
    }

    /** Parent implementation that calls GreetingChild#composeGreeting.**/
    public static class GreetingWorkflowImpl implements GreetingWorkflow {

    @Override
    public String getGreeting(String name) {
    GreetingChild child = Workflow.newChildWorkflowStub(GreetingChild.class);
    return child.composeGreeting("Hello", name);
    }
    }

    /** Child workflow implementation.**/
    public static class GreetingChildImpl implements GreetingChild {
    private final GreetingActivities activities =
    Workflow.newActivityStub(
    GreetingActivities.class,
    new ActivityOptions.Builder()
    .setScheduleToCloseTimeout(Duration.ofSeconds(10))
    .build());

    @Override
    public String composeGreeting(String greeting, String name) {
    return activities.composeGreeting(greeting, name);
    }
    }

    static class GreetingActivitiesImpl implements GreetingActivities {
    @Override
    public String composeGreeting(String greeting, String name) {
    try {
    throw new IOException(greeting + " " + name + "!");
    } catch (IOException e) {
    // Wrapping the exception as checked exceptions in activity and workflow interface methods
    // are prohibited.
    // It will be unwrapped and attached as a cause to the ActivityFailureException.
    throw Workflow.wrap(e);
    }
    }
    }

    public static void main(String[] args) {
    // Get a new client
    // NOTE: to set a different options, you can do like this:
    // ClientOptions.newBuilder().setRpcTimeout(5 * 1000).build();
    WorkflowClient workflowClient =
    WorkflowClient.newInstance(
    new WorkflowServiceTChannel(ClientOptions.defaultInstance()),
    WorkflowClientOptions.newBuilder().setDomain(DOMAIN).build());
    // Get worker to poll the task list.
    WorkerFactory factory = WorkerFactory.newInstance(workflowClient);
    Worker worker = factory.newWorker(TASK_LIST);
    worker.registerWorkflowImplementationTypes(GreetingWorkflowImpl.class, GreetingChildImpl.class);
    worker.registerActivitiesImplementations(new GreetingActivitiesImpl());
    factory.start();

    WorkflowOptions workflowOptions =
    new WorkflowOptions.Builder()
    .setTaskList(TASK_LIST)
    .setExecutionStartToCloseTimeout(Duration.ofSeconds(30))
    .build();
    GreetingWorkflow workflow =
    workflowClient.newWorkflowStub(GreetingWorkflow.class, workflowOptions);
    try {
    workflow.getGreeting("World");
    throw new IllegalStateException("unreachable");
    } catch (WorkflowException e) {
    Throwable cause = Throwables.getRootCause(e);
    // prints "Hello World!"
    System.out.println(cause.getMessage());
    System.out.println("\nStack Trace:\n" + Throwables.getStackTraceAsString(e));
    }
    System.exit(0);
    }

    }

    The code is slightly different if you are using client version prior to 3.0.0:

    -
    public static void main(String[] args) {
    Worker.Factory factory = new Worker.Factory(DOMAIN);
    Worker worker = factory.newWorker(TASK_LIST);
    worker.registerWorkflowImplementationTypes(GreetingWorkflowImpl.class, GreetingChildImpl.class);
    worker.registerActivitiesImplementations(new GreetingActivitiesImpl());
    factory.start();

    WorkflowClient workflowClient = WorkflowClient.newInstance(DOMAIN);
    WorkflowOptions workflowOptions =
    new WorkflowOptions.Builder()
    .setTaskList(TASK_LIST)
    .setExecutionStartToCloseTimeout(Duration.ofSeconds(30))
    .build();
    GreetingWorkflow workflow =
    workflowClient.newWorkflowStub(GreetingWorkflow.class, workflowOptions);
    try {
    workflow.getGreeting("World");
    throw new IllegalStateException("unreachable");
    } catch (WorkflowException e) {
    Throwable cause = Throwables.getRootCause(e);
    // prints "Hello World!"
    System.out.println(cause.getMessage());
    System.out.println("\nStack Trace:\n" + Throwables.getStackTraceAsString(e));
    }
    System.exit(0);
    }
    +
    public static void main(String[] args) {
    Worker.Factory factory = new Worker.Factory(DOMAIN);
    Worker worker = factory.newWorker(TASK_LIST);
    worker.registerWorkflowImplementationTypes(GreetingWorkflowImpl.class, GreetingChildImpl.class);
    worker.registerActivitiesImplementations(new GreetingActivitiesImpl());
    factory.start();

    WorkflowClient workflowClient = WorkflowClient.newInstance(DOMAIN);
    WorkflowOptions workflowOptions =
    new WorkflowOptions.Builder()
    .setTaskList(TASK_LIST)
    .setExecutionStartToCloseTimeout(Duration.ofSeconds(30))
    .build();
    GreetingWorkflow workflow =
    workflowClient.newWorkflowStub(GreetingWorkflow.class, workflowOptions);
    try {
    workflow.getGreeting("World");
    throw new IllegalStateException("unreachable");
    } catch (WorkflowException e) {
    Throwable cause = Throwables.getRootCause(e);
    // prints "Hello World!"
    System.out.println(cause.getMessage());
    System.out.println("\nStack Trace:\n" + Throwables.getStackTraceAsString(e));
    }
    System.exit(0);
    }
    \ No newline at end of file diff --git a/docs/java-client/exception-handling.html.html b/docs/java-client/exception-handling.html.html index f28b45c60..e63373a12 100644 --- a/docs/java-client/exception-handling.html.html +++ b/docs/java-client/exception-handling.html.html @@ -2,10 +2,10 @@ - - + + \ No newline at end of file diff --git a/docs/java-client/implementing-activities.html b/docs/java-client/implementing-activities.html index 6972cab26..b2a832e70 100644 --- a/docs/java-client/implementing-activities.html +++ b/docs/java-client/implementing-activities.html @@ -3,8 +3,8 @@ -Implementing activities | Cadence - +Implementing activities | Cadence + @@ -15,14 +15,14 @@ - - - + + + -

    Implementing activities

    +

    Implementing activities

    Activity implementation is an implementation of an activity interface. A single instance of the activities implementation is shared across multiple simultaneous activity invocations. Therefore, the activity implementation code must be thread safe.

    The values passed to activities through invocation parameters or returned through a result value are recorded in the execution history. @@ -49,6 +49,6 @@

    Activ details on an activity heartbeat. If an activity times out, the last value of details is included in the ActivityTimeoutException delivered to a workflow. Then the workflow can pass the details to the next activity invocation. This acts as a periodic checkpoint mechanism for the progress of an activity.

    -
    public class FileProcessingActivitiesImpl implements FileProcessingActivities {

    @Override
    public String download(String bucketName, String remoteName, String localName) {
    InputStream inputStream = openInputStream(file);
    try {
    byte[] bytes = new byte[MAX_BUFFER_SIZE];
    while ((read = inputStream.read(bytes)) != -1) {
    totalRead += read;
    f.write(bytes, 0, read);
    /*
    * Let the service know about the download progress.
    */
    Activity.heartbeat(totalRead);
    }
    } finally {
    inputStream.close();
    }
    }
    ...
    }

    +
    public class FileProcessingActivitiesImpl implements FileProcessingActivities {

    @Override
    public String download(String bucketName, String remoteName, String localName) {
    InputStream inputStream = openInputStream(file);
    try {
    byte[] bytes = new byte[MAX_BUFFER_SIZE];
    while ((read = inputStream.read(bytes)) != -1) {
    totalRead += read;
    f.write(bytes, 0, read);
    /*
    * Let the service know about the download progress.
    */
    Activity.heartbeat(totalRead);
    }
    } finally {
    inputStream.close();
    }
    }
    ...
    }
    \ No newline at end of file diff --git a/docs/java-client/implementing-activities.html.html b/docs/java-client/implementing-activities.html.html index 48fc0b01e..9ec0e07af 100644 --- a/docs/java-client/implementing-activities.html.html +++ b/docs/java-client/implementing-activities.html.html @@ -2,10 +2,10 @@ - - + + \ No newline at end of file diff --git a/docs/java-client/implementing-workflows.html b/docs/java-client/implementing-workflows.html index 72cfb583d..be554da36 100644 --- a/docs/java-client/implementing-workflows.html +++ b/docs/java-client/implementing-workflows.html @@ -3,8 +3,8 @@ -Implementing workflows | Cadence - +Implementing workflows | Cadence + @@ -15,14 +15,14 @@ - - - + + + -

    Implementing workflows

    + +Otherwise, no additional limitations exist on activity implementations.

    \ No newline at end of file diff --git a/docs/java-client/implementing-workflows.html.html b/docs/java-client/implementing-workflows.html.html index 2ca4f9567..e932db3b6 100644 --- a/docs/java-client/implementing-workflows.html.html +++ b/docs/java-client/implementing-workflows.html.html @@ -2,10 +2,10 @@ - - + + \ No newline at end of file diff --git a/docs/java-client/queries.html b/docs/java-client/queries.html index 9b1456f97..028b9bf36 100644 --- a/docs/java-client/queries.html +++ b/docs/java-client/queries.html @@ -3,8 +3,8 @@ -Queries | Cadence - +Queries | Cadence + @@ -15,14 +15,14 @@ - - - + + + -

    Queries

    +

    Queries

    Query is to expose this internal state to the external world Cadence provides a synchronous query feature. From the workflow implementer point of view the query is exposed as a synchronous callback that is invoked by external entities. Multiple such callbacks can be provided per workflow type exposing different information to different external systems.

    Query callbacks must be read-only not mutating the workflow state in any way. The other limitation is that the query callback cannot contain any blocking code. Both above limitations rule out ability to invoke activities from the query handlers.

    Built-in Query: Stack Trace

    @@ -54,7 +54,7 @@

    cadence: docker run --network=host --rm ubercadence/cli:master --do test-domain workflow signal --workflow_id "HelloQuery" --name "HelloWorld::updateGreeting" --input \"Bye\"
    Signal workflow succeeded.
    cadence: docker run --network=host --rm ubercadence/cli:master --do test-domain workflow query --workflow_id "HelloQuery" --query_type "HelloWorld::getCount"
    :query:Query: result as JSON:
    4

    The Query method can accept parameters. This might be useful if only part of the workflow state should be returned.

    Run Query from external application code

    -

    The WorkflowStub without WorkflowOptions is for signal or query

    +

    The WorkflowStub without WorkflowOptions is for signal or query

    Consistent Query

    Query has two consistency levels, eventual and strong. Consider if you were to signal a workflow and then immediately query the

    @@ -70,6 +70,6 @@

    Consistent

    In order to run consistent query through the CLI do the following:

    cadence-cli --domain samples-domain workflow query -w my_workflow_id -r my_run_id -qt current_state --qcl strong

    In order to run a query using application code, you need to use service client.

    -

    When using strongly consistent query you should expect higher latency than eventually consistent query.

    +

    When using strongly consistent query you should expect higher latency than eventually consistent query.

    \ No newline at end of file diff --git a/docs/java-client/queries.html.html b/docs/java-client/queries.html.html index d9181b968..d4ad11e33 100644 --- a/docs/java-client/queries.html.html +++ b/docs/java-client/queries.html.html @@ -2,10 +2,10 @@ - - + + \ No newline at end of file diff --git a/docs/java-client/retries.html b/docs/java-client/retries.html index 54bf6b5f4..330bebfa1 100644 --- a/docs/java-client/retries.html +++ b/docs/java-client/retries.html @@ -3,8 +3,8 @@ -Retries | Cadence - +Retries | Cadence + @@ -15,14 +15,14 @@ - - - + + + -

    Activity and workflow retries

    + +

    Since ExpirationInterval is always there, and in fact it's more useful. And I think it's quite confusing to use MaximumAttempts, so I would recommend just use ExpirationInterval. Unless you really need it.

    \ No newline at end of file diff --git a/docs/java-client/retries.html.html b/docs/java-client/retries.html.html index 7a6f7602e..9b4917e56 100644 --- a/docs/java-client/retries.html.html +++ b/docs/java-client/retries.html.html @@ -2,10 +2,10 @@ - - + + \ No newline at end of file diff --git a/docs/java-client/side-effect.html b/docs/java-client/side-effect.html index 8315385dd..788a98d2c 100644 --- a/docs/java-client/side-effect.html +++ b/docs/java-client/side-effect.html @@ -3,8 +3,8 @@ -Side Effect | Cadence - +Side Effect | Cadence + @@ -15,14 +15,14 @@ - - - + + + -

    Side Effect

    +

    Side Effect

    Side Effect allow workflow executes the provided function once, records its result into the workflow history. The recorded result on history will be returned without executing the provided function during replay. This guarantees the deterministic requirement for workflow as the exact same result will be returned @@ -55,6 +55,6 @@

    Mutable

    !!Caution: do not use mutableSideEffect function to modify any workflow sate. Only use the mutableSideEffect's return value.

    If function throws any exception it is not delivered to the workflow code. It is wrapped in -an Error causing failure of the current decision.

    +an Error causing failure of the current decision.

    \ No newline at end of file diff --git a/docs/java-client/side-effect.html.html b/docs/java-client/side-effect.html.html index 18b9b0a27..65b7b8e71 100644 --- a/docs/java-client/side-effect.html.html +++ b/docs/java-client/side-effect.html.html @@ -2,10 +2,10 @@ - - + + \ No newline at end of file diff --git a/docs/java-client/signals.html b/docs/java-client/signals.html index e00e3a566..bc4a72599 100644 --- a/docs/java-client/signals.html +++ b/docs/java-client/signals.html @@ -3,8 +3,8 @@ -Signals | Cadence - +Signals | Cadence + @@ -15,14 +15,14 @@ - - - + + + -

    Signals

    + +

    The WorkflowStub without WorkflowOptions is for signal or query

    \ No newline at end of file diff --git a/docs/java-client/signals.html.html b/docs/java-client/signals.html.html index 3620f4ad7..c1c690f83 100644 --- a/docs/java-client/signals.html.html +++ b/docs/java-client/signals.html.html @@ -2,10 +2,10 @@ - - + + \ No newline at end of file diff --git a/docs/java-client/starting-workflow-executions.html b/docs/java-client/starting-workflow-executions.html index d34c357bc..ba6a61df0 100644 --- a/docs/java-client/starting-workflow-executions.html +++ b/docs/java-client/starting-workflow-executions.html @@ -3,8 +3,8 @@ -Starting workflows | Cadence - +Starting workflows | Cadence + @@ -15,14 +15,14 @@ - - - + + + -

    Starting workflow executions

    +

    Starting workflow executions

    Creating a WorkflowClient

    A workflow interface that executes a workflow requires initializing a WorkflowClient instance, creating a client side stub to the workflow, and then calling a method annotated with @WorkflowMethod.

    @@ -48,6 +48,6 @@

    Executin of throwing DuplicateWorkflowException, it reconnects to an existing workflow and waits for its completion. The following example shows how to do this from a different process than the one that started the workflow. All this process needs is a WorkflowID.

    -
    WorkflowExecution execution = new WorkflowExecution().setWorkflowId(workflowId);
    FileProcessingWorkflow workflow = workflowClient.newWorkflowStub(execution);
    // Returns result potentially waiting for workflow to complete.
    String result = workflow.processFile(workflowArgs);

    +
    WorkflowExecution execution = new WorkflowExecution().setWorkflowId(workflowId);
    FileProcessingWorkflow workflow = workflowClient.newWorkflowStub(execution);
    // Returns result potentially waiting for workflow to complete.
    String result = workflow.processFile(workflowArgs);
    \ No newline at end of file diff --git a/docs/java-client/starting-workflow-executions.html.html b/docs/java-client/starting-workflow-executions.html.html index e80047bf2..aeb3671b1 100644 --- a/docs/java-client/starting-workflow-executions.html.html +++ b/docs/java-client/starting-workflow-executions.html.html @@ -2,10 +2,10 @@ - - + + \ No newline at end of file diff --git a/docs/java-client/testing.html b/docs/java-client/testing.html index 8e5b07374..b58861a47 100644 --- a/docs/java-client/testing.html +++ b/docs/java-client/testing.html @@ -3,8 +3,8 @@ -Testing | Cadence - +Testing | Cadence + @@ -15,14 +15,14 @@ - - - + + + -

    Activity Test Environment

    +

    Activity Test Environment

    TestActivityEnvironment is the helper class for unit testing activity implementations. Supports calls to Activity methods from the tested activities. An example test:

    See full example here.


    public interface TestActivity {
    String activity1(String input);
    }

    private static class ActivityImpl implements TestActivity {
    @Override
    public String activity1(String input) {
    return Activity.getTask().getActivityType().getName() + "-" + input;
    }
    }

    @Test
    public void testSuccess() {
    testEnvironment.registerActivitiesImplementations(new ActivityImpl());
    TestActivity activity = testEnvironment.newActivityStub(TestActivity.class);
    String result = activity.activity1("input1");
    assertEquals("TestActivity::activity1-input1", result);
    }

    @@ -30,6 +30,6 @@

    Wo

    TestWorkflowEnvironment provides workflow unit testing capabilities.

    Testing the workflow code is hard as it might be potentially very long running. The included in-memory implementation of the Cadence service supports an automatic time skipping. Anytime a workflow under the test as well as the unit test code are waiting on a timer (or sleep) the internal service time is automatically advanced to the nearest time that unblocks one of the waiting threads. This way a workflow that runs in production for months is unit tested in milliseconds. Here is an example of a test that executes in a few milliseconds instead of over two hours that are needed for the workflow to complete.

    See full example here.

    -
    public class SignaledWorkflowImpl implements SignaledWorkflow {
    private String signalInput;

    @Override
    public String workflow1(String input) {
    Workflow.sleep(Duration.ofHours(1));
    Workflow.await(() -> signalInput != null);
    Workflow.sleep(Duration.ofHours(1));
    return signalInput + "-" + input;
    }

    @Override
    public void processSignal(String input) {
    signalInput = input;
    }
    }

    @Test
    public void testSignal() throws ExecutionException, InterruptedException {
    // Get a workflow stub using the same task list the worker uses.
    WorkflowOptions workflowOptions =
    new WorkflowOptions.Builder()
    .setTaskList(HelloSignal.TASK_LIST)
    .setExecutionStartToCloseTimeout(Duration.ofDays(30))
    .build();
    GreetingWorkflow workflow =
    workflowClient.newWorkflowStub(GreetingWorkflow.class, workflowOptions);

    // Start workflow asynchronously to not use another thread to signal.
    WorkflowClient.start(workflow::getGreetings);

    // After start for getGreeting returns, the workflow is guaranteed to be started.
    // So we can send a signal to it using workflow stub immediately.
    // But just to demonstrate the unit testing of a long running workflow adding a long sleep here.
    testEnv.sleep(Duration.ofDays(1));
    // This workflow keeps receiving signals until exit is called
    workflow.waitForName("World");
    workflow.waitForName("Universe");
    workflow.exit();
    // Calling synchronous getGreeting after workflow has started reconnects to the existing
    // workflow and
    // blocks until result is available. Note that this behavior assumes that WorkflowOptions are
    // not configured
    // with WorkflowIdReusePolicy.AllowDuplicate. In that case the call would fail with
    // WorkflowExecutionAlreadyStartedException.
    List<String> greetings = workflow.getGreetings();
    assertEquals(2, greetings.size());
    assertEquals("Hello World!", greetings.get(0));
    assertEquals("Hello Universe!", greetings.get(1));
    }

    +
    public class SignaledWorkflowImpl implements SignaledWorkflow {
    private String signalInput;

    @Override
    public String workflow1(String input) {
    Workflow.sleep(Duration.ofHours(1));
    Workflow.await(() -> signalInput != null);
    Workflow.sleep(Duration.ofHours(1));
    return signalInput + "-" + input;
    }

    @Override
    public void processSignal(String input) {
    signalInput = input;
    }
    }

    @Test
    public void testSignal() throws ExecutionException, InterruptedException {
    // Get a workflow stub using the same task list the worker uses.
    WorkflowOptions workflowOptions =
    new WorkflowOptions.Builder()
    .setTaskList(HelloSignal.TASK_LIST)
    .setExecutionStartToCloseTimeout(Duration.ofDays(30))
    .build();
    GreetingWorkflow workflow =
    workflowClient.newWorkflowStub(GreetingWorkflow.class, workflowOptions);

    // Start workflow asynchronously to not use another thread to signal.
    WorkflowClient.start(workflow::getGreetings);

    // After start for getGreeting returns, the workflow is guaranteed to be started.
    // So we can send a signal to it using workflow stub immediately.
    // But just to demonstrate the unit testing of a long running workflow adding a long sleep here.
    testEnv.sleep(Duration.ofDays(1));
    // This workflow keeps receiving signals until exit is called
    workflow.waitForName("World");
    workflow.waitForName("Universe");
    workflow.exit();
    // Calling synchronous getGreeting after workflow has started reconnects to the existing
    // workflow and
    // blocks until result is available. Note that this behavior assumes that WorkflowOptions are
    // not configured
    // with WorkflowIdReusePolicy.AllowDuplicate. In that case the call would fail with
    // WorkflowExecutionAlreadyStartedException.
    List<String> greetings = workflow.getGreetings();
    assertEquals(2, greetings.size());
    assertEquals("Hello World!", greetings.get(0));
    assertEquals("Hello Universe!", greetings.get(1));
    }
    \ No newline at end of file diff --git a/docs/java-client/testing.html.html b/docs/java-client/testing.html.html index 19ce1576d..2f42b3257 100644 --- a/docs/java-client/testing.html.html +++ b/docs/java-client/testing.html.html @@ -2,10 +2,10 @@ - - + + \ No newline at end of file diff --git a/docs/java-client/versioning.html b/docs/java-client/versioning.html index 65eb3ea9f..12a362ae1 100644 --- a/docs/java-client/versioning.html +++ b/docs/java-client/versioning.html @@ -3,8 +3,8 @@ -Versioning | Cadence - +Versioning | Cadence + @@ -15,14 +15,14 @@ - - - + + + -

    Versioning

    +

    Versioning

    As outlined in the Workflow Implementation Constraints section, workflow code has to be deterministic by taking the same code path when replaying history events. Any workflow code change that affects the order in which decisions are generated breaks this assumption. The solution that allows updating code of already running workflows is to keep both the old and new code. @@ -38,6 +38,6 @@

    public void processFile(Arguments args) {
    String localName = null;
    String processedName = null;
    try {
    localName = activities.download(args.getSourceBucketName(), args.getSourceFilename());
    processedName = activities.processFile(localName);
    // getVersion call is left here to ensure that any attempt to replay history
    // for a different version fails. It can be removed later when there is no possibility
    // of this happening.
    Workflow.getVersion("checksumAdded", 1, 1);
    long checksum = activities.calculateChecksum(processedName);
    activities.uploadWithChecksum(
    args.getTargetBucketName(), args.getTargetFilename(), processedName, checksum);
    } finally {
    if (localName != null) { // File was downloaded.
    activities.deleteLocalFile(localName);
    }
    if (processedName != null) { // File was processed.
    activities.deleteLocalFile(processedName);
    }
    }
    }

    The ID that is passed to the getVersion call identifies the change. Each change is expected to have its own ID. But if a change spawns multiple places in the workflow code and the new code should be either executed in all of them or -in none of them, then they have to share the ID.

    +in none of them, then they have to share the ID.

    \ No newline at end of file diff --git a/docs/java-client/versioning.html.html b/docs/java-client/versioning.html.html index f23089ffc..0bee61ff3 100644 --- a/docs/java-client/versioning.html.html +++ b/docs/java-client/versioning.html.html @@ -2,10 +2,10 @@ - - + + \ No newline at end of file diff --git a/docs/java-client/workers.html b/docs/java-client/workers.html index 987d1a879..ca549b962 100644 --- a/docs/java-client/workers.html +++ b/docs/java-client/workers.html @@ -3,8 +3,8 @@ -Worker service | Cadence - +Worker service | Cadence + @@ -15,20 +15,20 @@ - - - + + + -

    Worker service

    +

    Worker service

    A worker or worker service is a service that hosts the workflow and activity implementations. The worker polls the Cadence service for tasks, performs those tasks, and communicates task execution results back to the Cadence service. Worker services are developed, deployed, and operated by Cadence customers.

    You can run a Cadence worker in a new or an existing service. Use the framework APIs to start the Cadence worker and link in all activity and workflow implementations that you require the service to execute.

      WorkerFactory factory = WorkerFactory.newInstance(workflowClient,
    WorkerFactoryOptions.newBuilder()
    .setMaxWorkflowThreadCount(1000)
    .setStickyCacheSize(100)
    .setDisableStickyExecution(false)
    .build());
    Worker worker = factory.newWorker(TASK_LIST,
    WorkerOptions.newBuilder()
    .setMaxConcurrentActivityExecutionSize(100)
    .setMaxConcurrentWorkflowExecutionSize(100)
    .build());

    // Workflows are stateful. So you need a type to create instances.
    worker.registerWorkflowImplementationTypes(GreetingWorkflowImpl.class);
    // Activities are stateless and thread safe. So a shared instance is used.
    worker.registerActivitiesImplementations(new GreetingActivitiesImpl());
    // Start listening to the workflow and activity task lists.
    factory.start();

    The code is slightly different if you are using client version prior to 3.0.0:

    Worker.Factory factory = new Worker.Factory(DOMAIN,
    new Worker.FactoryOptions.Builder()
    .setMaxWorkflowThreadCount(1000)
    .setCacheMaximumSize(100)
    .setDisableStickyExecution(false)
    .build());
    Worker worker = factory.newWorker(TASK_LIST,
    new WorkerOptions.Builder()
    .setMaxConcurrentActivityExecutionSize(100)
    .setMaxConcurrentWorkflowExecutionSize(100)
    .build());
    // Workflows are stateful. So you need a type to create instances.
    worker.registerWorkflowImplementationTypes(GreetingWorkflowImpl.class);
    // Activities are stateless and thread safe. So a shared instance is used.
    worker.registerActivitiesImplementations(new GreetingActivitiesImpl());
    // Start listening to the workflow and activity task lists.
    factory.start();

    The WorkerFactoryOptions includes those that need to be shared across workers on the hosts like thread pool, sticky cache.

    -

    In WorkerOptions you can customize things like pollerOptions, activities per second.

    +

    In WorkerOptions you can customize things like pollerOptions, activities per second.

    \ No newline at end of file diff --git a/docs/java-client/workers.html.html b/docs/java-client/workers.html.html index 4056b1328..758ddfd78 100644 --- a/docs/java-client/workers.html.html +++ b/docs/java-client/workers.html.html @@ -2,10 +2,10 @@ - - + + \ No newline at end of file diff --git a/docs/java-client/workflow-interface.html b/docs/java-client/workflow-interface.html index c52a2fa75..90112c1e9 100644 --- a/docs/java-client/workflow-interface.html +++ b/docs/java-client/workflow-interface.html @@ -3,8 +3,8 @@ -Workflow interface | Cadence - +Workflow interface | Cadence + @@ -15,14 +15,14 @@ - - - + + + -

    Workflow interface

    +

    Workflow interface

    Workflow encapsulates the orchestration of activities and child workflows. It can also answer synchronous queries and receive external events (also known as signals).

    A workflow must define an interface class. All of its methods must have one of the following annotations:

    @@ -34,6 +34,6 @@

    You can have more than one method with the same annotation (except @WorkflowMethod). For example:

    public interface FileProcessingWorkflow {

    @WorkflowMethod(executionStartToCloseTimeoutSeconds = 10, taskList = "file-processing")
    String processFile(Arguments args);

    @QueryMethod(name="history")
    List<String> getHistory();

    @QueryMethod(name="status")
    String getStatus();

    @SignalMethod
    void retryNow();

    @SignalMethod
    void abandon();
    }
    -

    We recommended that you use a single value type argument for workflow methods. In this way, adding new arguments as fields to the value type is a backwards-compatible change.

    +

    We recommended that you use a single value type argument for workflow methods. In this way, adding new arguments as fields to the value type is a backwards-compatible change.

    \ No newline at end of file diff --git a/docs/java-client/workflow-interface.html.html b/docs/java-client/workflow-interface.html.html index 5829f0397..f23f8cc84 100644 --- a/docs/java-client/workflow-interface.html.html +++ b/docs/java-client/workflow-interface.html.html @@ -2,10 +2,10 @@ - - + + \ No newline at end of file diff --git a/docs/java-client/workflow-replay-shadowing.html b/docs/java-client/workflow-replay-shadowing.html index 1165dbf96..9d3881dc9 100644 --- a/docs/java-client/workflow-replay-shadowing.html +++ b/docs/java-client/workflow-replay-shadowing.html @@ -3,8 +3,8 @@ -Workflow Replay and Shadowing | Cadence - +Workflow Replay and Shadowing | Cadence + @@ -15,14 +15,14 @@ - - - + + + -

    Workflow Replay and Shadowing

    +

    Workflow Replay and Shadowing

    In the Versioning section, we mentioned that incompatible changes to workflow definition code could cause non-deterministic issues when processing workflow tasks if versioning is not done correctly. However, it may be hard for you to tell if a particular change is incompatible or not and whether versioning logic is needed. To help you identify incompatible changes and catch them before production traffic is impacted, we implemented Workflow Replayer and Workflow Shadower.

    Workflow Replayer

    Workflow Replayer is a testing component for replaying existing workflow histories against a workflow definition. The replaying logic is the same as the one used for processing workflow tasks, so if there's any incompatible changes in the workflow definition, the replay test will fail.

    @@ -82,6 +82,6 @@

    Shadowing W

    To enable the shadow mode, you can initialize a shadowing worker and pass in the shadowing options.

    To enable the shadowing worker, here is a example. The example is also available here:

    WorkflowClient workflowClient =
    WorkflowClient.newInstance(
    new WorkflowServiceTChannel(ClientOptions.defaultInstance()),
    WorkflowClientOptions.newBuilder().setDomain(DOMAIN).build());
    ShadowingOptions options = ShadowingOptions
    .newBuilder()
    .setDomain(DOMAIN)
    .setShadowMode(Mode.Normal)
    .setWorkflowTypes(Lists.newArrayList("GreetingWorkflow::getGreeting"))
    .setWorkflowStatuses(Lists.newArrayList(WorkflowStatus.OPEN, WorkflowStatus.CLOSED))
    .setExitCondition(new ExitCondition().setExpirationIntervalInSeconds(60))
    .build();

    ShadowingWorker shadowingWorker = new ShadowingWorker(
    workflowClient,
    "HelloActivity",
    WorkerOptions.defaultInstance(),
    options);
    shadowingWorker.registerWorkflowImplementationTypes(HelloActivity.GreetingWorkflowImpl.class);
    shadowingWorker.start();
    -

    Registered workflows will be forwarded to the underlying WorkflowReplayer. DataConverter, WorkflowInterceptorChainFactories, ContextPropagators, and Tracer specified in the worker.Options will also be used as ReplayOptions. Since all shadow workflows are running in one system domain, to avoid conflict, the actual task list name used will be domain-tasklist.

    +

    Registered workflows will be forwarded to the underlying WorkflowReplayer. DataConverter, WorkflowInterceptorChainFactories, ContextPropagators, and Tracer specified in the worker.Options will also be used as ReplayOptions. Since all shadow workflows are running in one system domain, to avoid conflict, the actual task list name used will be domain-tasklist.

    \ No newline at end of file diff --git a/docs/java-client/workflow-replay-shadowing.html.html b/docs/java-client/workflow-replay-shadowing.html.html index 7d2d72eda..70f9c12c4 100644 --- a/docs/java-client/workflow-replay-shadowing.html.html +++ b/docs/java-client/workflow-replay-shadowing.html.html @@ -2,10 +2,10 @@ - - + + \ No newline at end of file diff --git a/docs/next/resources/index.html b/docs/next/resources/index.html index 3308de34c..1d83d044c 100644 --- a/docs/next/resources/index.html +++ b/docs/next/resources/index.html @@ -2,10 +2,10 @@ - - + + \ No newline at end of file diff --git a/docs/next/support/index.html b/docs/next/support/index.html index ae8781001..7e41f5ee7 100644 --- a/docs/next/support/index.html +++ b/docs/next/support/index.html @@ -2,10 +2,10 @@ - - + + \ No newline at end of file diff --git a/docs/next/team/index.html b/docs/next/team/index.html index 6e9a87742..29c379a88 100644 --- a/docs/next/team/index.html +++ b/docs/next/team/index.html @@ -2,10 +2,10 @@ - - + + \ No newline at end of file diff --git a/docs/operation-guide.html b/docs/operation-guide.html index d7eb84062..25ea40f35 100644 --- a/docs/operation-guide.html +++ b/docs/operation-guide.html @@ -3,8 +3,8 @@ -Overview | Cadence - +Overview | Cadence + @@ -15,14 +15,14 @@ - - - + + + - + \ No newline at end of file diff --git a/docs/operation-guide.html.html b/docs/operation-guide.html.html index 233365d19..66c56da2a 100644 --- a/docs/operation-guide.html.html +++ b/docs/operation-guide.html.html @@ -2,10 +2,10 @@ - - + + \ No newline at end of file diff --git a/docs/operation-guide/maintain.html b/docs/operation-guide/maintain.html index 7fbfdc560..522e2a1c7 100644 --- a/docs/operation-guide/maintain.html +++ b/docs/operation-guide/maintain.html @@ -3,8 +3,8 @@ -Cluster Maintenance | Cadence - +Cluster Maintenance | Cadence + @@ -15,26 +15,26 @@ - - - + + + -

    Cluster Maintenance

    +

    Cluster Maintenance

    This includes how to use and maintain a Cadence cluster for both clients and server clusters.

    Scale up & down Cluster

    Scale up a tasklist using Scalable tasklist feature

    By default a tasklist is not scalable enough to support hundreds of tasks per second. That’s mainly because each tasklist is assigned to a Matching service node, and dispatching tasks in a tasklist is in sequence.

    @@ -50,7 +50,7 @@

    dynamic config. +
  • Both domain names and taskListName should be specified in the dynamic config. An example of using this feature. See more details about dynamic config format using file based dynamic config.
  • matching.numTasklistWritePartitions:
    - value: 10
    constraints:
    domainName: "samples-domain"
    taskListName: "aScalableTasklistName"
    matching.numTasklistReadPartitions:
    - value: 10
    constraints:
    domainName: "samples-domain"
    taskListName: "aScalableTasklistName"

    NOTE: the value must be integer without double quotes.

    @@ -101,6 +101,6 @@

    Versioned Schema Changes for Default Store and Versioned Schema Changes for Visibility Store if you use database for basic visibility instead of ElasticSearch.

    If you use homebrew, the schema files are located at /usr/local/etc/cadence/schema/.

    -

    Alternatively, you can checkout the repo and the release tag. E.g. git checkout v0.21.0 and then the schema files is at ./schema/

    +

    Alternatively, you can checkout the repo and the release tag. E.g. git checkout v0.21.0 and then the schema files is at ./schema/

    \ No newline at end of file diff --git a/docs/operation-guide/maintain.html.html b/docs/operation-guide/maintain.html.html index c838cca55..f675925da 100644 --- a/docs/operation-guide/maintain.html.html +++ b/docs/operation-guide/maintain.html.html @@ -2,10 +2,10 @@ - - + + \ No newline at end of file diff --git a/docs/operation-guide/migration.html b/docs/operation-guide/migration.html index 22bd50f5c..05aa8d850 100644 --- a/docs/operation-guide/migration.html +++ b/docs/operation-guide/migration.html @@ -3,8 +3,8 @@ -Cluster Migration | Cadence - +Cluster Migration | Cadence + @@ -15,14 +15,14 @@ - - - + + + -

    Migrate Cadence cluster.

    +

    Migrate Cadence cluster.

    There could be some reasons that you need to migrate Cadence clusters:

    • Migrate to different storage, for example from Postgres/MySQL to Cassandra, or using multiple SQL database as a sharded SQL cluster for Cadence
    • @@ -43,8 +43,8 @@

      NOTE 2: This is the only way to migrate a local domain, because a local domain cannot be converted to a global domain, even after a cluster enables XDC feature.

      NOTE 3: Starting from version 0.22.0, global domain is preferred/recommended. Please ensure you create and use global domains only. If you are using local domains, an easy way is to create a global domain and migrate to the new global domain using the above steps.

      -

      Migrate with Global Domain Replication feature

      -

      NOTE 1: If a domain are NOT a global domain, you cannot use the XDC feature to migrate. The only way is to migrate in a naive approach

      +

      Migrate with Global Domain Replication feature

      +

      NOTE 1: If a domain are NOT a global domain, you cannot use the XDC feature to migrate. The only way is to migrate in a naive approach

      NOTE 2: Only migrating to the same numHistoryShards is allowed.

      Step 0 - Verify clusters' setup is correct

        @@ -110,7 +110,7 @@

        cadence --address <newClusterAddress> --do <domain_name> workflow show --workflow_id <wfID>

    cadence --address <initialClusterAddress> --do <domain_name> workflow show --workflow_id <wfID>

    Step 3 - Start to replicate all domains

    -

    You can repeat Step 2 for all the domains. Or you can use the managed failover feature to failover all the domains in the cluster with a single command. See more details in the global domain documentation.

    +

    You can repeat Step 2 for all the domains. Or you can use the managed failover feature to failover all the domains in the cluster with a single command. See more details in the global domain documentation.

    Because replication cannot be triggered without a decision. Again best way is to send a garbage signal to all the workflows.

    If advanced visibility is enabled, then use batch signal command to start a batch job to trigger replication for all open workflows:

    cadence --address <initialClusterAddress> --do <domain_name> workflow batch start --batch_type signal --query “CloseTime = missing” --signal_name <anything, e.g. xdcTest> --reason <anything> --input <anything> --yes
    @@ -127,6 +127,6 @@

    +

    Once above is done, you can shutdown the old cluster safely.

    \ No newline at end of file diff --git a/docs/operation-guide/migration.html.html b/docs/operation-guide/migration.html.html index 5130424b5..2ad6aabc0 100644 --- a/docs/operation-guide/migration.html.html +++ b/docs/operation-guide/migration.html.html @@ -2,10 +2,10 @@ - - + + \ No newline at end of file diff --git a/docs/operation-guide/monitoring.html b/docs/operation-guide/monitoring.html index 24199c458..35707dd24 100644 --- a/docs/operation-guide/monitoring.html +++ b/docs/operation-guide/monitoring.html @@ -3,8 +3,8 @@ -Cluster Monitoring | Cadence - +Cluster Monitoring | Cadence + @@ -15,14 +15,14 @@ - - - + + + -

    Cluster Monitoring

    +

    Cluster Monitoring

    Instructions

    Cadence emits metrics for both Server and client libraries:

    Client side dashboard looks like this:

    Screen Shot 2021-02-20 at 12 32 23 PM @@ -475,7 +475,7 @@

    Tra
  • Datadog query example
  • avg:cadence_history.task_latency.quantile{$pXXLatency,operation:transfer*} by {operation}
    avg:cadence_history.task_latency_processing.quantile{$pXXLatency,operation:transfer*} by {operation}
    avg:cadence_history.task_latency_queue.quantile{$pXXLatency,operation:transfer*} by {operation}
    -

    Timer Task Latency by type

    +

    Timer Task Latency by type

    • If latency is too high then it’s an issue for a workflow. For example, if you set the workflow.sleep() for 10 seconds and the timer latency is 5 secs then the workflow will sleep for 15 seconds.
    • Monitor should be set on diffeernt types of latency.
    • @@ -719,6 +719,6 @@

    +
    \ No newline at end of file diff --git a/docs/operation-guide/monitoring.html.html b/docs/operation-guide/monitoring.html.html index 79c5fb4e0..341bd1dfa 100644 --- a/docs/operation-guide/monitoring.html.html +++ b/docs/operation-guide/monitoring.html.html @@ -2,10 +2,10 @@ - - + + \ No newline at end of file diff --git a/docs/operation-guide/setup.html b/docs/operation-guide/setup.html index 6929f9981..3dfd4250f 100644 --- a/docs/operation-guide/setup.html +++ b/docs/operation-guide/setup.html @@ -3,8 +3,8 @@ -Cluster Configuration | Cadence - +Cluster Configuration | Cadence + @@ -15,20 +15,20 @@ - - - + + + -

    Cluster Configuration

    +

    Cluster Configuration

    This section will help to understand what you need for setting up a Cadence cluster.

    You should understand some basic static configuration of Cadence cluster.

    There are also many other configuration called "Dynamic Configuration" for fine tuning the cluster. The default values are good to go for small clusters.

    Cadence’s minimum dependency is a database(Cassandra or SQL based like MySQL/Postgres). Cadence uses it for persistence. All instances of Cadence clusters are stateless.

    For production you also need a metric server(Prometheus/Statsd/M3/etc).

    -

    For advanced features Cadence depends on others like Elastisearch/OpenSearch+Kafka if you need Advanced visibility feature to search workflows. Cadence will depends on a blob store like S3 if you need to enable archival feature.

    +

    For advanced features Cadence depends on others like Elastisearch/OpenSearch+Kafka if you need Advanced visibility feature to search workflows. Cadence will depends on a blob store like S3 if you need to enable archival feature.

    Static configuration

    Configuration Directory and Files

    The default directory for configuration files is named config/. This directory contains various configuration files, but not all files will necessarily be used in every scenario.

    @@ -47,7 +47,7 @@

    Note: If you want to include the $ symbol literally in your configuration file (without interpreting it as an environment variable substitution), escape it by using $$. This will prevent it from being replaced by an environment variable value.

    Understand the basic static configuration

    There are quite many configs in Cadence. Here are the most basic configuration that you should understand.

    -
    Config nameExplanationRecommended value
    numHistoryShardsThis is the most important one in Cadence config.It will be a fixed number in the cluster forever. The only way to change it is to migrate to another cluster. Refer to Migrate cluster section.

    Some facts about it:
    1. Each workflow will be mapped to a single shard. Within a shard, all the workflow creation/updates are serialized.
    2. Each shard will be assigned to only one History node to own the shard, using a Consistent Hashing Ring. Each shard will consume a small amount of memory/CPU to do background processing. Therefore, a single History node cannot own too many shards. You may need to figure out a good number range based on your instance size(memory/CPU).
    3. Also, you can’t add an infinite number of nodes to a cluster because this config is fixed. When the number of History nodes is closed or equal to numHistoryShards, there will be some History nodes that have no shards assigned to it. This will be wasting resources.

    Based on above, you don’t want to have a small number of shards which will limit the maximum size of your cluster. You also don’t want to have a too big number, which will require you to have a quite big initial size of the cluster.
    Also, typically a production cluster will start with a smaller number and then we add more nodes/hosts to it. But to keep high availability, it’s recommended to use at least 4 nodes for each service(Frontend/History/Matching) at the beginning.
    1K~16K depending on the size ranges of the cluster you expect to run, and the instance size. Typically 2K for SQL based persistence, and 8K for Cassandra based.
    ringpopThis is the config to let all nodes of all services connected to each other. ALL the bootstrap nodes MUST be reachable by ringpop when a service is starting up, within a MaxJoinDuration. defaultMaxJoinDuration is 2 minutes.

    It’s not required that bootstrap nodes need to be Frontend/History or Matching. In fact, it can be running none of them as long as it runs Ringpop protocol.
    For dns mode: Recommended to put the DNS of Frontend service

    For hosts or hostfile mode: A list of Frontend service node addresses if using hosts mode. Make sure all the bootstrap nodes are reachable at startup.
    publicClientThe Cadence Frontend service addresses that internal Cadence system(like system workflows) need to talk to.

    After connected, all nodes in Ringpop will form a ring with identifiers of what service they serve. Ideally Cadence should be able to get Frontend address from there. But Ringpop doesn’t expose this API yet.
    Recommended be DNS of Frontend service, so that requests will be distributed to all Frontend nodes.

    Using localhost+Port or local container IP address+Port will not work if the IP/container is not running frontend
    services.NAME.rpcConfiguration of how to listen to network ports and serve traffic.

    bindOnLocalHost:true will bind on 127.0.0.1. It’s mostly for local development. In production usually you have to specify the IP that containers will use by using bindOnIP

    NAME is the matter for the “--services” option in the server startup command.
    Name: Use as recommended in development.yaml. bindOnIP : an IP address that the container will serve the traffic with
    services.NAME.pprofGolang profiling service , will bind on the same IP as RPCa port that you want to serve pprof request
    services.Name.metricsSee Metrics&Logging sectioncc
    clusterMetadataCadence cluster configuration.

    enableGlobalDomain:true will enable Cadence Cross datacenter replication(aka XDC) feature.

    failoverVersionIncrement: This decides the maximum clusters that you will have replicated to each other at the same time. For example 10 is sufficient for most cases.

    masterClusterName: a master cluster must be one of the enabled clusters, usually the very first cluster to start. It is only meaningful for internal purposes.

    currentClusterName: current cluster name using this config file.

    clusterInformation is a map from clusterName to the cluster configure

    initialFailoverVersion: each cluster must use a different value from 0 to failoverVersionIncrement-1.

    rpcName: must be “cadence-frontend”. Can be improved in this issue.

    rpcAddress: the address to talk to the Frontend of the cluster for inter-cluster replication.

    Note that even if you don’t need XDC replication right now, if you want to migrate data stores in the future, you should enable xdc from every beginning. You just need to use the same name of cluster for both masterClusterName and currentClusterName.

    Go to cross dc replication for how to configure replication in production
    As explanation.
    dcRedirectionPolicyFor allowing forwarding frontend requests from passive cluster to active clusters.“selected-apis-forwarding”
    archivalThis is for archival history feature, skip if you don’t need it. Go to workflow archival for how to configure archival in productionN/A
    blobstoreThis is also for archival history feature Default cadence server is using file based blob store implementation.N/A
    domainDefaultsdefault config for each domain. Right now only being used for Archival feature.N/A
    dynamicconfig (previously known as dynamicConfigClient)Dynamic config is a config manager that enables you to change configs without restarting servers. It’s a good way for Cadence to keep high availability and make things easy to configure.

    By default Cadence server uses filebased client which allows you to override default configs using a YAML file. However, this approach can be cumbersome in production environment because it's the operator's responsibility to sync the YAML files across Cadence nodes.

    Therefore, we provide another option, configstore client, that stores config changes in the persistent data store for Cadence (e.g., Cassandra database) rather than the YAML file. This approach shifts the responsibility of syncing config changes from the operator to Cadence service. You can use Cadence CLI commands to list/get/update/restore config changes.

    You can also implement the dynamic config interface if you have a better way to manage configs.
    Same as the sample development config
    persistenceConfiguration for data store / persistence layer.

    Values of DefaultStore VisibilityStore AdvancedVisibilityStore should be keys of map DataStores.

    DefaultStore is for core Cadence functionality.

    VisibilityStore is for basic visibility feature

    AdvancedVisibilityStore is for advanced visibility

    Go to advanced visibility for detailed configuration of advanced visibility. See persistence documentation about using different database for Cadence
    As explanation
    +
    Config nameExplanationRecommended value
    numHistoryShardsThis is the most important one in Cadence config.It will be a fixed number in the cluster forever. The only way to change it is to migrate to another cluster. Refer to Migrate cluster section.

    Some facts about it:
    1. Each workflow will be mapped to a single shard. Within a shard, all the workflow creation/updates are serialized.
    2. Each shard will be assigned to only one History node to own the shard, using a Consistent Hashing Ring. Each shard will consume a small amount of memory/CPU to do background processing. Therefore, a single History node cannot own too many shards. You may need to figure out a good number range based on your instance size(memory/CPU).
    3. Also, you can’t add an infinite number of nodes to a cluster because this config is fixed. When the number of History nodes is closed or equal to numHistoryShards, there will be some History nodes that have no shards assigned to it. This will be wasting resources.

    Based on above, you don’t want to have a small number of shards which will limit the maximum size of your cluster. You also don’t want to have a too big number, which will require you to have a quite big initial size of the cluster.
    Also, typically a production cluster will start with a smaller number and then we add more nodes/hosts to it. But to keep high availability, it’s recommended to use at least 4 nodes for each service(Frontend/History/Matching) at the beginning.
    1K~16K depending on the size ranges of the cluster you expect to run, and the instance size. Typically 2K for SQL based persistence, and 8K for Cassandra based.
    ringpopThis is the config to let all nodes of all services connected to each other. ALL the bootstrap nodes MUST be reachable by ringpop when a service is starting up, within a MaxJoinDuration. defaultMaxJoinDuration is 2 minutes.

    It’s not required that bootstrap nodes need to be Frontend/History or Matching. In fact, it can be running none of them as long as it runs Ringpop protocol.
    For dns mode: Recommended to put the DNS of Frontend service

    For hosts or hostfile mode: A list of Frontend service node addresses if using hosts mode. Make sure all the bootstrap nodes are reachable at startup.
    publicClientThe Cadence Frontend service addresses that internal Cadence system(like system workflows) need to talk to.

    After connected, all nodes in Ringpop will form a ring with identifiers of what service they serve. Ideally Cadence should be able to get Frontend address from there. But Ringpop doesn’t expose this API yet.
    Recommended be DNS of Frontend service, so that requests will be distributed to all Frontend nodes.

    Using localhost+Port or local container IP address+Port will not work if the IP/container is not running frontend
    services.NAME.rpcConfiguration of how to listen to network ports and serve traffic.

    bindOnLocalHost:true will bind on 127.0.0.1. It’s mostly for local development. In production usually you have to specify the IP that containers will use by using bindOnIP

    NAME is the matter for the “--services” option in the server startup command.
    Name: Use as recommended in development.yaml. bindOnIP : an IP address that the container will serve the traffic with
    services.NAME.pprofGolang profiling service , will bind on the same IP as RPCa port that you want to serve pprof request
    services.Name.metricsSee Metrics&Logging sectioncc
    clusterMetadataCadence cluster configuration.

    enableGlobalDomain:true will enable Cadence Cross datacenter replication(aka XDC) feature.

    failoverVersionIncrement: This decides the maximum clusters that you will have replicated to each other at the same time. For example 10 is sufficient for most cases.

    masterClusterName: a master cluster must be one of the enabled clusters, usually the very first cluster to start. It is only meaningful for internal purposes.

    currentClusterName: current cluster name using this config file.

    clusterInformation is a map from clusterName to the cluster configure

    initialFailoverVersion: each cluster must use a different value from 0 to failoverVersionIncrement-1.

    rpcName: must be “cadence-frontend”. Can be improved in this issue.

    rpcAddress: the address to talk to the Frontend of the cluster for inter-cluster replication.

    Note that even if you don’t need XDC replication right now, if you want to migrate data stores in the future, you should enable xdc from every beginning. You just need to use the same name of cluster for both masterClusterName and currentClusterName.

    Go to cross dc replication for how to configure replication in production
    As explanation.
    dcRedirectionPolicyFor allowing forwarding frontend requests from passive cluster to active clusters.“selected-apis-forwarding”
    archivalThis is for archival history feature, skip if you don’t need it. Go to workflow archival for how to configure archival in productionN/A
    blobstoreThis is also for archival history feature Default cadence server is using file based blob store implementation.N/A
    domainDefaultsdefault config for each domain. Right now only being used for Archival feature.N/A
    dynamicconfig (previously known as dynamicConfigClient)Dynamic config is a config manager that enables you to change configs without restarting servers. It’s a good way for Cadence to keep high availability and make things easy to configure.

    By default Cadence server uses filebased client which allows you to override default configs using a YAML file. However, this approach can be cumbersome in production environment because it's the operator's responsibility to sync the YAML files across Cadence nodes.

    Therefore, we provide another option, configstore client, that stores config changes in the persistent data store for Cadence (e.g., Cassandra database) rather than the YAML file. This approach shifts the responsibility of syncing config changes from the operator to Cadence service. You can use Cadence CLI commands to list/get/update/restore config changes.

    You can also implement the dynamic config interface if you have a better way to manage configs.
    Same as the sample development config
    persistenceConfiguration for data store / persistence layer.

    Values of DefaultStore VisibilityStore AdvancedVisibilityStore should be keys of map DataStores.

    DefaultStore is for core Cadence functionality.

    VisibilityStore is for basic visibility feature

    AdvancedVisibilityStore is for advanced visibility

    Go to advanced visibility for detailed configuration of advanced visibility. See persistence documentation about using different database for Cadence
    As explanation

    The full list of static configuration

    Starting from v0.21.0, all the static configuration are defined by GoDocs in details.

    VersionGoDocs LinkGithub Link
    v0.21.0Configuration DocsConfiguration
    ...other higher versions...Replace the version in the URL of v0.21.0...Replace the version in the URL of v0.21.0
    @@ -126,13 +126,13 @@

    Config s

    Other Advanced Features

    Deployment & Release

    @@ -141,8 +141,8 @@

    Deployme

    It's always recommended to use the latest release. See Cadence release pages.

    Please subscribe the release of project by :

    Go to https://github.com/cadence-workflow/cadence -> Click the right top "Watch" button -> Custom -> "Release".

    -

    And see how to upgrade a Cadence cluster

    +

    And see how to upgrade a Cadence cluster

    Stress/Bench Test a cluster

    -

    It's recommended to run bench test on your cluster following this package to see the maximum throughput that it can take, whenever you change some setup.

    +

    It's recommended to run bench test on your cluster following this package to see the maximum throughput that it can take, whenever you change some setup.

    \ No newline at end of file diff --git a/docs/operation-guide/setup.html.html b/docs/operation-guide/setup.html.html index ffec3ddab..ca3c18f8b 100644 --- a/docs/operation-guide/setup.html.html +++ b/docs/operation-guide/setup.html.html @@ -2,10 +2,10 @@ - - + + \ No newline at end of file diff --git a/docs/operation-guide/troubleshooting.html b/docs/operation-guide/troubleshooting.html index 6e821d146..cbe390799 100644 --- a/docs/operation-guide/troubleshooting.html +++ b/docs/operation-guide/troubleshooting.html @@ -3,8 +3,8 @@ -Cluster Troubleshooting | Cadence - +Cluster Troubleshooting | Cadence + @@ -15,14 +15,14 @@ - - - + + + -

    Cluster Troubleshooting

    +

    Cluster Troubleshooting

    This section is to cover some common operation issues as a RunBook. Feel free to add more, or raise issues in the to ask for more in cadence-docs project.Or talk to us in Slack support channel!

    We will keep adding more stuff. Any contribution is very welcome.

    Errors

    @@ -47,12 +47,12 @@

    scale up the tasklist +
  • If this happens after traffic increased for a certain domain, it's likely that a tasklist is overloaded. Consider scale up the tasklist
  • -

    If the request volume aligned with the traffic increased on all domain, consider scale up the cluster

    +

    If the request volume aligned with the traffic increased on all domain, consider scale up the cluster

  • -

    +
    \ No newline at end of file diff --git a/docs/operation-guide/troubleshooting.html.html b/docs/operation-guide/troubleshooting.html.html index 057ce5c58..e03531f91 100644 --- a/docs/operation-guide/troubleshooting.html.html +++ b/docs/operation-guide/troubleshooting.html.html @@ -2,10 +2,10 @@ - - + + \ No newline at end of file diff --git a/docs/resources/index.html b/docs/resources/index.html index 3308de34c..1d83d044c 100644 --- a/docs/resources/index.html +++ b/docs/resources/index.html @@ -2,10 +2,10 @@ - - + + \ No newline at end of file diff --git a/docs/support/index.html b/docs/support/index.html index ae8781001..7e41f5ee7 100644 --- a/docs/support/index.html +++ b/docs/support/index.html @@ -2,10 +2,10 @@ - - + + \ No newline at end of file diff --git a/docs/team/index.html b/docs/team/index.html index 6e9a87742..29c379a88 100644 --- a/docs/team/index.html +++ b/docs/team/index.html @@ -2,10 +2,10 @@ - - + + \ No newline at end of file diff --git a/docs/use-cases.html b/docs/use-cases.html index 2d35a8293..608ff5856 100644 --- a/docs/use-cases.html +++ b/docs/use-cases.html @@ -3,8 +3,8 @@ -Introduction | Cadence - +Introduction | Cadence + @@ -15,20 +15,20 @@ - - - + + + -

    Use cases

    +

    Use cases

    As Cadence developers, we face a difficult non-technical problem: How to position and describe the Cadence platform.

    We call it workflow. But when most people hear the word "workflow" they think about low-code and UIs. While these might be useful for non technical users, they frequently bring more pain than value to software engineers. Most UIs and low-code DSLs are awesome for "hello world" demo applications, but any diagram with 100+ elements or a few thousand lines of JSON DSL is completely impractical. So positioning Cadence as a workflow is not ideal as it turns away developers that would enjoy its code-only approach.

    We call it orchestrator. But this term is pretty narrow and turns away customers that want to implement business process automation solutions.

    We call it durable function platform. It is technically a correct term. But most developers outside of the Microsoft ecosystem have never heard of Durable Functions.

    We believe that problem in naming comes from the fact that Cadence is indeed a new way to write distributed applications. It is generic enough that it can be applied to practically any use case that goes beyond a single request reply. It can be used to build applications that are in traditional areas of workflow or orchestration platforms. But it is also huge developer productivity boost for multiple use cases that traditionally rely on databases and/or task queues.

    This section represents a far from complete list of use cases where Cadence is a good fit. All of them have been used by real production services inside and outside of Uber.

    -

    Don't think of this list as exhaustive. It is common to employ multiple use types in a single application. For example, an operational management use case might need periodic execution, service orchestration, polling, event driven, as well as interactive parts.

    +

    Don't think of this list as exhaustive. It is common to employ multiple use types in a single application. For example, an operational management use case might need periodic execution, service orchestration, polling, event driven, as well as interactive parts.

    \ No newline at end of file diff --git a/docs/use-cases.html.html b/docs/use-cases.html.html index 249e9db78..a87d4c98d 100644 --- a/docs/use-cases.html.html +++ b/docs/use-cases.html.html @@ -2,10 +2,10 @@ - - + + \ No newline at end of file diff --git a/docs/use-cases/batch-job.html b/docs/use-cases/batch-job.html index d84bacee9..ec687418b 100644 --- a/docs/use-cases/batch-job.html +++ b/docs/use-cases/batch-job.html @@ -3,8 +3,8 @@ -Batch job | Cadence - +Batch job | Cadence + @@ -15,17 +15,17 @@ - - - + + + -

    Batch job

    +

    Batch job

    A lot of batch jobs are not pure data manipulation programs. For those, the existing big data frameworks are the best fit. But if processing a record requires external API calls that might fail and potentially take a long time, Cadence might be preferable.

    One of our internal Uber customer uses Cadence for end of month statement generation. Each statement requires calls to multiple -microservices and some statements can be really large. Cadence was chosen because it provides hard guarantees around durability of the financial data and seamlessly deals with long running operations, retries, and intermittent failures.

    +microservices and some statements can be really large. Cadence was chosen because it provides hard guarantees around durability of the financial data and seamlessly deals with long running operations, retries, and intermittent failures.

    \ No newline at end of file diff --git a/docs/use-cases/batch-job.html.html b/docs/use-cases/batch-job.html.html index cb268dfc4..a7e8fe26b 100644 --- a/docs/use-cases/batch-job.html.html +++ b/docs/use-cases/batch-job.html.html @@ -2,10 +2,10 @@ - - + + \ No newline at end of file diff --git a/docs/use-cases/big-ml.html b/docs/use-cases/big-ml.html index 3cb50c7cb..15db53c1c 100644 --- a/docs/use-cases/big-ml.html +++ b/docs/use-cases/big-ml.html @@ -3,8 +3,8 @@ -Big data and ML | Cadence - +Big data and ML | Cadence + @@ -15,15 +15,15 @@ - - - + + + -

    Big data and ML

    +

    Big data and ML

    A lot of companies build custom ETL and ML training and deployment solutions. Cadence is a good fit for a control plane for such applications.

    -

    One important feature of Cadence is its ability to route task execution to a specific process or host. It is useful to control how ML models and other large files are allocated to hosts. For example, if an ML model is partitioned by city, the requests should be routed to hosts that contain the corresponding city model.

    +

    One important feature of Cadence is its ability to route task execution to a specific process or host. It is useful to control how ML models and other large files are allocated to hosts. For example, if an ML model is partitioned by city, the requests should be routed to hosts that contain the corresponding city model.

    \ No newline at end of file diff --git a/docs/use-cases/big-ml.html.html b/docs/use-cases/big-ml.html.html index b2c648f39..25029f080 100644 --- a/docs/use-cases/big-ml.html.html +++ b/docs/use-cases/big-ml.html.html @@ -2,10 +2,10 @@ - - + + \ No newline at end of file diff --git a/docs/use-cases/deployment.html b/docs/use-cases/deployment.html index 32082a26a..33403e1e1 100644 --- a/docs/use-cases/deployment.html +++ b/docs/use-cases/deployment.html @@ -3,8 +3,8 @@ -Deployment | Cadence - +Deployment | Cadence + @@ -15,14 +15,14 @@ - - - + + + -

    CI/CD and Deployment

    +

    CI/CD and Deployment

    Implementing CI/CD pipelines and deployment of applications to containers or virtual or physical machines is a non-trivial process. Its business logic has to deal with complex requirements around rolling upgrades, canary deployments, and rollbacks. Cadence is a perfect platform for building a deployment solution because it provides all the necessary guarantees and abstractions @@ -31,6 +31,6 @@

    • Uber internal deployment infrastructure
    • Update push to IoT devices
    • -
    +
    \ No newline at end of file diff --git a/docs/use-cases/deployment.html.html b/docs/use-cases/deployment.html.html index 0584fdb28..b57643bc2 100644 --- a/docs/use-cases/deployment.html.html +++ b/docs/use-cases/deployment.html.html @@ -2,10 +2,10 @@ - - + + \ No newline at end of file diff --git a/docs/use-cases/dsl.html b/docs/use-cases/dsl.html index d1f9800a6..8b73371b6 100644 --- a/docs/use-cases/dsl.html +++ b/docs/use-cases/dsl.html @@ -3,8 +3,8 @@ -DSL workflows | Cadence - +DSL workflows | Cadence + @@ -15,20 +15,20 @@ - - - + + + -

    DSL workflows

    +

    DSL workflows

    Cadence supports implementing business logic directly in programming languages like Java and Go. But there are cases when using a domain-specific language is more appropriate. Or there might be a legacy system that uses some form of DSL for process definition but it is not operationally stable and scalable. This also applies to more recent systems like Apache Airflow, various BPMN engines and AWS Step Functions.

    An application that interprets the DSL definition can be written using the Cadence SDK. It automatically becomes highly fault tolerant, scalable, and durable when running on Cadence. Cadence has been used to deprecate several Uber internal DSL engines. The customers continue to use existing process definitions, but Cadence is used as an execution engine.

    There are multiple benefits of unifying all company workflow engines on top of Cadence. The most obvious one is that it is more efficient to support a single product instead of many. It is also difficult to beat the scalability and stability of Cadence which each of the integrations it comes with. Additionally, the ability to share activities across "engines" -might be a huge benefit in some cases.

    +might be a huge benefit in some cases.

    \ No newline at end of file diff --git a/docs/use-cases/dsl.html.html b/docs/use-cases/dsl.html.html index 5e45dbbe0..2c89a4d5a 100644 --- a/docs/use-cases/dsl.html.html +++ b/docs/use-cases/dsl.html.html @@ -2,10 +2,10 @@ - - + + \ No newline at end of file diff --git a/docs/use-cases/event-driven.html b/docs/use-cases/event-driven.html index 76da5651a..60311f25b 100644 --- a/docs/use-cases/event-driven.html +++ b/docs/use-cases/event-driven.html @@ -3,8 +3,8 @@ -Event driven application | Cadence - +Event driven application | Cadence + @@ -15,14 +15,14 @@ - - - + + + -

    Event driven application

    +

    Event driven application

    Many applications listen to multiple event sources, update the state of correspondent business entities, and have to execute actions if some state is reached. Cadence is a good fit for many of these. It has direct support for asynchronous events (aka signals), @@ -32,6 +32,6 @@

    • Fraud detection where workflow reacts to events generated by consumer behavior
    • Customer loyalty program where the workflow accumulates reward points and applies them when requested
    • -
    +
    \ No newline at end of file diff --git a/docs/use-cases/event-driven.html.html b/docs/use-cases/event-driven.html.html index 07ab872f7..1253c3cb2 100644 --- a/docs/use-cases/event-driven.html.html +++ b/docs/use-cases/event-driven.html.html @@ -2,10 +2,10 @@ - - + + \ No newline at end of file diff --git a/docs/use-cases/interactive.html b/docs/use-cases/interactive.html index a8cc2c7d5..3ba16c740 100644 --- a/docs/use-cases/interactive.html +++ b/docs/use-cases/interactive.html @@ -3,8 +3,8 @@ -Interactive application | Cadence - +Interactive application | Cadence + @@ -15,15 +15,15 @@ - - - + + + -

    Interactive application

    +

    Interactive application

    Cadence is performant and scalable enough to support interactive applications. It can be used to track UI session state and -at the same time execute background operations. For example, while placing an order a customer might need to go through several screens while a background task evaluates the customer for fraudulent activity.

    +at the same time execute background operations. For example, while placing an order a customer might need to go through several screens while a background task evaluates the customer for fraudulent activity.

    \ No newline at end of file diff --git a/docs/use-cases/interactive.html.html b/docs/use-cases/interactive.html.html index 721b7bba1..6bc2cb357 100644 --- a/docs/use-cases/interactive.html.html +++ b/docs/use-cases/interactive.html.html @@ -2,10 +2,10 @@ - - + + \ No newline at end of file diff --git a/docs/use-cases/operational-management.html b/docs/use-cases/operational-management.html index f91c67322..707ed15b6 100644 --- a/docs/use-cases/operational-management.html +++ b/docs/use-cases/operational-management.html @@ -3,8 +3,8 @@ -Operational management | Cadence - +Operational management | Cadence + @@ -15,16 +15,16 @@ - - - + + + -

    Operational management

    +

    Operational management

    Imagine that you have to create a self operating database similar to Amazon RDS. Cadence is used in multiple projects that automate managing and automatic recovery of various products like MySQL, Elasticsearch and Apache Cassandra.

    -

    Such systems are usually a mixture of different use cases. They need to monitor the status of resources using polling. They have to execute orchestration API calls to administrative interfaces of a database. They have to provision new hardware or Docker instances if necessary. They need to push configuration updates and perform other actions like backups periodically.

    +

    Such systems are usually a mixture of different use cases. They need to monitor the status of resources using polling. They have to execute orchestration API calls to administrative interfaces of a database. They have to provision new hardware or Docker instances if necessary. They need to push configuration updates and perform other actions like backups periodically.

    \ No newline at end of file diff --git a/docs/use-cases/operational-management.html.html b/docs/use-cases/operational-management.html.html index 93fcc60e7..f79595e96 100644 --- a/docs/use-cases/operational-management.html.html +++ b/docs/use-cases/operational-management.html.html @@ -2,10 +2,10 @@ - - + + \ No newline at end of file diff --git a/docs/use-cases/orchestration.html b/docs/use-cases/orchestration.html index bf11f1b4d..11bf1cfeb 100644 --- a/docs/use-cases/orchestration.html +++ b/docs/use-cases/orchestration.html @@ -3,8 +3,8 @@ -Orchestration | Cadence - +Orchestration | Cadence + @@ -15,14 +15,14 @@ - - - + + + -

    Microservice Orchestration and Saga

    + +
    \ No newline at end of file diff --git a/docs/use-cases/orchestration.html.html b/docs/use-cases/orchestration.html.html index 9843c204a..a0918e0c0 100644 --- a/docs/use-cases/orchestration.html.html +++ b/docs/use-cases/orchestration.html.html @@ -2,10 +2,10 @@ - - + + \ No newline at end of file diff --git a/docs/use-cases/partitioned-scan.html b/docs/use-cases/partitioned-scan.html index 4709a44a1..048b4ede0 100644 --- a/docs/use-cases/partitioned-scan.html +++ b/docs/use-cases/partitioned-scan.html @@ -3,8 +3,8 @@ -Storage scan | Cadence - +Storage scan | Cadence + @@ -15,14 +15,14 @@ - - - + + + -

    Storage scan

    +

    Storage scan

    It is common to have large data sets partitioned across a large number of hosts or databases, or having billions of files in an Amazon S3 bucket. Cadence is an ideal solution for implementing the full scan of such data in a scalable and resilient way. The standard pattern is to run an activity (or multiple parallel activities for partitioned data sets) that performs the scan and heartbeats its progress @@ -30,6 +30,6 @@

    A real-world example:

    • Cadence internal system workflow that performs periodic scan of all workflow_execution records
    • -
    +
    \ No newline at end of file diff --git a/docs/use-cases/partitioned-scan.html.html b/docs/use-cases/partitioned-scan.html.html index 68ad30fbd..69e24849c 100644 --- a/docs/use-cases/partitioned-scan.html.html +++ b/docs/use-cases/partitioned-scan.html.html @@ -2,10 +2,10 @@ - - + + \ No newline at end of file diff --git a/docs/use-cases/periodic-execution.html b/docs/use-cases/periodic-execution.html index 7b1159d05..4c869bdb9 100644 --- a/docs/use-cases/periodic-execution.html +++ b/docs/use-cases/periodic-execution.html @@ -3,8 +3,8 @@ -Periodic execution | Cadence - +Periodic execution | Cadence + @@ -15,14 +15,14 @@ - - - + + + -

    Periodic execution (aka Distributed Cron)

    +

    Periodic execution (aka Distributed Cron)

    Periodic execution, frequently referred to as distributed cron, is when you execute business logic periodically. The advantage of Cadence for these scenarios is that it guarantees execution, sophisticated error handling, retry policies, and visibility into execution history.

    Another important dimension is scale. Some use cases require periodic execution for a large number of entities. At Uber, there are applications that create periodic workflows per customer. @@ -32,6 +32,6 @@

    • An Uber backend service that recalculates various statistics for each hex in each city once a minute.
    • Monthly Uber for Business report generation.
    • -
    +
    \ No newline at end of file diff --git a/docs/use-cases/periodic-execution.html.html b/docs/use-cases/periodic-execution.html.html index 9d0ff3a14..5c4f828f1 100644 --- a/docs/use-cases/periodic-execution.html.html +++ b/docs/use-cases/periodic-execution.html.html @@ -2,10 +2,10 @@ - - + + \ No newline at end of file diff --git a/docs/use-cases/polling.html b/docs/use-cases/polling.html index 371e82643..6405811ee 100644 --- a/docs/use-cases/polling.html +++ b/docs/use-cases/polling.html @@ -3,8 +3,8 @@ -Polling | Cadence - +Polling | Cadence + @@ -15,14 +15,14 @@ - - - + + + -

    Polling

    + +
    \ No newline at end of file diff --git a/docs/use-cases/polling.html.html b/docs/use-cases/polling.html.html index f492172d2..409b5fe5f 100644 --- a/docs/use-cases/polling.html.html +++ b/docs/use-cases/polling.html.html @@ -2,10 +2,10 @@ - - + + \ No newline at end of file diff --git a/docs/use-cases/provisioning.html b/docs/use-cases/provisioning.html index a81244336..0dc2308ee 100644 --- a/docs/use-cases/provisioning.html +++ b/docs/use-cases/provisioning.html @@ -3,8 +3,8 @@ -Infrastructure provisioning | Cadence - +Infrastructure provisioning | Cadence + @@ -15,14 +15,14 @@ - - - + + + -

    Infrastructure provisioning

    +

    Infrastructure provisioning

    Provisioning a new datacenter or a pool of machines in a public cloud is a potentially long running operation with a lot of possibilities for intermittent failures. The scale is also a concern when tens or even hundreds of thousands of resources should be provisioned and configured. One useful feature for provisioning scenarios is Cadence support for routing activity execution to a specific process or host.

    A lot of operations require some sort of locking to ensure that no more than one mutation is executed on a resource at a time. @@ -31,6 +31,6 @@

    +
    \ No newline at end of file diff --git a/docs/use-cases/provisioning.html.html b/docs/use-cases/provisioning.html.html index 06b063a51..385900b85 100644 --- a/docs/use-cases/provisioning.html.html +++ b/docs/use-cases/provisioning.html.html @@ -2,10 +2,10 @@ - - + + \ No newline at end of file diff --git a/docs/workflow-troubleshooting.html b/docs/workflow-troubleshooting.html index 1f7ca92b2..b353efa6b 100644 --- a/docs/workflow-troubleshooting.html +++ b/docs/workflow-troubleshooting.html @@ -3,8 +3,8 @@ -Overview | Cadence - +Overview | Cadence + @@ -15,14 +15,14 @@ - - - + + + - + \ No newline at end of file diff --git a/docs/workflow-troubleshooting.html.html b/docs/workflow-troubleshooting.html.html index c8e374706..3d5c0bf03 100644 --- a/docs/workflow-troubleshooting.html.html +++ b/docs/workflow-troubleshooting.html.html @@ -2,10 +2,10 @@ - - + + \ No newline at end of file diff --git a/docs/workflow-troubleshooting/activity-failures.html b/docs/workflow-troubleshooting/activity-failures.html index 53cd4ac17..8538a92a5 100644 --- a/docs/workflow-troubleshooting/activity-failures.html +++ b/docs/workflow-troubleshooting/activity-failures.html @@ -3,8 +3,8 @@ -Activity Failures | Cadence - +Activity Failures | Cadence + @@ -15,14 +15,14 @@ - - - + + + -

    Activity failures

    +

    Activity failures

    An activity fails when it encounters an error during its execution. This results in ActivityTaskFailed event in the workflow execution with some details of the error. The different kinds of errors that can be seen in activity failures are listed here.

    Panic errors

    Description: There is a issue in the activity code that is causing a panic.

    @@ -34,6 +34,6 @@

    Custom errors<

    Generic errors

    Description: This is an error returned by the activity.

    Mitigation: This error is caused by something unexpected within the activity code, typically due to a downstream service that your activity communicates with. Cadence does not know anything about it and just puts all unknown errors in this category. Check your activity code to find the potential error cases. This is ideally an unexpected error scenario and should be debugged further to fix the rootcause.

    -

    Read more about error handling

    +

    Read more about error handling

    \ No newline at end of file diff --git a/docs/workflow-troubleshooting/activity-failures.html.html b/docs/workflow-troubleshooting/activity-failures.html.html index 000f73510..e653ae44f 100644 --- a/docs/workflow-troubleshooting/activity-failures.html.html +++ b/docs/workflow-troubleshooting/activity-failures.html.html @@ -2,10 +2,10 @@ - - + + \ No newline at end of file diff --git a/docs/workflow-troubleshooting/retries.html b/docs/workflow-troubleshooting/retries.html index 11369ec2a..1ab4f66b3 100644 --- a/docs/workflow-troubleshooting/retries.html +++ b/docs/workflow-troubleshooting/retries.html @@ -3,8 +3,8 @@ -Retries | Cadence - +Retries | Cadence + @@ -15,14 +15,14 @@ - - - + + + -

    Retries

    +

    Retries

    Cadence has a retry feature where a retry policy can be configured so that an activity or a workflow will be retried when it fails or times out.

    Read more about activity retries and workflow retries.

    Workflow execution history of retries

    @@ -34,6 +34,6 @@

    MaximumAttempts set to 1

    In both activity retries and workflow retries it is sufficient to mention a maximum number of attempts or an expiration interval. However, the maximum number of attempts counts the original attempt of the activity also. As a result, setting maximum number of attempts to 1 means the activity or workflow will not be retried.

    ExpirationIntervalInSeconds less than InitialIntervalInSeconds

    -

    In both activity retries and workflow retries it is sufficient to specify a maximum number of attempts or an expiration interval. The first retry attempt waits for the InitialIntervalInSeconds before starting and when an expiration interval is set lower than the initial interval, the retry policy becomes invalid and the activity or workflow will not be retried.

    +

    In both activity retries and workflow retries it is sufficient to specify a maximum number of attempts or an expiration interval. The first retry attempt waits for the InitialIntervalInSeconds before starting and when an expiration interval is set lower than the initial interval, the retry policy becomes invalid and the activity or workflow will not be retried.

    \ No newline at end of file diff --git a/docs/workflow-troubleshooting/retries.html.html b/docs/workflow-troubleshooting/retries.html.html index bf506c942..9aa7b88b4 100644 --- a/docs/workflow-troubleshooting/retries.html.html +++ b/docs/workflow-troubleshooting/retries.html.html @@ -2,10 +2,10 @@ - - + + \ No newline at end of file diff --git a/docs/workflow-troubleshooting/timeouts.html b/docs/workflow-troubleshooting/timeouts.html index 2559a94b1..9eac67b7b 100644 --- a/docs/workflow-troubleshooting/timeouts.html +++ b/docs/workflow-troubleshooting/timeouts.html @@ -3,8 +3,8 @@ -Timeouts | Cadence - +Timeouts | Cadence + @@ -15,14 +15,14 @@ - - - + + + -

    Timeouts

    +

    Timeouts

    A workflow could fail if an activity times out and will timeout when the entire workflow execution times out. Workflows or activities time out when their time to execute or time to start has been longer than their configured timeout. Some of the common causes for timeouts have been listed here.

    Missing Pollers

    Cadence workers are part of the service that hosts and executes the workflow. They are of two types: activity worker and workflow worker. Each of these workers are responsible for having pollers which are go-routines that poll for activity tasks and decision tasks respectively from the Cadence server. Without pollers, the workflow cannot proceed with the execution.

    @@ -55,6 +55,6 @@

    Example to send periodic heart beat

    In go client, there is an option to register the activity with auto heart beating so that it is done automatically

    -

    Configuring auto heart beat during activity registration example

    +

    Configuring auto heart beat during activity registration example

    \ No newline at end of file diff --git a/docs/workflow-troubleshooting/timeouts.html.html b/docs/workflow-troubleshooting/timeouts.html.html index e261804c9..97d884bf6 100644 --- a/docs/workflow-troubleshooting/timeouts.html.html +++ b/docs/workflow-troubleshooting/timeouts.html.html @@ -2,10 +2,10 @@ - - + + \ No newline at end of file diff --git a/index.html b/index.html index 232d3ba3a..2dbf5d541 100644 --- a/index.html +++ b/index.html @@ -3,8 +3,8 @@ -Cadence | Cadence - +Cadence | Cadence + @@ -15,13 +15,13 @@ - - - + + + -

    Cadence

    Orchestrate with Confidence: The Open-Source Workflow Engine for Tomorrow

    Simplify Stateful Application Development

    Arrow divert (filled)

    Encode complex business logic, while seamlessly managing scalability, reliability, and availability, freeing developers from these concerns

    Run Resilient Workflows in Any Environment

    Gears (outlined)

    Cadence enables writing stateful applications without worrying about the complexity of handling process failures.

    Horizontal Scalability for Massive Workflow Loads

    Chart bar ascending (filled),,,

    Cadence scales horizontally to handle millions of concurrent workflows, and it includes asynchronous history event replication out-of-the-box, providing robust recovery from zone failures

    +

    Cadence

    Orchestrate with Confidence: The Open-Source Workflow Engine for Tomorrow

    Simplify Stateful Application Development

    Arrow divert (filled)

    Encode complex business logic, while seamlessly managing scalability, reliability, and availability, freeing developers from these concerns

    Run Resilient Workflows in Any Environment

    Gears (outlined)

    Cadence enables writing stateful applications without worrying about the complexity of handling process failures.

    Horizontal Scalability for Massive Workflow Loads

    Chart bar ascending (filled),,,

    Cadence scales horizontally to handle millions of concurrent workflows, and it includes asynchronous history event replication out-of-the-box, providing robust recovery from zone failures

    \ No newline at end of file diff --git a/markdown-page.html b/markdown-page.html index 2bbaa7432..130869cef 100644 --- a/markdown-page.html +++ b/markdown-page.html @@ -3,8 +3,8 @@ -Markdown page example | Cadence - +Markdown page example | Cadence + @@ -15,14 +15,14 @@ - - - + + + - + \ No newline at end of file diff --git a/markdown-page.html.html b/markdown-page.html.html index 7e1295796..e7b5a4afe 100644 --- a/markdown-page.html.html +++ b/markdown-page.html.html @@ -2,10 +2,10 @@ - - + + \ No newline at end of file diff --git a/opensearch.xml b/opensearch.xml index 78075dacb..2608a7389 100644 --- a/opensearch.xml +++ b/opensearch.xml @@ -4,8 +4,8 @@ Cadence Search Cadence UTF-8 - https://cadenceworkflow.io/img/favicon.ico - - - https://cadenceworkflow.io/ + https://cadenceworkflow.io/Cadence-Docs/img/favicon.ico + + + https://cadenceworkflow.io/Cadence-Docs/ \ No newline at end of file diff --git a/search.html b/search.html index 7619f4daf..ae05dcbd0 100644 --- a/search.html +++ b/search.html @@ -3,8 +3,8 @@ -Search the documentation | Cadence - +Search the documentation | Cadence + @@ -15,13 +15,13 @@ - - - + + + - + \ No newline at end of file diff --git a/search.html.html b/search.html.html index dd7e08a80..acd5f3efc 100644 --- a/search.html.html +++ b/search.html.html @@ -2,10 +2,10 @@ - - + + \ No newline at end of file diff --git a/sitemap.xml b/sitemap.xml index e27b959fc..3f20a050b 100644 --- a/sitemap.xml +++ b/sitemap.xml @@ -1 +1 @@ -https://cadenceworkflow.io/blogweekly0.5https://cadenceworkflow.io/blog/2021/09/30/long-term-commitment-and-support-for-the-cadence-project-and-its-communityweekly0.5https://cadenceworkflow.io/blog/2021/10/13/announcing-cadence-oss-office-hours-and-community-sync-upweekly0.5https://cadenceworkflow.io/blog/2021/10/19/2021-10-19-moving-to-grpc/moving-to-grpcweekly0.5https://cadenceworkflow.io/blog/2022/01/31/community-spotlight-january-2022weekly0.5https://cadenceworkflow.io/blog/2022/02/28/community-spotlight-february-2022weekly0.5https://cadenceworkflow.io/blog/2022/03/31/community-spotlight-update-march-2022weekly0.5https://cadenceworkflow.io/blog/2022/04/30/community-spotlight-update-april-2022weekly0.5https://cadenceworkflow.io/blog/2022/05/31/community-spotlight-update-may-2022weekly0.5https://cadenceworkflow.io/blog/2022/06/30/community-spotlight-update-june-2022weekly0.5https://cadenceworkflow.io/blog/2022/07/31/community-spotlight-update-july-2022weekly0.5https://cadenceworkflow.io/blog/2022/08/31/community-spotlight-august-2022weekly0.5https://cadenceworkflow.io/blog/2022/09/30/community-spotlight-september-2022weekly0.5https://cadenceworkflow.io/blog/2022/10/31/community-spotlight-october-2022weekly0.5https://cadenceworkflow.io/blog/2022/11/30/community-spotlight-november-2022weekly0.5https://cadenceworkflow.io/blog/2022/12/23/community-spotlight-december-2022weekly0.5https://cadenceworkflow.io/blog/2023/01/31/community-spotlight-january-2023weekly0.5https://cadenceworkflow.io/blog/2023/02/28/community-spotlight-februaryweekly0.5https://cadenceworkflow.io/blog/2023/03/31/community-spotlight-march-2023weekly0.5https://cadenceworkflow.io/blog/2023/06/08/2023-06-08-survey-results/survey-resultsweekly0.5https://cadenceworkflow.io/blog/2023/06/28/components-of-cadence-application-setupweekly0.5https://cadenceworkflow.io/blog/2023/06/30/community-spotlight-june-2023weekly0.5https://cadenceworkflow.io/blog/2023/07/05/implement-cadence-worker-from-scratchweekly0.5https://cadenceworkflow.io/blog/2023/07/10/cadence-bad-practices-part-1weekly0.5https://cadenceworkflow.io/blog/2023/07/16/2023-07-16-write-your-first-workflow-with-cadence/write-your-first-workflow-with-cadenceweekly0.5https://cadenceworkflow.io/blog/2023/07/31/community-spotlight-july-2023weekly0.5https://cadenceworkflow.io/blog/2023/08/28/nondeterministic-errors-replayers-shadowersweekly0.5https://cadenceworkflow.io/blog/2023/08/31/community-spotlight-august-2023weekly0.5https://cadenceworkflow.io/blog/2023/11/30/community-spotlight-update-november-2023weekly0.5https://cadenceworkflow.io/blog/2024/02/15/cadence-non-deterministic-common-qaweekly0.5https://cadenceworkflow.io/blog/2024/07/11/2024-07-11-yearly-roadmap-update/yearly-roadmap-updateweekly0.5https://cadenceworkflow.io/blog/2024/09/05/workflow-specific-rate-limitsweekly0.5https://cadenceworkflow.io/blog/2024/10/01/announcing-cadence-helm-charts-v0weekly0.5https://cadenceworkflow.io/blog/2024/11/18/cadence-workflows-github-organizationweekly0.5https://cadenceworkflow.io/blog/2024/3/11/community-spotlight-update-march-2024weekly0.5https://cadenceworkflow.io/blog/archiveweekly0.5https://cadenceworkflow.io/blog/authorsweekly0.5https://cadenceworkflow.io/blog/authors/chopincodeweekly0.5https://cadenceworkflow.io/blog/authors/enderdemirkayaweekly0.5https://cadenceworkflow.io/blog/authors/ibarrajoweekly0.5https://cadenceworkflow.io/blog/authors/jakobhtweekly0.5https://cadenceworkflow.io/blog/authors/kcorbett-netappweekly0.5https://cadenceworkflow.io/blog/authors/meiliang-86weekly0.5https://cadenceworkflow.io/blog/authors/shaddollweekly0.5https://cadenceworkflow.io/blog/authors/sharanfweekly0.5https://cadenceworkflow.io/blog/authors/sharanf/authors/2weekly0.5https://cadenceworkflow.io/blog/authors/taylanisikdemirweekly0.5https://cadenceworkflow.io/blog/authors/vytautas-karpaviciusweekly0.5https://cadenceworkflow.io/blog/page/2weekly0.5https://cadenceworkflow.io/blog/page/3weekly0.5https://cadenceworkflow.io/blog/page/4weekly0.5https://cadenceworkflow.io/blog/tagsweekly0.5https://cadenceworkflow.io/blog/tags/announcementsweekly0.5https://cadenceworkflow.io/blog/tags/cadence-operationsweekly0.5https://cadenceworkflow.io/blog/tags/community-spotlightsweekly0.5https://cadenceworkflow.io/blog/tags/community-spotlights/page/2weekly0.5https://cadenceworkflow.io/blog/tags/deep-divesweekly0.5https://cadenceworkflow.io/blog/tags/introduction-to-cadenceweekly0.5https://cadenceworkflow.io/blog/tags/releasesweekly0.5https://cadenceworkflow.io/blog/tags/roadmapweekly0.5https://cadenceworkflow.io/blog/tags/testingweekly0.5https://cadenceworkflow.io/blog/zonal-isolation-v1/zonal-isolation-v1weekly0.5https://cadenceworkflow.io/markdown-pageweekly0.5https://cadenceworkflow.io/searchweekly0.5https://cadenceworkflow.io/community/contributingweekly0.5https://cadenceworkflow.io/community/resourcesweekly0.5https://cadenceworkflow.io/community/supportweekly0.5https://cadenceworkflow.io/community/teamweekly0.5https://cadenceworkflow.io/docs/aboutweekly0.5https://cadenceworkflow.io/docs/about/licenseweekly0.5https://cadenceworkflow.io/docs/cliweekly0.5https://cadenceworkflow.io/docs/conceptsweekly0.5https://cadenceworkflow.io/docs/concepts/activitiesweekly0.5https://cadenceworkflow.io/docs/concepts/archivalweekly0.5https://cadenceworkflow.io/docs/concepts/cross-dc-replicationweekly0.5https://cadenceworkflow.io/docs/concepts/eventsweekly0.5https://cadenceworkflow.io/docs/concepts/http-apiweekly0.5https://cadenceworkflow.io/docs/concepts/queriesweekly0.5https://cadenceworkflow.io/docs/concepts/search-workflowsweekly0.5https://cadenceworkflow.io/docs/concepts/task-listsweekly0.5https://cadenceworkflow.io/docs/concepts/topologyweekly0.5https://cadenceworkflow.io/docs/concepts/workflowsweekly0.5https://cadenceworkflow.io/docs/get-startedweekly0.5https://cadenceworkflow.io/docs/get-started/golang-hello-worldweekly0.5https://cadenceworkflow.io/docs/get-started/java-hello-worldweekly0.5https://cadenceworkflow.io/docs/get-started/server-installationweekly0.5https://cadenceworkflow.io/docs/get-started/video-tutorialsweekly0.5https://cadenceworkflow.io/docs/glossaryweekly0.5https://cadenceworkflow.io/docs/go-clientweekly0.5https://cadenceworkflow.io/docs/go-client/02.5-starting-workflowsweekly0.5https://cadenceworkflow.io/docs/go-client/activitiesweekly0.5https://cadenceworkflow.io/docs/go-client/activity-async-completionweekly0.5https://cadenceworkflow.io/docs/go-client/child-workflowsweekly0.5https://cadenceworkflow.io/docs/go-client/continue-as-newweekly0.5https://cadenceworkflow.io/docs/go-client/create-workflowsweekly0.5https://cadenceworkflow.io/docs/go-client/distributed-cronweekly0.5https://cadenceworkflow.io/docs/go-client/error-handlingweekly0.5https://cadenceworkflow.io/docs/go-client/execute-activityweekly0.5https://cadenceworkflow.io/docs/go-client/queriesweekly0.5https://cadenceworkflow.io/docs/go-client/retriesweekly0.5https://cadenceworkflow.io/docs/go-client/sessionsweekly0.5https://cadenceworkflow.io/docs/go-client/side-effectweekly0.5https://cadenceworkflow.io/docs/go-client/signalsweekly0.5https://cadenceworkflow.io/docs/go-client/tracingweekly0.5https://cadenceworkflow.io/docs/go-client/workersweekly0.5https://cadenceworkflow.io/docs/go-client/workflow-non-deterministic-errorweekly0.5https://cadenceworkflow.io/docs/go-client/workflow-replay-shadowingweekly0.5https://cadenceworkflow.io/docs/go-client/workflow-testingweekly0.5https://cadenceworkflow.io/docs/go-client/workflow-versioningweekly0.5https://cadenceworkflow.io/docs/java-clientweekly0.5https://cadenceworkflow.io/docs/java-client/activity-interfaceweekly0.5https://cadenceworkflow.io/docs/java-client/child-workflowsweekly0.5https://cadenceworkflow.io/docs/java-client/client-overviewweekly0.5https://cadenceworkflow.io/docs/java-client/continue-as-newweekly0.5https://cadenceworkflow.io/docs/java-client/distributed-cronweekly0.5https://cadenceworkflow.io/docs/java-client/exception-handlingweekly0.5https://cadenceworkflow.io/docs/java-client/implementing-activitiesweekly0.5https://cadenceworkflow.io/docs/java-client/implementing-workflowsweekly0.5https://cadenceworkflow.io/docs/java-client/queriesweekly0.5https://cadenceworkflow.io/docs/java-client/retriesweekly0.5https://cadenceworkflow.io/docs/java-client/side-effectweekly0.5https://cadenceworkflow.io/docs/java-client/signalsweekly0.5https://cadenceworkflow.io/docs/java-client/starting-workflow-executionsweekly0.5https://cadenceworkflow.io/docs/java-client/testingweekly0.5https://cadenceworkflow.io/docs/java-client/versioningweekly0.5https://cadenceworkflow.io/docs/java-client/workersweekly0.5https://cadenceworkflow.io/docs/java-client/workflow-interfaceweekly0.5https://cadenceworkflow.io/docs/java-client/workflow-replay-shadowingweekly0.5https://cadenceworkflow.io/docs/operation-guideweekly0.5https://cadenceworkflow.io/docs/operation-guide/maintainweekly0.5https://cadenceworkflow.io/docs/operation-guide/migrationweekly0.5https://cadenceworkflow.io/docs/operation-guide/monitoringweekly0.5https://cadenceworkflow.io/docs/operation-guide/setupweekly0.5https://cadenceworkflow.io/docs/operation-guide/troubleshootingweekly0.5https://cadenceworkflow.io/docs/use-casesweekly0.5https://cadenceworkflow.io/docs/use-cases/batch-jobweekly0.5https://cadenceworkflow.io/docs/use-cases/big-mlweekly0.5https://cadenceworkflow.io/docs/use-cases/deploymentweekly0.5https://cadenceworkflow.io/docs/use-cases/dslweekly0.5https://cadenceworkflow.io/docs/use-cases/event-drivenweekly0.5https://cadenceworkflow.io/docs/use-cases/interactiveweekly0.5https://cadenceworkflow.io/docs/use-cases/operational-managementweekly0.5https://cadenceworkflow.io/docs/use-cases/orchestrationweekly0.5https://cadenceworkflow.io/docs/use-cases/partitioned-scanweekly0.5https://cadenceworkflow.io/docs/use-cases/periodic-executionweekly0.5https://cadenceworkflow.io/docs/use-cases/pollingweekly0.5https://cadenceworkflow.io/docs/use-cases/provisioningweekly0.5https://cadenceworkflow.io/docs/workflow-troubleshootingweekly0.5https://cadenceworkflow.io/docs/workflow-troubleshooting/activity-failuresweekly0.5https://cadenceworkflow.io/docs/workflow-troubleshooting/retriesweekly0.5https://cadenceworkflow.io/docs/workflow-troubleshooting/timeoutsweekly0.5https://cadenceworkflow.io/weekly0.5 \ No newline at end of file +https://cadenceworkflow.io/Cadence-Docs/blogweekly0.5https://cadenceworkflow.io/Cadence-Docs/blog/2021/09/30/long-term-commitment-and-support-for-the-cadence-project-and-its-communityweekly0.5https://cadenceworkflow.io/Cadence-Docs/blog/2021/10/13/announcing-cadence-oss-office-hours-and-community-sync-upweekly0.5https://cadenceworkflow.io/Cadence-Docs/blog/2021/10/19/2021-10-19-moving-to-grpc/moving-to-grpcweekly0.5https://cadenceworkflow.io/Cadence-Docs/blog/2022/01/31/community-spotlight-january-2022weekly0.5https://cadenceworkflow.io/Cadence-Docs/blog/2022/02/28/community-spotlight-february-2022weekly0.5https://cadenceworkflow.io/Cadence-Docs/blog/2022/03/31/community-spotlight-update-march-2022weekly0.5https://cadenceworkflow.io/Cadence-Docs/blog/2022/04/30/community-spotlight-update-april-2022weekly0.5https://cadenceworkflow.io/Cadence-Docs/blog/2022/05/31/community-spotlight-update-may-2022weekly0.5https://cadenceworkflow.io/Cadence-Docs/blog/2022/06/30/community-spotlight-update-june-2022weekly0.5https://cadenceworkflow.io/Cadence-Docs/blog/2022/07/31/community-spotlight-update-july-2022weekly0.5https://cadenceworkflow.io/Cadence-Docs/blog/2022/08/31/community-spotlight-august-2022weekly0.5https://cadenceworkflow.io/Cadence-Docs/blog/2022/09/30/community-spotlight-september-2022weekly0.5https://cadenceworkflow.io/Cadence-Docs/blog/2022/10/31/community-spotlight-october-2022weekly0.5https://cadenceworkflow.io/Cadence-Docs/blog/2022/11/30/community-spotlight-november-2022weekly0.5https://cadenceworkflow.io/Cadence-Docs/blog/2022/12/23/community-spotlight-december-2022weekly0.5https://cadenceworkflow.io/Cadence-Docs/blog/2023/01/31/community-spotlight-january-2023weekly0.5https://cadenceworkflow.io/Cadence-Docs/blog/2023/02/28/community-spotlight-februaryweekly0.5https://cadenceworkflow.io/Cadence-Docs/blog/2023/03/31/community-spotlight-march-2023weekly0.5https://cadenceworkflow.io/Cadence-Docs/blog/2023/06/08/2023-06-08-survey-results/survey-resultsweekly0.5https://cadenceworkflow.io/Cadence-Docs/blog/2023/06/28/components-of-cadence-application-setupweekly0.5https://cadenceworkflow.io/Cadence-Docs/blog/2023/06/30/community-spotlight-june-2023weekly0.5https://cadenceworkflow.io/Cadence-Docs/blog/2023/07/05/implement-cadence-worker-from-scratchweekly0.5https://cadenceworkflow.io/Cadence-Docs/blog/2023/07/10/cadence-bad-practices-part-1weekly0.5https://cadenceworkflow.io/Cadence-Docs/blog/2023/07/16/2023-07-16-write-your-first-workflow-with-cadence/write-your-first-workflow-with-cadenceweekly0.5https://cadenceworkflow.io/Cadence-Docs/blog/2023/07/31/community-spotlight-july-2023weekly0.5https://cadenceworkflow.io/Cadence-Docs/blog/2023/08/28/nondeterministic-errors-replayers-shadowersweekly0.5https://cadenceworkflow.io/Cadence-Docs/blog/2023/08/31/community-spotlight-august-2023weekly0.5https://cadenceworkflow.io/Cadence-Docs/blog/2023/11/30/community-spotlight-update-november-2023weekly0.5https://cadenceworkflow.io/Cadence-Docs/blog/2024/02/15/cadence-non-deterministic-common-qaweekly0.5https://cadenceworkflow.io/Cadence-Docs/blog/2024/07/11/2024-07-11-yearly-roadmap-update/yearly-roadmap-updateweekly0.5https://cadenceworkflow.io/Cadence-Docs/blog/2024/09/05/workflow-specific-rate-limitsweekly0.5https://cadenceworkflow.io/Cadence-Docs/blog/2024/10/01/announcing-cadence-helm-charts-v0weekly0.5https://cadenceworkflow.io/Cadence-Docs/blog/2024/11/18/cadence-workflows-github-organizationweekly0.5https://cadenceworkflow.io/Cadence-Docs/blog/2024/3/11/community-spotlight-update-march-2024weekly0.5https://cadenceworkflow.io/Cadence-Docs/blog/archiveweekly0.5https://cadenceworkflow.io/Cadence-Docs/blog/authorsweekly0.5https://cadenceworkflow.io/Cadence-Docs/blog/authors/chopincodeweekly0.5https://cadenceworkflow.io/Cadence-Docs/blog/authors/enderdemirkayaweekly0.5https://cadenceworkflow.io/Cadence-Docs/blog/authors/ibarrajoweekly0.5https://cadenceworkflow.io/Cadence-Docs/blog/authors/jakobhtweekly0.5https://cadenceworkflow.io/Cadence-Docs/blog/authors/kcorbett-netappweekly0.5https://cadenceworkflow.io/Cadence-Docs/blog/authors/meiliang-86weekly0.5https://cadenceworkflow.io/Cadence-Docs/blog/authors/shaddollweekly0.5https://cadenceworkflow.io/Cadence-Docs/blog/authors/sharanfweekly0.5https://cadenceworkflow.io/Cadence-Docs/blog/authors/sharanf/authors/2weekly0.5https://cadenceworkflow.io/Cadence-Docs/blog/authors/taylanisikdemirweekly0.5https://cadenceworkflow.io/Cadence-Docs/blog/authors/vytautas-karpaviciusweekly0.5https://cadenceworkflow.io/Cadence-Docs/blog/page/2weekly0.5https://cadenceworkflow.io/Cadence-Docs/blog/page/3weekly0.5https://cadenceworkflow.io/Cadence-Docs/blog/page/4weekly0.5https://cadenceworkflow.io/Cadence-Docs/blog/tagsweekly0.5https://cadenceworkflow.io/Cadence-Docs/blog/tags/announcementsweekly0.5https://cadenceworkflow.io/Cadence-Docs/blog/tags/cadence-operationsweekly0.5https://cadenceworkflow.io/Cadence-Docs/blog/tags/community-spotlightsweekly0.5https://cadenceworkflow.io/Cadence-Docs/blog/tags/community-spotlights/page/2weekly0.5https://cadenceworkflow.io/Cadence-Docs/blog/tags/deep-divesweekly0.5https://cadenceworkflow.io/Cadence-Docs/blog/tags/introduction-to-cadenceweekly0.5https://cadenceworkflow.io/Cadence-Docs/blog/tags/releasesweekly0.5https://cadenceworkflow.io/Cadence-Docs/blog/tags/roadmapweekly0.5https://cadenceworkflow.io/Cadence-Docs/blog/tags/testingweekly0.5https://cadenceworkflow.io/Cadence-Docs/blog/zonal-isolation-v1/zonal-isolation-v1weekly0.5https://cadenceworkflow.io/Cadence-Docs/markdown-pageweekly0.5https://cadenceworkflow.io/Cadence-Docs/searchweekly0.5https://cadenceworkflow.io/Cadence-Docs/community/contributingweekly0.5https://cadenceworkflow.io/Cadence-Docs/community/resourcesweekly0.5https://cadenceworkflow.io/Cadence-Docs/community/supportweekly0.5https://cadenceworkflow.io/Cadence-Docs/community/teamweekly0.5https://cadenceworkflow.io/Cadence-Docs/docs/aboutweekly0.5https://cadenceworkflow.io/Cadence-Docs/docs/about/licenseweekly0.5https://cadenceworkflow.io/Cadence-Docs/docs/cliweekly0.5https://cadenceworkflow.io/Cadence-Docs/docs/conceptsweekly0.5https://cadenceworkflow.io/Cadence-Docs/docs/concepts/activitiesweekly0.5https://cadenceworkflow.io/Cadence-Docs/docs/concepts/archivalweekly0.5https://cadenceworkflow.io/Cadence-Docs/docs/concepts/cross-dc-replicationweekly0.5https://cadenceworkflow.io/Cadence-Docs/docs/concepts/eventsweekly0.5https://cadenceworkflow.io/Cadence-Docs/docs/concepts/http-apiweekly0.5https://cadenceworkflow.io/Cadence-Docs/docs/concepts/queriesweekly0.5https://cadenceworkflow.io/Cadence-Docs/docs/concepts/search-workflowsweekly0.5https://cadenceworkflow.io/Cadence-Docs/docs/concepts/task-listsweekly0.5https://cadenceworkflow.io/Cadence-Docs/docs/concepts/topologyweekly0.5https://cadenceworkflow.io/Cadence-Docs/docs/concepts/workflowsweekly0.5https://cadenceworkflow.io/Cadence-Docs/docs/get-startedweekly0.5https://cadenceworkflow.io/Cadence-Docs/docs/get-started/golang-hello-worldweekly0.5https://cadenceworkflow.io/Cadence-Docs/docs/get-started/java-hello-worldweekly0.5https://cadenceworkflow.io/Cadence-Docs/docs/get-started/server-installationweekly0.5https://cadenceworkflow.io/Cadence-Docs/docs/get-started/video-tutorialsweekly0.5https://cadenceworkflow.io/Cadence-Docs/docs/glossaryweekly0.5https://cadenceworkflow.io/Cadence-Docs/docs/go-clientweekly0.5https://cadenceworkflow.io/Cadence-Docs/docs/go-client/02.5-starting-workflowsweekly0.5https://cadenceworkflow.io/Cadence-Docs/docs/go-client/activitiesweekly0.5https://cadenceworkflow.io/Cadence-Docs/docs/go-client/activity-async-completionweekly0.5https://cadenceworkflow.io/Cadence-Docs/docs/go-client/child-workflowsweekly0.5https://cadenceworkflow.io/Cadence-Docs/docs/go-client/continue-as-newweekly0.5https://cadenceworkflow.io/Cadence-Docs/docs/go-client/create-workflowsweekly0.5https://cadenceworkflow.io/Cadence-Docs/docs/go-client/distributed-cronweekly0.5https://cadenceworkflow.io/Cadence-Docs/docs/go-client/error-handlingweekly0.5https://cadenceworkflow.io/Cadence-Docs/docs/go-client/execute-activityweekly0.5https://cadenceworkflow.io/Cadence-Docs/docs/go-client/queriesweekly0.5https://cadenceworkflow.io/Cadence-Docs/docs/go-client/retriesweekly0.5https://cadenceworkflow.io/Cadence-Docs/docs/go-client/sessionsweekly0.5https://cadenceworkflow.io/Cadence-Docs/docs/go-client/side-effectweekly0.5https://cadenceworkflow.io/Cadence-Docs/docs/go-client/signalsweekly0.5https://cadenceworkflow.io/Cadence-Docs/docs/go-client/tracingweekly0.5https://cadenceworkflow.io/Cadence-Docs/docs/go-client/workersweekly0.5https://cadenceworkflow.io/Cadence-Docs/docs/go-client/workflow-non-deterministic-errorweekly0.5https://cadenceworkflow.io/Cadence-Docs/docs/go-client/workflow-replay-shadowingweekly0.5https://cadenceworkflow.io/Cadence-Docs/docs/go-client/workflow-testingweekly0.5https://cadenceworkflow.io/Cadence-Docs/docs/go-client/workflow-versioningweekly0.5https://cadenceworkflow.io/Cadence-Docs/docs/java-clientweekly0.5https://cadenceworkflow.io/Cadence-Docs/docs/java-client/activity-interfaceweekly0.5https://cadenceworkflow.io/Cadence-Docs/docs/java-client/child-workflowsweekly0.5https://cadenceworkflow.io/Cadence-Docs/docs/java-client/client-overviewweekly0.5https://cadenceworkflow.io/Cadence-Docs/docs/java-client/continue-as-newweekly0.5https://cadenceworkflow.io/Cadence-Docs/docs/java-client/distributed-cronweekly0.5https://cadenceworkflow.io/Cadence-Docs/docs/java-client/exception-handlingweekly0.5https://cadenceworkflow.io/Cadence-Docs/docs/java-client/implementing-activitiesweekly0.5https://cadenceworkflow.io/Cadence-Docs/docs/java-client/implementing-workflowsweekly0.5https://cadenceworkflow.io/Cadence-Docs/docs/java-client/queriesweekly0.5https://cadenceworkflow.io/Cadence-Docs/docs/java-client/retriesweekly0.5https://cadenceworkflow.io/Cadence-Docs/docs/java-client/side-effectweekly0.5https://cadenceworkflow.io/Cadence-Docs/docs/java-client/signalsweekly0.5https://cadenceworkflow.io/Cadence-Docs/docs/java-client/starting-workflow-executionsweekly0.5https://cadenceworkflow.io/Cadence-Docs/docs/java-client/testingweekly0.5https://cadenceworkflow.io/Cadence-Docs/docs/java-client/versioningweekly0.5https://cadenceworkflow.io/Cadence-Docs/docs/java-client/workersweekly0.5https://cadenceworkflow.io/Cadence-Docs/docs/java-client/workflow-interfaceweekly0.5https://cadenceworkflow.io/Cadence-Docs/docs/java-client/workflow-replay-shadowingweekly0.5https://cadenceworkflow.io/Cadence-Docs/docs/operation-guideweekly0.5https://cadenceworkflow.io/Cadence-Docs/docs/operation-guide/maintainweekly0.5https://cadenceworkflow.io/Cadence-Docs/docs/operation-guide/migrationweekly0.5https://cadenceworkflow.io/Cadence-Docs/docs/operation-guide/monitoringweekly0.5https://cadenceworkflow.io/Cadence-Docs/docs/operation-guide/setupweekly0.5https://cadenceworkflow.io/Cadence-Docs/docs/operation-guide/troubleshootingweekly0.5https://cadenceworkflow.io/Cadence-Docs/docs/use-casesweekly0.5https://cadenceworkflow.io/Cadence-Docs/docs/use-cases/batch-jobweekly0.5https://cadenceworkflow.io/Cadence-Docs/docs/use-cases/big-mlweekly0.5https://cadenceworkflow.io/Cadence-Docs/docs/use-cases/deploymentweekly0.5https://cadenceworkflow.io/Cadence-Docs/docs/use-cases/dslweekly0.5https://cadenceworkflow.io/Cadence-Docs/docs/use-cases/event-drivenweekly0.5https://cadenceworkflow.io/Cadence-Docs/docs/use-cases/interactiveweekly0.5https://cadenceworkflow.io/Cadence-Docs/docs/use-cases/operational-managementweekly0.5https://cadenceworkflow.io/Cadence-Docs/docs/use-cases/orchestrationweekly0.5https://cadenceworkflow.io/Cadence-Docs/docs/use-cases/partitioned-scanweekly0.5https://cadenceworkflow.io/Cadence-Docs/docs/use-cases/periodic-executionweekly0.5https://cadenceworkflow.io/Cadence-Docs/docs/use-cases/pollingweekly0.5https://cadenceworkflow.io/Cadence-Docs/docs/use-cases/provisioningweekly0.5https://cadenceworkflow.io/Cadence-Docs/docs/workflow-troubleshootingweekly0.5https://cadenceworkflow.io/Cadence-Docs/docs/workflow-troubleshooting/activity-failuresweekly0.5https://cadenceworkflow.io/Cadence-Docs/docs/workflow-troubleshooting/retriesweekly0.5https://cadenceworkflow.io/Cadence-Docs/docs/workflow-troubleshooting/timeoutsweekly0.5https://cadenceworkflow.io/Cadence-Docs/weekly0.5 \ No newline at end of file