Skip to content

Commit 6595e8c

Browse files
committed
Remove intermediary vecs/btreemaps for ordering on index
1 parent 3430b7c commit 6595e8c

File tree

3 files changed

+48
-27
lines changed

3 files changed

+48
-27
lines changed

Cargo.lock

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/methods/index.rs

+39-18
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
1-
use std::{collections::BTreeMap, sync::Arc};
1+
use std::{cell::RefCell, sync::Arc};
22

33
use anyhow::Context;
44
use askama::Template;
5-
use axum::{response::IntoResponse, Extension};
5+
use axum::{
6+
response::{IntoResponse, Response},
7+
Extension,
8+
};
9+
use itertools::{Either, Itertools};
610

711
use super::filters;
812
use crate::{
@@ -12,28 +16,45 @@ use crate::{
1216

1317
#[derive(Template)]
1418
#[template(path = "index.html")]
15-
pub struct View {
16-
pub repositories: BTreeMap<Option<String>, Vec<YokedRepository>>,
19+
pub struct View<
20+
'a,
21+
Group: Iterator<Item = (&'a String, &'a YokedRepository)>,
22+
GroupIter: Iterator<Item = (&'a str, Group)>,
23+
> {
24+
// this type sig is a necessary evil unfortunately, because askama takes a reference
25+
// to the data for rendering.
26+
pub repositories: RefCell<Either<GroupIter, std::iter::Empty<(&'a str, Group)>>>,
27+
}
28+
29+
impl<'a, Group, GroupIter> View<'a, Group, GroupIter>
30+
where
31+
Group: Iterator<Item = (&'a String, &'a YokedRepository)>,
32+
GroupIter: Iterator<Item = (&'a str, Group)>,
33+
{
34+
fn take_iter(&self) -> Either<GroupIter, std::iter::Empty<(&'a str, Group)>> {
35+
self.repositories.replace(Either::Right(std::iter::empty()))
36+
}
1737
}
1838

1939
pub async fn handle(
2040
Extension(db): Extension<Arc<rocksdb::DB>>,
21-
) -> Result<impl IntoResponse, super::repo::Error> {
22-
let mut repositories: BTreeMap<Option<String>, Vec<YokedRepository>> = BTreeMap::new();
23-
41+
) -> Result<Response, super::repo::Error> {
2442
let fetched = tokio::task::spawn_blocking(move || Repository::fetch_all(&db))
2543
.await
2644
.context("Failed to join Tokio task")??;
2745

28-
for (k, v) in fetched {
29-
// TODO: fixme
30-
let mut split: Vec<_> = k.split('/').collect();
31-
split.pop();
32-
let key = Some(split.join("/")).filter(|v| !v.is_empty());
33-
34-
let k = repositories.entry(key).or_default();
35-
k.push(v);
36-
}
37-
38-
Ok(into_response(View { repositories }))
46+
// rocksdb returned the keys already ordered for us so group_by is a nice
47+
// operation we can use here to avoid writing into a map to group. though,
48+
// now that i think about it it might act a little bit strangely when mixing
49+
// root repositories and nested repositories. we're going to have to prefix
50+
// root repositories with a null byte or something. i'll just leave this here
51+
// as a TODO.
52+
let repositories = fetched
53+
.iter()
54+
.group_by(|(k, _)| memchr::memrchr(b'/', k.as_bytes()).map_or("", |idx| &k[..idx]));
55+
56+
Ok(into_response(View {
57+
repositories: Either::Left(repositories.into_iter()).into(),
58+
})
59+
.into_response())
3960
}

templates/index.html

+8-8
Original file line numberDiff line numberDiff line change
@@ -13,21 +13,21 @@
1313
</thead>
1414

1515
<tbody>
16-
{%- for (path, repositories) in repositories %}
17-
{%- if let Some(path) = path %}
16+
{%- for (path, repositories) in self.take_iter() %}
17+
{%- if !path.is_empty() %}
1818
<tr><td class="repo-section" colspan="4">{{ path }}</td></tr>
1919
{%- endif -%}
2020

2121
{%- for repository in repositories %}
22-
{% set repository = repository.get() %}
23-
<tr class="{% if path.is_some() %}has-parent{% endif %}">
22+
{% set repository = repository.1.get() %}
23+
<tr class="{% if !path.is_empty() %}has-parent{% endif %}">
2424
<td>
25-
<a href="/{% if let Some(path) = path %}{{ path }}/{% endif %}{{ repository.name }}">
25+
<a href="/{% if !path.is_empty() %}{{ path }}/{% endif %}{{ repository.name }}">
2626
{{- repository.name -}}
2727
</a>
2828
</td>
2929
<td>
30-
<a href="/{% if let Some(path) = path %}{{ path }}/{% endif %}{{ repository.name }}">
30+
<a href="/{% if !path.is_empty() %}{{ path }}/{% endif %}{{ repository.name }}">
3131
{%- if let Some(description) = repository.description.as_ref() -%}
3232
{{- description -}}
3333
{%- else -%}
@@ -36,14 +36,14 @@
3636
</a>
3737
</td>
3838
<td>
39-
<a href="/{% if let Some(path) = path %}{{ path }}/{% endif %}{{ repository.name }}">
39+
<a href="/{% if !path.is_empty() %}{{ path }}/{% endif %}{{ repository.name }}">
4040
{%- if let Some(owner) = repository.owner.as_ref() -%}
4141
{{- owner -}}
4242
{%- endif -%}
4343
</a>
4444
</td>
4545
<td>
46-
<a href="/{% if let Some(path) = path %}{{ path }}/{% endif %}{{ repository.name }}">
46+
<a href="/{% if !path.is_empty() %}{{ path }}/{% endif %}{{ repository.name }}">
4747
<time datetime="{{ repository.last_modified|format_time }}" title="{{ repository.last_modified|format_time }}">
4848
{{- repository.last_modified|timeago -}}
4949
</time>

0 commit comments

Comments
 (0)