Earlier quoted context omitted.
Hmmm. When was the last time you wrote php? One file per route has been outdated for over 10 years.
This particular codebase I am maintaining is 10-20 years old. The point stands. Isolated code paths are great until you have to care about the ways they are not actually isolated (e.g. common database, platform-specific code, etc.).
Keep the monolith, but split the workloads
141–150 of 161 posts
Re: Keep the monolith, but split the workloads
#142Earlier quoted context omitted.
You’ll find some libraries do this for you, such as HTTP servers. They do this because if your server code makes a mistake such as accessing a nil pointer, a segfault or panic would bring down the entire process. That’s why you want to recover(), to avoid a your process dying.
> They do this because if your server code makes a mistake This is neither good or best practice. My take: - Know that there are simple-mistake panics, and internal-state-just-went-bonkers panics. For the latter, you can guess the boundary of impact (one request, one connection, one job, one userID, one process, ...) but exit(1) is much more reliable than guessing. - Tests can easily catch simple mistakes like access…
Re: Keep the monolith, but split the workloads
#143We do something similar with Reclaim.ai: It's one monolith Java repo, split into two major workloads that have the same runtime code but are configured differently. In our case, the two workflows are "api" and "jobs". This allows for operational issues on, say, jobs while still allowing user-facing APIs to be less likely to be impacted. The source code itself has many modules, but we deploy it as a single unified run…
Re: Keep the monolith, but split the workloads
#144I never see a blog post looking at the specific requirements of an application and fitting the architecture, data model, and implementation to those requirements. "Monolith vs Microservices" is like saying "18-wheeler vs 20 Toyota Corollas". There are other forms of transportation, and using just one mode may not serve your business well. By the way, it's 2023... if you have a greenfield project, you should be using…
>if you have a greenfield project, you should be using event-driven data processing. We got rid of the horse and buggy, let's please get rid of cron jobs. I don't see why event driven processing and cron-jobs (or any other time-based task scheduling mechanism), are strictly mutually exclusive.
Re: Keep the monolith, but split the workloads
#145> When a bad Pub/Sub message was pulled into the binary, an unhandled panic would crash the entire app, meaning web, workers and crons all died.
Several years ago while working on a Message Queue based application, we had a poison message, one where the consumer process would read the message and then die because the message was malformed and then the message would get back to the queue and due to the FIFO nature of the queue, the retries will also fail.
Ideally, there should be enough checks to ensure that a poison message can never be created. But if edge cases cause this issue, the handler should have some way of knowing that it is retrying the message for the n-th time and then if it fails, move it to a dead-letter-queue and report failure on handling that message.
Unfortunately, this pattern of issues are quite common. So, we fully expect this and design around it.
Then, any message in a dead-letter-queue gives you an example of a crash-inducing message which can then be debugged for root-cause.
Re: Keep the monolith, but split the workloads
#146We do something similar with Reclaim.ai: It's one monolith Java repo, split into two major workloads that have the same runtime code but are configured differently. In our case, the two workflows are "api" and "jobs". This allows for operational issues on, say, jobs while still allowing user-facing APIs to be less likely to be impacted. The source code itself has many modules, but we deploy it as a single unified run…
When you deploy a new version does it go out to all nodes? Or are the distinct workloads versioned separately?
Re: Keep the monolith, but split the workloads
#147Earlier quoted context omitted.
Then you're depending on the schema of the other service, which means you can't deploy them independently. You might as well have kept everything in a single service.
Aren’t you doing that anyway with json, protobufs, or whatever and using RPC? There’s always some agreed upon contract between services and changing that contract can always be delicate.
Worse, schemas are often only part of the contract. It’s very common to have logic and constraints in code, maybe even a majority. To share that across services you end up with shared models, then you end up with some utils with logic, before you know it you have yet another deployment difficulty.
Might as well just not split into services and make it trivial to maintain compatibility and deploy changes.
Re: Keep the monolith, but split the workloads
#148Earlier quoted context omitted.
To me, it's unclear what the best solution is here. Other languages solve this differently with tradeoffs, e.g. Java defaults to threads silently dying when an exception isn't caught. Your program will continue to run, but it's probably in some undefined state at that point. There are mechanisms for propagating exceptions elsewhere, but they have to be explicitly set up (like in Go). You can set a default uncaught ex…
Erlang/Elixir have a great story here: “let it crash”. Because each slice of activity in an application is wrapped in its own process (think single threaded loop but you can run a million at a time, almost free to create and destroy), if it crashes it only takes down that web request/process. Recovery mechanisms are built in to get back to a know good state.
My concern isn't really "does the program keep running?", it's "does the program keep running correctly?".
Re: Keep the monolith, but split the workloads
#149Earlier quoted context omitted.
Erlang/Elixir have a great story here: “let it crash”. Because each slice of activity in an application is wrapped in its own process (think single threaded loop but you can run a million at a time, almost free to create and destroy), if it crashes it only takes down that web request/process. Recovery mechanisms are built in to get back to a know good state.
I haven't used Erlang extensively, what happens if you crash in the middle of e.g. holding a lock, or during a coordinated dance with other processes? My concern isn't really "does the program keep running?", it's "does the program keep running correctly ?".
If you're in a coordinated dance with another process you link to that process. If a process you're linked to crashes then you crash too. There's no way to block yourself in Erlang such that you can't be told to crash.
After you crash your supervisor might restart you, if that's what you configured. Or you might give up on your specific task.
Re: Keep the monolith, but split the workloads
#150Earlier quoted context omitted.
>if you have a greenfield project, you should be using event-driven data processing. We got rid of the horse and buggy, let's please get rid of cron jobs. I don't see why event driven processing and cron-jobs (or any other time-based task scheduling mechanism), are strictly mutually exclusive.
They're not mutually exclusive. But the vast majority of tasks run by cron jobs are not time-sensitive.