Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Abstracts MapStore and MapLane over the underlying map implementation. #739

Open
wants to merge 15 commits into
base: cleanup
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
101 changes: 49 additions & 52 deletions server/swimos_agent/src/agent_lifecycle/item_event/map/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@
// See the License for the specific language governing permissions and
// limitations under the License.

use std::cmp::Ordering;
use std::fmt::Debug;
use std::hash::Hash;
use std::marker::PhantomData;
use std::{cmp::Ordering, collections::HashMap};

use frunk::{Coprod, Coproduct};
use futures::future::Either;
Expand All @@ -30,58 +30,52 @@ use crate::lanes::map::{
on_update::{OnUpdate, OnUpdateShared},
MapLaneLifecycle,
},
MapLane, MapLaneEvent,
MapLaneEvent,
};
use crate::stores::MapStore;
use crate::map_storage::MapOpsWithEntry;

use super::{HLeaf, HTree, ItemEvent, ItemEventShared};

#[cfg(test)]
mod tests;

pub type MapLeaf<Context, K, V, LC> = MapBranch<Context, K, V, LC, HLeaf, HLeaf>;
pub type MapBranch<Context, K, V, LC, L, R> = MapLikeBranch<Context, K, V, MapLane<K, V>, LC, L, R>;

pub type MapStoreLeaf<Context, K, V, LC> = MapStoreBranch<Context, K, V, LC, HLeaf, HLeaf>;
pub type MapStoreBranch<Context, K, V, LC, L, R> =
MapLikeBranch<Context, K, V, MapStore<K, V>, LC, L, R>;

pub type MapLifecycleHandler<'a, Context, K, V, LC> = Coprod!(
<LC as OnUpdate<K, V, Context>>::OnUpdateHandler<'a>,
<LC as OnRemove<K, V, Context>>::OnRemoveHandler<'a>,
<LC as OnClear<K, V, Context>>::OnClearHandler<'a>,
pub type MapLifecycleHandler<'a, Context, K, V, M, LC> = Coprod!(
<LC as OnUpdate<K, V, M, Context>>::OnUpdateHandler<'a>,
<LC as OnRemove<K, V, M, Context>>::OnRemoveHandler<'a>,
<LC as OnClear<M, Context>>::OnClearHandler<'a>,
);

pub type MapLifecycleHandlerShared<'a, Context, Shared, K, V, LC> = Coprod!(
<LC as OnUpdateShared<K, V, Context, Shared>>::OnUpdateHandler<'a>,
<LC as OnRemoveShared<K, V, Context, Shared>>::OnRemoveHandler<'a>,
<LC as OnClearShared<K, V, Context, Shared>>::OnClearHandler<'a>,
pub type MapLifecycleHandlerShared<'a, Context, Shared, K, V, M, LC> = Coprod!(
<LC as OnUpdateShared<K, V, M, Context, Shared>>::OnUpdateHandler<'a>,
<LC as OnRemoveShared<K, V, M, Context, Shared>>::OnRemoveHandler<'a>,
<LC as OnClearShared<M, Context, Shared>>::OnClearHandler<'a>,
);

type MapBranchHandler<'a, Context, K, V, LC, L, R> = Either<
type MapBranchHandler<'a, Context, K, V, M, LC, L, R> = Either<
<L as ItemEvent<Context>>::ItemEventHandler<'a>,
Either<
MapLifecycleHandler<'a, Context, K, V, LC>,
MapLifecycleHandler<'a, Context, K, V, M, LC>,
<R as ItemEvent<Context>>::ItemEventHandler<'a>,
>,
>;

type MapBranchHandlerShared<'a, Context, Shared, K, V, LC, L, R> = Either<
type MapBranchHandlerShared<'a, Context, Shared, K, V, M, LC, L, R> = Either<
<L as ItemEventShared<Context, Shared>>::ItemEventHandler<'a>,
Either<
MapLifecycleHandlerShared<'a, Context, Shared, K, V, LC>,
MapLifecycleHandlerShared<'a, Context, Shared, K, V, M, LC>,
<R as ItemEventShared<Context, Shared>>::ItemEventHandler<'a>,
>,
>;

