Of all the syntax options they could've gone with, they settled on what I would say is arguably the worst. If you want a one-liner, decorators are widely used across different languages and Typescript supports them as well.
Decorators don't work for functions, unfortunately, so wouldn't work in this case. You'd need to add a bunch of class boilerplate to make it work.
JavaScript didn't have a lot of great options for this kind of statically-declared metaprogramming, which is why the "use X"; syntax has become so popular in various spaces. It's definitely not my favourite approach, but I don't think there's any clear "best" solution here.
Since this magic string requires a preprocessor step anyway, there's no reason they couldn't make it a decorator that works on functions. I don't see the problem?
Looking at the AST [0], this doesn't seem to be the case. Since Typescript already supports decorators in other contexts, it successfully parses everything and identifies the decorator to boot. Since you're working in a preprocessor context anyway, there's a number of options to make all of this work well together.
It's on the landing page, there is not even a standalone mode yet, so you can't use it with node.js you need to use with Next.js. All to say, it's just early alpha preview, I would wait the project to mature before considering using it anywhere.
This is Open Telemetry functions you're referencing. Being able to trace, profile and debug your own code that's executing in a highly distributed environment is a pretty useful thing. This isn't (necessarily) user behavior telemetry.
At least understand what you're looking at before getting the ick.
Good luck running a server without any sort of telemetry. How will you debug stuff without logs and traces? Seems to me that the priorities are with practical, real everyday engineering concerns.
This seems pretty similar to Cloudflare Workflows (https://developers.cloudflare.com/workflows/), but with code-rewriting to use syntax magic (functions annotated with "use workflow" and "use step") instead of Cloudflare's `step.do` and `step.sleep` function calls. (I think I lightly prefer Cloudflare's model for not relying on a code-rewriting step, partly because I think it's easier for programmers to see what's going on in the system.) Workflow's Hooks are similar to Cloudflare's `step.waitForEvent` + `instance.sendEvent`. It's kind of exciting to see this programming model get more popular. I wonder if the ecosystem can evolve into a standardized model.
So this seems similar to https://temporal.io/, am I reading this right? I used that briefly a few years ago and it was pretty nice at the time. It did make some features much easier to model like their welcome email example. Would love to hear from someone with extensive temporal experience, iirc the only drawback was on the infra side of things.
So at it's core this is "just" a toolkit to add automatic retries to functions inside another function?
I don't know if the audience Vercel is targetig knows about idempotency as well as they should before plastering all their functions with "use workflow".
I guess in the end it's another abstraction layer for queues or state machines and another way to lock you into Vercel.
This is actually pretty cool. We have a similar custom library at Xbox that's used extensively across all of our services.
I do wish that there was some kind of self-hostable World implementation at launch. If other PAAS providers jump onto this, I could see this sticking around.
Hi I’m Gal from the team. Thanks! We did ship a reference Postgres implementation. It would receive more love now that we open sourced, but we can’t call it “production ready” without running it in production.
But we did have convos in the last couple of days on what we can do next on the pg world ;D
I'd rather be explicit about what's going on at each step. That way idempotent functions can be handled differently, retry limits can be applied, and no separate preprocessor is required.
export async function welcome(userId: string) {
const user = await retry(() => getUser(userId));
const { subject, body } = await retry(() => generateEmail({
name: user.name, plan: user.plan
}));
const { status } = await retry(() => sendEmail({
to: user.email,
subject,
body,
}), 2);
return { status, subject, body };
}
It's not really clear how you "update" a workflow/step method?
What happens if you saw a bug, or you want to update and change a workflow? Is there a way to discard / upgrade the existing in-memory workflows that are being executed (and correspond to the previous version) so they are now "updated"?
Somewhat related since this about "workflows" and not cloud function, but are there any practical benefits to cloud functions other than the fact that it's cheaper for the providers as they don't have to run an entire bespoke runtime for every customer/application?
looking at the docs and examples, I see Workflows and Steps and Retries, but I don't see any Durable yet. none of the examples really make it clear how or where anything gets stored
That depends on the “world”. We built an adapter interface so you could store the data (and other things) anywhere you want. There are some docs which are wip regarding that: https://useworkflow.dev/docs/deploying/world
"use strict" has been around since 2009. That being said, this is not a TypeScript or React feature but yet another black box magic NextJS feature to try to lock you into the Vercel ecosystem.
Not only is it ugly in terms of language design, the feature depends on over-engineered frameworks like Next.js and Nitro. Magic string literals that rewrite your functions? No thanks.
Lost me at "use workflow" directive. This and Next16 expanding the set of directives just makes me question if I'm the mad man for thinking they are absolutely terrible.
Of all the syntax options they could've gone with, they settled on what I would say is arguably the worst. If you want a one-liner, decorators are widely used across different languages and Typescript supports them as well.
Decorators don't work for functions, unfortunately, so wouldn't work in this case. You'd need to add a bunch of class boilerplate to make it work.
JavaScript didn't have a lot of great options for this kind of statically-declared metaprogramming, which is why the "use X"; syntax has become so popular in various spaces. It's definitely not my favourite approach, but I don't think there's any clear "best" solution here.
You can use generator fns to achieve the exact same thing without magic strings or bundles. And the bonus is that you can debug it.
Since this magic string requires a preprocessor step anyway, there's no reason they couldn't make it a decorator that works on functions. I don't see the problem?
But then it's not valid TypeScript anymore. So all the other tooling breaks: syntax highlighting, LSP, Linter, ...
Looking at the AST [0], this doesn't seem to be the case. Since Typescript already supports decorators in other contexts, it successfully parses everything and identifies the decorator to boot. Since you're working in a preprocessor context anyway, there's a number of options to make all of this work well together.
[0] https://ts-ast-viewer.com/#code/GYVwdgxgLglg9mABMOcAUBKRBvAU...
Instead of decorators, it could be just a higher-order function. Which could handle it easily and in any scenario that interchanges between TS/JS.
Yea but it's a vercel product and they also pushed the 'use server' and 'use client' directives and probably want to build on them.
Absolutely bizarre decisions.
My bad, this is open telemetry stuff to check the status of your servers, not for vendors to extract as much data as they can from you.
> I'm trying to find how they implemented the "use workflow" thing, and before I could find it I already found https://github.com/vercel/workflow/blob/main/packages/core/s...
> Telemetry is part of the core.
> Yuck.
It's on the landing page, there is not even a standalone mode yet, so you can't use it with node.js you need to use with Next.js. All to say, it's just early alpha preview, I would wait the project to mature before considering using it anywhere.
My bad, this is open telemetry stuff to check the status of your servers, not for the vendor to slurp as much data from you as possible.
This is Open Telemetry functions you're referencing. Being able to trace, profile and debug your own code that's executing in a highly distributed environment is a pretty useful thing. This isn't (necessarily) user behavior telemetry.
At least understand what you're looking at before getting the ick.
That's fair. I'm too accustomed to seeing the other type of telemetry shoved in all over the place.
Good luck running a server without any sort of telemetry. How will you debug stuff without logs and traces? Seems to me that the priorities are with practical, real everyday engineering concerns.
It’s apparently an swc compiler plugin.
or no-op functions like useWorkflow() (with some kind of stub that prevents dead code elimination).
So vercel is adamant on making nextjs apps behavior completely unpredictable and hidden behind tons of magic code?
At least in any other framework library I can just command click and see why things are not working, place breakpoints and even modify code.
That's what I hate about Next.js.
I guess most of the people who develop with Next.js are probably newbies who don't know and don't even care how things work behind frameworks.
To go even further, they probably have no idea how to host a website in their own server, since they all they ever used is vercel CLI, lol.
It’s a great business model with epic lock in. Bored front end devs keep indulging / enabling it so why stop?
This seems pretty similar to Cloudflare Workflows (https://developers.cloudflare.com/workflows/), but with code-rewriting to use syntax magic (functions annotated with "use workflow" and "use step") instead of Cloudflare's `step.do` and `step.sleep` function calls. (I think I lightly prefer Cloudflare's model for not relying on a code-rewriting step, partly because I think it's easier for programmers to see what's going on in the system.) Workflow's Hooks are similar to Cloudflare's `step.waitForEvent` + `instance.sendEvent`. It's kind of exciting to see this programming model get more popular. I wonder if the ecosystem can evolve into a standardized model.
So this seems similar to https://temporal.io/, am I reading this right? I used that briefly a few years ago and it was pretty nice at the time. It did make some features much easier to model like their welcome email example. Would love to hear from someone with extensive temporal experience, iirc the only drawback was on the infra side of things.
And to DBOS too
So at it's core this is "just" a toolkit to add automatic retries to functions inside another function? I don't know if the audience Vercel is targetig knows about idempotency as well as they should before plastering all their functions with "use workflow".
I guess in the end it's another abstraction layer for queues or state machines and another way to lock you into Vercel.
This is actually pretty cool. We have a similar custom library at Xbox that's used extensively across all of our services.
I do wish that there was some kind of self-hostable World implementation at launch. If other PAAS providers jump onto this, I could see this sticking around.
Hi I’m Gal from the team. Thanks! We did ship a reference Postgres implementation. It would receive more love now that we open sourced, but we can’t call it “production ready” without running it in production.
But we did have convos in the last couple of days on what we can do next on the pg world ;D
Azures Durable Task Framework or something else? I guess there’s nothing public on it, which is a shame because it sounds interesting
I'd rather be explicit about what's going on at each step. That way idempotent functions can be handled differently, retry limits can be applied, and no separate preprocessor is required.
"use turnMyBrainOff";
"use blackBoxWrapperForEverything";
Am I stupid, or does the page not actually explain that workflow is?
It doesn't explain it on the landing page. Even skimming their docs, it seems like you mostly have to infer the purpose of this based on the features.
Use client and use server aren’t great, but the fact they had to be declared at the top of a file was at least clear.
Starting to scatter magic strings throughout a code base feels like a real step back.
There's nothing about "use server" that requires it to be at the top of the file though, it can go in function bodies and you have a typed RPC method.
I think "use client" is the only one that has to go at the top of a file.
You are correct. Use server can be slapped in many places
It's not really clear how you "update" a workflow/step method?
What happens if you saw a bug, or you want to update and change a workflow? Is there a way to discard / upgrade the existing in-memory workflows that are being executed (and correspond to the previous version) so they are now "updated"?
Somewhat related since this about "workflows" and not cloud function, but are there any practical benefits to cloud functions other than the fact that it's cheaper for the providers as they don't have to run an entire bespoke runtime for every customer/application?
can anyone point to the "Durable" part?
looking at the docs and examples, I see Workflows and Steps and Retries, but I don't see any Durable yet. none of the examples really make it clear how or where anything gets stored
That depends on the “world”. We built an adapter interface so you could store the data (and other things) anywhere you want. There are some docs which are wip regarding that: https://useworkflow.dev/docs/deploying/world
well that's some scary typescript syntax. i didnt know a string constant at the top of a function could change the operation.
or is this some extra compilation step to rewrite the code?
"use strict" has been around since 2009. That being said, this is not a TypeScript or React feature but yet another black box magic NextJS feature to try to lock you into the Vercel ecosystem.
Must be some compile step. Reminds me of “use strict”.
im becoming increasinglymore convinced that workflows are the wrong model
just build state machines folks
workflows is just short for state machine DSL
but with history length and replay determinism landmines
This seems... bad, inelegant.
Not only is it ugly in terms of language design, the feature depends on over-engineered frameworks like Next.js and Nitro. Magic string literals that rewrite your functions? No thanks.
i hate the new pattern of using these magic strings everywhere. “use workflow”, “use client”, etc etc.
I don’t like having custom bundler logic for my code.
Custom bundler + telemetry already included. Smells way too much like Microsoft, too much like lock-in with a deal that gets worse and worse.
"don't use next"
"don't use react"
Lost me at "use workflow" directive. This and Next16 expanding the set of directives just makes me question if I'm the mad man for thinking they are absolutely terrible.