Skip to content

Commit 3f0c35a

Browse files
committed
Check in demo site and update CI, also indexing changes
1 parent eac5771 commit 3f0c35a

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

68 files changed

+11430
-311
lines changed

.github/workflows/continuous_deployment.yml

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,20 +7,14 @@ jobs:
77
release:
88
runs-on: ubuntu-latest
99
steps:
10-
- uses: actions-rs/toolchain@v1
11-
with:
12-
toolchain: stable
13-
target: wasm32-unknown-unknown
14-
15-
- uses: jetli/[email protected]
16-
- uses: jetli/[email protected]
17-
1810
- uses: actions/checkout@v2
1911

20-
- run: cd parser_demo && trunk build --release
12+
- uses: actions/setup-node@v3
13+
14+
- run: cd airmail_site && yarn install && yarn build
2115

2216
- uses: peaceiris/actions-gh-pages@v3
2317
if: github.ref == 'refs/heads/main'
2418
with:
2519
github_token: ${{ secrets.GITHUB_TOKEN }}
26-
publish_dir: ./parser_demo/dist
20+
publish_dir: ./airmail_site/dist

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,11 @@ Airmail's killer feature is sub-100MB memory consumption for a serving instance.
1515
- [x] Index OpenAddresses data.
1616
- [ ] Index WhosOnFirst data.
1717
- [x] API server.
18+
- [ ] Support and test planet-scale indices.
1819
- [ ] Extend query parser for other locales.
1920
- [ ] Categorical search, e.g. "coffee shops near me".
2021
- [ ] Bounding box biasing and restriction.
21-
- [ ] Investigate feasibility of executing queries against remote indices via HTTP range requests.
22+
- [ ] Minutely updates.
2223
- [ ] Systematic/automatic quality testing in CI.
2324
- [ ] Alternate results, e.g. returning Starbucks locations for "Dunkin Donuts" queries on the US west coast.[^2]
2425

airmail_index/Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,8 @@ rand = "0.8.5"
3030
subprocess = "0.2.9"
3131
rustyline = "13.0.0"
3232
turbosm = { path = "../turbosm" }
33-
redb = "1.5.0"
33+
num_cpus = "1.16.0"
34+
lru = "0.12.2"
3435

3536
[[bin]]
3637
name = "query"

airmail_index/src/main.rs

