The runner now will cleanup resumed requests as they are completed
(either successfully or unsucessfully). Additionally, the
`FsRequestManager` will cleanup any requests that it cannot resume.
We are not able to fully remove `derive_more` becuase we use the Display
derive in `libfxrecord::net::message` to generate Display impls for
message kinds and the `DownloadStatus` enum.
The AssertInvoked test utility ensures that, when it is dropped, if it
was supposed to be marked as invoked that it is. This is used to ensure
that `cpu_and_disk_idle` is called (or not called) during integration
tests.
What was previously the `Taskcluster` struct is now the `Taskcluster`
trait and `FirefoxCi` struct, which implements that trait. This allows
us to only require testing the HTTP requests in our unit tests and
completely mock them out in integration tests, saving on test verbosity.
The `Taskcluster` trait is generic over an `Error` type, allowing for
easier mocking. The type that was `TaskclusterError` is now
`FirefoxCiError` (as it an implementation detail).
The `RunnerProtoError` is now generic over implementations of the
`Taskcluster` trait, again for easier mocking.
The RunnerProto only exposed only a single method: `handle_request`.
This interface has now been made a static function, replacing the
pattern of `RunnerProto::new().handle_request()` with
`RunnerProto::handle_request`.
Instead of the recorder constantly sending messages to the runner, it
now sends a single `Request` message and receives a series of responses
from the runner.
Tests will be fixed in a later commit.
Received profiles, prefs, and Firefox builds are not presently persisted
through restarts. This will be fixed in an upcoming patch.
The protocol docs no longer match what happens, so they've been removed
for now.
Instead of being generic over `S: Error + 'static`, the
`RunnerProtoError` type is now generic over `S: ShutdownProvider` and we
can use `S::Error` inside its definition, instead of instantiating it
from the `RunnerProto<S>` with `S::Error` directly.
This is a little cleaner and more readable, but does have a side effect
that requires `ShutdownProvider: Debug`.
This is in preparation for adding another generic parameter to
`RunnerProtoError`, making it generic over errors from the
`PerfProvider`. Without this change, it would require being generic over
both of the `PerfProvider`'s error types (`PerfProvider::DiskIoError`
and `PerfProvider::CpuTimeError`), making the types longer and messier.
We can now wait for the disk and CPU to settle out to acceptable levels
for our performance tests. LIke the `ShutdownProvider` API, the
`PerformanceProvider` API is implemented as a trait so that it can be
replaced for integration tests.
The `shutdown` module has been lightly refactored into an `osapi`
module. The error utilities (`WindowsError` and `get_last_error`) have
been refactored into the `osapi::error` module and the `Handle` API has
been refactored into the `osapi::handle` module.
The recorder now accepts prefs via the command-line, which will be sent
to the runner. If a profile was sent to the runner, that profile's
`user.js` will be appended with these new prefs. Otherwise, a new
profile will be used and these prefs will be written to that profile's
`user.js` instead.
The recorder can now specify a zipped Firefox profile for the runner to
use when running Firefox, which will be transferred from the recorder to
the runner.
The recorder will now request the runner download a specific build of
Firefox. A Taskcluster task ID for a build task is accepted by the
recorder on the command-line, which is used to determine the task to
download.
The runner now has an API for interacting with Taskcluster. Network
requests are run against a local server during unit tests so that they
do not require Internet access (or a valid Taskcluster setup) to run.
The interface between the `RunnerProto` and `RecorderProto` has been
more thoroughly tested for the handshake protocol. The infrastructure
added to accomplish this should make adding more tests easier as more of
the protocol is implemented.
The fxrunner has a `--skip-restart` flag that is only provided in debug
builds that allows it to skip doing an actual restart for local
development and testing.
fxrecorder will now request fxrunner to restart, wait, and re-connect.
This is accomplished with a exponential-backoff retrying algorithm.
The runner doesn't actually restart yet; instead, it just disconnects
from the recorder and sleeps for a duration.
This code sample is an command to find the name of the video device,
but `cargo test` was interpreting as a test. This was never caught until
now because there haven't been tests.
The main implementations of both fxrecorder and fxrunner have been split
into libraries which the binaries call into. This will enable
integration tests between the protocols.
The runner and recorder are now networked. The runner sets up a TCP
server and listens for incoming connections. The recorder connects to
the runner.
The bulk of this change is implementing the datatypes for messages and
protocols.
The `Proto` struct represents a protocol, which provides a way to send
and receive typed messages across a TCP socket. The `RunnerProto` and
`RecorderProto` are specializations of this type that implement that
actual business logic of sending and receiving messages in a certain
order for `fxrecorder` and `fxrunner` respectively.
Messages are the actual data sent across the socket. They are encoded by
the Proto as length-prefixed JSON blobs for transfer. There are two
types of messages:
1. `RecorderMessage`, which is sent from `fxrecorder` to `fxrunner`.
2. `RunnerMessage`, which is sent from `fxrecorder` to `fxrunner`.
Each type of message implements the `Message` interface, which allows
discriminationg between them with the `Message::kind()` method (and
imposes the serialization and deserialization constraints).
Message types are generated by the `impl_message!` and
`impl_message_inner!` macros to avoid writing boilerplate for each
message type.
The `ErrorMessage` type allows for `String` error messages (or anything
that implements `Display`, e.g. `&'static str`), which is useful for
representing errors in `fxrecorder` from `fxrunner` that cannot
otherwise be serialized over the network (e.g., `std::io::Error`).
These changes got rolled up into the tarpc patch (1125430, which has now
been reverted) instead of the previous patch (049619b), which made `run`
async.
This reverts commit 11254300fd.
As it turns out, tarpc cannot do what we need to do, vis-a-vis being
able to shutdown the server cleanly without causing errors on the client
side to reboot, as well as requiring a lot of state to be `Sync` (i.e.,
behind a `Rc<Mutex<T>>` or similar) for requests that will only ever
happen sequentially.
We now use the `tarpc` crate to allow fxrecorder to communicate with
fxrunner. The protocol is defined in `libfxrecord::service` and defines
a single method: `request_restart` (which is currently a no-op).