I think the Raft paper is more approachable for newcomers, but if you are finding Paxos hard to explain and Raft easy to explain, just use the Raft lingo to explain Paxos.
I think the Raft paper is more approachable for newcomers, but if you are finding Paxos hard to explain and Raft easy to explain, just use the Raft lingo to explain Paxos.
I see this phrase around a lot and I wish I could understand it better, having not worked with Erlang and only a teeny tiny bit with Elixir.
If I ship a feature that has a type error on some code path and it errors in production, I've now shipped a bug to my customer who was relying on that code path.
How is "let it crash" helpful to my customer who now needs to wait for the issue to be noticed, resolved, a fix deployed, etc.?
Let It Crash refers to a sort of middle ground between returning an error code and throwing an exception. It does not directly address your customer's need, and you are right that they are facing a bug.
So if you were to use Golang with Let It Crash ethos, say, you would write a lot of functions with the same template: they take an ID and a channel, they defer a call to recover from panics, and on panic or success they send a {pid int, success bool, error interface {}} to the channel -- and these are always ever run as goroutines.
Because this is how you write everything, you have some goroutines that supervise other goroutines. For example, auto-restart this other goroutine, with exponential backoff. But also the default is to panic every error rather than endless "if err != nil return nil, err" statements. You trust that you are always in the middle of such a supervisor tree and someone has already thought about what to do to handle uncaught errors. Because supervision trees is just the style of program that you write. Say you lose your connection to the database, it goes down for maintenance or something. Well the connection pool for the database was a separate go routine thread in your application, that thread is now in CrashLoopBackoff. But your application doesn't crash. Say it powers an HTTP server, while the database is down, it responds to any requests that do not use the database just fine, and returns HTTP 500 on all the requests that do use the database. Why? Because your HTTP library, allocates a new goroutine for every request it handles, and when those panic it by default doesn't retry and closes the connection with HTTP 500. Similarly for your broken codepath, it 500s the particular requests that x.(X) something that can't be asserted as an X, we log the error, but all other requests are peachy keen, we didn't panic the whole server.
Now that is different from the first thing that your parent commenter said to you, which is that the default idiom is to do something like this:
type Message {
MessageType string
Args interface{}
Caller chan<- Message
}
// ...
msg := <-myMailbox
switclMessageType {
case "allocate":
toAllocate := args.(int)
if allocated[toAllocate
msg.Caller <- Message{"fail", fmt.Errorf(...), my mailbox}
} else {
// Save this somewhere, then
msg.Caller <- Message{"ok", , my mailbox}
}
}
With a bit of discipline, this emulates Haskell algebraic data types which can give you a sort of runtime guarantee that bad code looks bad (imagine switching on an enum `case TypeFoo`: foo := arg.(Foo)`, if you put something wrong in there it is very easy to spot during code review because it's a very formulaic format)So the idea is that your type assertions don't crash the program, and they are usually correct because you send everything like a sum type.
Wish everyone had taken it more seriously.
Here's a PDF handout from 2023 for handing to hospital admins, https://www.nerode.org/clean-air/medical%20clean%20air%20rel... . The same statistics can probably be looked up for children acquiring covid at school, because like where else do they get it. $100 HEPAs in every classroom, $40 reusable p100 masks for every teacher, ask parents to voluntarily mask their kids.
Just share stories. You see [1], go to your social media and share it, “she got COVID like 3 or 4 times and it seems to have caused chronic kidney disease, even with vaccines reducing the rate of straight up death, we need get this thing under control otherwise our generation's not going to live to see 80. Each time you get it there is another small chance of long covid, another rolling the dice hoping for no snake eyes. Masking is just saying you want to roll the dice fewer times.”
Organize or join a covid slack channel at work, there are other groups like https://publichealthactionnetwork.org/ , if BTS Army can connect over K-pop we can connect over wanting to protect others.
1. https://x.com/HollyMars2/status/1936235382816784443?t=A4RaLq...
This scheme doesn't require them two people to be on-line simultaneously — all updates are mediated via the sync server, after all. So, where am I wrong?
The reason CRDT researchers don't like the sync server is, that's the very thing that CRDTs are meant to solve. CRDTs are a building-block for theoretically-correct eventual consistency: that's the goal. Which means our one source-of-truth now exists in N replicas, those replicas are getting updated separately, and now: why choose eventual consistency rather than strong consistency? You always want strong consistency if you can get it, but eventually, the cost of syncing the replicas is too high.
So now we have a sync server like you planned? Well, if we're at the scale where CRDTs make sense then presumably we have data races. Let's assume Alice and Bob both read from the sync server and it's a (synchronous, unencrypted!) last-write-wins register, both Alice and Bob pull down "v1" and Alice writes "v1a" to the register and Bob in parallel writes "v1b" as Alice disconnects and Bob wins because he happens to have the higher user-ID. Sync server acknowledged Alice's write but it got lost until she next comes online. OK so new solution, we need a compare-and-swap register, we need Bob to try to write to the server and get rejected. Well, except in the contention regime that we're anticipating, this means that we're running your sync server as a single-point-of-failure strong consistency node, and we're accepting the occasional loss of availability (CAP theorem) when we can't reach the server.
Even worse, such a sync server _forces_ you into strong consistency even if you're like "well the replicas can lose connection to the sync server and I'll still let them do stuff, I'll just put up a warning sign that says they're not synced yet." Why? Because they use the sync server as if it is one monolithic thing, but under contention we have to internally scale the sync server to contain multiple replicas so that we can survive crashes etc. ... if the stuff happening inside the sync server is not linearizable (aka strongly consistent) then external systems cannot pretend it is one monolithic thing!
So it's like, the sync server is basically a sort of GitHub, right? It's operating at a massive scale and so internally it presumably needs to have many Git-clones of the data so that if the primary replica goes down then we can still serve your repo to you and merge a pull request and whatever else. But then it absolutely sucks to merge a PR and find out that afterwards, it's not merged, so you go into panic mode and try to fix things, only for 5 minutes later to discover that the PR is now merged. And if you've got a really active eventually consistent CRDT system that has a lot of buggy potential.
For the CRDT researcher the idea of "we'll solve this all with a sync server" is a misunderstanding that takes you out of eventual-consistency-land. The CRDT equivalent that lacks this misunderstanding is, "a quorum of nodes will always remain online (or at least will eventually sync up) to make sure that everything eventually gets shared," and your "sync server" is actually just another replica that happens to remain online, but isn't doing anything fundamentally different from any of the other peers in the swarm.
Backup retention policy 60 days, respond within a week or two telling someone that you have purged their data from the main database but that these backups exist and cannot be changed, but that they will be automatically deleted in 60 days.
The only real difficulty is if those backups are actually restored, then the user deletion needs to be replayed, which is something that would be easy to forget.
IMO the easier derivation — may just be personal tastes as someone more on the engineering side — is just another integration by parts.
So with f(g(x)) = g(f(x)) = x, define y = g(x) for U-substitution with x = f(y):
∫ g(x) dx = ∫ g(f(y)) f'(y) dy
= ∫ y f'(y) dy
= y f(y) – ∫ f(y) dy
= g(x) x – F(g(x)) + C
The more interesting thing is that this is a really basic integration by parts which means that this diagram of yours that I like, is more universal than it appears at first? I'd have to think about that a bit more, how you can maybe graphically teach integration by parts that way, is there always a u substitution so that you can get u f(u) or so and get this nice pretty rectangle in a rectangle... hmm.Deleted Comment
Does anyone know why they care about this structure? Naively, there are 36^7 (minus edge cases) combinations available, which will always be sufficient.
In addition, all-numbers-plates, I believe, are reserved by California exempt plates (emergency vehicles, police), and vanity plates are absolutely a thing, much more likely to start and/or end on a letter, so that's why you see numbers at the beginning and end. Like you can kinda see “6EIC023” and say “oh yeah my car looks like an ad for Geico” but because the start and end are numbers it doesn't occur to most people.
The equation used creates a visually appealing result but I’m wondering what a good goal would be in terms of consistency in the distance between the spirals, or evenness in area divided, or something like that.
How was this particular function selected? Was it derived in some way or simply hand-selected to look pleasing?
The actual "correct" thing to do would probably be to have the point maintain constant speed in 3D space like a real boat sailing on a globe, right? But that's a rather bigger lift:
with outputs, I doubt that they did the ln(tan(phi/2)) thing though, but it's what you get when you integrate the k d{phi} = sin{phi} d{theta} equation that you have here.