Closed Bug 890203 Opened 12 years ago Closed 9 years ago

Make runInBatchMode to run batch asynchronously

Categories

(Toolkit :: Places, defect)

defect
Not set
normal

Tracking

()

RESOLVED WONTFIX

People

(Reporter: raymondlee, Unassigned)

References

Details

(Whiteboard: p=0)

We need to find a way to make runInBatchMode to run batch asynchronously. See Bug 885205 comment 20
This blocks bug 891303 with no apparent temporary work around.
Blocks: 891303
The solution proposed in bug 885205 comment 20 won't help transaction aggregation. Each transaction wishes to run on its own most of the time, but at times multiple transactions may be aggregated together, in which case it's appropriate to start a batch before the first transaction is about to be applied, and end it whenever the last transaction is fully applied, or if any transaction failed to apply. Ideally, runBatched could return a promise, but since runInBatchMode is implemented in c++ we cannot do that. I think we have no choice but reviving the API that preceded runInBatchMode, which is the beginBatch-endBatch couple, alongside the runInBatchMode API. Then, in PlacesUtils we could easily implement a promises-friendly version of runInBatchMode. This will work fine, and I don't expect it to result in any in-tree bugs, because beginBatch/endBatch will never be used directly except by the PlacesUtils wrapper. However, addons may go ahead and use the internal API, and I'm not sure what we can do about that.
One thing I could do to make addon authors at least feel guilty for using begingBatch is to force a *get*Interface call for using this method, so PlacesUtils would do something like runBatchec: function(aFunction) { return Task.spawn(function() { let placesUtilsHelpers = this.history.QueryInterface(Ci.nsIInterfaceRequestor) .getInterface(Ci.nsPIPriavatePlacesUtilsHelpers); placesUtilsHelpers.beginBatch(); try { yield aFunction(); } finally { placesUtilsHelpers.endBatch(); } }; } The reason for using getInterface rather than QueryInterface is that getInterface doesn't leave the private methods exposed on PlacesUtils.history.
Marco, are you ok with this approach?
Assignee: nobody → mano
Flags: needinfo?(mak77)
Blocks: 894256
Alternatively, the PlacesUtils helper could just call |BeginTransaction...Commit| on the places DB connection directly. It won't be a problem for runInBatchMode, because mozStorageTransaction does nothing if there's already a storage transaction in progress.
The "only" problem with that approach is onBeginBatch/onEndBatch listeners.
To be clear, the listeners issue consists of two separate issues: 1) If runInBatchMode was called while an "async batch" was already in progress, onBeginBatch shouldn't be called. That's easy to fix, becuase mozStorageTransaction::HasTransaction can tell you whether or not it generated a "real" transaction. Similarly, when runInBatchMode ends, onEndBatch shouldn't be called if an async batch is in progress. That's also easy to fix using DBConn::GetTansactionInProgress 2) If an "async batch" has been started by PlacesUtils and generated "a real transaction", onBeginUpdateBatch should be called, and when async batch completes, onEndUpdateBatch should be called if no transaction is in progress. We'll nned to extend nsPIPlacesHistoryListenersNotifier in order to do that.
as discussed over IRC, I think it's fragile to base on GetTransactionInProgress, due to concurrent usage of sync and async statements we do. before moving to a complicate management for batch notifications, I think we should try to investigate if it's possible to get rid of batch notifications completely, by making the result smart about changes. I will try to make an experimental patch doing that and see.
Flags: needinfo?(mak77)
Depends on: 894331
Whiteboard: p=0
No longer blocks: fxdesktopbacklog
Flags: firefox-backlog+
Assignee: asaf → nobody
We should rather do bug 1340498.
Status: NEW → RESOLVED
Closed: 9 years ago
Resolution: --- → WONTFIX
You need to log in before you can comment on or make changes to this bug.