How to undo generator actions initiated in error

A concrete example:

Following the Migrations section of the RW Tutorial, I initiated the command yarn rw prisma migrate dev Trying to answer the very first prompt Name of migration ... I failed to type the answer (“create posts”) because the terminal was for some reason solidly frozen (I am not going to chase the rathole to find the answer to why was it frozen)

So, I hit Ctrl-C to get the control from the terminal back - and while I did get it back, the generator proceeded ahead and created the migrations folder with content different from what I wanted.

Now, how to recover from this, not knowing what change the generator made to my code?. I cannot issue the yarn rw prisma migrate dev command again, as this will append a new migration to the already existing, unwanted one. Much less would I accept to start creating this app from scratch again, nor do I want to remove the migrations folder, hoping that this is the only thing I need to do in order to undo the initial yarn rw prisma migrate dev

The obvious solution is to ensure that all changes made by the interrupted generator are automatically removed by teaching the generators to use the transactional approach, a technique that Appolo supports.

Caveat: it is quite possible that I missed the fact that transactions are already being used :smiley_cat:

My guess to “trick” my app and just remove the migrations folder failed as I expected - as rerunning the command yarn rw prisma migrate dev resulted with:

yarn run v1.22.5
$ C:\work\redwood\RW-tutorial-1\node_modules\.bin\rw prisma migrate dev

Running Prisma CLI:
yarn prisma migrate dev --preview-feature --schema "C:\work\redwood\RW-tutorial-1\api\db\schema.prisma"

Prisma schema loaded from db\schema.prisma
Datasource "DS": SQLite database "dev.db" at "file:./dev.db"

? - Drift detected: Your database schema is not in sync with your migration history.
- The following migration(s) are applied to the database but missing from the local migrations directory: 20210306212943_cre

We need to reset the SQLite database "dev.db" at "file:./dev.db".
Do you want to continue? All data will be lost. » (y/N)

While I think that I know how to recover from this, without having to start with the tutorial from scratch. I am not sure that a random future user of the RWJS will not ask for support in this situation.

I was wrong guessing that I could recover from this easily - it was a silly guess. I took the db folder from a previous attempt to build redwoodblog application where I did not reach the migrations tasks yet. Then I added yarn rw prisma migrate dev and all seemed nice however after creating the post editor, I got the following error message

 | Change detected, building... Done. Took 1203ms.
api | (node:5268) MaxListenersExceededWarning: Possible EventEmitter memory leak detected. 11 exit listeners added to [process]. Use emitter.setMaxListeners() to increase limit
api | Change detected, building... (node:5268) MaxListenersExceededWarning: Possible EventEmitter memory leak detected. 11 SIGINT listeners added to [process]. Use emitter.setMaxListeners() to increase limit
api | (node:5268) MaxListenersExceededWarning: Possible EventEmitter memory leak detected. 11 SIGTERM listeners added to [process]. Use emitter.setMaxListeners() to increase limit
api | Done. Took 904ms.

Now it seems the only solution is to start from scratch :cold_sweat: as I created a bad mess - just check this discussion

Dreaming about a cool solution for my just described problem:

Just as a mental experiment imagine the RW application development process as a sequence of generator invocations with interspersed commands to the code editor that results in code changes that the Tutorial asks the reader to do -as an example. the reader is asked to replace the content of the generated schema.prisma with

datasource DS {
  provider = "sqlite"
  url      = env("DATABASE_URL")

generator client {
  provider      = "prisma-client-js"
  binaryTargets = "native"

model Post {
  id        Int      @id @default(autoincrement())
  title     String
  body      String
  createdAt DateTime @default(now())

So, in such a fully scripted app development one could execute the whole script (sequence of generator invocations with interspersed commands to the code editor) executed in a single batch, or in a step at a time fashion)

This is not such an outrageous concept - as I am describing “interactive basic program development”, where the lines of basic code are replaced with that mix of generator invocations and editor invocations.

Accepting this theoretical experiment, one would immediately think about “walking” my RW app forward - and in the case of a bad step forward, back up one step and correct the bad step. Extending it further, one can imagine backward steps to reach the point where the problem was introduced - and then continue forward with the corrected bad step.

If I would be reading such an article, I would think “this dude needs to get real” - but then I have my own experience of serious discussions with Ray Ozzie and Anders Hejlsberg discussing the issues of creating a bi-directional debugger, which would know how to step backward from the point of the exception that triggered the debugger.

The Prisma Migrate command, and respective “flows”, are new and take some getting used to. Admittedly it’s all new since v0.25 when we upgraded Prisma to the new Migration. We’d spent so much time trying to patch the local workflow and heavily wrap Prisma commands that we made the decision in that release to just pass the Prisma commands with the simple addition of adding the schema path so users didn’t have to. Pro: we aren’t having to patch Prisma changes with every Redwood release. Con: we ceded some DX to Prisma.

For the specific case you describe above, my personal best-practice is to manage my code “state” via Git and commits. Before I run any generators, I’m tracking my commits and likely working in a branch. If things go awry, I revert.

  • are you using a similar local dev workflow? If not, thoughts about how we could insert these kinds of best practices into the Tutorial as “tips”?

Lastly, these might be good cases to present to Prisma directly via their Discussion Forum or Issues. I have a feeling they’ll give you a complicated answer about using migrate resolve or just overwriting with a new migration. But agreed it would be interesting for them to have an “undo” option. Right?

I am using the same practice for the same reason. However, I am not sure that we could “impose” the same discipline on RWJS app developers. For some time I am pondering how to improve the tutorial project to make the developer’s life a bit easier, as God is my witness that between Tutorial text changes and RWJS framework changes I am close to go nuts :smiley_cat:

Let me think about this issue a bit more.

I believe that using git technology in the background is both the simplest and the safest way to implement a “fake” undo. While I believe that VSCode has general support for git, there is a chance that it has more than just general support.

here is a very basic example of this feature, which we could wrap in RWJS generators. I am dreaming for a long time of replacing the CLI approach with the “Screen Editor” interface (pun to the Command Line interface). Such SEI entity can manage the overall state of my application development process (talk about meta programming).

The idea of using git for state management is very natural, Redwood already has a great history with git, being funded by a Git founder, so this just might the next step.

If we relay this issue to Prisma, they might like it - but I would prefer “our own” solution that covers any steps not just db migrations, starting with your private solution:

Excluding the use of generators from this undo/redo is a lot less helpful than making CLI to support it throughout all generators, or even better to create SEI :smiley_cat:

P.S. this is an even better implementation.