mfateev
I certainly don't think I'm superior to them in any way and have great respect for the very capable team they are. We know each other personally. I even presented at the Flink conference while at Uber.
My message is that I'd prefer a more technical discussion of the merits of our products rather than simplified marketing attacks.
Temporal has 3 types of activities:
* local: executed in the same process as the orchestrator code. Many local activities can be executed locally before their results are sent to a backend server in a single RPC call.
* task queue based: executed by a pool of worker processes that poll from the queue. This is the most flexible model as it supports flow control, priorities, fair queueing out of the box.
* eager dispatch: task queue based but executed locally if possible as a performance optimization.
Temporal also supports stand alone activities that are invoked without a workflow and dispatched through a task queue.
Restate only supports local activities (using Temporal terminology).
I wouldn't call it a "more flexible programming model".
Restate made several decisions I consider questionable for the system's availability and stability, like pushing work to handlers instead of dispatching it through a queue. Any design decision has tradeoffs. It would be nice if you mentioned these trade-offs in your posts instead of making claims that sound like pure marketing.
So we switched to replay. The biggest benefit of replay is that it lets you implement Durable Execution in any language as a library without a complex runtime. It also supports code changes while workflows are in flight (Temporal calls this patching). Making snapshots of arbitrary code state backward-compatible with code changes isn't practical.
I personally think that, in the long term, Durable Execution will use a runtime that supports both snapshotting and determinism. That way, snapshots can be taken infrequently, and replay can bring workflow code to the latest state. Similarly to a database recovering from a WAL. WASM is the most promising technology to achieve this.
The ease of troubleshooting is one of the frequently cited benefits of the approach.
Check the UI screenshot at https://www.temporal.io/how-it-works.
Disclaimer: I'm one of the founders of the project.
At the framework level they might be pretty useful, but they rarely appear at the first version, but as a result of refactoring.
The other useful pattern is always running workflows that can be used to model lifecycle of various entities. For example you can have an always running workflow per customer which would manage its service subscription and other customer related features.
Here is a more detailed answer from Temporal forum: https://community.temporal.io/t/why-use-temporal-over-a-comb...
Disclaimer: I'm one of the founders of the project.
The issue is that 99.9% of developers use queues directly in their business applications.
Disclaimer: I'm the tech lead of the temporal.io open source project and the CEO of the affiliated company.
Here is an example using Typescript SDK:
async function main(userId, intervals){
// Send reminder emails, e.g. after 1, 7, and 30 days
for (const interval of intervals) {
await sleep(interval * DAYS);
// can take hours if the downstream service is down
await activities.sendEmail(interval, userId);
}
// Easily cancelled when user unsubscribes
}
Disclaimer: I'm one of the creators of the project.Microsoft is based on Git, but with a lot of engineering on top of it: https://devblogs.microsoft.com/bharry/scaling-git-and-some-b...
I believe you confused it with a Dynamo DB described in a paper Amazon published long ago. AWS DynamoDB has nothing to do with a eventually consistent design the paper describes. It was purely marketing gimmick to call the new AWS Service that.
temporal.io and Windows Workflow Foundation are completely different. WF uses code to generate an intermediate representation of the workflow AST. And that intermediate representation is executed. It is similar to the most existing workflow engines from Airflow to BMPN ones.
Temporal doesn't use any intermediate representation. It directly executes the code keeping all its state durable.
> I don't entirely agree with your comment about state management and argument passing in Petri nets.
When I say about the state I mean the overall state of the business project which is much more than a token in a certain dish. For example such state can include a list of line items to order with all associated attributes and counters of processed events.
> I'd argue that, the tool you describe could be modeled as a Petri net, but that perhaps you may not wish to have a user do it that way.
All software at the lowest level can be modeled as a state machine. And Petri net is one of the possible representation of FSN. I'm interested in simplifying the way the workflow logic is specified by an engineer. At this point I believe the temporal.io approach of giving your the full power of a high level programming language and taking care of durability and scalability is the best option.
Long time ago I worked with an internal Amazon workflow engine that was based on Petri nets. It worked, but I learned that for the majority of the business level workflows it was too low level. It was always a hassle to map a real use case to it.
The AWS Simple Workflow service was created as a replacement of that engine. It greatly elevated the lel of abstraction. The Azure Durable Functions, Uber Cadence, and our latest project temporal.io are all use this new way to represent workflows. The basic idea is to not implement the business logic using an intermediate representation. Instead rely on runtime to make any code state fully fault tolerant. Imagine that the full orchestrating program state (including threads, local variables and even blocking calls) is preserved across any process and other infrastructure failures. This allows to write production code like this:
boolean trialPeriod = true;
while (true) {
Workflow.sleep(Duration.ofDays(30));
activities.chargeMonthlyFee(customerId);
if (trialPeriod) {
activities.sendEndOfTrialEmail(customerId);
trialPeriod = false;
} else {
activities.sendMonthlyChargeEmail(customerId);
}
}
As the state is fault tolerant the 30 day sleep is absolutely OK. And if any of this operations takes long time (for example because a downstream service is down for a day) the code doesn't need to change. I bet that any Petri nets based version of the above code would be much more complicated. One of the reasons that large part of the complexity of the business level workflows is not in sequencing of actions (which Petri nets solve), but in state management and argument passing (which Petri nets don't solve at all). public void execute(String customerId) {
activities.sendWelcomeEmail(customerId);
try {
boolean trialPeriod = true;
while (true) {
Workflow.sleep(Duration.ofDays(30));
activities.chargeMonthlyFee(customerId);
if (trialPeriod) {
activities.sendEndOfTrialEmail(customerId);
trialPeriod = false;
} else {
activities.sendMonthlyChargeEmail(customerId);
}
}
} catch (CancellationException e) {
activities.processSubscriptionCancellation(customerId);
activities.sendSorryToSeeYouGoEmail(customerId);
}
}It is hard to describe as it is a new way to build distributed applications that doesn't have a commonly agreed name yet.
It looks simple on the surface. So almost any company ends up creating an implementation similar to the one described in the article. Then it learns that it is much harder than looks, but it is usually too late. So they end up maintaining it for a long time with the original team long gone.
BTW I believe that temporal.io (I'm tech lead of the project) is so far the best open source solution to this problem.
temporal.io our fork of Cadence will have PHP support very soon. Support for other languages is coming. Python and Typescript are the highest priority.