mirror of
https://github.com/yewstack/yew.git
synced 2025-12-08 21:26:25 +00:00
Implement PrivateAgent (#2318)
* Implement PrivateAgent, Separate Threaded into PublicAgent & PrivateAgent. * Add migration docs. * Update docs.
This commit is contained in:
parent
c46cda1e6f
commit
6f6519dab4
@ -1,5 +1,5 @@
|
|||||||
use agents::native_worker::Worker;
|
use agents::native_worker::Worker;
|
||||||
use yew_agent::Threaded;
|
use yew_agent::PublicAgent;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
wasm_logger::init(wasm_logger::Config::default());
|
wasm_logger::init(wasm_logger::Config::default());
|
||||||
|
|||||||
@ -5,7 +5,7 @@ pub mod agent;
|
|||||||
pub mod app;
|
pub mod app;
|
||||||
use app::Model;
|
use app::Model;
|
||||||
use wasm_bindgen::prelude::*;
|
use wasm_bindgen::prelude::*;
|
||||||
use yew_agent::Threaded;
|
use yew_agent::PublicAgent;
|
||||||
|
|
||||||
#[wasm_bindgen(start)]
|
#[wasm_bindgen(start)]
|
||||||
pub fn start() {
|
pub fn start() {
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
//! This module contains types to support multi-threading and state management.
|
//! This module contains Yew's web worker implementation.
|
||||||
|
|
||||||
mod hooks;
|
mod hooks;
|
||||||
mod link;
|
mod link;
|
||||||
@ -10,7 +10,7 @@ pub use link::AgentLink;
|
|||||||
pub(crate) use link::*;
|
pub(crate) use link::*;
|
||||||
pub(crate) use pool::*;
|
pub(crate) use pool::*;
|
||||||
pub use pool::{Dispatched, Dispatcher};
|
pub use pool::{Dispatched, Dispatcher};
|
||||||
pub use worker::{Private, Public, Threaded};
|
pub use worker::{Private, PrivateAgent, Public, PublicAgent};
|
||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|||||||
@ -2,8 +2,8 @@ mod private;
|
|||||||
mod public;
|
mod public;
|
||||||
mod queue;
|
mod queue;
|
||||||
|
|
||||||
pub use private::Private;
|
pub use private::{Private, PrivateAgent};
|
||||||
pub use public::Public;
|
pub use public::{Public, PublicAgent};
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
use js_sys::{Array, Reflect, Uint8Array};
|
use js_sys::{Array, Reflect, Uint8Array};
|
||||||
@ -13,11 +13,19 @@ use web_sys::{
|
|||||||
Blob, BlobPropertyBag, DedicatedWorkerGlobalScope, MessageEvent, Url, Worker, WorkerOptions,
|
Blob, BlobPropertyBag, DedicatedWorkerGlobalScope, MessageEvent, Url, Worker, WorkerOptions,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Implements rules to register a worker in a separate thread.
|
pub(crate) struct WorkerResponder {}
|
||||||
pub trait Threaded {
|
|
||||||
/// Executes an agent in the current environment.
|
impl<AGN> Responder<AGN> for WorkerResponder
|
||||||
/// Uses in `main` function of a worker.
|
where
|
||||||
fn register();
|
AGN: Agent,
|
||||||
|
<AGN as Agent>::Input: Serialize + for<'de> Deserialize<'de>,
|
||||||
|
<AGN as Agent>::Output: Serialize + for<'de> Deserialize<'de>,
|
||||||
|
{
|
||||||
|
fn respond(&self, id: HandlerId, output: AGN::Output) {
|
||||||
|
let msg = FromWorker::ProcessOutput(id, output);
|
||||||
|
let data = msg.pack();
|
||||||
|
worker_self().post_message_vec(data);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Message packager, based on serde::Serialize/Deserialize
|
/// Message packager, based on serde::Serialize/Deserialize
|
||||||
|
|||||||
@ -21,6 +21,56 @@ pub struct Private<AGN> {
|
|||||||
_agent: PhantomData<AGN>,
|
_agent: PhantomData<AGN>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A trait to enable private agents being registered in a web worker.
|
||||||
|
pub trait PrivateAgent {
|
||||||
|
/// Executes an agent in the current environment.
|
||||||
|
/// Uses in `main` function of a worker.
|
||||||
|
fn register();
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<AGN> PrivateAgent for AGN
|
||||||
|
where
|
||||||
|
AGN: Agent<Reach = Private<AGN>>,
|
||||||
|
<AGN as Agent>::Input: Serialize + for<'de> Deserialize<'de>,
|
||||||
|
<AGN as Agent>::Output: Serialize + for<'de> Deserialize<'de>,
|
||||||
|
{
|
||||||
|
fn register() {
|
||||||
|
let scope = AgentScope::<AGN>::new();
|
||||||
|
let responder = WorkerResponder {};
|
||||||
|
let link = AgentLink::connect(&scope, responder);
|
||||||
|
let upd = AgentLifecycleEvent::Create(link);
|
||||||
|
scope.send(upd);
|
||||||
|
let handler = move |data: Vec<u8>| {
|
||||||
|
let msg = ToWorker::<AGN::Input>::unpack(&data);
|
||||||
|
match msg {
|
||||||
|
ToWorker::Connected(_id) => {
|
||||||
|
let upd = AgentLifecycleEvent::Connected(SINGLETON_ID);
|
||||||
|
scope.send(upd);
|
||||||
|
}
|
||||||
|
ToWorker::ProcessInput(_id, value) => {
|
||||||
|
let upd = AgentLifecycleEvent::Input(value, SINGLETON_ID);
|
||||||
|
scope.send(upd);
|
||||||
|
}
|
||||||
|
ToWorker::Disconnected(_id) => {
|
||||||
|
let upd = AgentLifecycleEvent::Disconnected(SINGLETON_ID);
|
||||||
|
scope.send(upd);
|
||||||
|
}
|
||||||
|
ToWorker::Destroy => {
|
||||||
|
let upd = AgentLifecycleEvent::Destroy;
|
||||||
|
scope.send(upd);
|
||||||
|
// Terminates web worker
|
||||||
|
worker_self().close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let loaded: FromWorker<AGN::Output> = FromWorker::WorkerLoaded;
|
||||||
|
let loaded = loaded.pack();
|
||||||
|
let worker = worker_self();
|
||||||
|
worker.set_onmessage_closure(handler);
|
||||||
|
worker.post_message_vec(loaded);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<AGN> Discoverer for Private<AGN>
|
impl<AGN> Discoverer for Private<AGN>
|
||||||
where
|
where
|
||||||
AGN: Agent,
|
AGN: Agent,
|
||||||
|
|||||||
@ -181,22 +181,14 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct WorkerResponder {}
|
/// A trait to enable public agents being registered in a web worker.
|
||||||
|
pub trait PublicAgent {
|
||||||
impl<AGN> Responder<AGN> for WorkerResponder
|
/// Executes an agent in the current environment.
|
||||||
where
|
/// Uses in `main` function of a worker.
|
||||||
AGN: Agent,
|
fn register();
|
||||||
<AGN as Agent>::Input: Serialize + for<'de> Deserialize<'de>,
|
|
||||||
<AGN as Agent>::Output: Serialize + for<'de> Deserialize<'de>,
|
|
||||||
{
|
|
||||||
fn respond(&self, id: HandlerId, output: AGN::Output) {
|
|
||||||
let msg = FromWorker::ProcessOutput(id, output);
|
|
||||||
let data = msg.pack();
|
|
||||||
worker_self().post_message_vec(data);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<AGN> Threaded for AGN
|
impl<AGN> PublicAgent for AGN
|
||||||
where
|
where
|
||||||
AGN: Agent<Reach = Public<AGN>>,
|
AGN: Agent<Reach = Public<AGN>>,
|
||||||
<AGN as Agent>::Input: Serialize + for<'de> Deserialize<'de>,
|
<AGN as Agent>::Input: Serialize + for<'de> Deserialize<'de>,
|
||||||
|
|||||||
@ -36,8 +36,8 @@ The code can be found in the <desc> tag of the svgs.
|
|||||||
When no bridges are connected to this agent, the agent will disappear.
|
When no bridges are connected to this agent, the agent will disappear.
|
||||||
|
|
||||||
* Private - Spawn a new agent in a web worker for every new bridge. This is good for moving shared but
|
* Private - Spawn a new agent in a web worker for every new bridge. This is good for moving shared but
|
||||||
independent behavior that communicates with the browser out of components. \(TODO verify\) When
|
independent behavior that communicates with the browser out of components. When
|
||||||
the task is done, the agent will disappear.
|
the the connected bridge is dropped, the agent will disappear.
|
||||||
|
|
||||||
* Global \(WIP\)
|
* Global \(WIP\)
|
||||||
|
|
||||||
|
|||||||
@ -2,8 +2,21 @@
|
|||||||
title: "From 0.1.0 to 0.2.0"
|
title: "From 0.1.0 to 0.2.0"
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## Removal of `Context` and `Job` Agents
|
||||||
|
|
||||||
The `Context` and `Job` Agents have been removed in favour of Yew's Context API.
|
The `Context` and `Job` Agents have been removed in favour of Yew's Context API.
|
||||||
|
|
||||||
You can see the updated [`pub_sub`](https://github.com/yewstack/yew/tree/master/examples/pub_sub) example about how to use Context API.
|
You can see the updated [`pub_sub`](https://github.com/yewstack/yew/tree/master/examples/pub_sub) example about how to use Context API.
|
||||||
|
|
||||||
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).
|
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).
|
||||||
|
|
||||||
|
## `Threaded` is separated into `PublicAgent` and `PrivateAgent`
|
||||||
|
|
||||||
|
Replace `use yew_agent::Threaded;` with `use yew_agent::PublicAgent;`.
|
||||||
|
|
||||||
|
:::note
|
||||||
|
|
||||||
|
`Threaded` was never implemented for Private Agents.
|
||||||
|
All existing web worker-based agents are Public Agents.
|
||||||
|
|
||||||
|
:::
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user