9 ms·
Fault tolerance and resilience patterns for Go
- rickette 3y agoUsed the Java version (https://failsafe.dev/ https://failsafe.dev/) of this library a few times. It's been around for a number of years. Works great! Glad to see a Go version.
- hit8run 3y agoWas it a bad design decision to not include nullable types in Go? I can't count how often I've seen this: Go: panic: runtime error: invalid memory address or nil pointer dereference
- pjmlp 3y agoAnd enumerations, generics, less boilerplate way of error checking,.... It definitely wasn't due to lack of previous tested technologies with field experience since the 1970's.
- valenterry 3y agoThen you don't have to create a new language. Golang was explicitly designed for not very experienced people to learn it and become productive quickly, even in big groups/teams with high attrition; that is: Google. And I think they reached their goal. If Golang starts to add more and more features, it will lose this advantage and become just "yet another language". But worse: because of how was Golang designed, it will then end up worse than, say, Java. In other words, it will lose its advantages without really gaining much. The problem is that this is probably inevitable, because the people that start as inexperienced developers with Golang will grow and become unsatisfied with the language features. Some more, some less, but that will be the general trend. And I think they are already vocal enough to push the things you listed. Instead, I think it would be better for everyone if those people would instead switch programming languages and leave Go as is. Otherwise the cycle will repeat with the next Golang...
- baranul 3y agoThink that is a misconception, that Go was just designed for inexperienced people. Rather it was designed to be easier to use than C++, from which the motivation to have something different came. That a language is easier to use, doesn't mean it can't add features. The features are relative to how it helps the language be more useful and solve issues that users are having, so keeps it easier to use. Languages are always going to have pressure to adapt.
- zelphirkalt 3y agoTrue, but it still took them 12y to add generics.
- valenterry 3y agoI didn't say that it was designed only for inexperienced people. But it was the or at least one of the major goals of the language creators that inexperienced developers can become productive quickly. And the more features a language has and that a codebase uses, the longer it takes for someone to learn it and be productive (unless they can transfer knowledge from similar concepts of other languages of course).
- iainmerrick 3y agoBut it was the or at least one of the major goals of the language creators that inexperienced developers can become productive quickly. Do you have a citation for that? As far as I remember that’s as most a second order effect -- they wanted a language that felt as clean and straightforward as C, to benefit everybody including experienced developers, not primarily inexperienced ones.
- valenterry 3y ago> Do you have a citation for that? I do indeed have a citation for that by Rob Pike - and no matter how downvoted I am, it stays a fact: > The key point here is our programmers are Googlers, they’re not researchers. They’re typically, fairly young, fresh out of school, probably learned Java, maybe learned C or C++, probably learned Python. They’re not capable of understanding a brilliant language but we want to use them to build good software. So, the language that we give them has to be easy for them to understand and easy to adopt. (https://bravenewgeek.com/go-is-unapologetically-flawed-heres-why-we-use-it/ https://bravenewgeek.com/go-is-unapologetically-flawed-heres...) and also: > Programmers working at Google are early in their careers and are most familiar with procedural languages, particularly from the C family. The need to get programmers productive quickly in a new language means that the language cannot be too radical. (https://go.dev/talks/2012/splash.article https://go.dev/talks/2012/splash.article) > As far as I remember that’s as most a second order effect -- they wanted a language that felt as clean and straightforward as C, to benefit everybody including experienced developers, not primarily inexperienced ones. No, it's not a second order effect. Or rather: both what you say (a language "as clean and straightforward as C") as well as a language for devs early in their career (i.e. inexperienced) are both second order effects from the underlying reason that the language is targeted at developers at google.
- Hendrikto 3y agoYour opinion seems a bit outdated. Go has had generics for almost 2 years now.
- randomdata 3y agoAnd enumerations from the start.
- pjmlp 3y agoNo it doesn't, it has a hack using constants and iota.
- randomdata 3y agoWhich is what an enumeration is. Perhaps you're thinking of sum types? They are often confused as enums.
- pjmlp 3y agoNot at all. Go read Algol 60, Pascal, Modula-2, C manuals to understand what enumerations are all about. Not a comic dance between iota and manually written constants.
- randomdata 3y agoIt's always bizarre when someone on a discussion forum defers to the writings of someone else. If that someone else wanted to have a discussion, they could do so themselves. But since I'm in a silly mood, I'll play along with your silliness: From the GNU C manual: "An enumeration type represents a limited set of integer values, each with a name." Which is exactly what Go provides. Which isn't surprising as it is identical to C in that regard.
- pjmlp 3y agoNo my dear, this hack type Operation int const ( Escalated Operation = iota Archived Deleted Completed ) has nothing to do with typedef enum {Escalated, Archived, Deleted, Completed} Operation; Only someone that can't get type systems would ever assert they are the same. Literally "Go enums suck", https://news.ycombinator.com/item?id=39564737 https://news.ycombinator.com/item?id=39564737
- 65a 3y agoPointers are "nullable types", but if you're seeing that a lot, it generally indicates an architectural problem.
- segfaltnh 3y agoAgree with this. While I too wish that Go had better ways of handling this, there are patterns and guidelines to follow that should prevent this in practice. - Use factory functions for struct initialization where members are pointers. - Use errcheck and friends to ensure errors are not ignored. - Never dereference the left hand return value if the right hand is an error.
- itake 3y ago+1. I only run into this issue when I don't follow the proper patterns our of laziness.
- neonsunset 3y agoI believe the problem is if this happens to be an issue in a dependency, which you can have little recourse to. Let’s wait another decade or so and maybe the Go authors will catch on lessons learned by C# (and similar languages) long ago by introducing nullable reference types and all kinds of static analysis to help you not shoot yourself in the foot.
- groestl 3y ago> - Use errcheck and friends to ensure errors are not ignored. - Never dereference the left hand return value if the right hand is an error. This itself is a very concise argument for exceptions. Automatically checks errors are not ignored, and don't allow access to the left hand return value.
- ncruces 3y agoBubbling up errors is not handing them. Making bubbling up even easier because people find this too verbose is the original mistake: if err != nil { return err } I find it verbose too. But if the alternative is to design something that allows you to ignore it 99%, and then put a huge syntactic penalty into doing anything other than bubbling up, then people will just bubble up 99.95% of the time, and complain about the other 0.05. I'm all for ensuring errors are not silently ignored. That's Go's mistake. Exceptions are not the answer.
- welder 3y agoYes, it's a design flaw. It means the dev can make a mistake, forget to check for nil, BAM CRASH! I even wrote a blog post about this very thing: https://wakatime.com/blog/48-go-desperately-needs-nil-safe-types https://wakatime.com/blog/48-go-desperately-needs-nil-safe-t... Nullable types allow devs to write safe functions (functions that don't allow nullable types as input) and spread that safety through the whole codebase. That safety isn't even an option without having nullable types. Nullable types also mean the compiler knows and warns devs if they forgot to check for nil. There's really no reason why Go sholdn't have nullable types.
- kaashif 3y ago> There's really no reason why Go sholdn't have nullable types. Don't you mean non-nullable types? Go does have nullable types, everything is nullable. The blog post you linked calls them "non-nil types".
- wrs 3y ago“Nullable types” is a phenomenon that occurs when non-nullable types are introduced to a language that started with null and already has libraries that rely on it. When you change the default to be non-nullable, you have to introduce the explicit concept of nullability for backwards compatibility, thus “nullable types”. Like, if you already had type X that could be null, and you change the language so X can’t be null, now you need the type Nullable<X> (often written something like X?) to let it be null again. C# and Swift are examples of this evolutionary process.
- welder 3y agoYea, non-nullable types. Thanks.
- hypeatei 3y agoC# took the nullable types route and it isn't the greatest experience since everything can be null regardless of the annotations. Null as a language concept is the issue since it's inherently flawed.
- nicce 3y agoI would say that Rust does it pretty well with Option<>. You can define the logic when the Null should or can happen and you can avoid writing a lot of Error matching boilerplate, while still have a condition when something fails.
- hypeatei 3y agoYeah, Rust makes the handling of "None" values explicit, even if you want to ignore it with `unwrap()`
- deleted 3y ago[deleted]
- deergomoo 3y agoAs someone quite new to Go, who has found a lot to like, I find the lack of a built in way to model optionality (besides pointers, which rather muddy the intent) absolutely baffling. I want to use values over pointers for as much as I possibly can; the sort of stuff I work on is not so performance sensitive that it would be a problem. But zero-values are totally insufficient for modelling optional values, especially for numeric data. Now it has generics I could implement my own Optional[T] type, but backup from the compiler forcing me to check a value exists before doing anything with it is what really makes optional types shine in languages that have it.
- Mawr 3y agoYou can just do it yourself as you mention and the compiler does force you to check: https://gist.github.com/MawrBF2/0a60da26f66b82ee87b98b03336e1f84 https://gist.github.com/MawrBF2/0a60da26f66b82ee87b98b03336e...
- deergomoo 3y agoThat's cool, thanks for the link! Hadn't considered that multiple return values could cover this case
- cpursley 3y agoI feel like 2/3s of posts on here are people spending tremendous amounts of effort recreating OTP (things Erlang/Elixir already does natively).
- asplake 3y agoOn that, and slightly further off topic, if there’s a tutorial, cookbook, or worked example of using OTP but written in Gleam, I would lap it up. Enjoyed learning the language but kinda got stuck there. I didn’t want to have learn Elixir or Erlang just for that.
- neonsunset 3y agoA small disclaimer - proceed with Gleam only if you are okay with its and overall BEAM’s poor performance compared to compiled languages.
- cpursley 3y ago[flagged]
- victorbjorklund 3y agoMostly an issue if you are doing number crunching.
- throwaway743950 3y agoWhat aspects of BEAM perform poorly? (Genuinely asking. I’m not very familiar with it.)
- faizshah 3y agoI could be wrong but I don’t think OTP natively implements a load shedding strategy or concurrency controls or request hedging. You would implement a supervisor to do so if you don’t want to overload an external system like a DB or microservice (e.g https://github.com/fishcakez/sbroker https://github.com/fishcakez/sbroker).
- neonsunset 3y agoVery popular .NET library that does this is https://github.com/App-vNext/Polly https://github.com/App-vNext/Polly. It seems failsafe borrows heavily from it given first Polly version was released more than 10 years ago.
- jddj 3y agoWorth noting as well that in more recent .net versions Polly has been brought into Microsoft under (if I remember right) microsoft.extensions.http.resilience
- neonsunset 3y agoMicrosoft.Extensions.Resilience and its downstream dependencies simply reference Polly, it continues to be an independent and actively maintained set of packages.
- jodah 3y agoAuthor here - yes, Failsafe-go definitely took some inspiration from Polly, but it also borrows ideas from the Failsafe JVM library [1]. Polly and Failsafe influenced each other back and forth over the years. https://failsafe.dev/ https://failsafe.dev/
- mfbx9da4 3y agoThis is all great except it’s all in memory. To really fail safe you need to account for crashes and therefore need a persistent queue
- theflyinghorse 3y agoDepending on your performance requirements extra milliseconds of roundtrip to the externalized queue may be too long of a wait. Or you may simply not care enough for an extra piece of infrastructure that you'd need to support, and maybe this is good enough. It's is all about trade offs, no solution fits all use cases.
- convolvatron 3y agoits always about tradeoffs. one nice compromise position here is that the log is always consistent, so you don't need to wait at all if you don't mind losing the tail on a crash.
- javierhonduco 3y agoFor anybody interested in this topic, “Release it!” is a pretty good read. (Not affiliated in any way, just enjoyed reading it) https://www.oreilly.com/library/view/release-it/9781680500264/ https://www.oreilly.com/library/view/release-it/978168050026...
- jb3689 3y agoI just finished this. To each their own of course, but I found the writing too padded and tonally off-putting at times. Some of the stories felt dated both from a technological stance and a cultural stance. I prefer Azure's Cloud Pattern docs myself (though "Release It!" was really good if you prefer a storytelling approach): https://learn.microsoft.com/en-us/azure/architecture/patterns/ https://learn.microsoft.com/en-us/azure/architecture/pattern...
- javierhonduco 3y agoThis looks incredibly comprehensive, thanks for sharing! Should have added that I read this book in 2016, and the first edition is even older, so there’s naturally been lots of new (and exciting) developments in this area!
- synergy20 3y agowhat does OTP mean in the comments here?
- cmckn 3y agohttps://www.erlang.org/doc/design_principles/des_princ https://www.erlang.org/doc/design_principles/des_princ
- andrewstuart2 3y agoSince this page doesn't define the acronym either, it originally was an acronym for Open Telecom Platform.
- mariusor 3y agoIf I'm allowed to make a critique, I'd say that the module doesn't look very much like Go. The (ab)use of generics and having every policy to its own package feel a little over-engineered. I might be slightly biased, because, not knowing about this project, I implemented half of the functionality in my own simpler module: https://git.sr.ht/~mariusor/ssm https://git.sr.ht/~mariusor/ssm
- 1oooqooq 3y agocircuit breaks and a end point health dashboards are sure ways to be promoted above ic5 in most dysfunctionaly big companies. I've spend a lot of time ripping them out of java projects abusing those patterns for internal services, where service interruption was caused more by the delays from the circuit breakers than actual problems with the internal end points. but everyone who added them got promoted in the past. and on those companies, most java people are now go devs when they were retrained during the move to the clouds because then most tools were go or python.
- jodah 3y agoAuthor here - I do get this critique, and of course API design is subjective, but there was a rationale behind the design choices. Putting each policy in its own package allowed the API to be slightly more concise. And having the API use a generic to represent a function's result type allowed different parts of the API to be independent and composable while still ensuring that result types align. A bit more on that here: https://failsafe-go.dev/type-safety/ https://failsafe-go.dev/type-safety/
- mariusor 3y ago> allowed different parts of the API to be independent and composable while still ensuring that result types align I found that states are not really required to know anything about internals of the executed code. All that a policy needs to know if the next state is an error or not, that's all. I might have simplified the problem too much for my library to be useful in real life applications, but I still hold hope that a stateFn func(context.Context) stateFn is expressive enough for implementing the whole functionality. If I may make another suggestion, I found that for more complicated flows, it is useful to be able to build a graph. I have made a rough approximation of a toold for my project based on parsing the go sources and inferring a state diagram from it. You can check it here: https://git.sr.ht/~mariusor/ssm/tree/master/item/cmd https://git.sr.ht/~mariusor/ssm/tree/master/item/cmd (Apologies for the lack of documentation, my work is much more recent than yours :D)
- megan_ 3y agoThere's this feeling of fulfillment when what you pray for comes true i just want to appreciate this great spy agent (arpanethack @gmail dot com)at first, his first job for me wasn't successful and i got refunded back but,i had to give him benefit of the doubt to track my husband's phone and it was a success and all information was wired to my phone