Live data from Hacker News

A routine gem update ended up creating $73k worth of subscriptions

serpapi.com

231–240 of 336 posts

Re: A routine gem update ended up creating $73k worth of subscriptions

#231
How would you introduce this breaking change if you were the maintainer?

Maybe this:

1. In the first release, introduce a config value which enables the new behavior.

2. In the next release, print a warning or refuse to compile if the config option is not set.

3. In the final release, make the new behavior the default.

Plenty of time to adjust your code to the new behavior even if you don't read the changelogs. But it won't work if several releases are skipped during updates.

Re: A routine gem update ended up creating $73k worth of subscriptions

#232

Earlier quoted context omitted.

That link is reachable from their home page right now, under “Upgrading”. EDIT: just noticed the docs I found via Google are marked as “old” in the URL: https://mongoid.github.io/old/en/mongoid/ Are you suggesting they dropped semver in between these releases?

> Are you suggesting they dropped semver in between these releases? If this is the case, I kind of hope, for maximum irony, that they dropped it as part of a minor version bump.

Haha, this was the best thing I read today :)))

Re: A routine gem update ended up creating $73k worth of subscriptions

#233
post #35

Here's how true professionals would handle this: "We recently became aware of some erroneous subscription renewals made by our platform and traced the root cause to a major bug in downstream database technology affecting a very small number of accounts. Nonetheless, we working hard with our database provider to resolve the issue. In the meantime, if you are affected and believe you might have an unsolicited subscript…

And then nobody is aware of the huge breaking change in a popular open source library. This isn't "professional", this is your legal team making things worse.

Re: A routine gem update ended up creating $73k worth of subscriptions

#234
post #129

Earlier quoted context omitted.

You would feel spoiled if you were a ruby developer too. This type of library API breaking change on a minor version update basically never happens. And if it can happen in ruby land, it can happen in JS land too.

> This type of library API breaking change on a minor version update basically never happens. Literally happens all the time with Rails. To the point they decided to call their versioning schema “shifted semver” to afford themselves API changes on minor versions: https://guides.rubyonrails.org/maintenance_policy.html Good luck if you are using Rails and ecosystem and you expect any sort of sensible versioning.

Rails committer here.

First I get that people are used to SemVer, but it is unreasonable to assume all projects follow it. And yes in semver terms, you can simply assume that Rails X.Y is a major release.

Then, any breaking change in Rails must first emit deprecation warnings, so unless you are jumping one version, this kind of scenario shouldn't happen with Rails itself.

Also note that Ruby (MRI) itself more or less behave the same regarding versioning, deprecations and breaking changes. First emit warnings, then break.

Re: A routine gem update ended up creating $73k worth of subscriptions

#235

Earlier quoted context omitted.

Ultimately this is why I don't like to work in Ruby. You can just never trust any line of code between the gem updates, the unhelpful signatures, the overreliance on hashes everywhere, and a million different levels of mix-ins and indirection. Yeah, it's expressive, but how much time are you really saving once you consider all these maintenance headaches?

This exact problem could have happened in any language. Literally zero of it has to do with Ruby or the ecosystem.

In theory yes, but in practice there's a big difference between ecosystems. I maintain apps in Ruby and Elixir, and as far as I can remember, all the Elixir libraries I use respect semver. Whereas with Ruby it's much more mixed.

Re: A routine gem update ended up creating $73k worth of subscriptions

#237
Elixir has a command `mix hex.outdated` that shows every library about to be updated, and links to an auto-generated page with the source diff between the current and latest version for each. It encourages auditing changes before updating. It's a great habit to take to avoid this kind of trouble.

Re: A routine gem update ended up creating $73k worth of subscriptions

#238

This change gives me new respect for Denis Ritchie's decision not to mess with a wart in operator precedence in C. Even though we still live with this wart 30 years later. It was exactly this type of failure he sought to prevent. He refused to fix it because, "After all, we had several hundred kilobytes of source code, and maybe 3 installations...." https://www.lysator.liu.se/c/dmr-on-or.html

