Foundations for causal tracing
This commit is contained in:
parent
f7a5edff39
commit
4dc613a091
|
@ -1098,9 +1098,9 @@ checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "preserves"
|
name = "preserves"
|
||||||
version = "2.2.0"
|
version = "2.3.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c604be1e4ddac999d7c3d81ca9f7912a33a1234f5394fb902315f8cee25645cd"
|
checksum = "87e17ecd8e57af358d013c7f9cc30078a86bbba63eac64e73e1c9b9651304eb8"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"base64",
|
"base64",
|
||||||
"dtoa",
|
"dtoa",
|
||||||
|
@ -1112,9 +1112,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "preserves-schema"
|
name = "preserves-schema"
|
||||||
version = "2.3.1"
|
version = "2.4.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e1ae4749701948512784501bcc48bfee33e8511714fac9c3acfe7fabb1d7fbdf"
|
checksum = "758fe4013a89071fafdc71ba79bd919f68ec9baadaa77db78b4a41c21cf8c606"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"convert_case",
|
"convert_case",
|
||||||
"glob",
|
"glob",
|
||||||
|
@ -1318,9 +1318,9 @@ checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "security-framework"
|
name = "security-framework"
|
||||||
version = "2.4.2"
|
version = "2.5.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "525bc1abfda2e1998d152c45cf13e696f76d0a4972310b22fac1658b05df7c87"
|
checksum = "d09d3c15d814eda1d6a836f2f2b56a6abc1446c8a34351cb3180d3db92ffe4ce"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags",
|
||||||
"core-foundation",
|
"core-foundation",
|
||||||
|
@ -1331,9 +1331,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "security-framework-sys"
|
name = "security-framework-sys"
|
||||||
version = "2.4.2"
|
version = "2.5.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a9dd14d83160b528b7bfd66439110573efcfbe281b17fc2ca9f39f550d619c7e"
|
checksum = "e90dd10c41c6bfc633da6e0c659bd25d31e0791e5974ac42970267d59eba87f7"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"core-foundation-sys",
|
"core-foundation-sys",
|
||||||
"libc",
|
"libc",
|
||||||
|
@ -1386,9 +1386,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_json"
|
name = "serde_json"
|
||||||
version = "1.0.74"
|
version = "1.0.75"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ee2bb9cd061c5865d345bb02ca49fcef1391741b672b54a0bf7b679badec3142"
|
checksum = "c059c05b48c5c0067d4b4b2b4f0732dd65feb52daf7e0ea09cd87e7dadc1af79"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"itoa 1.0.1",
|
"itoa 1.0.1",
|
||||||
"ryu",
|
"ryu",
|
||||||
|
@ -1459,9 +1459,9 @@ checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "structopt"
|
name = "structopt"
|
||||||
version = "0.3.25"
|
version = "0.3.26"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "40b9788f4202aa75c240ecc9c15c65185e6a39ccdeb0fd5d008b98825464c87c"
|
checksum = "0c6b5c64445ba8094a6ab0c3cd2ad323e07171012d9c98b0b15651daf1787a10"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"clap",
|
"clap",
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
|
@ -1890,9 +1890,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasi"
|
name = "wasi"
|
||||||
version = "0.10.2+wasi-snapshot-preview1"
|
version = "0.10.3+wasi-snapshot-preview1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6"
|
checksum = "46a2e384a3f170b0c7543787a91411175b71afd56ba4d3a0ae5678d4e2243c0e"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasm-bindgen"
|
name = "wasm-bindgen"
|
||||||
|
|
|
@ -8,11 +8,11 @@ use syndicate::value::NestedValue;
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
syndicate::convenient_logging()?;
|
syndicate::convenient_logging()?;
|
||||||
Actor::new(None).boot(tracing::Span::current(), |t| {
|
Actor::top(None, |t| {
|
||||||
let ds = Cap::new(&t.create(Dataspace::new(None)));
|
let ds = Cap::new(&t.create(Dataspace::new(None)));
|
||||||
let _ = t.prevent_inert_check();
|
let _ = t.prevent_inert_check();
|
||||||
|
|
||||||
t.spawn(syndicate::name!("box"), enclose!((ds) move |t| {
|
t.spawn(Some(AnyValue::symbol("box")), enclose!((ds) move |t| {
|
||||||
let current_value = t.named_field("current_value", 0u64);
|
let current_value = t.named_field("current_value", 0u64);
|
||||||
|
|
||||||
t.dataflow({
|
t.dataflow({
|
||||||
|
@ -49,7 +49,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}));
|
}));
|
||||||
|
|
||||||
t.spawn(syndicate::name!("client"), enclose!((ds) move |t| {
|
t.spawn(Some(AnyValue::symbol("client")), enclose!((ds) move |t| {
|
||||||
let box_state_handler = syndicate::entity(0u32)
|
let box_state_handler = syndicate::entity(0u32)
|
||||||
.on_asserted(enclose!((ds) move |count, t, captures: AnyValue| {
|
.on_asserted(enclose!((ds) move |count, t, captures: AnyValue| {
|
||||||
*count = *count + 1;
|
*count = *count + 1;
|
||||||
|
|
|
@ -26,7 +26,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
let config = Config::from_args();
|
let config = Config::from_args();
|
||||||
let sturdyref = sturdy::SturdyRef::from_hex(&config.dataspace)?;
|
let sturdyref = sturdy::SturdyRef::from_hex(&config.dataspace)?;
|
||||||
let (i, o) = TcpStream::connect("127.0.0.1:8001").await?.into_split();
|
let (i, o) = TcpStream::connect("127.0.0.1:8001").await?.into_split();
|
||||||
Actor::new(None).boot(syndicate::name!("consumer"), |t| {
|
Actor::top(None, |t| {
|
||||||
relay::connect_stream(t, i, o, false, sturdyref, (), |_state, t, ds| {
|
relay::connect_stream(t, i, o, false, sturdyref, (), |_state, t, ds| {
|
||||||
let consumer = syndicate::entity(0)
|
let consumer = syndicate::entity(0)
|
||||||
.on_message(|message_count, _t, m: AnyValue| {
|
.on_message(|message_count, _t, m: AnyValue| {
|
||||||
|
@ -44,13 +44,14 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
observer: Arc::clone(&consumer),
|
observer: Arc::clone(&consumer),
|
||||||
});
|
});
|
||||||
|
|
||||||
t.linked_task(syndicate::name!("tick"), async move {
|
t.linked_task(Some(AnyValue::symbol("tick")), async move {
|
||||||
let mut stats_timer = interval(Duration::from_secs(1));
|
let mut stats_timer = interval(Duration::from_secs(1));
|
||||||
loop {
|
loop {
|
||||||
stats_timer.tick().await;
|
stats_timer.tick().await;
|
||||||
let consumer = Arc::clone(&consumer);
|
let consumer = Arc::clone(&consumer);
|
||||||
external_event(&Arc::clone(&consumer.underlying.mailbox),
|
external_event(&Arc::clone(&consumer.underlying.mailbox),
|
||||||
&Account::new(syndicate::name!("account")),
|
None,
|
||||||
|
&Account::new(None, None),
|
||||||
Box::new(move |t| t.with_entity(
|
Box::new(move |t| t.with_entity(
|
||||||
&consumer.underlying,
|
&consumer.underlying,
|
||||||
|t, e| e.message(t, AnyValue::new(true)))))?;
|
|t, e| e.message(t, AnyValue::new(true)))))?;
|
||||||
|
|
|
@ -93,7 +93,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
let config = Config::from_args();
|
let config = Config::from_args();
|
||||||
let sturdyref = sturdy::SturdyRef::from_hex(&config.dataspace)?;
|
let sturdyref = sturdy::SturdyRef::from_hex(&config.dataspace)?;
|
||||||
let (i, o) = TcpStream::connect("127.0.0.1:8001").await?.into_split();
|
let (i, o) = TcpStream::connect("127.0.0.1:8001").await?.into_split();
|
||||||
Actor::new(None).boot(syndicate::name!("pingpong"), |t| {
|
Actor::top(None, |t| {
|
||||||
relay::connect_stream(t, i, o, false, sturdyref, (), move |_state, t, ds| {
|
relay::connect_stream(t, i, o, false, sturdyref, (), move |_state, t, ds| {
|
||||||
|
|
||||||
let (send_label, recv_label, report_latency_every, should_echo, bytes_padding) =
|
let (send_label, recv_label, report_latency_every, should_echo, bytes_padding) =
|
||||||
|
@ -172,13 +172,14 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
observer: Arc::clone(&consumer),
|
observer: Arc::clone(&consumer),
|
||||||
});
|
});
|
||||||
|
|
||||||
t.linked_task(syndicate::name!("tick"), async move {
|
t.linked_task(Some(AnyValue::symbol("tick")), async move {
|
||||||
let mut stats_timer = interval(Duration::from_secs(1));
|
let mut stats_timer = interval(Duration::from_secs(1));
|
||||||
loop {
|
loop {
|
||||||
stats_timer.tick().await;
|
stats_timer.tick().await;
|
||||||
let consumer = Arc::clone(&consumer);
|
let consumer = Arc::clone(&consumer);
|
||||||
external_event(&Arc::clone(&consumer.underlying.mailbox),
|
external_event(&Arc::clone(&consumer.underlying.mailbox),
|
||||||
&Account::new(syndicate::name!("account")),
|
None,
|
||||||
|
&Account::new(None, None),
|
||||||
Box::new(move |t| t.with_entity(
|
Box::new(move |t| t.with_entity(
|
||||||
&consumer.underlying,
|
&consumer.underlying,
|
||||||
|t, e| e.message(t, AnyValue::new(true)))))?;
|
|t, e| e.message(t, AnyValue::new(true)))))?;
|
||||||
|
@ -189,7 +190,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
let turn_count = c.turn_count;
|
let turn_count = c.turn_count;
|
||||||
let action_count = c.action_count;
|
let action_count = c.action_count;
|
||||||
let account = Arc::clone(t.account());
|
let account = Arc::clone(t.account());
|
||||||
t.linked_task(syndicate::name!("boot-ping"), async move {
|
t.linked_task(Some(AnyValue::symbol("boot-ping")), async move {
|
||||||
let padding = AnyValue::bytestring(vec![0; bytes_padding]);
|
let padding = AnyValue::bytestring(vec![0; bytes_padding]);
|
||||||
for _ in 0..turn_count {
|
for _ in 0..turn_count {
|
||||||
let mut events: PendingEventQueue = vec![];
|
let mut events: PendingEventQueue = vec![];
|
||||||
|
@ -203,7 +204,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
&ds.underlying,
|
&ds.underlying,
|
||||||
|t, e| e.message(t, current_rec))));
|
|t, e| e.message(t, current_rec))));
|
||||||
}
|
}
|
||||||
external_events(&ds.underlying.mailbox, &account, events)?
|
external_events(&ds.underlying.mailbox, None, &account, events)?
|
||||||
}
|
}
|
||||||
Ok(LinkedTaskTermination::KeepFacet)
|
Ok(LinkedTaskTermination::KeepFacet)
|
||||||
});
|
});
|
||||||
|
|
|
@ -2,9 +2,10 @@ use structopt::StructOpt;
|
||||||
|
|
||||||
use syndicate::actor::*;
|
use syndicate::actor::*;
|
||||||
use syndicate::enclose;
|
use syndicate::enclose;
|
||||||
|
use syndicate::preserves::rec;
|
||||||
use syndicate::relay;
|
use syndicate::relay;
|
||||||
use syndicate::sturdy;
|
use syndicate::sturdy;
|
||||||
use syndicate::value::Value;
|
use syndicate::value::NestedValue;
|
||||||
|
|
||||||
use tokio::net::TcpStream;
|
use tokio::net::TcpStream;
|
||||||
|
|
||||||
|
@ -20,35 +21,30 @@ pub struct Config {
|
||||||
dataspace: String,
|
dataspace: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn says(who: AnyValue, what: AnyValue) -> AnyValue {
|
|
||||||
let mut r = Value::simple_record("Says", 2);
|
|
||||||
r.fields_vec_mut().push(who);
|
|
||||||
r.fields_vec_mut().push(what);
|
|
||||||
r.finish().wrap()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
syndicate::convenient_logging()?;
|
syndicate::convenient_logging()?;
|
||||||
let config = Config::from_args();
|
let config = Config::from_args();
|
||||||
let sturdyref = sturdy::SturdyRef::from_hex(&config.dataspace)?;
|
let sturdyref = sturdy::SturdyRef::from_hex(&config.dataspace)?;
|
||||||
let (i, o) = TcpStream::connect("127.0.0.1:8001").await?.into_split();
|
let (i, o) = TcpStream::connect("127.0.0.1:8001").await?.into_split();
|
||||||
Actor::new(None).boot(syndicate::name!("producer"), |t| {
|
Actor::top(None, |t| {
|
||||||
relay::connect_stream(t, i, o, false, sturdyref, (), move |_state, t, ds| {
|
relay::connect_stream(t, i, o, false, sturdyref, (), move |_state, t, ds| {
|
||||||
let padding: AnyValue = Value::ByteString(vec![0; config.bytes_padding]).wrap();
|
let padding = AnyValue::new(&vec![0u8; config.bytes_padding][..]);
|
||||||
let action_count = config.action_count;
|
let action_count = config.action_count;
|
||||||
let account = Account::new(syndicate::name!("account"));
|
let account = Account::new(None, None);
|
||||||
t.linked_task(syndicate::name!("sender"), async move {
|
t.linked_task(Some(AnyValue::symbol("sender")), async move {
|
||||||
loop {
|
loop {
|
||||||
account.ensure_clear_funds().await;
|
account.ensure_clear_funds().await;
|
||||||
let mut events: PendingEventQueue = Vec::new();
|
let mut events: PendingEventQueue = Vec::new();
|
||||||
for _ in 0..action_count {
|
for _ in 0..action_count {
|
||||||
events.push(Box::new(enclose!((ds, padding) move |t| t.with_entity(
|
events.push(Box::new(enclose!((ds, padding) move |t| t.with_entity(
|
||||||
&ds.underlying, |t, e| e.message(
|
&ds.underlying, |t, e| e.message(
|
||||||
t, says(Value::from("producer").wrap(), padding))))));
|
t,
|
||||||
|
rec![AnyValue::symbol("Says"),
|
||||||
|
AnyValue::new("producer"),
|
||||||
|
padding])))));
|
||||||
}
|
}
|
||||||
external_events(&ds.underlying.mailbox, &account, events)?;
|
external_events(&ds.underlying.mailbox, None, &account, events)?;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
Ok(None)
|
Ok(None)
|
||||||
|
|
|
@ -26,7 +26,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
let config = Config::from_args();
|
let config = Config::from_args();
|
||||||
let sturdyref = sturdy::SturdyRef::from_hex(&config.dataspace)?;
|
let sturdyref = sturdy::SturdyRef::from_hex(&config.dataspace)?;
|
||||||
let (i, o) = TcpStream::connect("127.0.0.1:8001").await?.into_split();
|
let (i, o) = TcpStream::connect("127.0.0.1:8001").await?.into_split();
|
||||||
Actor::new(None).boot(syndicate::name!("state-consumer"), |t| {
|
Actor::top(None, |t| {
|
||||||
relay::connect_stream(t, i, o, false, sturdyref, (), |_state, t, ds| {
|
relay::connect_stream(t, i, o, false, sturdyref, (), |_state, t, ds| {
|
||||||
let consumer = {
|
let consumer = {
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
|
@ -65,13 +65,14 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
observer: Arc::clone(&consumer),
|
observer: Arc::clone(&consumer),
|
||||||
});
|
});
|
||||||
|
|
||||||
t.linked_task(syndicate::name!("tick"), async move {
|
t.linked_task(Some(AnyValue::symbol("tick")), async move {
|
||||||
let mut stats_timer = interval(Duration::from_secs(1));
|
let mut stats_timer = interval(Duration::from_secs(1));
|
||||||
loop {
|
loop {
|
||||||
stats_timer.tick().await;
|
stats_timer.tick().await;
|
||||||
let consumer = Arc::clone(&consumer);
|
let consumer = Arc::clone(&consumer);
|
||||||
external_event(&Arc::clone(&consumer.underlying.mailbox),
|
external_event(&Arc::clone(&consumer.underlying.mailbox),
|
||||||
&Account::new(syndicate::name!("account")),
|
None,
|
||||||
|
&Account::new(None, None),
|
||||||
Box::new(move |t| t.with_entity(
|
Box::new(move |t| t.with_entity(
|
||||||
&consumer.underlying,
|
&consumer.underlying,
|
||||||
|t, e| e.message(t, AnyValue::new(true)))))?;
|
|t, e| e.message(t, AnyValue::new(true)))))?;
|
||||||
|
|
|
@ -4,9 +4,10 @@ use structopt::StructOpt;
|
||||||
|
|
||||||
use syndicate::actor::*;
|
use syndicate::actor::*;
|
||||||
use syndicate::enclose;
|
use syndicate::enclose;
|
||||||
|
use syndicate::preserves::rec;
|
||||||
use syndicate::relay;
|
use syndicate::relay;
|
||||||
use syndicate::sturdy;
|
use syndicate::sturdy;
|
||||||
use syndicate::value::Value;
|
use syndicate::value::NestedValue;
|
||||||
|
|
||||||
use tokio::net::TcpStream;
|
use tokio::net::TcpStream;
|
||||||
|
|
||||||
|
@ -22,23 +23,21 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
let config = Config::from_args();
|
let config = Config::from_args();
|
||||||
let sturdyref = sturdy::SturdyRef::from_hex(&config.dataspace)?;
|
let sturdyref = sturdy::SturdyRef::from_hex(&config.dataspace)?;
|
||||||
let (i, o) = TcpStream::connect("127.0.0.1:8001").await?.into_split();
|
let (i, o) = TcpStream::connect("127.0.0.1:8001").await?.into_split();
|
||||||
Actor::new(None).boot(syndicate::name!("state-producer"), |t| {
|
Actor::top(None, |t| {
|
||||||
relay::connect_stream(t, i, o, false, sturdyref, (), move |_state, t, ds| {
|
relay::connect_stream(t, i, o, false, sturdyref, (), move |_state, t, ds| {
|
||||||
let account = Account::new(syndicate::name!("account"));
|
let account = Account::new(None, None);
|
||||||
t.linked_task(syndicate::name!("sender"), async move {
|
t.linked_task(Some(AnyValue::symbol("sender")), async move {
|
||||||
let presence: AnyValue = Value::simple_record1(
|
let presence = rec![AnyValue::symbol("Present"), AnyValue::new(std::process::id())];
|
||||||
"Present",
|
|
||||||
Value::from(std::process::id()).wrap()).wrap();
|
|
||||||
let handle = syndicate::actor::next_handle();
|
let handle = syndicate::actor::next_handle();
|
||||||
let assert_e = || {
|
let assert_e = || {
|
||||||
external_event(
|
external_event(
|
||||||
&Arc::clone(&ds.underlying.mailbox), &account, Box::new(enclose!(
|
&Arc::clone(&ds.underlying.mailbox), None, &account, Box::new(enclose!(
|
||||||
(ds, presence, handle) move |t| t.with_entity(
|
(ds, presence, handle) move |t| t.with_entity(
|
||||||
&ds.underlying, |t, e| e.assert(t, presence, handle)))))
|
&ds.underlying, |t, e| e.assert(t, presence, handle)))))
|
||||||
};
|
};
|
||||||
let retract_e = || {
|
let retract_e = || {
|
||||||
external_event(
|
external_event(
|
||||||
&Arc::clone(&ds.underlying.mailbox), &account, Box::new(enclose!(
|
&Arc::clone(&ds.underlying.mailbox), None, &account, Box::new(enclose!(
|
||||||
(ds, handle) move |t| t.with_entity(
|
(ds, handle) move |t| t.with_entity(
|
||||||
&ds.underlying, |t, e| e.retract(t, handle)))))
|
&ds.underlying, |t, e| e.retract(t, handle)))))
|
||||||
};
|
};
|
||||||
|
|
|
@ -5,6 +5,7 @@ use std::sync::Arc;
|
||||||
use syndicate::actor::*;
|
use syndicate::actor::*;
|
||||||
use syndicate::during::entity;
|
use syndicate::during::entity;
|
||||||
use syndicate::enclose;
|
use syndicate::enclose;
|
||||||
|
use syndicate::preserves::rec;
|
||||||
use syndicate::schemas::dataspace::Observe;
|
use syndicate::schemas::dataspace::Observe;
|
||||||
use syndicate::schemas::service;
|
use syndicate::schemas::service;
|
||||||
use syndicate::value::NestedValue;
|
use syndicate::value::NestedValue;
|
||||||
|
@ -16,10 +17,10 @@ use crate::schemas::internal_services;
|
||||||
use syndicate_macros::during;
|
use syndicate_macros::during;
|
||||||
|
|
||||||
pub fn boot(t: &mut Activation, ds: Arc<Cap>) {
|
pub fn boot(t: &mut Activation, ds: Arc<Cap>) {
|
||||||
t.spawn(syndicate::name!("dependencies"), move |t| {
|
t.spawn(Some(AnyValue::symbol("dependencies_listener")), move |t| {
|
||||||
Ok(during!(t, ds, language(), <require-service $spec>, |t: &mut Activation| {
|
Ok(during!(t, ds, language(), <require-service $spec>, |t: &mut Activation| {
|
||||||
tracing::debug!(?spec, "tracking dependencies");
|
tracing::debug!(?spec, "tracking dependencies");
|
||||||
t.spawn_link(syndicate::name!(parent: None, "dependencies", spec = ?spec),
|
t.spawn_link(Some(rec![AnyValue::symbol("dependencies"), language().unparse(&spec)]),
|
||||||
enclose!((ds) |t| run(t, ds, spec)));
|
enclose!((ds) |t| run(t, ds, spec)));
|
||||||
Ok(())
|
Ok(())
|
||||||
}))
|
}))
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
use preserves_schema::Codec;
|
use preserves_schema::Codec;
|
||||||
|
|
||||||
|
use std::io;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
@ -11,6 +12,7 @@ use syndicate::enclose;
|
||||||
use syndicate::relay;
|
use syndicate::relay;
|
||||||
use syndicate::schemas::service;
|
use syndicate::schemas::service;
|
||||||
use syndicate::schemas::transport_address;
|
use syndicate::schemas::transport_address;
|
||||||
|
use syndicate::trace;
|
||||||
|
|
||||||
use syndicate::value::Map;
|
use syndicate::value::Map;
|
||||||
use syndicate::value::NestedValue;
|
use syndicate::value::NestedValue;
|
||||||
|
@ -50,6 +52,9 @@ struct ServerConfig {
|
||||||
|
|
||||||
#[structopt(long)]
|
#[structopt(long)]
|
||||||
no_banner: bool,
|
no_banner: bool,
|
||||||
|
|
||||||
|
#[structopt(short = "t", long)]
|
||||||
|
trace_file: Option<PathBuf>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
|
@ -83,13 +88,18 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
|
|
||||||
tracing::trace!("startup");
|
tracing::trace!("startup");
|
||||||
|
|
||||||
Actor::new(None).boot(tracing::Span::current(), move |t| {
|
let trace_collector = config.trace_file.clone().map(
|
||||||
let server_config_ds = Cap::new(&t.create(Dataspace::new(Some(syndicate::name!("config")))));
|
|p| Ok::<trace::TraceCollector, io::Error>(trace::TraceCollector::ascii(
|
||||||
let log_ds = Cap::new(&t.create(Dataspace::new(Some(syndicate::name!("log")))));
|
io::BufWriter::new(std::fs::File::create(p)?))))
|
||||||
|
.transpose()?;
|
||||||
|
|
||||||
|
Actor::top(trace_collector, move |t| {
|
||||||
|
let server_config_ds = Cap::new(&t.create(Dataspace::new(Some(AnyValue::symbol("config")))));
|
||||||
|
let log_ds = Cap::new(&t.create(Dataspace::new(Some(AnyValue::symbol("log")))));
|
||||||
|
|
||||||
if config.inferior {
|
if config.inferior {
|
||||||
tracing::info!("inferior server instance");
|
tracing::info!("inferior server instance");
|
||||||
t.spawn(syndicate::name!("parent"), enclose!((server_config_ds) move |t| {
|
t.spawn(Some(AnyValue::symbol("parent")), enclose!((server_config_ds) move |t| {
|
||||||
protocol::run_io_relay(t,
|
protocol::run_io_relay(t,
|
||||||
relay::Input::Bytes(Box::pin(tokio::io::stdin())),
|
relay::Input::Bytes(Box::pin(tokio::io::stdin())),
|
||||||
relay::Output::Bytes(Box::pin(tokio::io::stdout())),
|
relay::Output::Bytes(Box::pin(tokio::io::stdout())),
|
||||||
|
@ -154,7 +164,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
t.spawn(tracing::Span::current(), enclose!((log_ds) move |t| {
|
t.spawn(Some(AnyValue::symbol("logger")), enclose!((log_ds) move |t| {
|
||||||
let n_unknown: AnyValue = AnyValue::symbol("-");
|
let n_unknown: AnyValue = AnyValue::symbol("-");
|
||||||
let n_pid: AnyValue = AnyValue::symbol("pid");
|
let n_pid: AnyValue = AnyValue::symbol("pid");
|
||||||
let n_line: AnyValue = AnyValue::symbol("line");
|
let n_line: AnyValue = AnyValue::symbol("line");
|
||||||
|
|
|
@ -9,6 +9,7 @@ use syndicate::actor::*;
|
||||||
use syndicate::error::Error;
|
use syndicate::error::Error;
|
||||||
use syndicate::error::error;
|
use syndicate::error::error;
|
||||||
use syndicate::relay;
|
use syndicate::relay;
|
||||||
|
use syndicate::trace;
|
||||||
use syndicate::value::NestedValue;
|
use syndicate::value::NestedValue;
|
||||||
|
|
||||||
use tokio::net::TcpStream;
|
use tokio::net::TcpStream;
|
||||||
|
@ -37,16 +38,19 @@ pub fn run_io_relay(
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn run_connection(
|
pub fn run_connection(
|
||||||
|
trace_collector: Option<trace::TraceCollector>,
|
||||||
facet: FacetRef,
|
facet: FacetRef,
|
||||||
i: relay::Input,
|
i: relay::Input,
|
||||||
o: relay::Output,
|
o: relay::Output,
|
||||||
initial_ref: Arc<Cap>,
|
initial_ref: Arc<Cap>,
|
||||||
) {
|
) {
|
||||||
facet.activate(Account::new(syndicate::name!("start-session")),
|
let cause = trace_collector.as_ref().map(|_| trace::TurnCause::external("start-session"));
|
||||||
|t| run_io_relay(t, i, o, initial_ref));
|
let account = Account::new(Some(AnyValue::symbol("start-session")), trace_collector);
|
||||||
|
facet.activate(&account, cause, |t| run_io_relay(t, i, o, initial_ref));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn detect_protocol(
|
pub async fn detect_protocol(
|
||||||
|
trace_collector: Option<trace::TraceCollector>,
|
||||||
facet: FacetRef,
|
facet: FacetRef,
|
||||||
stream: TcpStream,
|
stream: TcpStream,
|
||||||
gateway: Arc<Cap>,
|
gateway: Arc<Cap>,
|
||||||
|
@ -76,7 +80,7 @@ pub async fn detect_protocol(
|
||||||
_ => unreachable!()
|
_ => unreachable!()
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
run_connection(facet, i, o, gateway);
|
run_connection(trace_collector, facet, i, o, gateway);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,8 @@ use notify::Watcher;
|
||||||
use notify::RecursiveMode;
|
use notify::RecursiveMode;
|
||||||
use notify::watcher;
|
use notify::watcher;
|
||||||
|
|
||||||
|
use syndicate::preserves::rec;
|
||||||
|
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use std::future;
|
use std::future;
|
||||||
use std::io;
|
use std::io;
|
||||||
|
@ -16,6 +18,7 @@ use syndicate::actor::*;
|
||||||
use syndicate::error::Error;
|
use syndicate::error::Error;
|
||||||
use syndicate::enclose;
|
use syndicate::enclose;
|
||||||
use syndicate::supervise::{Supervisor, SupervisorConfiguration};
|
use syndicate::supervise::{Supervisor, SupervisorConfiguration};
|
||||||
|
use syndicate::trace;
|
||||||
use syndicate::value::BinarySource;
|
use syndicate::value::BinarySource;
|
||||||
use syndicate::value::BytesBinarySource;
|
use syndicate::value::BytesBinarySource;
|
||||||
use syndicate::value::Map;
|
use syndicate::value::Map;
|
||||||
|
@ -32,11 +35,11 @@ use crate::script;
|
||||||
use syndicate_macros::during;
|
use syndicate_macros::during;
|
||||||
|
|
||||||
pub fn on_demand(t: &mut Activation, config_ds: Arc<Cap>) {
|
pub fn on_demand(t: &mut Activation, config_ds: Arc<Cap>) {
|
||||||
t.spawn(syndicate::name!("config_watcher"), move |t| {
|
t.spawn(Some(AnyValue::symbol("config_watcher")), move |t| {
|
||||||
Ok(during!(t, config_ds, language(), <run-service $spec: internal_services::ConfigWatcher>, |t| {
|
Ok(during!(t, config_ds, language(), <run-service $spec: internal_services::ConfigWatcher>, |t| {
|
||||||
Supervisor::start(
|
Supervisor::start(
|
||||||
t,
|
t,
|
||||||
syndicate::name!(parent: None, "config", path = ?spec.path),
|
Some(rec![AnyValue::symbol("config"), AnyValue::new(spec.path.clone())]),
|
||||||
SupervisorConfiguration::default(),
|
SupervisorConfiguration::default(),
|
||||||
enclose!((config_ds, spec) lifecycle::updater(config_ds, spec)),
|
enclose!((config_ds, spec) lifecycle::updater(config_ds, spec)),
|
||||||
enclose!((config_ds) move |t| enclose!((config_ds, spec) run(t, config_ds, spec))))
|
enclose!((config_ds) move |t| enclose!((config_ds, spec) run(t, config_ds, spec))))
|
||||||
|
@ -175,15 +178,18 @@ fn run(
|
||||||
watcher.watch(&env.path, RecursiveMode::Recursive).map_err(convert_notify_error)?;
|
watcher.watch(&env.path, RecursiveMode::Recursive).map_err(convert_notify_error)?;
|
||||||
|
|
||||||
let facet = t.facet.clone();
|
let facet = t.facet.clone();
|
||||||
|
let trace_collector = t.trace_collector();
|
||||||
let span = tracing::Span::current();
|
let span = tracing::Span::current();
|
||||||
thread::spawn(move || {
|
thread::spawn(move || {
|
||||||
let _entry = span.enter();
|
let _entry = span.enter();
|
||||||
|
|
||||||
let mut path_state: Map<PathBuf, FacetId> = Map::new();
|
let mut path_state: Map<PathBuf, FacetId> = Map::new();
|
||||||
|
|
||||||
|
{
|
||||||
|
let cause = trace_collector.as_ref().map(|_| trace::TurnCause::external("initial_scan"));
|
||||||
|
let account = Account::new(Some(AnyValue::symbol("initial_scan")), trace_collector.clone());
|
||||||
if !facet.activate(
|
if !facet.activate(
|
||||||
Account::new(syndicate::name!("initial_scan")),
|
&account, cause, |t| {
|
||||||
|t| {
|
|
||||||
initial_scan(t, &mut path_state, &config_ds, env.clone());
|
initial_scan(t, &mut path_state, &config_ds, env.clone());
|
||||||
config_ds.assert(t, language(), &lifecycle::ready(&spec));
|
config_ds.assert(t, language(), &lifecycle::ready(&spec));
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -191,10 +197,13 @@ fn run(
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
tracing::trace!("initial_scan complete");
|
tracing::trace!("initial_scan complete");
|
||||||
|
|
||||||
let mut rescan = |paths: Vec<PathBuf>| {
|
let mut rescan = |paths: Vec<PathBuf>| {
|
||||||
facet.activate(Account::new(syndicate::name!("rescan")), |t| {
|
let cause = trace_collector.as_ref().map(|_| trace::TurnCause::external("rescan"));
|
||||||
|
let account = Account::new(Some(AnyValue::symbol("rescan")), trace_collector.clone());
|
||||||
|
facet.activate(&account, cause, |t| {
|
||||||
let mut to_stop = Vec::new();
|
let mut to_stop = Vec::new();
|
||||||
for path in paths.into_iter() {
|
for path in paths.into_iter() {
|
||||||
let maybe_facet_id = path_state.remove(&path);
|
let maybe_facet_id = path_state.remove(&path);
|
||||||
|
@ -236,15 +245,19 @@ fn run(
|
||||||
if !keep_running { break; }
|
if !keep_running { break; }
|
||||||
}
|
}
|
||||||
|
|
||||||
facet.activate(Account::new(syndicate::name!("termination")), |t| {
|
{
|
||||||
|
let cause = trace_collector.as_ref().map(|_| trace::TurnCause::external("termination"));
|
||||||
|
let account = Account::new(Some(AnyValue::symbol("termination")), trace_collector);
|
||||||
|
facet.activate(&account, cause, |t| {
|
||||||
tracing::trace!("linked thread terminating associated facet");
|
tracing::trace!("linked thread terminating associated facet");
|
||||||
Ok(t.stop())
|
Ok(t.stop())
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
tracing::trace!("linked thread done");
|
tracing::trace!("linked thread done");
|
||||||
});
|
});
|
||||||
|
|
||||||
t.linked_task(syndicate::name!("cancel-wait"), async move {
|
t.linked_task(Some(AnyValue::symbol("cancel-wait")), async move {
|
||||||
future::pending::<()>().await;
|
future::pending::<()>().await;
|
||||||
drop(watcher);
|
drop(watcher);
|
||||||
Ok(LinkedTaskTermination::KeepFacet)
|
Ok(LinkedTaskTermination::KeepFacet)
|
||||||
|
|
|
@ -4,8 +4,10 @@ use std::sync::Arc;
|
||||||
|
|
||||||
use syndicate::actor::*;
|
use syndicate::actor::*;
|
||||||
use syndicate::enclose;
|
use syndicate::enclose;
|
||||||
|
use syndicate::preserves::rec;
|
||||||
use syndicate::schemas::service;
|
use syndicate::schemas::service;
|
||||||
use syndicate::supervise::{Supervisor, SupervisorConfiguration};
|
use syndicate::supervise::{Supervisor, SupervisorConfiguration};
|
||||||
|
use syndicate::trace;
|
||||||
use syndicate::value::NestedValue;
|
use syndicate::value::NestedValue;
|
||||||
|
|
||||||
use tokio::io::AsyncRead;
|
use tokio::io::AsyncRead;
|
||||||
|
@ -21,7 +23,7 @@ use crate::schemas::external_services::*;
|
||||||
use syndicate_macros::during;
|
use syndicate_macros::during;
|
||||||
|
|
||||||
pub fn on_demand(t: &mut Activation, config_ds: Arc<Cap>, root_ds: Arc<Cap>) {
|
pub fn on_demand(t: &mut Activation, config_ds: Arc<Cap>, root_ds: Arc<Cap>) {
|
||||||
t.spawn(syndicate::name!("daemon"), move |t| {
|
t.spawn(Some(AnyValue::symbol("daemon_listener")), move |t| {
|
||||||
Ok(during!(t, config_ds, language(), <run-service $spec: DaemonService>,
|
Ok(during!(t, config_ds, language(), <run-service $spec: DaemonService>,
|
||||||
enclose!((config_ds, root_ds) move |t: &mut Activation| {
|
enclose!((config_ds, root_ds) move |t: &mut Activation| {
|
||||||
supervise_daemon(t, config_ds, root_ds, spec)
|
supervise_daemon(t, config_ds, root_ds, spec)
|
||||||
|
@ -46,7 +48,7 @@ fn supervise_daemon(
|
||||||
}));
|
}));
|
||||||
Supervisor::start(
|
Supervisor::start(
|
||||||
t,
|
t,
|
||||||
syndicate::name!(parent: None, "daemon", id = ?spec.id),
|
Some(language().unparse(&spec)),
|
||||||
SupervisorConfiguration::on_error_only(),
|
SupervisorConfiguration::on_error_only(),
|
||||||
enclose!((config_ds, spec) lifecycle::updater(config_ds, spec)),
|
enclose!((config_ds, spec) lifecycle::updater(config_ds, spec)),
|
||||||
enclose!((config_ds, root_ds) move |t|
|
enclose!((config_ds, root_ds) move |t|
|
||||||
|
@ -162,7 +164,6 @@ struct DaemonInstance {
|
||||||
config_ds: Arc<Cap>,
|
config_ds: Arc<Cap>,
|
||||||
log_ds: Arc<Cap>,
|
log_ds: Arc<Cap>,
|
||||||
service: AnyValue,
|
service: AnyValue,
|
||||||
name: tracing::Span,
|
|
||||||
cmd: process::Command,
|
cmd: process::Command,
|
||||||
announce_presumed_readiness: bool,
|
announce_presumed_readiness: bool,
|
||||||
unready_configs: Arc<Field<isize>>,
|
unready_configs: Arc<Field<isize>>,
|
||||||
|
@ -236,9 +237,13 @@ impl DaemonInstance {
|
||||||
Some(n) => AnyValue::new(n),
|
Some(n) => AnyValue::new(n),
|
||||||
None => AnyValue::symbol("unknown"),
|
None => AnyValue::symbol("unknown"),
|
||||||
};
|
};
|
||||||
t.spawn(syndicate::name!(parent: self.name.clone(), "log"), move |t| {
|
let trace_collector = t.trace_collector();
|
||||||
t.linked_task(tracing::Span::current(), async move {
|
t.spawn(Some(rec![AnyValue::symbol("log"), kind.clone(), self.service.clone()]), move |t| {
|
||||||
|
t.linked_task(None, async move {
|
||||||
let mut r = BufReader::new(r);
|
let mut r = BufReader::new(r);
|
||||||
|
let cause = trace_collector.as_ref().map(
|
||||||
|
|_| trace::TurnCause::external(kind.value().as_symbol().unwrap()));
|
||||||
|
let account = Account::new(None, trace_collector);
|
||||||
loop {
|
loop {
|
||||||
let mut buf = Vec::new();
|
let mut buf = Vec::new();
|
||||||
if r.read_until(b'\n', &mut buf).await? == 0 {
|
if r.read_until(b'\n', &mut buf).await? == 0 {
|
||||||
|
@ -250,8 +255,7 @@ impl DaemonInstance {
|
||||||
};
|
};
|
||||||
let now = AnyValue::new(chrono::Utc::now().to_rfc3339());
|
let now = AnyValue::new(chrono::Utc::now().to_rfc3339());
|
||||||
if !facet.activate(
|
if !facet.activate(
|
||||||
Account::new(tracing::Span::current()),
|
&account, cause.clone(), enclose!((pid, service, kind) |t| {
|
||||||
enclose!((pid, service, kind) |t| {
|
|
||||||
log_ds.message(t, &(), &syndicate_macros::template!(
|
log_ds.message(t, &(), &syndicate_macros::template!(
|
||||||
"<log =now {
|
"<log =now {
|
||||||
pid: =pid,
|
pid: =pid,
|
||||||
|
@ -304,13 +308,17 @@ impl DaemonInstance {
|
||||||
counter::adjust(t, &self.unready_configs, -1);
|
counter::adjust(t, &self.unready_configs, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let trace_collector = t.trace_collector();
|
||||||
t.linked_task(
|
t.linked_task(
|
||||||
syndicate::name!(parent: self.name.clone(), "wait"),
|
Some(rec![AnyValue::symbol("wait"), self.service.clone()]),
|
||||||
enclose!((facet) async move {
|
enclose!((facet) async move {
|
||||||
tracing::trace!("waiting for process exit");
|
tracing::trace!("waiting for process exit");
|
||||||
let status = child.wait().await?;
|
let status = child.wait().await?;
|
||||||
tracing::debug!(?status);
|
tracing::debug!(?status);
|
||||||
facet.activate(Account::new(syndicate::name!("instance-terminated")), |t| {
|
let cause = trace_collector.as_ref().map(
|
||||||
|
|_| trace::TurnCause::external("instance-terminated"));
|
||||||
|
let account = Account::new(Some(AnyValue::symbol("instance-terminated")), trace_collector);
|
||||||
|
facet.activate(&account, cause, |t| {
|
||||||
let m = if status.success() { None } else { Some(format!("{}", status)) };
|
let m = if status.success() { None } else { Some(format!("{}", status)) };
|
||||||
self.handle_exit(t, m)
|
self.handle_exit(t, m)
|
||||||
});
|
});
|
||||||
|
@ -378,9 +386,10 @@ fn run(
|
||||||
Ok(())
|
Ok(())
|
||||||
}))?;
|
}))?;
|
||||||
|
|
||||||
|
let trace_collector = t.trace_collector();
|
||||||
enclose!((config_ds, unready_configs, completed_processes)
|
enclose!((config_ds, unready_configs, completed_processes)
|
||||||
during!(t, config_ds.clone(), language(), <daemon #(&service.id) $config>, {
|
during!(t, config_ds.clone(), language(), <daemon #(&service.id) $config>, {
|
||||||
enclose!((spec, config_ds, root_ds, unready_configs, completed_processes)
|
enclose!((spec, config_ds, root_ds, unready_configs, completed_processes, trace_collector)
|
||||||
|t: &mut Activation| {
|
|t: &mut Activation| {
|
||||||
tracing::debug!(?config, "new config");
|
tracing::debug!(?config, "new config");
|
||||||
counter::adjust(t, &unready_configs, 1);
|
counter::adjust(t, &unready_configs, 1);
|
||||||
|
@ -391,7 +400,7 @@ fn run(
|
||||||
tracing::info!(?config);
|
tracing::info!(?config);
|
||||||
let config = config.elaborate();
|
let config = config.elaborate();
|
||||||
let facet = t.facet.clone();
|
let facet = t.facet.clone();
|
||||||
t.linked_task(syndicate::name!("subprocess"), async move {
|
t.linked_task(Some(AnyValue::symbol("subprocess")), async move {
|
||||||
let mut cmd = config.process.build_command().ok_or("Cannot start daemon process")?;
|
let mut cmd = config.process.build_command().ok_or("Cannot start daemon process")?;
|
||||||
|
|
||||||
let announce_presumed_readiness = match config.ready_on_start {
|
let announce_presumed_readiness = match config.ready_on_start {
|
||||||
|
@ -432,7 +441,6 @@ fn run(
|
||||||
config_ds,
|
config_ds,
|
||||||
log_ds: root_ds,
|
log_ds: root_ds,
|
||||||
service: spec,
|
service: spec,
|
||||||
name: tracing::Span::current(),
|
|
||||||
cmd,
|
cmd,
|
||||||
announce_presumed_readiness,
|
announce_presumed_readiness,
|
||||||
unready_configs,
|
unready_configs,
|
||||||
|
@ -441,7 +449,10 @@ fn run(
|
||||||
protocol,
|
protocol,
|
||||||
};
|
};
|
||||||
|
|
||||||
facet.activate(Account::new(syndicate::name!("instance-startup")), |t| {
|
let cause = trace_collector.as_ref().map(
|
||||||
|
|_| trace::TurnCause::external("instance-startup"));
|
||||||
|
let account = Account::new(Some(AnyValue::symbol("instance-startup")), trace_collector);
|
||||||
|
facet.activate(&account, cause, |t| {
|
||||||
daemon_instance.start(t)
|
daemon_instance.start(t)
|
||||||
});
|
});
|
||||||
Ok(LinkedTaskTermination::KeepFacet)
|
Ok(LinkedTaskTermination::KeepFacet)
|
||||||
|
|
|
@ -1,7 +1,11 @@
|
||||||
|
use preserves_schema::Codec;
|
||||||
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use syndicate::actor::*;
|
use syndicate::actor::*;
|
||||||
use syndicate::enclose;
|
use syndicate::enclose;
|
||||||
|
use syndicate::preserves::rec;
|
||||||
|
use syndicate::preserves::value::NestedValue;
|
||||||
|
|
||||||
use crate::language::language;
|
use crate::language::language;
|
||||||
use crate::lifecycle;
|
use crate::lifecycle;
|
||||||
|
@ -10,9 +14,10 @@ use crate::schemas::internal_services::DebtReporter;
|
||||||
use syndicate_macros::during;
|
use syndicate_macros::during;
|
||||||
|
|
||||||
pub fn on_demand(t: &mut Activation, ds: Arc<Cap>) {
|
pub fn on_demand(t: &mut Activation, ds: Arc<Cap>) {
|
||||||
t.spawn(syndicate::name!("debt_reporter"), move |t| {
|
t.spawn(Some(AnyValue::symbol("debt_reporter_listener")), move |t| {
|
||||||
Ok(during!(t, ds, language(), <run-service $spec: DebtReporter>, |t: &mut Activation| {
|
Ok(during!(t, ds, language(), <run-service $spec: DebtReporter>, |t: &mut Activation| {
|
||||||
t.spawn_link(tracing::Span::current(), enclose!((ds) |t| run(t, ds, spec)));
|
t.spawn_link(Some(rec![AnyValue::symbol("debt_reporter"), language().unparse(&spec)]),
|
||||||
|
enclose!((ds) |t| run(t, ds, spec)));
|
||||||
Ok(())
|
Ok(())
|
||||||
}))
|
}))
|
||||||
});
|
});
|
||||||
|
@ -23,8 +28,7 @@ fn run(t: &mut Activation, ds: Arc<Cap>, spec: DebtReporter) -> ActorResult {
|
||||||
ds.assert(t, language(), &lifecycle::ready(&spec));
|
ds.assert(t, language(), &lifecycle::ready(&spec));
|
||||||
t.every(core::time::Duration::from_millis((spec.interval_seconds.0 * 1000.0) as u64), |_t| {
|
t.every(core::time::Duration::from_millis((spec.interval_seconds.0 * 1000.0) as u64), |_t| {
|
||||||
for (id, (name, debt)) in syndicate::actor::ACCOUNTS.read().iter() {
|
for (id, (name, debt)) in syndicate::actor::ACCOUNTS.read().iter() {
|
||||||
let _enter = name.enter();
|
tracing::info!(id, ?name, debt = ?debt.load(std::sync::atomic::Ordering::Relaxed));
|
||||||
tracing::info!(id, debt = ?debt.load(std::sync::atomic::Ordering::Relaxed));
|
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,7 +1,10 @@
|
||||||
|
use preserves_schema::Codec;
|
||||||
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use syndicate::actor::*;
|
use syndicate::actor::*;
|
||||||
use syndicate::enclose;
|
use syndicate::enclose;
|
||||||
|
use syndicate::preserves::value::NestedValue;
|
||||||
use syndicate::supervise::{Supervisor, SupervisorConfiguration};
|
use syndicate::supervise::{Supervisor, SupervisorConfiguration};
|
||||||
|
|
||||||
use crate::language::language;
|
use crate::language::language;
|
||||||
|
@ -11,11 +14,11 @@ use crate::schemas::internal_services::Milestone;
|
||||||
use syndicate_macros::during;
|
use syndicate_macros::during;
|
||||||
|
|
||||||
pub fn on_demand(t: &mut Activation, ds: Arc<Cap>) {
|
pub fn on_demand(t: &mut Activation, ds: Arc<Cap>) {
|
||||||
t.spawn(syndicate::name!("milestone"), move |t| {
|
t.spawn(Some(AnyValue::symbol("milestone_listener")), move |t| {
|
||||||
Ok(during!(t, ds, language(), <run-service $spec: Milestone>, |t: &mut Activation| {
|
Ok(during!(t, ds, language(), <run-service $spec: Milestone>, |t: &mut Activation| {
|
||||||
Supervisor::start(
|
Supervisor::start(
|
||||||
t,
|
t,
|
||||||
syndicate::name!(parent: None, "milestone", name = ?spec.name),
|
Some(language().unparse(&spec)),
|
||||||
SupervisorConfiguration::default(),
|
SupervisorConfiguration::default(),
|
||||||
|_, _| Ok(()),
|
|_, _| Ok(()),
|
||||||
enclose!((ds) move |t| enclose!((ds, spec) run(t, ds, spec))))
|
enclose!((ds) move |t| enclose!((ds, spec) run(t, ds, spec))))
|
||||||
|
|
|
@ -1,9 +1,14 @@
|
||||||
|
use preserves_schema::Codec;
|
||||||
|
|
||||||
use std::convert::TryFrom;
|
use std::convert::TryFrom;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use syndicate::actor::*;
|
use syndicate::actor::*;
|
||||||
use syndicate::enclose;
|
use syndicate::enclose;
|
||||||
|
use syndicate::preserves::rec;
|
||||||
|
use syndicate::preserves::value::NestedValue;
|
||||||
use syndicate::supervise::{Supervisor, SupervisorConfiguration};
|
use syndicate::supervise::{Supervisor, SupervisorConfiguration};
|
||||||
|
use syndicate::trace;
|
||||||
|
|
||||||
use tokio::net::TcpListener;
|
use tokio::net::TcpListener;
|
||||||
|
|
||||||
|
@ -15,11 +20,11 @@ use crate::schemas::internal_services::TcpRelayListener;
|
||||||
use syndicate_macros::during;
|
use syndicate_macros::during;
|
||||||
|
|
||||||
pub fn on_demand(t: &mut Activation, ds: Arc<Cap>) {
|
pub fn on_demand(t: &mut Activation, ds: Arc<Cap>) {
|
||||||
t.spawn(syndicate::name!("tcp_relay_listener"), move |t| {
|
t.spawn(Some(AnyValue::symbol("tcp_relay_listener")), move |t| {
|
||||||
Ok(during!(t, ds, language(), <run-service $spec: TcpRelayListener>, |t| {
|
Ok(during!(t, ds, language(), <run-service $spec: TcpRelayListener>, |t| {
|
||||||
Supervisor::start(
|
Supervisor::start(
|
||||||
t,
|
t,
|
||||||
syndicate::name!(parent: None, "relay", addr = ?spec),
|
Some(rec![AnyValue::symbol("relay"), language().unparse(&spec)]),
|
||||||
SupervisorConfiguration::default(),
|
SupervisorConfiguration::default(),
|
||||||
enclose!((ds, spec) lifecycle::updater(ds, spec)),
|
enclose!((ds, spec) lifecycle::updater(ds, spec)),
|
||||||
enclose!((ds) move |t| enclose!((ds, spec) run(t, ds, spec))))
|
enclose!((ds) move |t| enclose!((ds, spec) run(t, ds, spec))))
|
||||||
|
@ -31,14 +36,17 @@ fn run(t: &mut Activation, ds: Arc<Cap>, spec: TcpRelayListener) -> ActorResult
|
||||||
lifecycle::terminate_on_service_restart(t, &ds, &spec);
|
lifecycle::terminate_on_service_restart(t, &ds, &spec);
|
||||||
let host = spec.addr.host.clone();
|
let host = spec.addr.host.clone();
|
||||||
let port = u16::try_from(&spec.addr.port).map_err(|_| "Invalid TCP port number")?;
|
let port = u16::try_from(&spec.addr.port).map_err(|_| "Invalid TCP port number")?;
|
||||||
let parent_span = tracing::Span::current();
|
|
||||||
let facet = t.facet.clone();
|
let facet = t.facet.clone();
|
||||||
t.linked_task(syndicate::name!("listener"), async move {
|
let trace_collector = t.trace_collector();
|
||||||
|
t.linked_task(Some(AnyValue::symbol("listener")), async move {
|
||||||
let listen_addr = format!("{}:{}", host, port);
|
let listen_addr = format!("{}:{}", host, port);
|
||||||
let listener = TcpListener::bind(listen_addr).await?;
|
let listener = TcpListener::bind(listen_addr).await?;
|
||||||
|
|
||||||
|
{
|
||||||
|
let cause = trace_collector.as_ref().map(|_| trace::TurnCause::external("readiness"));
|
||||||
|
let account = Account::new(Some(AnyValue::symbol("readiness")), trace_collector.clone());
|
||||||
if !facet.activate(
|
if !facet.activate(
|
||||||
Account::new(syndicate::name!("readiness")), |t| {
|
&account, cause, |t| {
|
||||||
tracing::info!("listening");
|
tracing::info!("listening");
|
||||||
ds.assert(t, language(), &lifecycle::ready(&spec));
|
ds.assert(t, language(), &lifecycle::ready(&spec));
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -46,25 +54,27 @@ fn run(t: &mut Activation, ds: Arc<Cap>, spec: TcpRelayListener) -> ActorResult
|
||||||
{
|
{
|
||||||
return Ok(LinkedTaskTermination::Normal);
|
return Ok(LinkedTaskTermination::Normal);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
let (stream, addr) = listener.accept().await?;
|
let (stream, addr) = listener.accept().await?;
|
||||||
let gatekeeper = spec.gatekeeper.clone();
|
let gatekeeper = spec.gatekeeper.clone();
|
||||||
let name = syndicate::name!(parent: parent_span.clone(), "conn");
|
let name = Some(rec![AnyValue::symbol("tcp"), AnyValue::new(format!("{}", &addr))]);
|
||||||
|
let cause = trace_collector.as_ref().map(|_| trace::TurnCause::external("connect"));
|
||||||
|
let account = Account::new(name.clone(), trace_collector.clone());
|
||||||
if !facet.activate(
|
if !facet.activate(
|
||||||
Account::new(name.clone()),
|
&account, cause, enclose!((trace_collector) move |t| {
|
||||||
move |t| {
|
|
||||||
t.spawn(name, move |t| {
|
t.spawn(name, move |t| {
|
||||||
Ok(t.linked_task(tracing::Span::current(), {
|
Ok(t.linked_task(None, {
|
||||||
let facet = t.facet.clone();
|
let facet = t.facet.clone();
|
||||||
async move {
|
async move {
|
||||||
detect_protocol(facet, stream, gatekeeper, addr).await?;
|
detect_protocol(trace_collector, facet, stream, gatekeeper, addr).await?;
|
||||||
Ok(LinkedTaskTermination::KeepFacet)
|
Ok(LinkedTaskTermination::KeepFacet)
|
||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
});
|
});
|
||||||
Ok(())
|
Ok(())
|
||||||
})
|
}))
|
||||||
{
|
{
|
||||||
return Ok(LinkedTaskTermination::Normal);
|
return Ok(LinkedTaskTermination::Normal);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
use preserves_schema::Codec;
|
||||||
|
|
||||||
use std::io;
|
use std::io;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
@ -5,8 +7,11 @@ use std::sync::Arc;
|
||||||
use syndicate::actor::*;
|
use syndicate::actor::*;
|
||||||
use syndicate::enclose;
|
use syndicate::enclose;
|
||||||
use syndicate::error::Error;
|
use syndicate::error::Error;
|
||||||
|
use syndicate::preserves::rec;
|
||||||
|
use syndicate::preserves::value::NestedValue;
|
||||||
use syndicate::relay;
|
use syndicate::relay;
|
||||||
use syndicate::supervise::{Supervisor, SupervisorConfiguration};
|
use syndicate::supervise::{Supervisor, SupervisorConfiguration};
|
||||||
|
use syndicate::trace;
|
||||||
|
|
||||||
use tokio::net::UnixListener;
|
use tokio::net::UnixListener;
|
||||||
use tokio::net::UnixStream;
|
use tokio::net::UnixStream;
|
||||||
|
@ -19,11 +24,11 @@ use crate::schemas::internal_services::UnixRelayListener;
|
||||||
use syndicate_macros::during;
|
use syndicate_macros::during;
|
||||||
|
|
||||||
pub fn on_demand(t: &mut Activation, ds: Arc<Cap>) {
|
pub fn on_demand(t: &mut Activation, ds: Arc<Cap>) {
|
||||||
t.spawn(syndicate::name!("unix_relay_listener"), move |t| {
|
t.spawn(Some(AnyValue::symbol("unix_relay_listener")), move |t| {
|
||||||
Ok(during!(t, ds, language(), <run-service $spec: UnixRelayListener>, |t| {
|
Ok(during!(t, ds, language(), <run-service $spec: UnixRelayListener>, |t| {
|
||||||
Supervisor::start(
|
Supervisor::start(
|
||||||
t,
|
t,
|
||||||
syndicate::name!(parent: None, "relay", addr = ?spec),
|
Some(rec![AnyValue::symbol("relay"), language().unparse(&spec)]),
|
||||||
SupervisorConfiguration::default(),
|
SupervisorConfiguration::default(),
|
||||||
enclose!((ds, spec) lifecycle::updater(ds, spec)),
|
enclose!((ds, spec) lifecycle::updater(ds, spec)),
|
||||||
enclose!((ds) move |t| enclose!((ds, spec) run(t, ds, spec))))
|
enclose!((ds) move |t| enclose!((ds, spec) run(t, ds, spec))))
|
||||||
|
@ -34,13 +39,16 @@ pub fn on_demand(t: &mut Activation, ds: Arc<Cap>) {
|
||||||
fn run(t: &mut Activation, ds: Arc<Cap>, spec: UnixRelayListener) -> ActorResult {
|
fn run(t: &mut Activation, ds: Arc<Cap>, spec: UnixRelayListener) -> ActorResult {
|
||||||
lifecycle::terminate_on_service_restart(t, &ds, &spec);
|
lifecycle::terminate_on_service_restart(t, &ds, &spec);
|
||||||
let path_str = spec.addr.path.clone();
|
let path_str = spec.addr.path.clone();
|
||||||
let parent_span = tracing::Span::current();
|
|
||||||
let facet = t.facet.clone();
|
let facet = t.facet.clone();
|
||||||
t.linked_task(syndicate::name!("listener"), async move {
|
let trace_collector = t.trace_collector();
|
||||||
|
t.linked_task(Some(AnyValue::symbol("listener")), async move {
|
||||||
let listener = bind_unix_listener(&PathBuf::from(path_str)).await?;
|
let listener = bind_unix_listener(&PathBuf::from(path_str)).await?;
|
||||||
|
|
||||||
|
{
|
||||||
|
let cause = trace_collector.as_ref().map(|_| trace::TurnCause::external("readiness"));
|
||||||
|
let account = Account::new(Some(AnyValue::symbol("readiness")), trace_collector.clone());
|
||||||
if !facet.activate(
|
if !facet.activate(
|
||||||
Account::new(syndicate::name!("readiness")), |t| {
|
&account, cause, |t| {
|
||||||
tracing::info!("listening");
|
tracing::info!("listening");
|
||||||
ds.assert(t, language(), &lifecycle::ready(&spec));
|
ds.assert(t, language(), &lifecycle::ready(&spec));
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -48,24 +56,27 @@ fn run(t: &mut Activation, ds: Arc<Cap>, spec: UnixRelayListener) -> ActorResult
|
||||||
{
|
{
|
||||||
return Ok(LinkedTaskTermination::Normal);
|
return Ok(LinkedTaskTermination::Normal);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
let (stream, _addr) = listener.accept().await?;
|
let (stream, _addr) = listener.accept().await?;
|
||||||
let peer = stream.peer_cred()?;
|
let peer = stream.peer_cred()?;
|
||||||
let gatekeeper = spec.gatekeeper.clone();
|
let gatekeeper = spec.gatekeeper.clone();
|
||||||
let name = syndicate::name!(parent: parent_span.clone(), "conn",
|
let name = Some(rec![AnyValue::symbol("unix"),
|
||||||
pid = ?peer.pid().unwrap_or(-1),
|
AnyValue::new(peer.pid().unwrap_or(-1)),
|
||||||
uid = peer.uid());
|
AnyValue::new(peer.uid())]);
|
||||||
|
let cause = trace_collector.as_ref().map(|_| trace::TurnCause::external("connect"));
|
||||||
|
let account = Account::new(name.clone(), trace_collector.clone());
|
||||||
if !facet.activate(
|
if !facet.activate(
|
||||||
Account::new(name.clone()),
|
&account, cause, enclose!((trace_collector) move |t| {
|
||||||
move |t| {
|
|
||||||
t.spawn(name, |t| {
|
t.spawn(name, |t| {
|
||||||
Ok(t.linked_task(tracing::Span::current(), {
|
Ok(t.linked_task(None, {
|
||||||
let facet = t.facet.clone();
|
let facet = t.facet.clone();
|
||||||
async move {
|
async move {
|
||||||
tracing::info!(protocol = %"unix");
|
tracing::info!(protocol = %"unix");
|
||||||
let (i, o) = stream.into_split();
|
let (i, o) = stream.into_split();
|
||||||
run_connection(facet,
|
run_connection(trace_collector,
|
||||||
|
facet,
|
||||||
relay::Input::Bytes(Box::pin(i)),
|
relay::Input::Bytes(Box::pin(i)),
|
||||||
relay::Output::Bytes(Box::pin(o)),
|
relay::Output::Bytes(Box::pin(o)),
|
||||||
gatekeeper);
|
gatekeeper);
|
||||||
|
@ -74,7 +85,7 @@ fn run(t: &mut Activation, ds: Arc<Cap>, spec: UnixRelayListener) -> ActorResult
|
||||||
}))
|
}))
|
||||||
});
|
});
|
||||||
Ok(())
|
Ok(())
|
||||||
})
|
}))
|
||||||
{
|
{
|
||||||
return Ok(LinkedTaskTermination::Normal);
|
return Ok(LinkedTaskTermination::Normal);
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,19 +52,19 @@ pub fn bench_pub(c: &mut Criterion) {
|
||||||
b.iter_custom(|iters| {
|
b.iter_custom(|iters| {
|
||||||
let start = Instant::now();
|
let start = Instant::now();
|
||||||
rt.block_on(async move {
|
rt.block_on(async move {
|
||||||
Actor::new(None).boot(syndicate::name!("dataspace"), move |t| {
|
Actor::top(None, move |t| {
|
||||||
let ds = t.create(Dataspace::new(None));
|
let ds = t.create(Dataspace::new(None));
|
||||||
let shutdown = t.create(ShutdownEntity);
|
let shutdown = t.create(ShutdownEntity);
|
||||||
let account = Account::new(syndicate::name!("sender-account"));
|
let account = Account::new(None, None);
|
||||||
t.linked_task(syndicate::name!("sender"), async move {
|
t.linked_task(Some(AnyValue::symbol("sender")), async move {
|
||||||
for _ in 0..iters {
|
for _ in 0..iters {
|
||||||
external_event(&ds.mailbox, &account, Box::new(
|
external_event(&ds.mailbox, None, &account, Box::new(
|
||||||
enclose!((ds) move |t| t.with_entity(
|
enclose!((ds) move |t| t.with_entity(
|
||||||
&ds,
|
&ds,
|
||||||
|t, e| e.message(t, says(AnyValue::new("bench_pub"),
|
|t, e| e.message(t, says(AnyValue::new("bench_pub"),
|
||||||
Value::ByteString(vec![]).wrap()))))))?
|
Value::ByteString(vec![]).wrap()))))))?
|
||||||
}
|
}
|
||||||
external_event(&shutdown.mailbox, &account, Box::new(
|
external_event(&shutdown.mailbox, None, &account, Box::new(
|
||||||
enclose!((shutdown) move |t| t.with_entity(
|
enclose!((shutdown) move |t| t.with_entity(
|
||||||
&shutdown,
|
&shutdown,
|
||||||
|t, e| e.message(t, AnyValue::new(true))))))?;
|
|t, e| e.message(t, AnyValue::new(true))))))?;
|
||||||
|
@ -83,7 +83,7 @@ pub fn bench_pub(c: &mut Criterion) {
|
||||||
rt.block_on(async move {
|
rt.block_on(async move {
|
||||||
let turn_count = Arc::new(AtomicU64::new(0));
|
let turn_count = Arc::new(AtomicU64::new(0));
|
||||||
|
|
||||||
Actor::new(None).boot(syndicate::name!("dataspace"), {
|
Actor::top(None, {
|
||||||
let iters = iters.clone();
|
let iters = iters.clone();
|
||||||
let turn_count = Arc::clone(&turn_count);
|
let turn_count = Arc::clone(&turn_count);
|
||||||
|
|
||||||
|
@ -103,7 +103,7 @@ pub fn bench_pub(c: &mut Criterion) {
|
||||||
observer: shutdown,
|
observer: shutdown,
|
||||||
});
|
});
|
||||||
|
|
||||||
t.spawn(syndicate::name!("consumer"), move |t| {
|
t.spawn(Some(AnyValue::symbol("consumer")), move |t| {
|
||||||
struct Receiver(Arc<AtomicU64>);
|
struct Receiver(Arc<AtomicU64>);
|
||||||
impl Entity<AnyValue> for Receiver {
|
impl Entity<AnyValue> for Receiver {
|
||||||
fn message(&mut self, _t: &mut Activation, _m: AnyValue) -> ActorResult {
|
fn message(&mut self, _t: &mut Activation, _m: AnyValue) -> ActorResult {
|
||||||
|
@ -139,10 +139,11 @@ pub fn bench_pub(c: &mut Criterion) {
|
||||||
});
|
});
|
||||||
|
|
||||||
let account = Arc::clone(t.account());
|
let account = Arc::clone(t.account());
|
||||||
t.linked_task(syndicate::name!("sender"), async move {
|
t.linked_task(Some(AnyValue::symbol("sender")), async move {
|
||||||
for _i in 0..iters {
|
for _i in 0..iters {
|
||||||
let ds = Arc::clone(&ds);
|
let ds = Arc::clone(&ds);
|
||||||
external_event(&Arc::clone(&ds.underlying.mailbox), &account, Box::new(
|
external_event(
|
||||||
|
&Arc::clone(&ds.underlying.mailbox), None, &account, Box::new(
|
||||||
move |t| t.with_entity(
|
move |t| t.with_entity(
|
||||||
&ds.underlying,
|
&ds.underlying,
|
||||||
|t, e| e.message(t, says(AnyValue::new("bench_pub"),
|
|t, e| e.message(t, says(AnyValue::new("bench_pub"),
|
||||||
|
@ -150,7 +151,8 @@ pub fn bench_pub(c: &mut Criterion) {
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
let ds = Arc::clone(&ds);
|
let ds = Arc::clone(&ds);
|
||||||
external_event(&Arc::clone(&ds.underlying.mailbox), &account, Box::new(
|
external_event(
|
||||||
|
&Arc::clone(&ds.underlying.mailbox), None, &account, Box::new(
|
||||||
move |t| t.with_entity(
|
move |t| t.with_entity(
|
||||||
&ds.underlying,
|
&ds.underlying,
|
||||||
|t, e| e.message(t, AnyValue::new(true)))))?;
|
|t, e| e.message(t, AnyValue::new(true)))))?;
|
||||||
|
|
|
@ -7,6 +7,8 @@ use std::time::Duration;
|
||||||
use std::time::Instant;
|
use std::time::Instant;
|
||||||
|
|
||||||
use syndicate::actor::*;
|
use syndicate::actor::*;
|
||||||
|
use syndicate::preserves::rec;
|
||||||
|
use syndicate::value::NestedValue;
|
||||||
|
|
||||||
use tokio::runtime::Runtime;
|
use tokio::runtime::Runtime;
|
||||||
|
|
||||||
|
@ -88,7 +90,9 @@ pub fn bench_ring(c: &mut Criterion) {
|
||||||
self.i += 1;
|
self.i += 1;
|
||||||
let spawner_ref = Arc::clone(&self.self_ref);
|
let spawner_ref = Arc::clone(&self.self_ref);
|
||||||
ACTORS_CREATED.fetch_add(1, Ordering::Relaxed);
|
ACTORS_CREATED.fetch_add(1, Ordering::Relaxed);
|
||||||
t.spawn(syndicate::name!("forwarder", ?i), move |t| {
|
t.spawn(
|
||||||
|
Some(rec![AnyValue::symbol("forwarder"), AnyValue::new(i)]),
|
||||||
|
move |t| {
|
||||||
let _ = t.prevent_inert_check();
|
let _ = t.prevent_inert_check();
|
||||||
let f = t.create(Forwarder {
|
let f = t.create(Forwarder {
|
||||||
next,
|
next,
|
||||||
|
@ -118,7 +122,7 @@ pub fn bench_ring(c: &mut Criterion) {
|
||||||
}
|
}
|
||||||
|
|
||||||
ACTORS_CREATED.fetch_add(1, Ordering::Relaxed);
|
ACTORS_CREATED.fetch_add(1, Ordering::Relaxed);
|
||||||
Actor::new(None).boot(syndicate::name!("counter"), move |t| {
|
Actor::top(None, move |t| {
|
||||||
let _ = t.prevent_inert_check();
|
let _ = t.prevent_inert_check();
|
||||||
let mut s = Spawner {
|
let mut s = Spawner {
|
||||||
self_ref: t.create_inert(),
|
self_ref: t.create_inert(),
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -20,7 +20,7 @@ use preserves_schema::Codec;
|
||||||
/// A Dataspace object (entity).
|
/// A Dataspace object (entity).
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Dataspace {
|
pub struct Dataspace {
|
||||||
pub name: tracing::Span,
|
pub name: Name,
|
||||||
/// Index over assertions placed in the dataspace; used to
|
/// Index over assertions placed in the dataspace; used to
|
||||||
/// efficiently route assertion changes and messages to observers.
|
/// efficiently route assertion changes and messages to observers.
|
||||||
pub index: skeleton::Index,
|
pub index: skeleton::Index,
|
||||||
|
@ -31,10 +31,9 @@ pub struct Dataspace {
|
||||||
|
|
||||||
impl Dataspace {
|
impl Dataspace {
|
||||||
/// Construct a new, empty dataspace.
|
/// Construct a new, empty dataspace.
|
||||||
pub fn new(name: Option<tracing::Span>) -> Self {
|
pub fn new(name: Name) -> Self {
|
||||||
Self {
|
Self {
|
||||||
name: name.map_or_else(|| crate::name!("anonymous_dataspace"),
|
name: name,
|
||||||
|n| crate::name!(parent: &n, "dataspace")),
|
|
||||||
index: skeleton::Index::new(),
|
index: skeleton::Index::new(),
|
||||||
handle_map: Map::new(),
|
handle_map: Map::new(),
|
||||||
}
|
}
|
||||||
|
@ -62,10 +61,8 @@ impl Dataspace {
|
||||||
|
|
||||||
impl Entity<_Any> for Dataspace {
|
impl Entity<_Any> for Dataspace {
|
||||||
fn assert(&mut self, t: &mut Activation, a: _Any, h: Handle) -> ActorResult {
|
fn assert(&mut self, t: &mut Activation, a: _Any, h: Handle) -> ActorResult {
|
||||||
let _guard = self.name.enter();
|
|
||||||
|
|
||||||
let is_new = self.index.insert(t, &a);
|
let is_new = self.index.insert(t, &a);
|
||||||
tracing::trace!(assertion = ?a, handle = ?h, ?is_new, "assert");
|
tracing::trace!(dataspace = ?self.name, assertion = ?a, handle = ?h, ?is_new, "assert");
|
||||||
|
|
||||||
if is_new {
|
if is_new {
|
||||||
if let Ok(o) = language().parse::<Observe>(&a) {
|
if let Ok(o) = language().parse::<Observe>(&a) {
|
||||||
|
@ -78,13 +75,11 @@ impl Entity<_Any> for Dataspace {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn retract(&mut self, t: &mut Activation, h: Handle) -> ActorResult {
|
fn retract(&mut self, t: &mut Activation, h: Handle) -> ActorResult {
|
||||||
let _guard = self.name.enter();
|
|
||||||
|
|
||||||
match self.handle_map.remove(&h) {
|
match self.handle_map.remove(&h) {
|
||||||
None => tracing::warn!(handle = ?h, "retract of unknown handle"),
|
None => tracing::warn!(dataspace = ?self.name, handle = ?h, "retract of unknown handle"),
|
||||||
Some(a) => {
|
Some(a) => {
|
||||||
let is_last = self.index.remove(t, &a);
|
let is_last = self.index.remove(t, &a);
|
||||||
tracing::trace!(assertion = ?a, handle = ?h, ?is_last, "retract");
|
tracing::trace!(dataspace = ?self.name, assertion = ?a, handle = ?h, ?is_last, "retract");
|
||||||
|
|
||||||
if is_last {
|
if is_last {
|
||||||
if let Ok(o) = language().parse::<Observe>(&a) {
|
if let Ok(o) = language().parse::<Observe>(&a) {
|
||||||
|
@ -97,9 +92,7 @@ impl Entity<_Any> for Dataspace {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn message(&mut self, t: &mut Activation, m: _Any) -> ActorResult {
|
fn message(&mut self, t: &mut Activation, m: _Any) -> ActorResult {
|
||||||
let _guard = self.name.enter();
|
tracing::trace!(dataspace = ?self.name, body = ?m, "message");
|
||||||
tracing::trace!(body = ?m, "message");
|
|
||||||
|
|
||||||
self.index.send(t, &m);
|
self.index.send(t, &m);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
#![doc = include_str!("../README.md")]
|
#![doc = include_str!("../README.md")]
|
||||||
|
#![feature(min_specialization)]
|
||||||
|
|
||||||
#[doc(inline)]
|
#[doc(inline)]
|
||||||
pub use preserves::value;
|
pub use preserves::value;
|
||||||
|
@ -29,13 +30,33 @@ pub mod schemas {
|
||||||
|
|
||||||
pub mod skeleton;
|
pub mod skeleton;
|
||||||
pub mod sturdy;
|
pub mod sturdy;
|
||||||
pub mod tracer;
|
pub mod trace;
|
||||||
|
|
||||||
#[doc(inline)]
|
#[doc(inline)]
|
||||||
pub use during::entity;
|
pub use during::entity;
|
||||||
|
|
||||||
#[doc(inline)]
|
/// Sets up [`tracing`] logging in a reasonable way.
|
||||||
pub use tracer::convenient_logging;
|
///
|
||||||
|
/// Useful at the top of `main` functions.
|
||||||
|
pub fn convenient_logging() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
|
let filter = match std::env::var(tracing_subscriber::filter::EnvFilter::DEFAULT_ENV) {
|
||||||
|
Err(std::env::VarError::NotPresent) =>
|
||||||
|
tracing_subscriber::filter::EnvFilter::default()
|
||||||
|
.add_directive(tracing_subscriber::filter::LevelFilter::INFO.into()),
|
||||||
|
_ =>
|
||||||
|
tracing_subscriber::filter::EnvFilter::try_from_default_env()?,
|
||||||
|
};
|
||||||
|
let subscriber = tracing_subscriber::fmt()
|
||||||
|
.with_ansi(true)
|
||||||
|
.with_thread_ids(true)
|
||||||
|
.with_max_level(tracing::Level::TRACE)
|
||||||
|
.with_env_filter(filter)
|
||||||
|
.with_writer(std::io::stderr)
|
||||||
|
.finish();
|
||||||
|
tracing::subscriber::set_global_default(subscriber)
|
||||||
|
.expect("Could not set tracing global subscriber");
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
preserves_schema::define_language!(language(): Language<actor::AnyValue> {
|
preserves_schema::define_language!(language(): Language<actor::AnyValue> {
|
||||||
syndicate: schemas::Language,
|
syndicate: schemas::Language,
|
||||||
|
|
|
@ -9,6 +9,7 @@ use crate::error::error;
|
||||||
use crate::schemas::gatekeeper;
|
use crate::schemas::gatekeeper;
|
||||||
use crate::schemas::protocol as P;
|
use crate::schemas::protocol as P;
|
||||||
use crate::schemas::sturdy;
|
use crate::schemas::sturdy;
|
||||||
|
use crate::trace;
|
||||||
|
|
||||||
use futures::Sink;
|
use futures::Sink;
|
||||||
use futures::SinkExt;
|
use futures::SinkExt;
|
||||||
|
@ -248,8 +249,10 @@ impl TunnelRelay {
|
||||||
|io| Arc::clone(&tr.membranes.import_oid(t, &tr_ref, io).inc_ref().obj));
|
|io| Arc::clone(&tr.membranes.import_oid(t, &tr_ref, io).inc_ref().obj));
|
||||||
dump_membranes!(tr.membranes);
|
dump_membranes!(tr.membranes);
|
||||||
*tr_ref.lock() = Some(tr);
|
*tr_ref.lock() = Some(tr);
|
||||||
t.linked_task(crate::name!("writer"), output_loop(o, output_rx));
|
t.linked_task(Some(AnyValue::symbol("writer")),
|
||||||
t.linked_task(crate::name!("reader"), input_loop(t.facet.clone(), i, tr_ref));
|
output_loop(o, output_rx));
|
||||||
|
t.linked_task(Some(AnyValue::symbol("reader")),
|
||||||
|
input_loop(t.trace_collector(), t.facet.clone(), i, tr_ref));
|
||||||
t.state.add_exit_hook(&self_entity);
|
t.state.add_exit_hook(&self_entity);
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
@ -619,11 +622,13 @@ impl DomainEncode<Arc<Cap>> for Membranes {
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn input_loop(
|
async fn input_loop(
|
||||||
|
trace_collector: Option<trace::TraceCollector>,
|
||||||
facet: FacetRef,
|
facet: FacetRef,
|
||||||
i: Input,
|
i: Input,
|
||||||
relay: TunnelRelayRef,
|
relay: TunnelRelayRef,
|
||||||
) -> Result<LinkedTaskTermination, Error> {
|
) -> Result<LinkedTaskTermination, Error> {
|
||||||
let account = Account::new(crate::name!("input-loop"));
|
let account = Account::new(Some(AnyValue::symbol("input-loop")), trace_collector);
|
||||||
|
let cause = trace::TurnCause::external("input-loop");
|
||||||
match i {
|
match i {
|
||||||
Input::Packets(mut src) => {
|
Input::Packets(mut src) => {
|
||||||
loop {
|
loop {
|
||||||
|
@ -631,12 +636,15 @@ async fn input_loop(
|
||||||
match src.next().await {
|
match src.next().await {
|
||||||
None => break,
|
None => break,
|
||||||
Some(bs) => {
|
Some(bs) => {
|
||||||
let is_alive = facet.activate(Arc::clone(&account), |t| {
|
if !facet.activate(
|
||||||
|
&account, Some(cause.clone()), |t| {
|
||||||
let mut g = relay.lock();
|
let mut g = relay.lock();
|
||||||
let tr = g.as_mut().expect("initialized");
|
let tr = g.as_mut().expect("initialized");
|
||||||
tr.handle_inbound_datagram(t, &bs?)
|
tr.handle_inbound_datagram(t, &bs?)
|
||||||
});
|
})
|
||||||
if !is_alive { break; }
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -659,12 +667,15 @@ async fn input_loop(
|
||||||
match n {
|
match n {
|
||||||
0 => break,
|
0 => break,
|
||||||
_ => {
|
_ => {
|
||||||
let is_alive = facet.activate(Arc::clone(&account), |t| {
|
if !facet.activate(
|
||||||
|
&account, Some(cause.clone()), |t| {
|
||||||
let mut g = relay.lock();
|
let mut g = relay.lock();
|
||||||
let tr = g.as_mut().expect("initialized");
|
let tr = g.as_mut().expect("initialized");
|
||||||
tr.handle_inbound_stream(t, &mut buf)
|
tr.handle_inbound_stream(t, &mut buf)
|
||||||
});
|
})
|
||||||
if !is_alive { break; }
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
//! Extremely simple single-actor supervision. Vastly simplified compared to the available
|
//! Extremely simple single-actor supervision. Vastly simplified compared to the available
|
||||||
//! options in [Erlang/OTP](https://erlang.org/doc/man/supervisor.html).
|
//! options in [Erlang/OTP](https://erlang.org/doc/man/supervisor.html).
|
||||||
|
|
||||||
|
use preserves::value::NestedValue;
|
||||||
|
|
||||||
use std::collections::VecDeque;
|
use std::collections::VecDeque;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
@ -8,7 +10,6 @@ use std::time::Duration;
|
||||||
use tokio::time::Instant;
|
use tokio::time::Instant;
|
||||||
|
|
||||||
use crate::actor::*;
|
use crate::actor::*;
|
||||||
use crate::enclose;
|
|
||||||
use crate::schemas::service::State;
|
use crate::schemas::service::State;
|
||||||
|
|
||||||
pub type Boot = Box<dyn Send + FnMut(&mut Activation) -> ActorResult>;
|
pub type Boot = Box<dyn Send + FnMut(&mut Activation) -> ActorResult>;
|
||||||
|
@ -36,7 +37,8 @@ pub struct SupervisorConfiguration {
|
||||||
|
|
||||||
pub struct Supervisor {
|
pub struct Supervisor {
|
||||||
self_ref: Arc<Ref<Protocol>>,
|
self_ref: Arc<Ref<Protocol>>,
|
||||||
name: tracing::Span,
|
my_name: Name,
|
||||||
|
child_name: Name,
|
||||||
config: SupervisorConfiguration,
|
config: SupervisorConfiguration,
|
||||||
boot_fn: Option<Boot>,
|
boot_fn: Option<Boot>,
|
||||||
restarts: VecDeque<Instant>,
|
restarts: VecDeque<Instant>,
|
||||||
|
@ -86,8 +88,7 @@ impl Entity<Protocol> for Supervisor
|
||||||
}
|
}
|
||||||
|
|
||||||
fn retract(&mut self, t: &mut Activation, _h: Handle) -> ActorResult {
|
fn retract(&mut self, t: &mut Activation, _h: Handle) -> ActorResult {
|
||||||
let _name = self.name.clone();
|
let _entry = tracing::info_span!("supervisor", name = ?self.child_name).entered();
|
||||||
let _entry = _name.enter();
|
|
||||||
let exit_status =
|
let exit_status =
|
||||||
self.ac_ref.take().expect("valid supervisee ActorRef")
|
self.ac_ref.take().expect("valid supervisee ActorRef")
|
||||||
.exit_status()
|
.exit_status()
|
||||||
|
@ -144,8 +145,9 @@ impl Entity<Protocol> for Supervisor
|
||||||
}
|
}
|
||||||
|
|
||||||
fn stop(&mut self, _t: &mut Activation) -> ActorResult {
|
fn stop(&mut self, _t: &mut Activation) -> ActorResult {
|
||||||
let _entry = self.name.enter();
|
tracing::info!(name = ?self.my_name,
|
||||||
tracing::info!(self_ref = ?self.self_ref, "Supervisor terminating");
|
self_ref = ?self.self_ref,
|
||||||
|
"Supervisor terminating");
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -154,18 +156,21 @@ impl Supervisor {
|
||||||
pub fn start<C: 'static + Send + FnMut(&mut Activation, State) -> ActorResult,
|
pub fn start<C: 'static + Send + FnMut(&mut Activation, State) -> ActorResult,
|
||||||
B: 'static + Send + FnMut(&mut Activation) -> ActorResult>(
|
B: 'static + Send + FnMut(&mut Activation) -> ActorResult>(
|
||||||
t: &mut Activation,
|
t: &mut Activation,
|
||||||
name: tracing::Span,
|
name: Name,
|
||||||
config: SupervisorConfiguration,
|
config: SupervisorConfiguration,
|
||||||
mut state_cb: C,
|
mut state_cb: C,
|
||||||
boot_fn: B,
|
boot_fn: B,
|
||||||
) -> ActorResult {
|
) -> ActorResult {
|
||||||
let _entry = name.enter();
|
let _entry = tracing::info_span!("supervisor", ?name).entered();
|
||||||
tracing::trace!(?config);
|
tracing::trace!(?config);
|
||||||
let self_ref = t.create_inert();
|
let self_ref = t.create_inert();
|
||||||
let state_field = t.named_field("supervisee_state", State::Started);
|
let state_field = t.named_field("supervisee_state", State::Started);
|
||||||
|
let my_name = name.as_ref().map(
|
||||||
|
|n| preserves::rec![AnyValue::symbol("supervisor"), n.clone()]);
|
||||||
let mut supervisor = Supervisor {
|
let mut supervisor = Supervisor {
|
||||||
self_ref: Arc::clone(&self_ref),
|
self_ref: Arc::clone(&self_ref),
|
||||||
name: name.clone(),
|
my_name: my_name.clone(),
|
||||||
|
child_name: name,
|
||||||
config,
|
config,
|
||||||
boot_fn: Some(Box::new(boot_fn)),
|
boot_fn: Some(Box::new(boot_fn)),
|
||||||
restarts: VecDeque::new(),
|
restarts: VecDeque::new(),
|
||||||
|
@ -174,14 +179,11 @@ impl Supervisor {
|
||||||
};
|
};
|
||||||
tracing::info!(self_ref = ?supervisor.self_ref, "Supervisor starting");
|
tracing::info!(self_ref = ?supervisor.self_ref, "Supervisor starting");
|
||||||
supervisor.ensure_started(t)?;
|
supervisor.ensure_started(t)?;
|
||||||
t.dataflow(enclose!((name) move |t| {
|
t.dataflow(move |t| {
|
||||||
let state = t.get(&state_field).clone();
|
let state = t.get(&state_field).clone();
|
||||||
{
|
tracing::debug!(name = ?my_name, ?state);
|
||||||
let _entry = name.enter();
|
|
||||||
tracing::debug!(?state);
|
|
||||||
}
|
|
||||||
state_cb(t, state)
|
state_cb(t, state)
|
||||||
}))?;
|
})?;
|
||||||
self_ref.become_entity(supervisor);
|
self_ref.become_entity(supervisor);
|
||||||
t.on_stop_notify(&self_ref);
|
t.on_stop_notify(&self_ref);
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -190,16 +192,16 @@ impl Supervisor {
|
||||||
fn ensure_started(&mut self, t: &mut Activation) -> ActorResult {
|
fn ensure_started(&mut self, t: &mut Activation) -> ActorResult {
|
||||||
match self.boot_fn.take() {
|
match self.boot_fn.take() {
|
||||||
None => {
|
None => {
|
||||||
let _entry = self.name.enter();
|
|
||||||
t.set(&self.state, State::Failed);
|
t.set(&self.state, State::Failed);
|
||||||
tracing::error!("Cannot restart supervisee, because it panicked at startup")
|
tracing::error!(name = ?self.my_name,
|
||||||
|
"Cannot restart supervisee, because it panicked at startup")
|
||||||
}
|
}
|
||||||
Some(mut boot_fn) => {
|
Some(mut boot_fn) => {
|
||||||
let self_ref = Arc::clone(&self.self_ref);
|
let self_ref = Arc::clone(&self.self_ref);
|
||||||
t.facet(|t: &mut Activation| {
|
t.facet(|t: &mut Activation| {
|
||||||
t.assert(&self.self_ref, Protocol::SuperviseeStarted);
|
t.assert(&self.self_ref, Protocol::SuperviseeStarted);
|
||||||
self.ac_ref = Some(t.spawn_link(
|
self.ac_ref = Some(t.spawn_link(
|
||||||
crate::name!(parent: &self.name, "supervisee"),
|
self.child_name.clone(),
|
||||||
move |t| {
|
move |t| {
|
||||||
match boot_fn(t) {
|
match boot_fn(t) {
|
||||||
Ok(()) => {
|
Ok(()) => {
|
||||||
|
|
|
@ -0,0 +1,187 @@
|
||||||
|
//! Records *describing* actions committed at the end of a turn and
|
||||||
|
//! events triggering the start of a turn. These are not the actions
|
||||||
|
//! or events themselves: they are reflective information on the
|
||||||
|
//! action of the system, enough to reconstruct interesting
|
||||||
|
//! projections of system activity.
|
||||||
|
|
||||||
|
pub use super::schemas::trace::*;
|
||||||
|
|
||||||
|
use preserves::value::NestedValue;
|
||||||
|
use preserves::value::Writer;
|
||||||
|
use preserves_schema::Codec;
|
||||||
|
|
||||||
|
use super::actor::{self, AnyValue, Ref, Cap};
|
||||||
|
use super::language;
|
||||||
|
|
||||||
|
use std::sync::Arc;
|
||||||
|
use std::time::SystemTime;
|
||||||
|
|
||||||
|
use tokio::select;
|
||||||
|
use tokio::sync::mpsc::{unbounded_channel, UnboundedSender};
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct TraceCollector {
|
||||||
|
pub tx: UnboundedSender<TraceEntry>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<M> From<&Ref<M>> for Target {
|
||||||
|
fn from(v: &Ref<M>) -> Target {
|
||||||
|
Target {
|
||||||
|
actor: ActorId(AnyValue::new(v.mailbox.actor_id)),
|
||||||
|
facet: FacetId(AnyValue::new(u64::from(v.facet_id))),
|
||||||
|
oid: Oid(AnyValue::new(v.oid())),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<M: std::fmt::Debug> From<&M> for AssertionDescription {
|
||||||
|
default fn from(v: &M) -> Self {
|
||||||
|
Self::Opaque { description: AnyValue::new(format!("{:?}", v)) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<&AnyValue> for AssertionDescription {
|
||||||
|
fn from(v: &AnyValue) -> Self {
|
||||||
|
Self::Value { value: v.clone() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TraceCollector {
|
||||||
|
pub fn record(&self, id: actor::ActorId, a: ActorActivation) {
|
||||||
|
let _ = self.tx.send(TraceEntry {
|
||||||
|
timestamp: SystemTime::now().duration_since(SystemTime::UNIX_EPOCH)
|
||||||
|
.expect("Time after Unix epoch").as_secs_f64().into(),
|
||||||
|
actor: ActorId(AnyValue::new(id)),
|
||||||
|
item: a,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TurnDescription {
|
||||||
|
pub fn new(activation_id: u64, cause: TurnCause) -> Self {
|
||||||
|
Self {
|
||||||
|
id: TurnId(AnyValue::new(activation_id)),
|
||||||
|
cause,
|
||||||
|
actions: Vec::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn record(&mut self, a: ActionDescription) {
|
||||||
|
self.actions.push(a)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn take(&mut self) -> Self {
|
||||||
|
Self {
|
||||||
|
id: self.id.clone(),
|
||||||
|
cause: self.cause.clone(),
|
||||||
|
actions: std::mem::take(&mut self.actions),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TurnCause {
|
||||||
|
pub fn external(description: &str) -> Self {
|
||||||
|
Self::External { description: AnyValue::new(description) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct CapEncoder;
|
||||||
|
|
||||||
|
impl preserves::value::DomainEncode<Arc<Cap>> for CapEncoder {
|
||||||
|
fn encode_embedded<W: Writer>(
|
||||||
|
&mut self,
|
||||||
|
w: &mut W,
|
||||||
|
d: &Arc<Cap>,
|
||||||
|
) -> std::io::Result<()> {
|
||||||
|
w.write_string(&d.debug_str())
|
||||||
|
|
||||||
|
// use preserves::value::writer::CompoundWriter;
|
||||||
|
// use preserves::value::boundary as B;
|
||||||
|
// let mut c = w.start_record(Some(3))?;
|
||||||
|
|
||||||
|
// let mut b = B::start(B::Item::RecordLabel);
|
||||||
|
// c.boundary(&b)?;
|
||||||
|
// c.write_symbol("cap")?;
|
||||||
|
|
||||||
|
// b.shift(Some(B::Item::RecordField));
|
||||||
|
// c.boundary(&b)?;
|
||||||
|
// c.write_u64(d.underlying.mailbox.actor_id)?;
|
||||||
|
|
||||||
|
// b.shift(Some(B::Item::RecordField));
|
||||||
|
// c.boundary(&b)?;
|
||||||
|
// c.write_u64(u64::from(d.underlying.facet_id))?;
|
||||||
|
|
||||||
|
// b.shift(Some(B::Item::RecordField));
|
||||||
|
// c.boundary(&b)?;
|
||||||
|
// c.write_u64(d.underlying.oid() as u64)?;
|
||||||
|
|
||||||
|
// // TODO: write attenuation?
|
||||||
|
|
||||||
|
// b.shift(None);
|
||||||
|
// c.boundary(&b)?;
|
||||||
|
// w.end_record(c)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum CollectorEvent {
|
||||||
|
Event(TraceEntry),
|
||||||
|
PeriodicFlush,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TraceCollector {
|
||||||
|
pub fn new<F: 'static + Send + FnMut(CollectorEvent)>(mut f: F) -> TraceCollector {
|
||||||
|
let (tx, mut rx) = unbounded_channel::<TraceEntry>();
|
||||||
|
tokio::spawn(async move {
|
||||||
|
let mut timer = tokio::time::interval(std::time::Duration::from_secs(1));
|
||||||
|
loop {
|
||||||
|
select! {
|
||||||
|
maybe_entry = rx.recv() => {
|
||||||
|
match maybe_entry {
|
||||||
|
None => break,
|
||||||
|
Some(entry) => {
|
||||||
|
tracing::trace!(?entry);
|
||||||
|
f(CollectorEvent::Event(entry));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
_ = timer.tick() => f(CollectorEvent::PeriodicFlush),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
TraceCollector { tx }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn ascii<W: 'static + std::io::Write + Send>(w: W) -> TraceCollector {
|
||||||
|
let mut writer = preserves::value::TextWriter::new(w);
|
||||||
|
Self::new(move |event| match event {
|
||||||
|
CollectorEvent::Event(entry) => {
|
||||||
|
writer.write(&mut CapEncoder, &language().unparse(&entry))
|
||||||
|
.expect("failed to write TraceCollector entry");
|
||||||
|
writer.borrow_write().write_all(b"\n")
|
||||||
|
.expect("failed to write TraceCollector newline");
|
||||||
|
},
|
||||||
|
CollectorEvent::PeriodicFlush =>
|
||||||
|
writer.flush().expect("failed to flush TraceCollector output"),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn packed<W: 'static + std::io::Write + Send>(w: W) -> TraceCollector {
|
||||||
|
let mut writer = preserves::value::PackedWriter::new(w);
|
||||||
|
Self::new(move |event| match event {
|
||||||
|
CollectorEvent::Event(entry) =>
|
||||||
|
writer.write(&mut CapEncoder, &language().unparse(&entry))
|
||||||
|
.expect("failed to write TraceCollector entry"),
|
||||||
|
CollectorEvent::PeriodicFlush =>
|
||||||
|
writer.flush().expect("failed to flush TraceCollector output"),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<actor::Name> for Name {
|
||||||
|
fn from(v: actor::Name) -> Name {
|
||||||
|
match v {
|
||||||
|
None => Name::Anonymous,
|
||||||
|
Some(n) => Name::Named { name: n.clone() },
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,66 +0,0 @@
|
||||||
use crate::actor::*;
|
|
||||||
|
|
||||||
use std::fmt::Debug;
|
|
||||||
use std::io;
|
|
||||||
use std::sync::Arc;
|
|
||||||
|
|
||||||
struct Tracer(tracing::Span);
|
|
||||||
|
|
||||||
fn set_name_oid<M>(t: &mut Tracer, r: &Arc<Ref<M>>) {
|
|
||||||
t.0.record("oid", &tracing::field::display(&r.oid()));
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn tracer<M: Debug>(t: &mut Activation, name: tracing::Span) -> Arc<Ref<M>> {
|
|
||||||
let mut e = Tracer(name);
|
|
||||||
let r = t.create_inert();
|
|
||||||
set_name_oid(&mut e, &r);
|
|
||||||
r.become_entity(e);
|
|
||||||
r
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<M: Debug> Entity<M> for Tracer {
|
|
||||||
fn assert(&mut self, _t: &mut Activation, a: M, h: Handle) -> ActorResult {
|
|
||||||
let _guard = self.0.enter();
|
|
||||||
tracing::trace!(?a, ?h, "assert");
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
fn retract(&mut self, _t: &mut Activation, h: Handle) -> ActorResult {
|
|
||||||
let _guard = self.0.enter();
|
|
||||||
tracing::trace!(?h, "retract");
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
fn message(&mut self, _t: &mut Activation, m: M) -> ActorResult {
|
|
||||||
let _guard = self.0.enter();
|
|
||||||
tracing::trace!(?m, "message");
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
fn sync(&mut self, t: &mut Activation, peer: Arc<Ref<Synced>>) -> ActorResult {
|
|
||||||
let _guard = self.0.enter();
|
|
||||||
tracing::trace!(?peer, "sync");
|
|
||||||
t.message(&peer, Synced);
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Sets up [`tracing`] logging in a reasonable way.
|
|
||||||
///
|
|
||||||
/// Useful at the top of `main` functions.
|
|
||||||
pub fn convenient_logging() -> Result<(), Box<dyn std::error::Error>> {
|
|
||||||
let filter = match std::env::var(tracing_subscriber::filter::EnvFilter::DEFAULT_ENV) {
|
|
||||||
Err(std::env::VarError::NotPresent) =>
|
|
||||||
tracing_subscriber::filter::EnvFilter::default()
|
|
||||||
.add_directive(tracing_subscriber::filter::LevelFilter::INFO.into()),
|
|
||||||
_ =>
|
|
||||||
tracing_subscriber::filter::EnvFilter::try_from_default_env()?,
|
|
||||||
};
|
|
||||||
let subscriber = tracing_subscriber::fmt()
|
|
||||||
.with_ansi(true)
|
|
||||||
.with_thread_ids(true)
|
|
||||||
.with_max_level(tracing::Level::TRACE)
|
|
||||||
.with_env_filter(filter)
|
|
||||||
.with_writer(io::stderr)
|
|
||||||
.finish();
|
|
||||||
tracing::subscriber::set_global_default(subscriber)
|
|
||||||
.expect("Could not set tracing global subscriber");
|
|
||||||
Ok(())
|
|
||||||
}
|
|
Loading…
Reference in New Issue