refac(console): use a newtype to separate ID types #358
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
The console TUI's state model deals with two different types of IDs:
tracing
span IDs for an object (task, resource, or asyncop), which are not assigned sequentially, and may be reused over
the program's lifetime, and
span IDs when an object is sent to the console. These are assigned
based on separate counters for each type of object (so there can be
both a task 1 and a resource 1, for example).
Remote span IDs are mapped to rewritten sequential IDs by the
Id
type,which stores a map of span IDs to sequential IDs, and generates new
sequential IDs when a new span ID is recorded. The
Ids::id_for
methodtakes a span ID and returns the corresponding sequential ID, and this
must be called before looking up or inserting an object by its remote
span ID.
Currently, all of these IDs are represented as
u64
s. This isunfortunate, as it makes it very easy to accidentally introduce bugs
where the wrong kind of ID is used. For example, it's possible to
accidentally look up a task in the map of active tasks based on its span
ID on the remote application, which is likely to return
None
even ifthere is a task with that span ID. PR #251 fixed one such ID-confusion
issue (where
WatchDetails
RPCs were performed with local, rewrittentask IDs rather than the remote's span ID for that task). However, it
would be better if we could just not have this class of issue.
This branch refactors the console's
state
module to make ID confusionissues much harder to write. This is accomplished by adding an
Id
newtype to represent our rewritten sequential IDs.
Ids::id_for
nowstill takes a
u64
(as the remote span IDs are represented asu64
s inprotobuf, so there's nothing we can do), but it returns an
Id
newtype.Looking up or inserting objects in a state map now takes the
Id
newtype. This ensures that all lookups are performed with sequential IDs
at the type level, and the only way to get a sequential ID is to ask the
Ids
map for one.Additionally, the
Id
type has a type parameter for the type of objectit identifies. This prevents additional issues where we might look up
the ID of a task in the map of resources, or similar.