u/Pozzuh
-
0points
-
4points
-
4points
Pozzuh
Pozzuh
Do you think "no code" still makes sense? Shouldn't an AI build these workflows for me instead of being forced to drag around nodes in a graph builder?
Pozzuh
Pi. With a couple of small custom built extensions that enhance my personal workflow.
Pozzuh
Makker. Wat is dit voor repost? Dit is letterlijk mijn huis. Heb hier m'n best voor gedronken.
Pozzuh
Could you share a bit more details?
Pozzuh
Do you have some examples of agent tooling you're talking about? Not sure I understand the question. I try to use remote MCPs when possible.
Pozzuh
Building integrations with external APIs is now relatively simple (because of coding agents, of course), but actually creating API keys, test accounts, etc is still a pain. Agents usually don't help there. Also in an enterprise context there are often subtle differences between what features customers of a SaaS are paying for, feature flags are enabled, etc. This makes it very hard to test all edge cases for integrations. Especially when you need to create separate accounts and API keys for these cases, and potentially pay the SaaS provider even though you're only using them for testing an integration.
A platform of fake SaaS APIs that require minimal setup sounds very useful to me.
Pozzuh
Heerlijk glaasje Duits melk, geniet er van beste man
Pozzuh
I want it to be more integrated with the ecosystem I'm building. You can see the outline here, but it's not production ready.
Pozzuh
I'm working on something like this myself, but until that's ready: https://openworkflow.dev/
Pozzuh
Making sure your database schema makes sense and checking if all indexes are present/used is usually way better ROI than profiling backend code. Unless you're doing super compute intensive stuff. YMMV
Pozzuh
I do think it's a culture thing. A toolkit like Fragno wouldn't really even be needed in the Django, Rails, or Laravel worlds. Those frameworks are already very much "batteries included".
Pozzuh
You make a good point. Right now, database migrations are handled by the user's migration system (e.g. Drizzle). We do track schema changes by making the schema definition an "append-only log":
```ts const mySchema = schema((s) => { return s .addTable("users", (t) => t.addColumn("id", idColumn()).addColumn("name", column("string"))) .addTable("posts", (t) => t.addColumn("id", idColumn()).addColumn("title", column("string"))) .alterTable("users", (t) => t.addColumn("email", column("string"))); });
// mySchema.version === 3 // Three operations = version 3 ```
Right now, the schema altering operations are intentionally limited. You can only add tables, columns and indexes. I.e. removing is unsupported right now. This is something that makes everything easier for now, but will have to be worked on in the future.
For breaking changes in routes we also take the easy path. Since we integrate into full-stack applications, we assume frontend and backend are updated at the same time. Also something we can adjust in the future. Many of these things can be fixed in "user land" by adding new routes/hooks instead of having breaking changes in pre-existing ones.
Pozzuh
Building blocks for other SaaS developers. One click integration for Stripe, Form Building, File Uploads, etc.
Pozzuh
I don't think a boilerplate is really worth it. To be honest, I always found them a bit iffy. Not knowing the very basis of the codebase your product is built on top of makes everything harder.
What I'm bullish on is modular building blocks that can be integrated into codebases. That's what I'm working on with Fragno.
We built "full-stack libraries" that are basically full integration packages for Stripe and a Form builder/submission system. With these building blocks, you don't need a boilerplate.
Pozzuh
Thanks for checking it out! The Workflow Library/fragment isn't quite ready for prime time yet, hence why I didn't mention it in the initial post.
The dispatcher system (that workflows use) is to process the durable hooks outbox that I also mentioned in my other comment. If you're self hosting it's fine to use the database polling method. For serverless platforms, there's not really a generic way to have background processes, that's why we built the HTTP-based method, since that would work anywhere.
Right now I'm not sure what a Redis-based solution could look like, but everything is set up in a pretty generic way, so I'm sure it would be possible.
Pozzuh
Yes, that's precisely how you'd integrate.
In Express:
ts
app.all("/api/example-fragment/*", toNodeHandler(createExampleFragmentInstance().handler));
In something like Next.js you'd have to create a file-based router file in the right location, e.g. app/api/example-fragment/[...all]/route.ts.
Pozzuh
These are good questions (and a lot of them).
It really depends on your setup. Our docs site (and testbed) is deployed to Cloudflare Workers, there we use a SQLite setup on top of Durable Objects. That makes it easy to have full isolation (each library gets a separate DO). So basically this is a isolated DB per library.
Having everything in a single Postgres database also works, here we use Postgres Schemas by default. The end-user can also overwrite this to instead have a suffix on every database table. This pattern is nicest when you want to do cross-library joins from application code. In MySQL we default to <table_name>_<library_name> by default.
I used to work on distributed systems, so I'm taking inspiration from there for interop. We have a concept of "durable hooks" which is basically the outbox pattern. Libraries can define hooks that are persisted along with other database operations in a transaction. Users can then use these to execute logic in their own application. If the logic fails, we can retry.
For example, we have a library for tracking our mailing list. The library has a hook onUserSubscribed, which we use to notify ourselves that someone has signed up. You can read more on this here.
Not sure I understand your middleware question. We support middleware so that the end-user can control if routes defined in libraries are accessible. Docs here
Pozzuh
Yeah, for every problem ORMs solve they seem to introduce a new one as well. Love-hate relationship.
Pozzuh
Interesting idea, but the current implementation seems quite noisy. I ran this on my OSS project Fragno, to give readers an idea:
▼ /Users/me/dev/fragno (1568)
├── ▼ Fragment Platform (106)
│ ├── ▶ Fragment Authoring (7)
│ ├── ▶ *.md: Developer Guidelines (9)
│ ├── ▶ Upload Fragment (10)
│ ├── ▶ Stripe Integration (9)
│ ├── ▶ Service Middleware (6)
│ ├── ▶ Server Integration (12)
│ ├── ▶ Corpus Tools (9)
│ ├── ▶ Project Overview (11)
│ ├── ▶ apps/docs/content/docs/*meta.json: Docs Metadata (14)
│ ├── ▶ packages/auth/src/*.ts: Auth Services (12)
│ └── ▶ packages/auth/src/*.ts: Auth Types (7)
├── ▶ Schema Runtime (205)
├── ▶ Release Workflow (66)
├── ▼ Workflow Runner (100)
│ ├── ▶ *.md: Workflows Implementation (6)
│ ├── ▶ Dispatcher Implementation (5)
│ ├── ▶ Workflows Documentation (6)
│ ├── ▶ Test Prompts (6)
│ ├── ▼ Durable Hooks (4)
│ │ ├── apps/docs/content/docs/fragno/for-library-authors/database-integration/durable-hooks.mdx: Durable hooks usage and guidance
│ │ ├── packages/fragno-db/src/hooks/durable-hooks-processor.ts: Create durable hooks processor utility
│ │ ├── packages/fragno-db/src/hooks/hooks.ts: Hook lifecycle and scheduling implementation
│ │ └── packages/fragno-test/src/durable-hooks.ts: Test helper to drain hooks
│ ├── ▶ *.ts: Workflow Servers (5)
│ ├── ▶ *.ts: Database Schemas (4)
│ ├── ▶ *.test.ts: Workflow Tests (5)
│ ├── ▶ Runner Internals (5)
│ ├── ▶ packages/fragment-workflows/src/*.ts: Fragment Core (7)
│ ├── ▶ packages/frag*.ts: Bindings Adapter (4)
│ ├── ▶ packages/fragment-workflows/src/runner*.ts: Runner Orchestrator (4)
│ ├── ▶ packages/fragment-workflows/src/*s.ts: Runner Utilities (4)
│ ├── ▼ packages/fragment-workflows/workflows-smoke-artifacts/*.js: Concurrency Tests
(and it goes on for a while, but Reddit doesn't allow me to post it all)
Pozzuh
Cloudflare D1 is a confusing product to me. It feels feature incomplete. Are we just supposed to use Durable Objects instead?
We can’t, for instance, run a batch of updates, and fail the whole batch if one update didn’t change any record. The batch will only fail if the database throws an exception. An exception can be in SQLite only called by a table constraint or trigger.
This has bitten me as well. Makes batching pretty useless for transactional semantics.
Pozzuh
This post about Split Brain Stripe Integrations will probably help you understand what problems you'll be dealing with. Good luck!
Would love to see both RSIs solved