I am wondering what does the querying if the connection is in transaction or not actually do ?
Example :
....
try
if not DATA_MODULE.ACRDatabase1.InTransaction then
DATA_MODULE.ACRDatabase1.StartTransaction;
....
DATA_MODULE.ACRDatabase1.Commit();
except
DATA_MODULE.ACRDatabase1.Rollback;
Does it temporarily stop the current transaction if it detects that there is another transaction going on and waits for the other transaction to complete and only then executes or what? Or does it just misfire (rollback) if there's another transaction detected?
Attempting to start a transaction which has already been started will raise an exception. The call to InTransaction simply determines if the transaction has already started or not and returns a True/False response.
I prefer this...it protects you if you have any problems while editing...and only rollback if you have a problem with the Commit. If any exception is raised after the StartTransaction...you will never get to the Commit. You will always run the finally and will make sure you are not in a Tranaction, if so Rollback. I try not to use Try Except, don't have to worry about the Raise
try
DATA_MODULE.ACRDatabase1.StartTransaction;
....
DATA_MODULE.ACRDatabase1.Commit();
finally
if DATA_MODULE.ACRDatabase1.InTransaction then
DATA_MODULE.ACRDatabase1.Rollback;
at the very least the code should be reraising the exception or your user will never know why the data is not saving. ReRaising Exception
Related
I've never done that before and I don't know if it is possible. I've got two process which I thing should most likely be wrapped in a database transaction to have the guarantee that either all changes in the database from the transaction will be made or no changes will be made.
process.campaign_code.update(state: 'used')
Campaign.find(process.campaign_code.campaign_id).increment!(:used_campaign_codes_amount, 1)
Try ActiveRecord::Base.transaction:
https://api.rubyonrails.org/classes/ActiveRecord/Transactions/ClassMethods.html
ActiveRecord::Base.transaction do
process.campaign_code.update!(state: 'used')
Campaign.find(process.campaign_code.campaign_id).increment!(:used_campaign_codes_amount, 1)
end
If any of the commands in the transaction throw an error, all SQL transactions in the block will be reverted.
EDIT: It's also worth changing update to update! to ensure an error is thrown if the update is unsuccessful, otherwise it can fail without throwing an error and the block will continue.
As my understanding, if we have any code inside this transaction and when it happens any error with (save!, ...) in that block the entire code will revert, here the problem is if any timeout (rack timeout = 12) happens in this block.
def create
ActiveRecord::Base.transaction do
// timeout happens
end
end
How can we rollback a code with a transaction when a Rack::Timeout occurs?
When a Rack timeout happens, any transaction in process will be rolled back, but transactions that have already been committed will, of course remain committed. You should not have to worry about it.
Once you start a database transaction, it will eventually either be committed or rolled back. Those are the only two possibilities for ending a transaction. When you commit the transaction, you are saying that you want those changes to be saved regardless of what happens next. If you do not commit the transaction, the database will automatically rollback the transaction once it gets into any state where the transaction cannot move forward, such as a broken network connection.
ActiveRecord automatically commits the transaction when the ActiveRecord::Base.transaction do block exits normally. Abnormal exits may cause ActiveRecord to issue a ROLLBACK command to the database, which is efficient and good practice and returns the connection to a ready state, but it is not strictly necessary, because unless the transaction is explicitly committed, the database will eventually automatically roll it back.
If you look at ActiveRecord::ConnectionAdapters::TransactionManager#within_new_transaction on line 270 and 283 Rails is rescuing Exception. Rescuing Exception will catch anything and everything including kill commands and should generally be avoided. It is used in this case to ensure that no matter what is raised (including Rack::Timeout) the transaction will rollback.
You need to explicitly specify an error class, then it will be rescued and ActiveRecord will rollback the transaction.
e.g. Timeout.timeout(1, Timeout::Error) do
https://ruby-doc.org/stdlib-2.4.0/libdoc/timeout/rdoc/Timeout.html
The exception thrown to terminate the given block cannot be rescued
inside the block unless klass is given explicitly.
Without it ActiveRecord thinks that there is no error and makes a COMMIT.
It seems it was a default behavior until ruby 2.1
I have a case where I need to create like 10000 entries in a table and after some research I decided to use a transaction to do it.
My problem is I haven't found any documentation or guide that will tell me where I put a transaction or how I execute it
This can be achieved very easily:
ActiveRecord::Base.transaction do
... your code ...
end
The code inside the block will run within a database transaction. If any error occurs during execution, all the changes will be rolled back.
Regarding my previous question:
I have a problem with GraphDatabaseService.registerTransactionEventHandler(). When I try to run this test against this handler, I don't get any calls to the beforeCommit method when running 1.9.2 and only once for a new database for 2.0.0-M03, and for that TransactionData.createdNodes() returns an empty iterator even though a a node has been created. The test fails with org.neo4j.kernel.api.exceptions.PropertyKeyNotFoundException: Property key 'uuid' not found for these reasons.
Am I doing something wrong, or is there a bug in registerTransactionEventHandler?
You're lacking tx.finish() on the first transaction just after https://github.com/ttiurani/neo4j-uuid/blob/master/src/test/java/org/neo4j/extension/uuid/UUIDTransactionEventHandlerTest.java#L2. Therefore the transaction is not committed and the TransactionEventHandler not called, see http://docs.neo4j.org/chunked/stable/transactions-interaction.html.
I'm unable to create a row in the DB. Rails apparently starts and then immediately rolls back the transaction without any errors. I'm using sqlite3.
logger.debug("creating billing name...")
BillingName.create() #also tried BillingName.new.save
logger.debug("...created")
Log file:
creating billing name...
^[[1m^[[36m (0.1ms)^[[0m ^[[1mbegin transaction^[[0m
^[[1m^[[35m (0.1ms)^[[0m rollback transaction
...created
select * from billing_name shows indeed no entry has been added. How can I tell why the transaction is being rejected?
You can check the errors after a save or valid?
billing_name = BillingName.new
billing_name.save # or billing_name.valid?
puts billing_name.errors.inspect
These are good answers that help you find the error by inspecting the model. I use those too.
But I've found that ActiveRecord doesn't always provide useful information, especially in callbacks. valid? will be true, errors will be empty, and the console won't show anything except the rollback. So, a good place to look is what is happening in those callbacks, specifically the before_create filter.
As someone who always uses the bang methods, I recently had a similar issue and could not debug it.
The only thing is, I had upgraded to rails 7.
Yup, so apparently, using return inside of a transaction block is no longer supported and will result in a rollback.
GITHUB: Deprecate committing a transaction exited with return or throw #29333