Skip to content

Commit e0e0885

Browse files
Merge pull request #720 from swimos/connector-lanes
Moves lane opening into swimos_connector.
2 parents 8a5ed6c + a1e64c7 commit e0e0885

File tree

24 files changed

+662
-387
lines changed

24 files changed

+662
-387
lines changed

api/swimos_api/src/address.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,17 @@ impl<T> Address<T> {
5454
}
5555
}
5656

57+
impl Address<&str> {
58+
pub fn owned(&self) -> Address<String> {
59+
let Address { host, node, lane } = self;
60+
Address {
61+
host: host.as_ref().map(|s| s.to_string()),
62+
node: node.to_string(),
63+
lane: lane.to_string(),
64+
}
65+
}
66+
}
67+
5768
impl<T: Display + Debug> Display for Address<T> {
5869
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
5970
write!(

server/swimos_agent/src/lanes/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ impl<OnDone> OpenLane<OnDone> {
122122
/// * `name` - The name of the new lane.
123123
/// * `kind` - The kind of the new lane.
124124
/// * `on_done` - A callback tht produces an event handler that will be executed after the request completes.
125-
pub(crate) fn new(name: String, kind: WarpLaneKind, on_done: OnDone) -> Self {
125+
pub fn new(name: String, kind: WarpLaneKind, on_done: OnDone) -> Self {
126126
OpenLane {
127127
name,
128128
kind,

server/swimos_connector/src/connector/egress/mod.rs

Lines changed: 27 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414

1515
use std::{collections::HashMap, time::Duration};
1616

17-
use swimos_api::address::Address;
17+
use swimos_api::{address::Address, agent::WarpLaneKind};
1818
use swimos_model::Value;
1919

2020
use super::{BaseConnector, ConnectorFuture};
@@ -42,12 +42,12 @@ pub trait EgressConnector: BaseConnector {
4242
/// The type of the sender created by this connector.
4343
type Sender: EgressConnectorSender<Self::Error> + 'static;
4444

45-
/// Open the downlinks required by the connector. This is called during the agent's `on_start`
45+
/// Open the lanes and downlinks required by the connector. This is called during the agent's `on_start`
4646
/// event.
4747
///
4848
/// # Arguments
49-
/// * `context` - The connector makes calls to the context to request the downlinks.
50-
fn open_downlinks(&self, context: &mut dyn EgressContext);
49+
/// * `context` - The connector makes calls to the context to request the lanes and downlinks.
50+
fn initialize(&self, context: &mut dyn EgressContext) -> Result<(), Self::Error>;
5151

5252
/// Create sender for the connector which is used to send messages to the external data sink. This is called
5353
/// exactly ones during the agent's `on_start` event but must implement [`Clone`] so that copies can be passed
@@ -61,22 +61,6 @@ pub trait EgressConnector: BaseConnector {
6161
) -> Result<Self::Sender, Self::Error>;
6262
}
6363

64-
/// A reference to an egress context is passed to an [`EgressConnector`] when it starts allowing it
65-
/// to request that downlinks be opened to remote lanes.
66-
pub trait EgressContext {
67-
/// Request an event downlink to a remote lane.
68-
///
69-
/// # Arguments
70-
/// * `address` - The address of the remote lane.
71-
fn open_event_downlink(&mut self, address: Address<String>);
72-
73-
/// Request a map-event downlink to a remote lane.
74-
///
75-
/// # Arguments
76-
/// * `address` - The address of the remote lane.
77-
fn open_map_downlink(&mut self, address: Address<String>);
78-
}
79-
8064
/// Possible results of sending a message to the external sink.
8165
pub enum SendResult<F, E> {
8266
/// The process of attempting to send the message can begin. When the provided future completes,
@@ -154,3 +138,26 @@ pub trait EgressConnectorSender<SendError>: Send + Clone {
154138
timer_id: u64,
155139
) -> Option<SendResult<impl ConnectorFuture<SendError>, SendError>>;
156140
}
141+
142+
/// A reference to an egress context is passed to an [egress connector](`EgressConnector`) when it starts
143+
/// allowing it to request that lanes or downlinks to remote lanes be opened.
144+
pub trait EgressContext {
145+
/// Request a new, dynamic WARP lane be opened on the agent.
146+
///
147+
/// # Arguments
148+
/// * `name` - The name of the lane.
149+
/// * `kind` - The kind of the lane.
150+
fn open_lane(&mut self, name: &str, kind: WarpLaneKind);
151+
152+
/// Request an event downlink to a remote lane.
153+
///
154+
/// # Arguments
155+
/// * `address` - The address of the remote lane.
156+
fn open_event_downlink(&mut self, address: Address<&str>);
157+
158+
/// Request a map-event downlink to a remote lane.
159+
///
160+
/// # Arguments
161+
/// * `address` - The address of the remote lane.
162+
fn open_map_downlink(&mut self, address: Address<&str>);
163+
}

server/swimos_connector/src/connector/ingress/mod.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ use swimos_agent::{
2020
agent_lifecycle::HandlerContext,
2121
event_handler::{HandlerAction, HandlerActionExt, TryHandlerActionExt},
2222
};
23+
use swimos_api::agent::WarpLaneKind;
2324

2425
use crate::generic::ConnectorAgent;
2526

@@ -46,6 +47,13 @@ pub trait IngressConnector: BaseConnector {
4647
/// Create an asynchronous stream that consumes events from the external data source and produces
4748
/// [event handlers](swimos_agent::event_handler::EventHandler) from them which modify the state of the agent.
4849
fn create_stream(&self) -> Result<impl ConnectorStream<Self::Error>, Self::Error>;
50+
51+
/// Open the lanes required by the connector. This is called during the agent's `on_start`
52+
/// event.
53+
///
54+
/// # Arguments
55+
/// * `context` - The connector makes calls to the context to request the lanes.
56+
fn initialize(&self, context: &mut dyn IngressContext) -> Result<(), Self::Error>;
4957
}
5058

5159
/// A trait for fallible streams of event handlers that are returned by a [`IngressConnector`].
@@ -86,3 +94,14 @@ where
8694
};
8795
context.suspend(fut)
8896
}
97+
98+
/// A reference to an ingress context is passed to an [ingress connector](`IngressConnector`) when it starts
99+
/// allowing it to request that lanes be opened.
100+
pub trait IngressContext {
101+
/// Request a new, dynamic WARP lane be opened on the agent.
102+
///
103+
/// # Arguments
104+
/// * `name` - The name of the lane.
105+
/// * `kind` - The kind of the lane.
106+
fn open_lane(&mut self, name: &str, kind: WarpLaneKind);
107+
}

server/swimos_connector/src/connector/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ pub use egress::{
1919
EgressConnector, EgressConnectorSender, EgressContext, MessageSource, SendResult,
2020
};
2121
use futures::TryFuture;
22-
pub use ingress::{suspend_connector, ConnectorStream, IngressConnector};
22+
pub use ingress::{suspend_connector, ConnectorStream, IngressConnector, IngressContext};
2323
use swimos_agent::event_handler::EventHandler;
2424
use swimos_utilities::trigger;
2525

server/swimos_connector/src/lib.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@ mod route;
2222
mod test_support;
2323
pub use connector::{
2424
BaseConnector, ConnectorFuture, ConnectorHandler, ConnectorStream, EgressConnector,
25-
EgressConnectorSender, EgressContext, IngressConnector, MessageSource, SendResult,
25+
EgressConnectorSender, EgressContext, IngressConnector, IngressContext, MessageSource,
26+
SendResult,
2627
};
2728
pub use error::ConnectorInitError;
2829
pub use generic::{ConnectorAgent, MapLaneSelectorFn, ValueLaneSelectorFn};

server/swimos_connector/src/lifecycle/egress/mod.rs

Lines changed: 37 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
use std::{cell::OnceCell, collections::HashMap};
1616

1717
use bitflags::bitflags;
18-
use futures::{FutureExt, TryFutureExt};
18+
use futures::{future::join, FutureExt, TryFutureExt};
1919
use swimos_agent::{
2020
agent_lifecycle::{
2121
item_event::{dynamic_handler, DynamicHandler, DynamicLifecycle, ItemEvent},
@@ -34,16 +34,18 @@ use swimos_agent::{
3434
AgentMetadata,
3535
};
3636
use swimos_agent_protocol::MapMessage;
37-
use swimos_api::address::Address;
37+
use swimos_api::{address::Address, agent::WarpLaneKind};
3838
use swimos_model::Value;
3939
use swimos_utilities::trigger;
4040

4141
use crate::{
42-
connector::{EgressConnector, EgressConnectorSender},
42+
connector::{EgressConnector, EgressConnectorSender, EgressContext},
4343
error::ConnectorInitError,
44-
ConnectorAgent, EgressContext, MessageSource, SendResult,
44+
ConnectorAgent, MessageSource, SendResult,
4545
};
4646

47+
use super::open_lanes;
48+
4749
#[cfg(test)]
4850
mod tests;
4951

@@ -96,18 +98,23 @@ bitflags! {
9698
}
9799

98100
#[derive(Default, Debug)]
99-
struct DownlinkCollector {
101+
struct RequestCollector {
102+
lanes: Vec<(String, WarpLaneKind)>,
100103
value_downlinks: Vec<Address<String>>,
101104
map_downlinks: Vec<Address<String>>,
102105
}
103106

104-
impl EgressContext for DownlinkCollector {
105-
fn open_event_downlink(&mut self, address: Address<String>) {
106-
self.value_downlinks.push(address);
107+
impl EgressContext for RequestCollector {
108+
fn open_event_downlink(&mut self, address: Address<&str>) {
109+
self.value_downlinks.push(address.owned());
110+
}
111+
112+
fn open_map_downlink(&mut self, address: Address<&str>) {
113+
self.map_downlinks.push(address.owned());
107114
}
108115

109-
fn open_map_downlink(&mut self, address: Address<String>) {
110-
self.map_downlinks.push(address);
116+
fn open_lane(&mut self, name: &str, kind: WarpLaneKind) {
117+
self.lanes.push((name.to_string(), kind));
111118
}
112119
}
113120

@@ -117,11 +124,12 @@ where
117124
{
118125
fn on_start(&self) -> impl EventHandler<ConnectorAgent> + '_ {
119126
let EgressConnectorLifecycle { lifecycle, sender } = self;
120-
let (tx, rx) = trigger::trigger();
127+
let (on_start_tx, on_start_rx) = trigger::trigger();
128+
let (lanes_tx, lanes_rx) = trigger::trigger();
121129
let context: HandlerContext<ConnectorAgent> = Default::default();
122-
let mut collector = DownlinkCollector::default();
123-
let on_start = lifecycle.on_start(tx);
124-
lifecycle.open_downlinks(&mut collector);
130+
let mut collector = RequestCollector::default();
131+
let init_result = lifecycle.initialize(&mut collector);
132+
let on_start = lifecycle.on_start(on_start_tx);
125133
let create_sender = context
126134
.with_parameters(|params| lifecycle.make_sender(params))
127135
.try_handler()
@@ -131,14 +139,24 @@ where
131139
})
132140
});
133141
let await_init = context.suspend(async move {
142+
let (r1, r2) = join(on_start_rx, lanes_rx).await;
134143
context
135-
.value(rx.await)
144+
.value(r1.and(r2))
136145
.try_handler()
137146
.followed_by(ConnectorAgent::set_flags(EgressFlags::INITIALIZED.bits()))
138147
});
139-
let open_downlinks = self.open_downlinks(collector);
140-
await_init
148+
let RequestCollector {
149+
lanes,
150+
value_downlinks,
151+
map_downlinks,
152+
} = collector;
153+
let open_lanes = open_lanes(lanes, lanes_tx);
154+
let open_downlinks = self.open_downlinks(value_downlinks, map_downlinks);
155+
let check_init = context.value(init_result).try_handler();
156+
check_init
157+
.followed_by(await_init)
141158
.followed_by(on_start)
159+
.followed_by(open_lanes)
142160
.followed_by(create_sender)
143161
.followed_by(open_downlinks)
144162
}
@@ -252,18 +270,15 @@ where
252270
{
253271
fn open_downlinks(
254272
&self,
255-
collector: DownlinkCollector,
273+
value_downlinks: Vec<Address<String>>,
274+
map_downlinks: Vec<Address<String>>,
256275
) -> impl EventHandler<ConnectorAgent> + '_ {
257276
let EgressConnectorLifecycle { sender, .. } = self;
258277
let context: HandlerContext<ConnectorAgent> = Default::default();
259278
context
260279
.effect(|| sender.get().ok_or(ConnectorInitError))
261280
.try_handler()
262281
.and_then(move |sender: &C::Sender| {
263-
let DownlinkCollector {
264-
value_downlinks,
265-
map_downlinks,
266-
} = collector;
267282
let mut open_value_dls = vec![];
268283
let mut open_map_dls = vec![];
269284
for address in value_downlinks {

server/swimos_connector/src/lifecycle/egress/tests.rs

Lines changed: 27 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -38,13 +38,13 @@ use swimos_model::{Text, Value};
3838
use swimos_utilities::trigger;
3939
use thiserror::Error;
4040

41+
use crate::connector::EgressContext;
4142
use crate::lifecycle::fixture::{
4243
drive_downlink, run_handle_with_futs, DownlinkRecord, RequestsRecord, TimerRecord,
4344
};
4445
use crate::{
4546
BaseConnector, ConnectorAgent, ConnectorFuture, EgressConnector, EgressConnectorLifecycle,
46-
EgressConnectorSender, EgressContext, MapLaneSelectorFn, MessageSource, SendResult,
47-
ValueLaneSelectorFn,
47+
EgressConnectorSender, MapLaneSelectorFn, MessageSource, SendResult, ValueLaneSelectorFn,
4848
};
4949

5050
#[derive(Default)]
@@ -167,22 +167,23 @@ const NODE2: &str = "/node2";
167167
const LANE1: &str = "value_lane";
168168
const LANE2: &str = "map_lane";
169169

170-
fn value_lane_addr() -> Address<String> {
171-
Address::new(Some(HOST.to_string()), NODE1.to_string(), LANE1.to_string())
170+
fn value_lane_addr() -> Address<&'static str> {
171+
Address::new(Some(HOST), NODE1, LANE1)
172172
}
173173

174-
fn map_lane_addr() -> Address<String> {
175-
Address::new(None, NODE2.to_string(), LANE2.to_string())
174+
fn map_lane_addr() -> Address<&'static str> {
175+
Address::new(None, NODE2, LANE2)
176176
}
177177

178178
impl EgressConnector for TestConnector {
179179
type Error = TestError;
180180

181181
type Sender = TestSender;
182182

183-
fn open_downlinks(&self, context: &mut dyn EgressContext) {
183+
fn initialize(&self, context: &mut dyn EgressContext) -> Result<(), Self::Error> {
184184
context.open_event_downlink(value_lane_addr());
185185
context.open_map_downlink(map_lane_addr());
186+
Ok(())
186187
}
187188

188189
fn make_sender(
@@ -265,6 +266,7 @@ async fn init_connector(
265266
let RequestsRecord {
266267
mut downlinks,
267268
timers,
269+
..
268270
} = run_handle_with_futs(agent, handler)
269271
.await
270272
.expect("Handler failed.");
@@ -415,11 +417,16 @@ async fn connector_lifecycle_value_lane_event_busy() {
415417
let handler = lifecycle
416418
.item_event(&agent, VALUE_LANE)
417419
.expect("No pending event.");
418-
let RequestsRecord { downlinks, timers } = run_handle_with_futs(&agent, handler)
420+
let RequestsRecord {
421+
downlinks,
422+
timers,
423+
lanes,
424+
} = run_handle_with_futs(&agent, handler)
419425
.await
420426
.expect("Handler failed.");
421427

422428
assert!(downlinks.is_empty());
429+
assert!(lanes.is_empty());
423430

424431
let id = match timers.as_slice() {
425432
&[TimerRecord { id, .. }] => id,
@@ -461,11 +468,16 @@ async fn connector_lifecycle_value_lane_event_busy_twice() {
461468
let handler = lifecycle
462469
.item_event(&agent, VALUE_LANE)
463470
.expect("No pending event.");
464-
let RequestsRecord { downlinks, timers } = run_handle_with_futs(&agent, handler)
471+
let RequestsRecord {
472+
downlinks,
473+
timers,
474+
lanes,
475+
} = run_handle_with_futs(&agent, handler)
465476
.await
466477
.expect("Handler failed.");
467478

468479
assert!(downlinks.is_empty());
480+
assert!(lanes.is_empty());
469481

470482
let id = match timers.as_slice() {
471483
&[TimerRecord { id, .. }] => id,
@@ -478,10 +490,15 @@ async fn connector_lifecycle_value_lane_event_busy_twice() {
478490

479491
let handler = lifecycle.on_timer(id);
480492

481-
let RequestsRecord { downlinks, timers } = run_handle_with_futs(&agent, handler)
493+
let RequestsRecord {
494+
downlinks,
495+
timers,
496+
lanes,
497+
} = run_handle_with_futs(&agent, handler)
482498
.await
483499
.expect("Handler failed.");
484500
assert!(downlinks.is_empty());
501+
assert!(lanes.is_empty());
485502

486503
let id = match timers.as_slice() {
487504
&[TimerRecord { id, .. }] => id,

0 commit comments

Comments
 (0)