Can we rollback our database transactions in strapi? #6437

This discussion has been migrated from our Github Discussion #6437


sanojsilva189d ago

Hey is there a way to rollback database transactions if something goes wrong?

Responses to the discussion on Github


lauriejim156d ago

Maintainer

Hello, this is not possible to do that.
Can you please give me more detail about the way you would like that works in Strapi.
This will help us. Thank you.


sonlamnguyen155d ago

I have the same problem. I want to do serial jobs with DB.

Create a post.
Create a comment follow to post and occur errors.
I want to rollback post.
So, I don’t find a document about transactions. Please, can you help me?


MattieBelt155d ago

@sonlamnguyen Maybe you could use the bookshelf instance if using a SQL DB. I have no experience in using Bookshelf transactions.

strapi.connections.default.transaction();


sanojsilva155d ago

Author

I have used the following way to manage db transactions.

const res = await strapi.connections.default.transaction(async (trx) => { await trx(“voters”).insert(result.data); return true; });

check out this link for more information
http://knexjs.org/#Transactions


sonlamnguyen154d ago

@sanojsilva Thank you very much!. you saved my life


luwes117d ago

the pattern used in strapi core seems to be something like the below.
see here,

strapi/packages/strapi-connector-bookshelf/lib/queries.js

Line 39 in 97922f9

const wrapTransaction = (fn, { transacting } = {}) => {

an example of my project:

await strapi.connections.default.transaction(async (transacting) => { mediaFile = await strapi.services[‘media-file’].getOrCreate( { md5 }, mediaFileData, { transacting } ); const clip = await strapi.services.clip.findOne({ id }, null, { transacting, }); await strapi.services.clip.update( { id }, { mediaFiles: _.uniq([…clip.mediaFiles, mediaFile.id]), }, { transacting } ); });

getOrCreate is one of my custom service functions by the way, it’s not added by default.

  async getOrCreate(params, data, { transacting } = {}) {
    let entry = await this.findOne(params, null, { transacting });
    if (!entry) {
      entry = await this.create(data, { transacting });
    }
    return entry;
  }

ps-rschantl50d ago

@luwes Did you test your implementation, because it looks like Strapi doesn’t pass the transaction to the bookshelf-connector functions when you use the entity services?

So e.g. this

strapi.services[MODEL_NAME].create(ctx.request.body, { transacting })

doesn’t rollback but if I directly go to the bookshelf-connector like this

strapi.query(MODEL_NAME).create(ctx.request.body, { transacting })

it works.


luwes49d ago

good catch, I don’t think I tested

there’s also strapi.entityService.create, not sure what the difference is there


emahuni16d ago

@luwes could you please shed light on how you extended every model’s services to include your custom getOrCreate service


emahuni16d ago

this transaction method doesn’t work in current version of Strapi version 3.3.x