Skip to content

Conversation

@PaulOstazeski
Copy link
Contributor

This adds inserted_at and updated_at columns to the database table when using Ecto, and uses the built-in Ecto behavior to populate their values without any additional work. This makes it possible to directly measure how long a given flag has been in its current state, which in turn makes it easier to determine when a flag is safe to be removed (i.e. that it has been "on" for some/many/all users for "long enough" that we haven't observed any downsides).

Comment on lines +6 to +10
# from versions `<= 1.10.0`.
#
# https://hexdocs.pm/ecto_sql/Ecto.Migration.html#timestamps/1
#
# If the table has been created with a migration from `>= 1.11.0`,
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am just guessing that this change would necessitate a minor version bump. Note that this PR does not actually change any version numbers.

@ArgyleWerewolf
Copy link

To me, this is good.

@tylerbarker
Copy link
Contributor

Hey @PaulOstazeski, I've had a PR up here for quite some time so until @tompave returns I've created a Hex published fork. You're welcome to raise your pull request there and I'll check it out 🙂

Copy link
Owner

@tompave tompave left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for using the package and for working on this. And apologies for the very late reply.

This change makes sense. Now that I think about it, this should have been present from the start.

true

{:error, _} ->
# Assume error is from timestamp columns not existing, run migration
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is very elegant. 👍

@tompave tompave merged commit fc4884f into tompave:master Jul 23, 2023
@tompave
Copy link
Owner

tompave commented Jul 23, 2023

Hey @PaulOstazeski, I'm afraid I have to revert this. (revert PR: #160)

This weekend I've been catching up on some long overdue maintenance work on this repo, and I think I merged this a bit too quickly. This was my mistake, and I apologize.

I'm also afraid that I forgot to run CI on this PR. Normally I have to approve GHA runs for PRs, but it usually presents me a big visible button on the PR page to do so. For some reasons it didn't for this PR. (It could be either because it's been too long since the PR was opened, or because in the meantime I updated the GHA workflow on the master branch.) I thought "sure, it seems safe, I can run it locally", and just merged it.

Unfortunately I came across a few issues after that. I think we need to address them before we can consider this to be merged. Normally I'd work on it myself and roll forward, but my time at the moment is limited, and I don't want to leave the master branch in a not-working state, sorry.

If you would like to give this another try, here are my observations after testing this locally:

  1. Elixir 1.15 won't translate anymore repo to repo(), as it raises a compiler error. I fixed it with Invoke repo() with parenthesis to avoid ambiguity in Elixir 1.15 #159 (later reverted).
  2. The migration doesn't contain a down function and it cannot be rolled back. I fixed it with a4d8e32 in my working branch.
  3. On the incremental migration: I wonder if you have only tested it in MySQL. I could apply your migration locally on MySQL, but I couldn't run mix ecto.migrate on Postgres. I think that the issue is that once an error is raised within the migration (the very thing that I thought was elegant 🙃), then the migration transaction is flagged as aborted, and every subsequent SQL statements fail. In order for this to be merged, it needs to work for Postgres too.
  4. Still on the incremental migration: I couldn't apply it on either MySQL or Postgres if the table already contained records. That's because Ecto's timestamps default to NOT NULL and the migration doesn't provide a default. There are two solutions for this:
    1. Provide a default value. However adding a column with a default value is a blocking operation on Postgres, and I believe it can be tricky on MySQL too unless some non-blocking DDL API is used. That's not a problem for small tables, but it can lock the table in production if there is too much data. I'd be very uncomfortable releasing a new minor version of the package where the upgrade instructions come with a warning that it might require a DB maintenance window. 😬
    2. An alternative on the above is to do it in multiple steps, which is a common workaround in Postgres: add the column, add a default value (or backfill it), make it NOT NULL later. It's just more complex to rollout and to automate within the package.
    3. Make the timestamp columns nullable, so that the problem goes away. I was exploring this, but then I realized that I was still blocked by point 3 on Postgres, mentioned above.

On the last two points, I suppose that my main concern is: if I add this functionality to the package, then the upgrade path should be smooth and painless. If it requires too many manual steps, and it comes with risks, then I'd be more inclined to add it to the next major version, rather than a minor version bump.

I hope it makes sense!

@PaulOstazeski
Copy link
Contributor Author

Thanks @tompave, I definitely missed some subtleties here. I'll take another crack at it and see if I can address these.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants