Skip to content
This repository has been archived by the owner on Mar 9, 2023. It is now read-only.

Gloo Workers v2 #214

Merged
merged 10 commits into from
Jun 19, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions osm2lanes-web/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
name = "osm2lanes-web"
version = "0.1.0"
description = "Website for osm2lanes"
readme = true
repository = "https://github.com/a-b-street/osm2lanes"
license = "Apache 2.0"
keywords = ["osm", "lanes", "web"]
Expand All @@ -15,9 +14,9 @@ edition = "2021"

[dependencies]
console_log = { version = "0.2", optional = true, features = ["color"] }
console_error_panic_hook = "0.1"
geo = { version = "0.20" }
gloo-utils = "0.1"
gloo-timers = "0.2"
leaflet = { git = "https://github.com/droogmic/leaflet-rs", branch = "polyline_get_bounds" }
log = "0.4"
osm-tags = { path = "../osm-tags" }
Expand All @@ -28,10 +27,11 @@ serde = { version = "1", features = ["derive"] }
serde_json = "1"
syntect = { version = "5.0", default-features = false, features = [
"default-fancy",
] } # TODO: https://github.com/trishume/syntect/issues/135#issuecomment-700306068, webwroker + create json bundle
] } # TODO: https://github.com/trishume/syntect/issues/135#issuecomment-700306068, webworker + create json bundle
wasm-bindgen = "0.2"
wee_alloc = { version = "0.4", optional = true }
yew = "0.19"
gloo-worker = { git = "https://github.com/futursolo/gloo", rev = "a2101e166260294292c8121fdb8ed883dae62ed8" }

[dependencies.web-sys]
version = "0.3"
Expand Down
6 changes: 5 additions & 1 deletion osm2lanes-web/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,12 @@
integrity="sha512-BB3hKbKWOc9Ez/TAwyWxNXeoV9c1v6FIeYiBieIWkpLjauysF18NzgR1MBNBXf8/KABdlkX68nAhlwcDFLGPCQ=="
crossorigin></script>
<link rel="stylesheet" href="//unpkg.com/leaflet-gesture-handling/dist/leaflet-gesture-handling.min.css"
type="text/css" />
type="text/css">
<script src="https://unpkg.com/leaflet-gesture-handling"></script>

<!-- Web Workers -->
<link data-trunk rel="rust" href="Cargo.toml" data-bin="app" data-type="main" />
<link data-trunk rel="rust" href="Cargo.toml" data-bin="worker" data-type="worker" />
</head>

</html>
56 changes: 56 additions & 0 deletions osm2lanes-web/src/agent.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
use gloo_worker::{Codec, HandlerId, Worker, WorkerScope};
use osm2lanes::test::{get_tests, TestCase};
use serde::{Deserialize, Serialize};
use wasm_bindgen::JsValue;

pub struct JsonCodec;

impl Codec for JsonCodec {
fn encode<I>(input: I) -> JsValue
where
I: Serialize,
{
let data = serde_json::to_string(&input).expect("can't serialize worker message");
log::trace!("message in: {data}");
JsValue::from_str(&data)
}

fn decode<O>(input: JsValue) -> O
where
O: for<'de> Deserialize<'de>,
{
let data = input.as_string().expect("JsValue string");
log::trace!("message out: {data}");
serde_json::from_str(&data).expect("can't deserialize worker message")
}
}

pub(crate) const NAME: &str = "worker.js";

pub struct ExampleLoader;

#[derive(Serialize, Deserialize)]
pub struct ExampleLoaderOutput(pub Vec<TestCase>);

impl Worker for ExampleLoader {
type Message = ();
type Input = ();
type Output = ExampleLoaderOutput;

fn create(_scope: &WorkerScope<Self>) -> Self {
Self
}

fn update(&mut self, _scope: &WorkerScope<Self>, _msg: Self::Message) {
// no messaging
}

fn received(&mut self, scope: &WorkerScope<Self>, _msg: Self::Input, id: HandlerId) {
let tests = get_tests();
let examples = tests
.into_iter()
.filter(|t| t.example().is_some())
.collect();
scope.respond(id, ExampleLoaderOutput(examples));
}
}
8 changes: 8 additions & 0 deletions osm2lanes-web/src/bin/app.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
use osm2lanes_web::App;

fn main() {
console_error_panic_hook::set_once();
console_log::init_with_level(log::Level::Debug).expect("logging failed");
log::trace!("Initializing yew...");
yew::start_app::<App>();
}
11 changes: 11 additions & 0 deletions osm2lanes-web/src/bin/worker.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
use gloo_worker::Registrable;
use osm2lanes_web::agent::{ExampleLoader, JsonCodec};

fn main() {
console_error_panic_hook::set_once();
console_log::init_with_level(log::Level::Debug).expect("logging failed");
log::trace!("Initializing worker...");
ExampleLoader::registrar()
.encoding::<JsonCodec>()
.register();
}
48 changes: 29 additions & 19 deletions osm2lanes-web/src/control.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,21 @@ use std::cell::RefCell;
use std::collections::BTreeMap;
use std::rc::Rc;

use gloo_timers::callback::Timeout;
use gloo_worker::{WorkerBridge, WorkerSpawner};
use osm2lanes::locale::{Country, DrivingSide, Locale};
use osm2lanes::test::{get_tests, TestCase};
use osm2lanes::test::TestCase;
use web_sys::{Event, FocusEvent, HtmlInputElement, HtmlSelectElement, KeyboardEvent, MouseEvent};
use yew::{html, Callback, Component, Context, Html, NodeRef, Properties, TargetCast};

use crate::agent::{ExampleLoader, ExampleLoaderOutput, JsonCodec, NAME};
use crate::{Msg as AppMsg, State};

