[adr] network handler behavior proposal#17685
Conversation
PR Summary by QodoADR: Define network handler disposition, ordering, and failure semantics Description
Diagram
High-Level Assessment
Files changed (1)
|
Code Review by Qodo
Context used✅ Compliance rules (platform):
11 rules 1. Java order nondeterministic
|
b09a2bc to
18895d1
Compare
|
Code review by qodo was updated up to the latest commit 18895d1 |
| network.add_request_handler { |r| r.remove_header("X-Test") } | ||
| ``` | ||
|
|
||
| 4. **Handlers with uncaught exceptions are not processed.** Handling proceeds as if the handler |
There was a problem hiding this comment.
Actually, maybe the right answer here is to make this user-toggled with the default being to raise. I didn't consider this when suggesting alternatives below. Perhaps we do want to error-by-default but provide a global escape hatch while things are still in draft.
There was a problem hiding this comment.
I feel fail fast should always be the right approach for people
There was a problem hiding this comment.
First, to clarify, Python as written does the error behavior in this ADR (except for it doesn't discard staged changes).
As for fast-fail, that's correct for synchronous code evaluating the behavior. In network handlers, the failures will come from things the author didn't write like third-party scripts, analytics beacons, favicon retries, an auth challenge from an unrelated CDN. We don't want to necessarily couple the test's pass/fail to the open internet via a still-under-development BiDi protocol.
The reason I don't love this proposal as written is because when a user wants to mutate a specific thing as the intent of the test, silently ignoring it is a real problem, but I also don't want to de facto require users to always wrap everything in a try/catch which seems like a bad experience.
Honestly the desired default behavior is going to be different if a user wants to observe vs mutate, which might be a good reason to support the differentiation earlier. The alternative would be an error handling toggle for propagate vs log
There was a problem hiding this comment.
+1 to fail fast, notifying user your handler is bad. In low-level BiDi/.NET the default behavior is to break entire pipeline:
Example (pseudo code):
var handler = using network.intercept(r => raise exception)
network.navigate("selenium.dev")
navigate fails, swallowed. User sees exception at disposal. Dear user, investigate.
There was a problem hiding this comment.
I wasn't suggesting my way was correct, I followed what other docs suggested which is why I did it.
There was a problem hiding this comment.
As the ADR says though, I'd prefer if we could limit propagating failures to the tests/intentions not any potential malformed network call that the code or BiDi spec doesn't properly parse.
@nvborisenko yeah intercepts should propagate errors because they likely get into the intent of the test and are likely filtered in one fashion or another. My concern is when you create a handler to "log everything" that you're going to end up with a ton of unexpected errors because the internet is complicated and our spec is new. My concern goes away if we differentiate behavior between observers and intercepts, but if we continue with the "everything is an intercept for now" I see potential problems.
There was a problem hiding this comment.
Intercepting and just listening are different cases. BiDi provides different capabilities. I feel it should be different api methods. Argue: to listen to network traffic, we just subscribe. To intercept it: we have to add interception and react accordingly. Seems unnecessary client/server roundtrip just for listening.
There was a problem hiding this comment.
Yes, I see it how @nvborisenko sees it. That is why I think this ADR and #17671 complement each other.
diemol
left a comment
There was a problem hiding this comment.
I think this ADR will help us unify handler behavior across all language bindings, which is currently handled differently in each language.
If I understand this correctly, @titusfortner suggests this ADR is an alternative to #17671. But what I see is that this ADR covers network interception, which blocks because it waits for a handler disposition. Whereas #17671 is about observation, which should not block, and only subscribes to events (did I get that right, @AutomatedTester?).
That is why I believe the two ADRs complement each other.
In addition, this ADR, like #17671, seems to me to be a middle-layer API. One that users would use for specific use cases that the high-level API won't cover.
| The TLC discussed these ideas in a design document (by @p0deje). That document included | ||
| prescribed implementation details that this ADR is avoiding, to focus on the user-facing | ||
| behaviors we want rather than what needs to be implemented to achieve them. |
There was a problem hiding this comment.
I don't think this part is necessary unless you want to give more context by linking to the document. Which I think is not really necessary.
There was a problem hiding this comment.
Yes, this more accurately belongs in the PR body not the ADR itself.
After a few ADRs I think I better understand what the split should look like and I tried to clarify here: #17697
| ## Decision | ||
|
|
||
| This applies to request and response handlers, but not authentication handlers, since | ||
| authentication should not use a callable. |
There was a problem hiding this comment.
I am confused. What does this mean? Is this "A user can register more than one handler for the same network phase, and matching handlers can disagree", the decision?
I am just looking for a paragraph that describes the decision.
There was a problem hiding this comment.
"This" == "This ADR"
Yeah, let me update this ADR
In the last TLC meeting people were pushing for the idea that for now everything that can block will block in our implementations and we won't handle it any differently. I'm saying they are in opposition because if you adopt this ADR, you don't need the extra methods proposed by the other ADR. Also, I think it is wrong to characterize these as "middle-layer API." Anything that affects the code the user needs to write is user-facing and needs to be part of the high-level API contract we are creating that we want to maintain. |
The way I see these two ADRs:
That's why I think there are two other options: either observe or intercept here. I still think that this is a middle-layer API. I don't want the user to have to handle all these callbacks and other things to manipulate their code in BiDi. I want this API to land and be used in a higher-level API to do network routing, mocking, and method interception, covering all of this implementation. In my head, we should have:
If this current ADR is what we're doing at the high level, it is way too complex. |
|
Code review by qodo was updated up to the latest commit 281e9bb |
|
Code review by qodo was updated up to the latest commit 895d532 |
Can we get the functionality implemented across the bindings then figure out which wrappers and helpers and fixtures to add later? I feel like we may need to step back from the ADRs and agree to the milestones and requirements for Selenium 5 again. |
📄 The decision, its rationale, considered options, and consequences are in the record file
this PR adds (
docs/decisions/17685-network-handler-behavior.md);read it there. The sections below are proposal notes and review logistics.
🔗 Related
📝 Proposal notes
on/route, and [docs] decision: BiDi events are awaited with expect_* context managers #17671 — observation and interception are treated as mutually exclusive, requiring separate APIs; a separate record would concede that framing, which is what's contested. Body collection is here because it's part of the same handler registration, not a separable concern.complete/capture primitive for saving an event for later assertion (considered but deferred — not worth adding right now).🗣 Discussion
For reviewers and the TLC (input wanted, not a defect):
📌 Tracking
Tracking issue: (linked on acceptance)