Reputation: 63687
I wrapped a function writeTransaction()
with Meteor._wrapAsync
and called it 5 times in a for
loop which writes a MySQL transaction.
However from the MySQL query logs, it seems that the next iteration of the loop is executed before the function writeTransactionSync()
in the previous loop has finished.
If Meteor._wrapAsync
does not make the function blocking, how can we make the function synchronous?
Server-side Code
writeTransaction = function(data, callback) {
var mysql = Meteor.require('mysql')
var connection = mysql.createConnection(info).connect()
connection.beginTransaction(Meteor.bindEnvironment(function(err) {
connection.query('DELETE FROM orders WHERE _id = ?', [data._id], Meteor.bindEnvironment( function(err) {
connection.commit( Meteor.bindEnvironment( function(err) {
}))
}))
}))
callback(null)
}
writeTransactionSync = Meteor._wrapAsync(writeTransaction)
for(var i=0; i<5; i++) {
writeTransactionSync(data[i])
}
MySQL Query Log
329 Connect root@localhost on meteor
330 Connect root@localhost on meteor
331 Connect root@localhost on meteor
332 Connect root@localhost on meteor
333 Connect root@localhost on meteor
329 Query START TRANSACTION
330 Query START TRANSACTION
331 Query START TRANSACTION
332 Query START TRANSACTION
333 Query START TRANSACTION
329 Query DELETE FROM orders WHERE _id = '34zCYZXBxEkJapkYh'
330 Query DELETE FROM orders WHERE _id = 'SNR8zTEzGCw6X7RZ2'
331 Query DELETE FROM orders WHERE _id = 'TAF2TJkN5LzFRqAnX'
332 Query DELETE FROM orders WHERE _id = '57pJbvFYmHTpM5E6a'
333 Query DELETE FROM orders WHERE _id = 'BtNLGa3gjRGAfmMFf'
331 Query COMMIT
332 Query COMMIT
329 Query COMMIT
330 Query COMMIT
333 Query COMMIT
Upvotes: 3
Views: 849
Reputation: 181
You can checkout this video on Meteor._wrapAsync here in eventedmind. It did a good job on this topic.
Upvotes: 1
Reputation: 75955
Meteor._wrapAsync
is synchronous, provided that you fire the callback after all the tasks are done. It will only block the fiber if it knows the method has completed, so when you call callback(null)
, it assumes it is complete.
You have used callback(null)
after you call connection.query
but it would be called regardless of whether your query has completed or not, and since it takes a bit of time for a query to execute with MySQL, its likely its always complete (and act asynchronous) before the query has actually run.
You should place it inside the callback of the query:
connection.beginTransaction(function(err) {
connection.query('DELETE FROM orders WHERE _id = ?', [data._id], function(err) {
connection.commit(function(err) {
callback(null);
});
});
});
Also you don't need Meteor.bindEnvironment
when you use Meteor._wrapAsync
, especially when you're not using any Meteor code in the functions anywhere (You dont use meteor code in any of your connection callbacks, so its not needed).
Upvotes: 4