pub(crate) enum Msg {
/// Pass the message to the parent
Up(Box<AppMsg>),
FirstLazy,
/// Worker's response with examples
WorkerMsg(ExampleLoaderOutput),
/// Select example given name
Example(String),
}

Expand All @@ -28,8 +32,8 @@ pub(crate) struct Props {
pub(crate) state: Rc<RefCell<State>>,
}

#[derive(Default)]
pub(crate) struct Control {
_worker: WorkerBridge<ExampleLoader>,
textarea_input_ref: NodeRef,
textarea_output_ref: NodeRef,
example: Option<String>,
Expand All @@ -40,16 +44,32 @@ impl Component for Control {
type Properties = Props;
type Message = Msg;

fn create(_ctx: &Context<Self>) -> Self {
Self::default()
fn create(ctx: &Context<Self>) -> Self {
let link = ctx.link().clone();
let cb = move |output| link.send_message(Self::Message::WorkerMsg(output));
let worker = WorkerSpawner::<ExampleLoader>::new()
.encoding::<JsonCodec>()
.callback(cb)
.spawn(NAME);

// Trigger worker
worker.send(());

Self {
_worker: worker,
textarea_input_ref: NodeRef::default(),
textarea_output_ref: NodeRef::default(),
example: Option::default(),
examples: Option::default(),
}
}

fn update(&mut self, ctx: &Context<Self>, msg: Self::Message) -> bool {
match msg {
Msg::Up(msg) => ctx.props().callback_msg.emit(*msg),
Msg::FirstLazy => {
let tests = get_tests();
let examples: BTreeMap<_, _> = tests
Msg::WorkerMsg(examples) => {
let examples: BTreeMap<String, TestCase> = examples
.0
.into_iter()
.filter_map(|t| {
let example_name = t.example().map(std::borrow::ToOwned::to_owned);
Expand Down Expand Up @@ -256,14 +276,4 @@ impl Component for Control {
</>
}
}

fn rendered(&mut self, ctx: &Context<Self>, first_render: bool) {
if first_render {
let handle = {
let link = ctx.link().clone();
Timeout::new(1, move || link.send_message(Msg::FirstLazy))
};
handle.forget();
}
}
}
10 changes: 3 additions & 7 deletions osm2lanes-web/src/main.rs → osm2lanes-web/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
#![warn(unreachable_pub)]
#![deny(unsafe_code)]
#![deny(unsafe_op_in_unsafe_fn)]
#![warn(unused_crate_dependencies)]
// #![warn(unused_crate_dependencies)] // https://github.com/rust-lang/rust/issues/57274
#![warn(unused_lifetimes)]
#![warn(unused_qualifications)]
// Clippy
Expand Down Expand Up @@ -57,6 +57,8 @@ use syntect::parsing::SyntaxSet;
use web_sys::HtmlInputElement;
use yew::prelude::*;

pub mod agent;

mod control;
use control::Control;

Expand Down Expand Up @@ -361,9 +363,3 @@ impl App {
}
}
}

fn main() {
console_log::init_with_level(log::Level::Debug).expect("logging failed");
log::trace!("Initializing yew...");
yew::start_app::<App>();
}
2 changes: 1 addition & 1 deletion osm2lanes/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
#![warn(unreachable_pub)]
#![deny(unsafe_code)]
#![deny(unsafe_op_in_unsafe_fn)]
// #![warn(unused_crate_dependencies)] // TODO: report upstream
// #![warn(unused_crate_dependencies)] // https://github.com/rust-lang/rust/issues/57274
#![warn(unused_lifetimes)]
#![warn(unused_qualifications)]
// Clippy
Expand Down
31 changes: 28 additions & 3 deletions osm2lanes/src/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use crate::locale::DrivingSide;
use crate::road::{Lane, Road};

#[derive(Clone)]
#[cfg_attr(feature = "serde", derive(serde::Deserialize))]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "serde", serde(untagged, deny_unknown_fields))]
pub enum RustTesting {
Enabled(bool),
Expand All @@ -16,7 +16,7 @@ pub enum RustTesting {
}

#[derive(Clone)]
#[cfg_attr(feature = "serde", derive(serde::Deserialize))]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "serde", serde(rename_all = "snake_case"))]
pub enum Expected {
Road(Road),
Expand All @@ -26,7 +26,7 @@ pub enum Expected {

#[allow(clippy::module_name_repetitions)]
#[derive(Clone)]
#[cfg_attr(feature = "serde", derive(serde::Deserialize))]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct TestCase {
// Metadata
/// The OSM way unique identifier
Expand Down Expand Up @@ -478,6 +478,31 @@ mod tests {
});
}

#[test]
fn test_json() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was motivated by tracking down where the serde flattening bug was happening, right?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah, if you replace this with bincode, the test fails :)

env_logger_init();
let tests = get_tests();
for test in &tests {
serde_json::to_string(&test.tags).expect("can't serialize tags");
match &test.expected {
Expected::Road(expected_road) => {
serde_json::to_string(&expected_road.lanes)
.expect("can't serialize expected road lanes");
serde_json::to_string(&expected_road.highway)
.expect("can't serialize expected road highway");
serde_json::to_string(&expected_road).expect("can't serialize expected road");
},
Expected::Output(expected_output) => {
serde_json::to_string(expected_output)
.expect("can't serialize expected output");
},
}
serde_json::to_string(&test.expected).expect("can't serialize expected");
serde_json::to_string(&test).expect("can't serialize test case");
}
serde_json::to_string(&tests).expect("can't serialize test cases");
}

#[test]
fn test_from_data() {
env_logger_init();
Expand Down