Skip to content

Commit

Permalink
refac(console): factor out a Store type (#359)
Browse files Browse the repository at this point in the history
Currently, there's a bit of repeated boilerplate code for processing
updates to the stored state for tasks, resources, and async ops, such as
tracking a list of new items since the last update, and handling ID
remapping. This PR builds upon the refactor in #358, and replaces the
`state::id` module with a new `state::store` module. This module
contains all of the old code for ID remapping along with a new `Store`
type that implements a store of objects by ID. The `Store` type now
implements much of the boilerplate code that was previously repeated in
the `state::tasks`, `state::resources`, and `state::async_ops` modules.
  • Loading branch information
hawkw authored Jul 13, 2022
1 parent dd36e4c commit e4eff4d
Show file tree
Hide file tree
Showing 6 changed files with 493 additions and 395 deletions.
139 changes: 63 additions & 76 deletions tokio-console/src/state/async_ops.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
use crate::{
intern::{self, InternedStr},
state::{
id::{Id, Ids},
pb_duration,
resources::Resource,
store::{self, Id, Store},
tasks::Task,
Attribute, Field, Metadata, Visibility,
},
Expand All @@ -21,9 +21,7 @@ use tui::text::Span;

#[derive(Default, Debug)]
pub(crate) struct AsyncOpsState {
async_ops: HashMap<Id<AsyncOp>, Rc<RefCell<AsyncOp>>>,
ids: Ids<AsyncOp>,
new_async_ops: Vec<AsyncOpRef>,
async_ops: Store<AsyncOp>,
dropped_events: u64,
}

Expand All @@ -41,15 +39,15 @@ pub(crate) enum SortBy {

#[derive(Debug)]
pub(crate) struct AsyncOp {
num: Id<AsyncOp>,
id: Id<AsyncOp>,
parent_id: InternedStr,
resource_id: Id<Resource>,
meta_id: u64,
source: InternedStr,
stats: AsyncOpStats,
}

pub(crate) type AsyncOpRef = Weak<RefCell<AsyncOp>>;
pub(crate) type AsyncOpRef = store::Ref<AsyncOp>;

#[derive(Debug)]
struct AsyncOpStats {
Expand All @@ -76,7 +74,7 @@ impl Default for SortBy {
impl SortBy {
pub fn sort(&self, now: SystemTime, ops: &mut [Weak<RefCell<AsyncOp>>]) {
match self {
Self::Aid => ops.sort_unstable_by_key(|ao| ao.upgrade().map(|a| a.borrow().num)),
Self::Aid => ops.sort_unstable_by_key(|ao| ao.upgrade().map(|a| a.borrow().id)),
Self::Task => ops.sort_unstable_by_key(|ao| ao.upgrade().map(|a| a.borrow().task_id())),
Self::Source => {
ops.sort_unstable_by_key(|ao| ao.upgrade().map(|a| a.borrow().source.clone()))
Expand Down Expand Up @@ -118,7 +116,7 @@ impl view::SortBy for SortBy {
impl AsyncOpsState {
/// Returns any new async ops for a resource that were added since the last async ops update.
pub(crate) fn take_new_async_ops(&mut self) -> impl Iterator<Item = AsyncOpRef> + '_ {
self.new_async_ops.drain(..)
self.async_ops.take_new_items()
}

/// Returns all async ops.
Expand All @@ -135,77 +133,66 @@ impl AsyncOpsState {
strings: &mut intern::Strings,
metas: &HashMap<u64, Metadata>,
update: proto::async_ops::AsyncOpUpdate,
resource_ids: &mut Ids<Resource>,
task_ids: &mut Ids<Task>,
resource_ids: &mut store::Ids<Resource>,
task_ids: &mut store::Ids<Task>,
visibility: Visibility,
) {
let mut stats_update = update.stats_update;
let new_list = &mut self.new_async_ops;
if matches!(visibility, Visibility::Show) {
new_list.clear();
}

let new_async_ops = update.new_async_ops.into_iter().filter_map(|async_op| {
if async_op.id.is_none() {
tracing::warn!(?async_op, "skipping async op with no id");
}

let meta_id = match async_op.metadata.as_ref() {
Some(id) => id.id,
None => {
tracing::warn!(?async_op, "async op has no metadata ID, skipping");
return None;
}
};
let meta = match metas.get(&meta_id) {
Some(meta) => meta,
None => {
tracing::warn!(?async_op, meta_id, "no metadata for async op, skipping");
return None;
}
};

let span_id = async_op.id?.id;
let stats = AsyncOpStats::from_proto(
stats_update.remove(&span_id)?,
meta,
styles,
strings,
task_ids,
);

let num = self.ids.id_for(span_id);
let resource_id = resource_ids.id_for(async_op.resource_id?.id);
let parent_id = match async_op.parent_async_op_id {
Some(id) => strings.string(format!("{}", self.ids.id_for(id.id))),
None => strings.string("n/a".to_string()),
};

let source = strings.string(async_op.source);

let async_op = AsyncOp {
num,
parent_id,
resource_id,
meta_id,
source,
stats,
};
let async_op = Rc::new(RefCell::new(async_op));
new_list.push(Rc::downgrade(&async_op));
Some((num, async_op))
});

self.async_ops.extend(new_async_ops);

for (span_id, stats) in stats_update {
let num = self.ids.id_for(span_id);
if let Some(async_op) = self.async_ops.get_mut(&num) {
let mut async_op = async_op.borrow_mut();
if let Some(meta) = metas.get(&async_op.meta_id) {
async_op.stats =
AsyncOpStats::from_proto(stats, meta, styles, strings, task_ids);
self.async_ops
.insert_with(visibility, update.new_async_ops, |ids, async_op| {
if async_op.id.is_none() {
tracing::warn!(?async_op, "skipping async op with no id");
}

let meta_id = match async_op.metadata.as_ref() {
Some(id) => id.id,
None => {
tracing::warn!(?async_op, "async op has no metadata ID, skipping");
return None;
}
};
let meta = match metas.get(&meta_id) {
Some(meta) => meta,
None => {
tracing::warn!(?async_op, meta_id, "no metadata for async op, skipping");
return None;
}
};

let span_id = async_op.id?.id;
let stats = AsyncOpStats::from_proto(
stats_update.remove(&span_id)?,
meta,
styles,
strings,
task_ids,
);

let id = ids.id_for(span_id);
let resource_id = resource_ids.id_for(async_op.resource_id?.id);
let parent_id = match async_op.parent_async_op_id {
Some(id) => strings.string(format!("{}", ids.id_for(id.id))),
None => strings.string("n/a".to_string()),
};

let source = strings.string(async_op.source);

let async_op = AsyncOp {
id,
parent_id,
resource_id,
meta_id,
source,
stats,
};
Some((id, async_op))
});

for (stats, mut async_op) in self.async_ops.updated(stats_update) {
if let Some(meta) = metas.get(&async_op.meta_id) {
tracing::trace!(?async_op, ?stats, "processing stats update for");
async_op.stats = AsyncOpStats::from_proto(stats, meta, styles, strings, task_ids);
}
}

Expand Down Expand Up @@ -234,7 +221,7 @@ impl AsyncOpsState {

impl AsyncOp {
pub(crate) fn id(&self) -> Id<AsyncOp> {
self.num
self.id
}

pub(crate) fn parent_id(&self) -> &str {
Expand Down Expand Up @@ -300,7 +287,7 @@ impl AsyncOpStats {
meta: &Metadata,
styles: &view::Styles,
strings: &mut intern::Strings,
task_ids: &mut Ids<Task>,
task_ids: &mut store::Ids<Task>,
) -> Self {
let mut pb = pb;

Expand Down
118 changes: 0 additions & 118 deletions tokio-console/src/state/id.rs

This file was deleted.

8 changes: 4 additions & 4 deletions tokio-console/src/state/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,11 @@ use tui::{

pub mod async_ops;
pub mod histogram;
pub mod id;
pub mod resources;
pub mod store;
pub mod tasks;

pub(crate) use self::id::Id;
pub(crate) use self::store::Id;

pub(crate) type DetailsRef = Rc<RefCell<Option<Details>>>;

Expand Down Expand Up @@ -162,8 +162,8 @@ impl State {
&mut self.strings,
&self.metas,
async_ops_update,
&mut self.resources_state.ids,
&mut self.tasks_state.ids,
self.resources_state.ids_mut(),
self.tasks_state.ids_mut(),
visibility,
)
}
Expand Down
Loading

0 comments on commit e4eff4d

Please sign in to comment.