fn map_handler<'a, Context, K, V, LC>(
event: MapLaneEvent<K, V>,
fn map_handler<'a, Context, K, V, M, LC>(
event: MapLaneEvent<K, V, M>,
lifecycle: &'a LC,
map: &HashMap<K, V>,
) -> MapLifecycleHandler<'a, Context, K, V, LC>
map: &M,
) -> MapLifecycleHandler<'a, Context, K, V, M, LC>
where
K: Hash + Eq,
LC: MapLaneLifecycle<K, V, Context>,
LC: MapLaneLifecycle<K, V, M, Context>,
M: MapOpsWithEntry<K, V, K>,
{
match event {
MapLaneEvent::Update(k, old) => {
Expand All @@ -97,16 +91,17 @@ where
}
}

fn map_handler_shared<'a, Context, Shared, K, V, LC>(
fn map_handler_shared<'a, Context, Shared, K, V, M, LC>(
shared: &'a Shared,
handler_context: HandlerContext<Context>,
event: MapLaneEvent<K, V>,
event: MapLaneEvent<K, V, M>,
lifecycle: &'a LC,
map: &HashMap<K, V>,
) -> MapLifecycleHandlerShared<'a, Context, Shared, K, V, LC>
map: &M,
) -> MapLifecycleHandlerShared<'a, Context, Shared, K, V, M, LC>
where
K: Hash + Eq,
LC: MapLaneLifecycleShared<K, V, Context, Shared>,
LC: MapLaneLifecycleShared<K, V, M, Context, Shared>,
M: MapOpsWithEntry<K, V, K>,
{
match event {
MapLaneEvent::Update(k, old) => {
Expand All @@ -126,19 +121,19 @@ where
}
}

type KeyValue<K, V> = fn((K, V)) -> (K, V);
type MapKeyValue<M, K, V> = fn((&M, K, V)) -> (K, V);
/// Map lane lifecycle as a branch node of an [`HTree`].
pub struct MapLikeBranch<Context, K, V, Item, LC, L, R> {
_type: PhantomData<KeyValue<K, V>>,
pub struct MapLikeBranch<Context, K, V, M, Item, LC, L, R> {
_type: PhantomData<MapKeyValue<M, K, V>>,
label: &'static str,
projection: fn(&Context) -> &Item,
lifecycle: LC,
left: L,
right: R,
}

impl<Context, K, V, Item, LC: Clone, L: Clone, R: Clone> Clone
for MapLikeBranch<Context, K, V, Item, LC, L, R>
impl<Context, K, V, M, Item, LC: Clone, L: Clone, R: Clone> Clone
for MapLikeBranch<Context, K, V, M, Item, LC, L, R>
{
fn clone(&self) -> Self {
Self {
Expand All @@ -152,15 +147,15 @@ impl<Context, K, V, Item, LC: Clone, L: Clone, R: Clone> Clone
}
}

impl<Context, K, V, Item, LC, L: HTree, R: HTree> HTree
for MapLikeBranch<Context, K, V, Item, LC, L, R>
impl<Context, K, V, M, Item, LC, L: HTree, R: HTree> HTree
for MapLikeBranch<Context, K, V, M, Item, LC, L, R>
{
fn label(&self) -> Option<&'static str> {
Some(self.label)
}
}

impl<Context, K, V, Item, LC, L, R> Debug for MapLikeBranch<Context, K, V, Item, LC, L, R>
impl<Context, K, V, M, Item, LC, L, R> Debug for MapLikeBranch<Context, K, V, M, Item, LC, L, R>
where
LC: Debug,
L: Debug,
Expand All @@ -177,13 +172,13 @@ where
}
}