Lines changed: 34 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -39,22 +39,22 @@ pub async fn populate_admin_areas(poi: &mut AirmailPoi, port: usize) -> Result<(
3939
.locality
4040
.unwrap_or_default()
4141
.iter()
42-
.map(|a| a.name.to_lowercase())
42+
.map(|a| a.to_lowercase())
4343
.collect();
4444
if let Some(neighbourhood) = pip_response.neighbourhood {
45-
locality.extend(neighbourhood.iter().map(|a| a.name.to_lowercase()));
45+
locality.extend(neighbourhood.iter().map(|a| a.to_lowercase()));
4646
}
4747
let region = pip_response
4848
.region
4949
.unwrap_or_default()
5050
.iter()
51-
.map(|a| a.name.to_lowercase())
51+
.map(|a| a.to_lowercase())
5252
.collect();
5353
let country = pip_response
5454
.country
5555
.unwrap_or_default()
5656
.iter()
57-
.map(|a| a.name.to_lowercase())
57+
.map(|a| a.to_lowercase())
5858
.collect();
5959

6060
poi.locality = locality;
@@ -69,7 +69,7 @@ struct Args {
6969
/// Path to the Docker socket.
7070
#[clap(long, short)]
7171
docker_socket: Option<String>,
72-
/// Path to the Who's On First SQLite database.
72+
/// Path to the Who's On First Spatialite database.
7373
#[clap(long, short)]
7474
wof_db: String,
7575
/// Whether to forcefully recreate the container. Default false.
@@ -96,7 +96,7 @@ enum ContainerStatus {
9696
DoesNotExist,
9797
}
9898

99-
const PIP_SERVICE_IMAGE: &str = "docker.io/pelias/pip-service:latest";
99+
const PIP_SERVICE_IMAGE: &str = "docker.io/pelias/spatial:latest";
100100

101101
async fn docker_connect() -> Result<Docker, Box<dyn std::error::Error>> {
102102
let docker = if let Some(docker_socket) = &Args::parse().docker_socket {
@@ -134,10 +134,11 @@ async fn get_container_status(
134134

135135
async fn maybe_start_pip_container(
136136
wof_db_path: &str,
137-
idx: usize,
138137
recreate: bool,
139138
docker: &Docker,
140139
) -> Result<(), Box<dyn std::error::Error>> {
140+
// Holdover from when we had multiple containers.
141+
let idx = 0;
141142
let container_state = get_container_status(idx, docker).await?;
142143
if container_state == ContainerStatus::Running && !recreate {
143144
println!(
@@ -154,23 +155,26 @@ async fn maybe_start_pip_container(
154155
env: Some(vec![]),
155156
host_config: Some(HostConfig {
156157
port_bindings: Some(HashMap::from([(
157-
3102.to_string(),
158+
3000.to_string(),
158159
Some(vec![bollard::models::PortBinding {
159160
host_ip: None,
160161
host_port: Some(format!("{}", 3102 + idx)),
161162
}]),
162163
)])),
163164
mounts: Some(vec![bollard::models::Mount {
164165
source: Some(wof_db_path.to_string()),
165-
target: Some(
166-
"/mnt/pelias/whosonfirst/sqlite/whosonfirst-data-mapped.db".to_string(),
167-
),
166+
target: Some("/mnt/whosonfirst/whosonfirst-spatialite.db".to_string()),
168167
typ: Some(MountTypeEnum::BIND),
169168
..Default::default()
170169
}]),
171170
..Default::default()
172171
}),
173-
exposed_ports: Some(HashMap::from([("3102/tcp", HashMap::new())])),
172+
cmd: Some(vec![
173+
"server",
174+
"--db",
175+
"/mnt/whosonfirst/whosonfirst-spatialite.db",
176+
]),
177+
exposed_ports: Some(HashMap::from([("3000/tcp", HashMap::new())])),
174178
..Default::default()
175179
};
176180

@@ -244,23 +248,21 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
244248
let args = Args::parse();
245249
let index_path = args.index.clone();
246250
let docker = docker_connect().await?;
247-
let max_pip = 8;
248-
for i in 0..max_pip {
249-
let _ = subprocess::Exec::cmd("chcon")
250-
.arg("-t")
251-
.arg("container_file_t")
252-
.arg(&args.wof_db)
253-
.join();
254-
maybe_start_pip_container(&args.wof_db, i, args.recreate, &docker).await?;
255-
}
251+
let _ = subprocess::Exec::cmd("chcon")
252+
.arg("-t")
253+
.arg("container_file_t")
254+
.arg(&args.wof_db)
255+
.join();
256+
maybe_start_pip_container(&args.wof_db, args.recreate, &docker).await?;
256257

257258
if let Some(turbosm_path) = args.turbosm {
258259
let mut nonblocking_join_handles = Vec::new();
259260
let (no_admin_sender, no_admin_receiver): (Sender<AirmailPoi>, Receiver<AirmailPoi>) =
260-
crossbeam::channel::bounded(1024);
261+
crossbeam::channel::bounded(1024 * 64);
261262
let (to_index_sender, to_index_receiver): (Sender<AirmailPoi>, Receiver<AirmailPoi>) =
262-
crossbeam::channel::bounded(1024);
263-
for _ in 0..128 {
263+
crossbeam::channel::bounded(1024 * 64);
264+
265+
for _ in 0..1.max(num_cpus::get() / 2) {
264266
let no_admin_receiver = no_admin_receiver.clone();
265267
let to_index_sender = to_index_sender.clone();
266268
nonblocking_join_handles.push(spawn(async move {
@@ -271,8 +273,12 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
271273
break;
272274
};
273275
let mut sent = false;
274-
for _attempt in 0..5 {
275-
let port = (rand::random::<usize>() % max_pip) + 3102;
276+
for attempt in 0..5 {
277+
if attempt > 0 {
278+
println!("Retrying to populate admin areas.");
279+
tokio::time::sleep(std::time::Duration::from_millis(10)).await;
280+
}
281+
let port = 3102;
276282
if let Err(err) = populate_admin_areas(&mut poi, port).await {
277283
println!("Failed to populate admin areas. {}", err);
278284
} else {
@@ -351,7 +357,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
351357
crossbeam::channel::bounded(1024);
352358
let mut blocking_join_handles = Vec::new();
353359
let mut nonblocking_join_handles = Vec::new();
354-
for _ in 0..16 {
360+
for _ in 0..64 {
355361
let receiver = raw_receiver.clone();
356362
let no_admin_sender = no_admin_sender.clone();
357363
let count = count.clone();
@@ -402,7 +408,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
402408
};
403409
let mut sent = false;
404410
for _attempt in 0..5 {
405-
let port = (rand::random::<usize>() % max_pip) + 3102;
411+
let port = 3102;
406412
if let Err(err) = populate_admin_areas(&mut poi, port).await {
407413
println!("Failed to populate admin areas. {}", err);
408414
} else {

airmail_index/src/openstreetmap.rs

Lines changed: 20 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use std::collections::HashMap;
1+
use std::{collections::HashMap, error::Error};
22

33
use airmail::poi::AirmailPoi;
44
use airmail_common::categories::{
@@ -79,15 +79,7 @@ fn tags_to_poi(tags: &HashMap<String, String>, lat: f64, lng: f64) -> Option<Air
7979
unit,
8080
lat,
8181
lng,
82-
tags.iter()
83-
.filter_map(|(k, v)| {
84-
if k.starts_with("addr:") || v.len() > 1024 {
85-
None
86-
} else {
87-
Some((k.to_string(), v.to_string()))
88-
}
89-
})
90-
.collect(),
82+
vec![],
9183
)
9284
.unwrap(),
9385
)
@@ -118,11 +110,15 @@ fn index_way(tags: &HashMap<String, String>, way: &Way) -> Option<AirmailPoi> {
118110
tags_to_poi(&tags, lat, lng)
119111
}
120112

121-
fn relation_centroid(relation: &Relation, level: u32) -> Option<(f64, f64)> {
113+
fn relation_centroid(
114+
relation: &Relation,
115+
level: u32,
116+
turbosm: &Turbosm,
117+
) -> Result<(f64, f64), Box<dyn Error>> {
122118
let mut points = Vec::new();
123119
if level > 3 {
124120
debug!("Skipping relation with level > 10: {:?}", relation.id());
125-
return None;
121+
return Err("Skipping relation with level > 10".into());
126122
}
127123
for member in relation.members() {
128124
match member {
@@ -134,8 +130,9 @@ fn relation_centroid(relation: &Relation, level: u32) -> Option<(f64, f64)> {
134130
points.push(Point::new(centroid.0, centroid.1));
135131
}
136132
}
137-
RelationMember::Relation(_, relation) => {
138-
if let Some(centroid) = relation_centroid(&relation, level + 1) {
133+
RelationMember::Relation(_, other_relation) => {
134+
let other_relation = turbosm.relation(*other_relation)?;
135+
if let Ok(centroid) = relation_centroid(&other_relation, level + 1, turbosm) {
139136
points.push(Point::new(centroid.0, centroid.1));
140137
} else {
141138
debug!("Skipping relation with no centroid: {:?}", relation.id());
@@ -144,35 +141,36 @@ fn relation_centroid(relation: &Relation, level: u32) -> Option<(f64, f64)> {
144141
}
145142
}
146143
let multipoint = MultiPoint::from(points);
147-
let centroid = multipoint.centroid()?;
148-
Some((centroid.x(), centroid.y()))
144+
let centroid = multipoint.centroid().ok_or("No centroid")?;
145+
Ok((centroid.x(), centroid.y()))
149146
}
150147

151148
pub fn parse_osm<CB: Sync + Fn(AirmailPoi) -> Result<(), Box<dyn std::error::Error>>>(
152149
db_path: &str,
153150
callback: &CB,
154151
) -> Result<(), Box<dyn std::error::Error>> {
155-
let mut osm = Turbosm::open(db_path).unwrap();
152+
let mut osm =
153+
Turbosm::open(db_path, &["natural", "highway", "admin_level", "boundary"]).unwrap();
156154
println!("Processing nodes");
157-
osm.process_all_nodes(|node| {
155+
osm.process_all_nodes(|node, _| {
158156
if let Some(poi) = tags_to_poi(node.tags(), node.lat(), node.lng()) {
159157
if let Err(err) = callback(poi) {
160158
warn!("Error from callback: {}", err);
161159
}
162160
}
163161
})?;
164162
println!("Processing ways");
165-
osm.process_all_ways(|way| {
163+
osm.process_all_ways(|way, _| {
166164
index_way(way.tags(), &way).map(|poi| {
167165
if let Err(err) = callback(poi) {
168166
warn!("Error from callback: {}", err);
169167
}
170168
});
171169
})?;
172170
println!("Processing relations");
173-
osm.process_all_relations(|relation| {
174-
let centroid = relation_centroid(&relation, 0);
175-
if let Some(centroid) = centroid {
171+
osm.process_all_relations(|relation, turbosm| {
172+
let centroid = relation_centroid(&relation, 0, turbosm);
173+
if let Ok(centroid) = centroid {
176174
if let Some(poi) = tags_to_poi(relation.tags(), centroid.1, centroid.0) {
177175
if let Err(err) = callback(poi) {
178176
warn!("Error from callback: {}", err);

0 commit comments

Comments
 (0)