Add Torvalds to the list too - SHUT THE FUCK UP. WE DO NOT BREAK USERSPACE! https://lkml.org/lkml/2012/12/23/75 This style is indeed controversial but honestly, these kind of situations seem apt for such a chewing out. Backwards compatibility seems to be one of those things that people regularly compromise despite it repeatedly hitting back. For a database driver of one of the most popular databases in the world, it…

Absolutely.

Breaking changes, major version update, bug fixes, minor version update, and think really hard about the pain the major version update will cause. It seems so easy...

The problem comes when applications depend on a bug. The library maintainers don't necessarily know about this, but it's handy to think further ahead and understand what the effect of an update is. That's why one line fixes take time - thinking through the implications.

Perl 5 vs 6, Python 2 vs 3 are good examples of breaking major changes to languages, and the various fallout that happens, both good and bad. It's amazing how far c++ has come without such a major bifurcation

Re: A routine gem update ended up creating $73k worth of subscriptions

#239

Besides the issue, I always create a method like get/find find_one, find_unique, find_unique, or find_only, in cases where I expect exactly one result. I’m a query or collection. I’ll have a separate for when I expect one or zero results. Unfortunately it’s crazy difficult to even get such a small addition committed upstream, but that’s a different story

I think you may have slightly misunderstood the issue—the problem isn't that the method was returning too many accounts, the problem was that the method was returning an account unrelated to the one whose subscription had expired . Therefore, subsequent calls by the same expired user would renew for more and more random accounts—but only one random account per call.

Yeah I didn't look into it.. But reading further, it still would've prevented this bug. If you expect 1 or 0 results, just make sure it does.

The query here returned where id = xxx or renew_locked_at >= xxx or renew_locked_at is null. That will return more than 1 result. If find_one actually did what the name says it does, find 1. Not 0, not 2, not 475. This issue would've never existed.

Both mongoid and activerecord (don't remember if this was the case with hibernate / jpa) will not throw an exception if there are more than one records. They will check for zero results, although it would just result in an NPE if they didn't..

Besides this, I'd have made it more explicit by doing something like: where(xxx, or(yyy, yyy)). This is still an implicit 'and', but chaining always seems confusing to me, so I never use it like that.

Mongoid shouldn't have done such a change, even with a major upgrade. At least not in this way.

IMO, both the author and mongoid set themselves up for issues.

I like to throw around exceptions and asserts. I like to fail fast. Strictness is easy to handle for a programmer. Only external human input should/could be handled less strict. Unfortunately, many disagree..

It's different with other types of software (client side apps), but for applications that have no state, or a state that can easily be recovered (webapps), it seems plain stupid not to fail fast whenever something's wrong

Re: A routine gem update ended up creating $73k worth of subscriptions

#240
post #211

Earlier quoted context omitted.

This exact problem could have happened in any language. Literally zero of it has to do with Ruby or the ecosystem.

Certainly it has something to do with the ecosystem, if the most popular MongoDB driver in the ecosystem is making breaking changes in minor versions. That said, strong types can be a godsend for catching accidental breaks, even if it wouldn’t necessarily have helped here. A strongly typed language that has a more disciplined ecosystem is less likely to run into these kinds of issues. It’s one of the tradeoffs you pi…

This is exactly the case where nothing about types, language or opinions about the Ruby community has to do with the problem at hand.

This would not be caught by compiling, strong types or anything else - this is a change in behavior which has been arbitrarily done by the maintainers of the dependency.

> Certainly it has something to do with the ecosystem, if the most popular MongoDB driver in the ecosystem is making breaking changes in minor versions.

How should this be handled? Should a "good" ecosystem vet every single change in every single library that gets updated? Or should there be no libraries and only stdlib instead (wait, I think I know a compiled language which did just that for quite a few years, let me think which one that was again...)

Post reply on HN