impl<Context, K, V, Item, LC> MapLikeBranch<Context, K, V, Item, LC, HLeaf, HLeaf> {
impl<Context, K, V, M, Item, LC> MapLikeBranch<Context, K, V, M, Item, LC, HLeaf, HLeaf> {
pub fn leaf(label: &'static str, projection: fn(&Context) -> &Item, lifecycle: LC) -> Self {
MapLikeBranch::new(label, projection, lifecycle, HLeaf, HLeaf)
}
}

impl<Context, K, V, Item, LC, L, R> MapLikeBranch<Context, K, V, Item, LC, L, R>
impl<Context, K, V, M, Item, LC, L, R> MapLikeBranch<Context, K, V, M, Item, LC, L, R>
where
L: HTree,
R: HTree,
Expand Down Expand Up @@ -212,16 +207,17 @@ where
}
}

impl<Context, K, V, Item, LC, L, R> ItemEvent<Context>
for MapLikeBranch<Context, K, V, Item, LC, L, R>
impl<Context, K, V, M, Item, LC, L, R> ItemEvent<Context>
for MapLikeBranch<Context, K, V, M, Item, LC, L, R>
where
K: Clone + Eq + Hash,
Item: MapItem<K, V>,
LC: MapLaneLifecycle<K, V, Context>,
Item: MapItem<K, V, M>,
LC: MapLaneLifecycle<K, V, M, Context>,
L: HTree + ItemEvent<Context>,
R: HTree + ItemEvent<Context>,
M: MapOpsWithEntry<K, V, K>,
{
type ItemEventHandler<'a> = MapBranchHandler<'a, Context, K, V, LC, L, R>
type ItemEventHandler<'a> = MapBranchHandler<'a, Context, K, V, M, LC, L, R>
where
Self: 'a;

Expand Down Expand Up @@ -253,16 +249,17 @@ where
}
}

impl<Context, Shared, K, V, Item, LC, L, R> ItemEventShared<Context, Shared>
for MapLikeBranch<Context, K, V, Item, LC, L, R>
impl<Context, Shared, K, V, M, Item, LC, L, R> ItemEventShared<Context, Shared>
for MapLikeBranch<Context, K, V, M, Item, LC, L, R>
where
K: Clone + Eq + Hash,
Item: MapItem<K, V>,
LC: MapLaneLifecycleShared<K, V, Context, Shared>,
Item: MapItem<K, V, M>,
LC: MapLaneLifecycleShared<K, V, M, Context, Shared>,
L: HTree + ItemEventShared<Context, Shared>,
R: HTree + ItemEventShared<Context, Shared>,
M: MapOpsWithEntry<K, V, K>,
{
type ItemEventHandler<'a> = MapBranchHandlerShared<'a, Context, Shared, K, V, LC, L, R>
type ItemEventHandler<'a> = MapBranchHandlerShared<'a, Context, Shared, K, V, M, LC, L, R>
where
Self: 'a,
Shared: 'a;
Expand Down
14 changes: 10 additions & 4 deletions server/swimos_agent/src/agent_lifecycle/item_event/map/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ use swimos_model::Text;
use swimos_utilities::routing::RouteUri;

use crate::{
agent_lifecycle::item_event::{tests::run_handler, HLeaf, ItemEvent, MapBranch, MapLeaf},
agent_lifecycle::item_event::{tests::run_handler, HLeaf, ItemEvent},
event_handler::{ActionContext, HandlerAction, StepResult},
lanes::map::{
lifecycle::{on_clear::OnClear, on_remove::OnRemove, on_update::OnUpdate},
Expand All @@ -29,6 +29,12 @@ use crate::{
meta::AgentMetadata,
};

use super::MapLikeBranch;

type MapLeaf<Context, K, V, M, LC> = MapBranch<Context, K, V, M, LC, HLeaf, HLeaf>;
type MapBranch<Context, K, V, M, LC, L, R> =
MapLikeBranch<Context, K, V, M, MapLane<K, V, M>, LC, L, R>;

struct TestAgent {
first: MapLane<i32, i32>,
second: MapLane<i32, Text>,
Expand Down Expand Up @@ -248,7 +254,7 @@ impl<K, V> FakeLifecycle<K, V> {
}
}

impl<K, V> OnUpdate<K, V, TestAgent> for FakeLifecycle<K, V>
impl<K, V> OnUpdate<K, V, HashMap<K, V>, TestAgent> for FakeLifecycle<K, V>
where
K: Clone + Send + 'static,
V: Clone + Send + 'static,
Expand All @@ -268,7 +274,7 @@ where
}
}

impl<K, V> OnRemove<K, V, TestAgent> for FakeLifecycle<K, V>
impl<K, V> OnRemove<K, V, HashMap<K, V>, TestAgent> for FakeLifecycle<K, V>
where
K: Clone + Send + 'static,
V: Clone + Send + 'static,
Expand All @@ -287,7 +293,7 @@ where
}
}

