Skip to content

Commit b85627c

Browse files
sergeypospelovDomonion
authored andcommitted
Create ResultAndErrorHandlingApiOfTheInstrumentedProcess.md
1 parent 70d099a commit b85627c

File tree

1 file changed

+55
-0
lines changed

1 file changed

+55
-0
lines changed
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
# Result & Error Handling API of the Instrumented Process
2+
3+
## Terminology
4+
5+
- The _instrumented process_ is an external process used for the isolated invocation.
6+
- The `ConcreteExecutor` is a class which provides smooth and concise interaction with the _instrumented process_. It works in the _main process_.
7+
- A client is an object which directly uses `ConcreteExecutor`, so it works in the _main process_ as well.
8+
- An _Instrumentation_ is an object which should be passed to `ConcreteExecutor`. It defines the logic of invocation and bytecode instrumentation in the _instrumented process_.
9+
10+
## Common
11+
12+
Basically, if any exception happens inside the _instrumented process_, it is rethrown to the client process via RD.
13+
- Some of the errors lead to the instant death of the _instrumented process_. Such errors are wrapped in `InstrumentedProcessDeathException`. Before processing the next request, the _instrumented process_ will be restarted automatically, but it can take some time.
14+
- Errors which do not cause the termination of the _instrumented process_ are wrapped in `InstrumentedProcessError`. Process won't be restarted, so client's requests will be handled by the same process. We believe, that the state of the _instrumented process_ is consistent, but in some tricky situations it may be not.
15+
16+
The extra logic of error and result handling depends on the provided instrumentation.
17+
18+
## UtConcreteExecutionInstrumentation
19+
20+
The next sections are related only to the `UtExecutionInstrumentation` passed to the _instrumented process_.
21+
22+
The calling of `ConcreteExecutor::executeAsync` instantiated by the `UtExecutionInstrumentation` can lead to the three possible situations:
23+
- `InstrumentedProcessDeathException` occurs. Usually, this situation means there is an internal issue in the _instrumented process_, but, nevertheless, this exception should be handled by the client.
24+
- `InstrumentedProcessError` occurs. It also means an internal issue and should be handled by the client. Sometimes it happens because the client provided the wrong configuration or parameters, but the _instrumented process_ **can't determine exactly** what's wrong with the client's data. The cause contains the description of the phase which threw the exception.
25+
- No exception occurs, so the `UtConcreteExecutionResult` is returned. It means that everything went well during the invocation or something broke down because of the wrong input, and the _instrumented process_ **knows exactly** what's wrong with the client's input. The _instrumented process_ guarantee that the state **is consistent**. The exact reason of failure is a `UtConcreteExecutionResult::result` field. It includes:
26+
- `UtSandboxFailure` --- violation of permissions.
27+
- `UtTimeoutException` --- the test execution time exceeds the provided time limit (`UtConcreteExecutionData::timeout`).
28+
- `UtExecutionSuccess` --- the test executed successfully.
29+
- `UtExplicitlyThrownException` --- the target method threw exception explicitly (via `throw` instruction).
30+
- `UtImplicitlyThrownException` --- the target method threw exception implicitly (`NPE`, `OOB`, etc. or it was thrown inside the system library)
31+
- etc.
32+
33+
### How the error handling works
34+
35+
The flow of the `UtExecutionInstrumentation::invoke` consists of 6 phases:
36+
- `ValueConstructionPhase` --- constructs values from the models.
37+
- `PreparationPhase` --- prepares statics, etc.
38+
- `InvocationPhase` --- invokes the target method.
39+
- `StatisticsCollectionPhase` --- collects the coverage and execution-related data.
40+
- `ModelConstructionPhase` --- constructs the result models from.
41+
- `PostprocessingPhase` --- restores statics, clear mocks, etc.
42+
43+
Each phase can throw two kinds of exceptions:
44+
- `ExecutionPhaseStop` --- indicates that the phase want to stop the invocation pipeline completely, because it's already has a result. The returned result is the `ExecutionPhaseStop::result` field.
45+
- `ExecutionPhaseError` --- indicates that an unexpected error happened inside the phase execution, so it's rethrown to the main process.
46+
47+
The `PhasesController::computeConcreteExecutionResult` then matches on the exception type and rethrows the exception if it's an `ExecutionPhaseError`, and returns the result if it's an `ExecutionPhaseStop`.
48+
49+
### Timeout
50+
51+
There is a time limit on the concrete execution, so the `UtExecutionInstrumentation::invoke` method must respect. We wrap phases which can take a long time with the `executePhaseInTimeout` block, which internally keeps and updates the elapsed time. If any wrapped phase exceeds the timeout, we return the `TimeoutException` as the result of that phase.
52+
53+
The clients cannot depend that cancellation request immediately breaks the invocation inside the _instrumented process_. The invocation is guaranteed to finish in the time of passed timeout, but not earlier.
54+
55+
Even if the `TimeoutException` occurs, the _instrumented process_ is ready to receive new requests.

0 commit comments

Comments
 (0)