atproto blogging
1//! Host-side management for the embed worker.
2//!
3//! Provides `EmbedWorkerHost` for spawning and communicating with the embed
4//! worker from the main thread. This centralizes worker lifecycle management
5//! so consuming code just needs to provide a callback for results.
6
7use crate::{EmbedWorkerInput, EmbedWorkerOutput};
8use gloo_worker::{Spawnable, WorkerBridge};
9
10/// Host-side manager for the embed worker.
11///
12/// Handles spawning the worker and sending messages. The callback provided
13/// at construction receives all worker outputs.
14///
15/// # Example
16///
17/// ```ignore
18/// let host = EmbedWorkerHost::spawn("/embed_worker.js", |output| {
19/// match output {
20/// EmbedWorkerOutput::Embeds { results, errors, fetch_ms } => {
21/// // Handle fetched embeds
22/// }
23/// EmbedWorkerOutput::CacheCleared => {}
24/// }
25/// });
26///
27/// host.fetch_embeds(vec!["at://did:plc:xxx/app.bsky.feed.post/yyy".into()]);
28/// ```
29pub struct EmbedWorkerHost {
30 bridge: WorkerBridge<crate::EmbedWorker>,
31}
32
33impl EmbedWorkerHost {
34 /// Spawn the embed worker with a callback for outputs.
35 ///
36 /// The `worker_url` should point to the compiled worker JS file,
37 /// typically "/embed_worker.js".
38 pub fn spawn(worker_url: &str, on_output: impl Fn(EmbedWorkerOutput) + 'static) -> Self {
39 let bridge = crate::EmbedWorker::spawner()
40 .callback(on_output)
41 .spawn(worker_url);
42 Self { bridge }
43 }
44
45 /// Request embeds for a list of AT URIs.
46 ///
47 /// The worker will check its cache first, then fetch any missing embeds.
48 /// Results arrive via the callback provided at construction.
49 pub fn fetch_embeds(&self, uris: Vec<String>) {
50 if uris.is_empty() {
51 return;
52 }
53 self.bridge.send(EmbedWorkerInput::FetchEmbeds { uris });
54 }
55
56 /// Clear the worker's embed cache.
57 pub fn clear_cache(&self) {
58 self.bridge.send(EmbedWorkerInput::ClearCache);
59 }
60}