-
Notifications
You must be signed in to change notification settings - Fork 8
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
discussion of sync vs async API #10
Comments
Sorry for the late response. My concern, is API extensibility. Your proposal may work well for a specific use case you described, but you may want to add a new feature to the API and the current sync API may prevent you from doing that (completely, or cleanly). You may think that the above is abstract and both sync/async APIs may suffer the same kind of problem (with different situations), but I believe sync APIs in general are less flexible and you'll be more likely in trouble when you add more features. Hence my first question is: Do you foresee more usecases in the future in addition to those described in https://github.com/WICG/unload-beacon#readme? If the answer is yes, I'd prefer the async model, or removing If the answer is no, I'd like to ask if const beacon = new PendingBeacon(url, {repeating: true});
beacon.setData(data);
...
// If the beacon has sent the previous data or is sending the previous data, then
// set `data` for the next request body. Otherwise, replace the current beacon data.
beacon.setData(data); I believe this is what the example wants to do. With this, we don't need to choose whether |
Hey @yutakahirano! :) In #9 we heard from both @philipwalton and @nicjansma that their main concern with an async API that's lacking a Regarding async APIs being more flexible, that's true (e.g. they enable cross-process communication, etc), but that flexibility comes with a cost, in terms of developer ergonomics and control. |
Thank you. If you're certain that the synchronous |
@yutakahirano Thanks. I'm going to leave some a closing argument here for why I think we are not creating a future problem. The real choice we're making here is in the implementation about what process is authoritative for the state of the beacon. If the renderer is authoritative (while alive) then the API never involves IPCs under the hood and anything that is just updating state (up to the point of sending) can be synchronous now and in the future. So I think the question of whether we will regret this API is really a question of whether we will ever regret making the renderer authoritative. It's hard to imagine that, since all state changes either come from
I don't know what other source of state changes there could be but if there was one, it could also just send IPCs to the renderer to request state changes. That other process might have to deal with the asynchronicity but as Yoav points out, it still seems better to put this theoretical future burden on the browser-implementer instead of putting it on the API callers right now. |
This CL does not change any PendingBeacon's behavior yet. It is to prepare for subsequent renderer-side timeout implementation. - Replaced `PendingBeaconHostRemote` with `PendingBeaconDispatcher` and exported the latter as an independent class. - Removed `timeout` from the mojom message to browser process. All timeout behavior will be implemented on the renderer-side, according to [1]. - Browser-side will still be responsible for making network requests. And trigger sending all beacons on page destroyed. Design Doc: https://docs.google.com/document/d/1QIFUu6Ne8x0W62RKJSoTtZjSd_bIM2yXZSELxdeuTFo/edit?pli=1#heading=h.nxtqzwddjsbk [1]: WICG/pending-beacon#10 (comment) Bug: 1293679 Change-Id: I04534a95d8540dd4344cc2b916a028a96ed3fbf4 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3809613 Reviewed-by: Daniel Cheng <dcheng@chromium.org> Reviewed-by: Rakina Zata Amni <rakina@chromium.org> Commit-Queue: Ming-Ying Chung <mych@chromium.org> Cr-Commit-Position: refs/heads/main@{#1035441}
This CL does not change any PendingBeacon's behavior yet. It is to prepare for subsequent renderer-side timeout implementation. - Replaced `PendingBeaconHostRemote` with `PendingBeaconDispatcher` and exported the latter as an independent class. - Removed `timeout` from the mojom message to browser process. All timeout behavior will be implemented on the renderer-side, according to [1]. - Browser-side will still be responsible for making network requests. And trigger sending all beacons on page destroyed. Design Doc: https://docs.google.com/document/d/1QIFUu6Ne8x0W62RKJSoTtZjSd_bIM2yXZSELxdeuTFo/edit?pli=1#heading=h.nxtqzwddjsbk [1]: WICG/pending-beacon#10 (comment) Bug: 1293679 Change-Id: I04534a95d8540dd4344cc2b916a028a96ed3fbf4 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3809613 Reviewed-by: Daniel Cheng <dcheng@chromium.org> Reviewed-by: Rakina Zata Amni <rakina@chromium.org> Commit-Queue: Ming-Ying Chung <mych@chromium.org> Cr-Commit-Position: refs/heads/main@{#1035441} NOKEYCHECK=True GitOrigin-RevId: 845c545f2edbec473cb270eaf97a82440338669e
Forking this from #9 (comment)
@yutakahirano
This problem exists even with very simple use-cases. Imagine we want to count or summarise events in some way (e.g. intersection observer events that help us compute how long an ad was displayed or just keep logging LCP values). With every event, we update the summary and want to call
setData
on the beacon. We have no control over the timing of these events. With an async API, the next event could arrive before the first one'ssetData
promise has resolved or rejected, forcing the application to write logic to handle this case. As you say, the application needs to deal with the problem by "queueing/filtering/merging requests" and that is con, especially as many devs will just write the naive version of the code and not even notice that a race exists.Purely from an API user's perspective, with the sync API these problems just don't exist, every event just computes the latest data and calls
setData
if the beacon is pending or replaces the beacon with a new one if it is no longer pending. It also doesn't matter if the different parts of the application access the same beacon simultaneously (we're single thread, so I take "simultaneously" to mean in the same JS task). I see no reason to tell developers that they shouldn't do that. That problem comes from the async API, it is not a fundamentally problematic thing to do.It seems to me that almost many uses of the API would need wrap the beacon in another layer to essentially present the sync API to the application.
We need a justification to push the burden of dealing with this onto JS and I don't think it's justified by implementation concerns. Even if the implementation was difficult, pushing the complexity to JS would not be good, however I believe the implementation is not difficult.
implementation concerns
I'll use chrome terminology, here renderer means the process running JS and browser means the process responsible for making the network request.
The concern that I am aware of is about the need to transfer the information from the renderer to the browser and getting that correct in all cases, including the crash case. There is no way to avoid transferring information from the renderer to the browser and I agree that minimising and making this atomic is good, e.g. #8 but the payload and also signals like
sendNow
andcancel
will always come from the renderer. With the async API we also need to transfer information from browser to renderer to know whether it's possible to set a new payload or cancel. The async API forces us to have 2-way communication of state.The sync API allows us to have 1-way communication of state. While the renderer is alive, the renderer is authoritative for the state of the beacon. This makes all API calls sync and return immediately, without blocking on events from other processes/network/etc. The sending step, at first, appears to be browser->renderer information flow but actually if you model it the right way, it's not. The browser requests clearance to send the beacon, the renderer updates the beacon's pending state to false and communicates the change in state to the browser. The browser cannot send until the pending state is false or the document has been discarded. There is no state transferred from browser to renderer in this model, all updates to the beacon state (payload, settings, pending, cancellation) are passed from the renderer to the browser.
If, in the future, we added an API to notify the renderer when sending completes or fails, that would introduce browser->renderer communication but at that point we are past the time where we have to defend against races and complexity in the JS.
The text was updated successfully, but these errors were encountered: