feat(wit): define resident actor protocol

Add the versioned wasmeld:resident@0.1.0 event/effect contract for timers, streams, datagrams, messages, extension sources, and shutdown.

Add a resident-probe Component with locked service and resident WIT dependencies so the ABI can be built, packed, and exercised independently.
This commit is contained in:
Maofeng
2026-07-30 07:40:02 +08:00
parent b304b038a4
commit 949b8d6cdb
8 changed files with 251 additions and 0 deletions
+72
View File
@@ -0,0 +1,72 @@
use std::sync::atomic::{AtomicU64, Ordering};
mod bindings {
wit_bindgen::generate!({
path: "wit",
world: "resident-probe-component",
generate_all,
});
}
use bindings::exports::wasmeld::resident::actor::{
DatagramSend, Effect, Event, Guest as ResidentGuest, MessageAck, SourceCommand, StreamWrite,
TimerArm,
};
static EVENTS_HANDLED: AtomicU64 = AtomicU64::new(0);
struct ResidentProbe;
impl bindings::Guest for ResidentProbe {
fn init(_config: Vec<u8>) -> Result<(), bindings::ServiceError> {
EVENTS_HANDLED.store(0, Ordering::Relaxed);
Ok(())
}
fn invoke(_input: Vec<u8>) -> Result<Vec<u8>, bindings::ServiceError> {
Ok(EVENTS_HANDLED
.load(Ordering::Relaxed)
.to_le_bytes()
.to_vec())
}
}
impl ResidentGuest for ResidentProbe {
fn handle_event(
input: Event,
) -> Result<Vec<Effect>, bindings::exports::wasmeld::resident::actor::ResidentError> {
EVENTS_HANDLED.fetch_add(1, Ordering::Relaxed);
Ok(match input {
Event::StreamData(chunk) => vec![Effect::WriteStream(StreamWrite {
stream_id: chunk.stream_id,
bytes: chunk.bytes,
})],
Event::Datagram(datagram) => vec![Effect::SendDatagram(DatagramSend {
endpoint_id: datagram.endpoint_id,
peer: datagram.peer,
bytes: datagram.bytes,
})],
Event::Timer(timer) => vec![Effect::ArmTimer(TimerArm {
timer_id: timer.timer_id,
delay_ms: 10,
interval_ms: None,
})],
Event::Message(message) => vec![Effect::AcknowledgeMessage(MessageAck {
subscription_id: message.subscription_id,
message_id: message.message_id,
})],
Event::Source(source) => vec![Effect::SourceCommand(SourceCommand {
source_id: source.source_id,
command: source.kind,
payload: source.payload,
})],
Event::StreamOpened(_)
| Event::StreamWritable(_)
| Event::StreamHalfClosed(_)
| Event::StreamClosed(_)
| Event::Shutdown => Vec::new(),
})
}
}
bindings::export!(ResidentProbe with_types_in bindings);