impl<K, V> OnClear<K, V, TestAgent> for FakeLifecycle<K, V>
impl<K, V> OnClear<HashMap<K, V>, TestAgent> for FakeLifecycle<K, V>
where
K: Clone + Send + 'static,
V: Clone + Send + 'static,
Expand Down
5 changes: 1 addition & 4 deletions server/swimos_agent/src/agent_lifecycle/item_event/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,7 @@ pub use demand_map::{
DemandMapBranch, DemandMapLeaf, DemandMapLifecycleHandler, DemandMapLifecycleHandlerShared,
};
pub use http::{HttpBranch, HttpLeaf};
pub use map::{
MapBranch, MapLeaf, MapLifecycleHandler, MapLifecycleHandlerShared, MapLikeBranch,
MapStoreBranch, MapStoreLeaf,
};
pub use map::{MapLifecycleHandler, MapLifecycleHandlerShared, MapLikeBranch};
pub use value::{
ValueBranch, ValueLeaf, ValueLifecycleHandler, ValueLifecycleHandlerShared, ValueLikeBranch,
ValueStoreBranch, ValueStoreLeaf,
Expand Down
10 changes: 5 additions & 5 deletions server/swimos_agent/src/agent_lifecycle/utility/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -234,13 +234,13 @@ impl<Agent: AgentDescription + 'static> HandlerContext<Agent> {
) -> impl HandlerAction<Agent, Completion = U> + Send + 'a
where
Agent: 'static,
Item: InspectableMapLikeItem<K, V> + 'static,
Item: InspectableMapLikeItem<K, V, B> + 'static,
K: Send + Clone + Eq + Hash + 'static,
V: Borrow<B> + 'static,
B: ?Sized + 'static,
F: FnOnce(Option<&B>) -> U + Send + 'a,
{
Item::with_entry_handler::<Agent, F, B, U>(item, key, f)
Item::with_entry_handler::<Agent, F, U>(item, key, f)
}

/// Create an event handler that will transform the value in an entry of a map lane or store of the agent.
Expand Down Expand Up @@ -326,12 +326,12 @@ impl<Agent: AgentDescription + 'static> HandlerContext<Agent> {
///
/// #Arguments
/// * `item` - Projection to the map-like item.
pub fn get_map<Item, K, V>(
pub fn get_map<Item, K, V, M>(
&self,
item: fn(&Agent) -> &Item,
) -> impl HandlerAction<Agent, Completion = HashMap<K, V>> + Send + 'static
) -> impl HandlerAction<Agent, Completion = M> + Send + 'static
where
Item: MapLikeItem<K, V>,
Item: MapLikeItem<K, V, M>,
K: Send + Clone + Eq + Hash + 'static,
V: Send + Clone + 'static,
{
Expand Down
Loading
Loading