imdrasil/jennifer.cr

Do not create empty transaction if model unchanged

richardboehme opened this issue · 3 comments

Hey!

During building my first app with Amber and Jennifer, I noticed that when saving a model with no changes, an empty transaction will be committed to the database.
I guess this behavior is not really wanted, is it? At least ActiveRecord will not start a transaction without any changes to the model, but maybe this issue has already been discussed.

Currently it looks like that:

  model = Model.all.first
  model.save 
  => Log: 2020-10-15T14:42:50.901888Z  DEBUG - db: BEGIN
          2020-10-15T14:42:50.900497Z  DEBUG - db: COMMIT

I've tried to look into the source code and saw that a check for changes is already made in the update_record method of the model. However, the transaction is invoked prior to that in the save method. I guess the before_update callbacks should still be running which is why this change seems not that trivial to me.

I'm still kinda new to the Crystal language, the Amber framework and of course Jennifer, so let me know if I missed anything.

My current workaround is to check whether the model has changed before updating. However, this will only work if one is not dependent on the model callbacks.

model.changed? ? model.save : true   

Environment:

  • Jennifer 0.9.0 with the sqlite3 adapter (version 0.3.0)
  • Crystal 0.35.1
  • Amber 0.35.0

Agree that this may look weird a bit, but an empty transaction is a price we have to pay for flexibility. Instance can be changed inside of the callback chain so we can't avoid opening a transaction.
As you can see empty transaction take very little time so I believe you can just do model.save

Ok, thanks for the answer though. I understand that, with the current architecture, it's hard to fix this. Maybe this could be addressed in the far future.

Might be, but this scenario is pretty popular among other similar ORMs