Skip to content

Commit 6f6519d

Browse files
authored
Implement PrivateAgent (#2318)
* Implement PrivateAgent, Separate Threaded into PublicAgent & PrivateAgent. * Add migration docs. * Update docs.
1 parent c46cda1 commit 6f6519d

File tree

8 files changed

+90
-27
lines changed

8 files changed

+90
-27
lines changed

examples/agents/src/bin/worker.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use agents::native_worker::Worker;
2-
use yew_agent::Threaded;
2+
use yew_agent::PublicAgent;
33

44
fn main() {
55
wasm_logger::init(wasm_logger::Config::default());

examples/web_worker_fib/src/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ pub mod agent;
55
pub mod app;
66
use app::Model;
77
use wasm_bindgen::prelude::*;
8-
use yew_agent::Threaded;
8+
use yew_agent::PublicAgent;
99

1010
#[wasm_bindgen(start)]
1111
pub fn start() {

packages/yew-agent/src/lib.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
//! This module contains types to support multi-threading and state management.
1+
//! This module contains Yew's web worker implementation.
22
33
mod hooks;
44
mod link;
@@ -10,7 +10,7 @@ pub use link::AgentLink;
1010
pub(crate) use link::*;
1111
pub(crate) use pool::*;
1212
pub use pool::{Dispatched, Dispatcher};
13-
pub use worker::{Private, Public, Threaded};
13+
pub use worker::{Private, PrivateAgent, Public, PublicAgent};
1414

1515
use serde::{Deserialize, Serialize};
1616
use std::fmt;

packages/yew-agent/src/worker/mod.rs

+15-7
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ mod private;
22
mod public;
33
mod queue;
44

5-
pub use private::Private;
6-
pub use public::Public;
5+
pub use private::{Private, PrivateAgent};
6+
pub use public::{Public, PublicAgent};
77

88
use super::*;
99
use js_sys::{Array, Reflect, Uint8Array};
@@ -13,11 +13,19 @@ use web_sys::{
1313
Blob, BlobPropertyBag, DedicatedWorkerGlobalScope, MessageEvent, Url, Worker, WorkerOptions,
1414
};
1515

16-
/// Implements rules to register a worker in a separate thread.
17-
pub trait Threaded {
18-
/// Executes an agent in the current environment.
19-
/// Uses in `main` function of a worker.
20-
fn register();
16+
pub(crate) struct WorkerResponder {}
17+
18+
impl<AGN> Responder<AGN> for WorkerResponder
19+
where
20+
AGN: Agent,
21+
<AGN as Agent>::Input: Serialize + for<'de> Deserialize<'de>,
22+
<AGN as Agent>::Output: Serialize + for<'de> Deserialize<'de>,
23+
{
24+
fn respond(&self, id: HandlerId, output: AGN::Output) {
25+
let msg = FromWorker::ProcessOutput(id, output);
26+
let data = msg.pack();
27+
worker_self().post_message_vec(data);
28+
}
2129
}
2230

2331
/// Message packager, based on serde::Serialize/Deserialize

packages/yew-agent/src/worker/private.rs

+50
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,56 @@ pub struct Private<AGN> {
2121
_agent: PhantomData<AGN>,
2222
}
2323

24+
/// A trait to enable private agents being registered in a web worker.
25+
pub trait PrivateAgent {
26+
/// Executes an agent in the current environment.
27+
/// Uses in `main` function of a worker.
28+
fn register();
29+
}
30+
31+
impl<AGN> PrivateAgent for AGN
32+
where
33+
AGN: Agent<Reach = Private<AGN>>,
34+
<AGN as Agent>::Input: Serialize + for<'de> Deserialize<'de>,
35+
<AGN as Agent>::Output: Serialize + for<'de> Deserialize<'de>,
36+
{
37+
fn register() {
38+
let scope = AgentScope::<AGN>::new();
39+
let responder = WorkerResponder {};
40+
let link = AgentLink::connect(&scope, responder);
41+
let upd = AgentLifecycleEvent::Create(link);
42+
scope.send(upd);
43+
let handler = move |data: Vec<u8>| {
44+
let msg = ToWorker::<AGN::Input>::unpack(&data);
45+
match msg {
46+
ToWorker::Connected(_id) => {
47+
let upd = AgentLifecycleEvent::Connected(SINGLETON_ID);
48+
scope.send(upd);
49+
}
50+
ToWorker::ProcessInput(_id, value) => {
51+
let upd = AgentLifecycleEvent::Input(value, SINGLETON_ID);
52+
scope.send(upd);
53+
}
54+
ToWorker::Disconnected(_id) => {
55+
let upd = AgentLifecycleEvent::Disconnected(SINGLETON_ID);
56+
scope.send(upd);
57+
}
58+
ToWorker::Destroy => {
59+
let upd = AgentLifecycleEvent::Destroy;
60+
scope.send(upd);
61+
// Terminates web worker
62+
worker_self().close();
63+
}
64+
}
65+
};
66+
let loaded: FromWorker<AGN::Output> = FromWorker::WorkerLoaded;
67+
let loaded = loaded.pack();
68+
let worker = worker_self();
69+
worker.set_onmessage_closure(handler);
70+
worker.post_message_vec(loaded);
71+
}
72+
}
73+
2474
impl<AGN> Discoverer for Private<AGN>
2575
where
2676
AGN: Agent,

packages/yew-agent/src/worker/public.rs

+6-14
Original file line numberDiff line numberDiff line change
@@ -181,22 +181,14 @@ where
181181
}
182182
}
183183

184-
struct WorkerResponder {}
185-
186-
impl<AGN> Responder<AGN> for WorkerResponder
187-
where
188-
AGN: Agent,
189-
<AGN as Agent>::Input: Serialize + for<'de> Deserialize<'de>,
190-
<AGN as Agent>::Output: Serialize + for<'de> Deserialize<'de>,
191-
{
192-
fn respond(&self, id: HandlerId, output: AGN::Output) {
193-
let msg = FromWorker::ProcessOutput(id, output);
194-
let data = msg.pack();
195-
worker_self().post_message_vec(data);
196-
}
184+
/// A trait to enable public agents being registered in a web worker.
185+
pub trait PublicAgent {
186+
/// Executes an agent in the current environment.
187+
/// Uses in `main` function of a worker.
188+
fn register();
197189
}
198190

199-
impl<AGN> Threaded for AGN
191+
impl<AGN> PublicAgent for AGN
200192
where
201193
AGN: Agent<Reach = Public<AGN>>,
202194
<AGN as Agent>::Input: Serialize + for<'de> Deserialize<'de>,

website/docs/concepts/agents.mdx

+2-2
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,8 @@ The code can be found in the <desc> tag of the svgs.
3636
When no bridges are connected to this agent, the agent will disappear.
3737

3838
* Private - Spawn a new agent in a web worker for every new bridge. This is good for moving shared but
39-
independent behavior that communicates with the browser out of components. \(TODO verify\) When
40-
the task is done, the agent will disappear.
39+
independent behavior that communicates with the browser out of components. When
40+
the the connected bridge is dropped, the agent will disappear.
4141

4242
* Global \(WIP\)
4343

website/docs/migration-guides/yew-agent/from-0_1_0-to-0_2_0.mdx

+13
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,21 @@
22
title: "From 0.1.0 to 0.2.0"
33
---
44

5+
## Removal of `Context` and `Job` Agents
6+
57
The `Context` and `Job` Agents have been removed in favour of Yew's Context API.
68

79
You can see the updated [`pub_sub`](https://github.com/yewstack/yew/tree/master/examples/pub_sub) example about how to use Context API.
810

911
For users of `yew_agent::utils::store`, you may switch to third party solutions like: [Yewdux](https://github.com/intendednull/yewdux) or [Bounce](https://github.com/futursolo/bounce).
12+
13+
## `Threaded` is separated into `PublicAgent` and `PrivateAgent`
14+
15+
Replace `use yew_agent::Threaded;` with `use yew_agent::PublicAgent;`.
16+
17+
:::note
18+
19+
`Threaded` was never implemented for Private Agents.
20+
All existing web worker-based agents are Public Agents.
21+
22+
:::

0 commit comments

Comments
 (0)