Compare commits

...

8 Commits

Author SHA1 Message Date
f6d5d3755b chore: Release
All checks were successful
Continuous integration / Check (push) Successful in 38s
Continuous integration / Test Suite (push) Successful in 46s
Continuous integration / Trunk (push) Successful in 38s
Continuous integration / Rustfmt (push) Successful in 36s
Continuous integration / build (push) Successful in 52s
Continuous integration / Disallow unused dependencies (push) Successful in 2m8s
2025-04-22 21:24:53 -07:00
5226fe090e server & web: run label_unprocessed before notifying web client 2025-04-22 21:22:50 -07:00
c10ad00ca7 chore: Release
All checks were successful
Continuous integration / Check (push) Successful in 38s
Continuous integration / Trunk (push) Successful in 38s
Continuous integration / Test Suite (push) Successful in 1m18s
Continuous integration / Rustfmt (push) Successful in 32s
Continuous integration / Disallow unused dependencies (push) Successful in 56s
Continuous integration / build (push) Successful in 1m39s
2025-04-22 17:52:04 -07:00
64fc92c3d6 web: refresh including the server side on websocket reconnect 2025-04-22 17:51:53 -07:00
b9c116d5b6 server: mark spam as read 2025-04-22 17:51:53 -07:00
007200b37b fix(deps): update rust crate xtracing to v0.3.2
All checks were successful
Continuous integration / Check (push) Successful in 37s
Continuous integration / Test Suite (push) Successful in 44s
Continuous integration / Trunk (push) Successful in 37s
Continuous integration / Rustfmt (push) Successful in 39s
Continuous integration / build (push) Successful in 51s
Continuous integration / Disallow unused dependencies (push) Successful in 2m7s
2025-04-22 23:01:17 +00:00
9824ad1e18 chore(deps): lock file maintenance
All checks were successful
Continuous integration / Test Suite (push) Successful in 45s
Continuous integration / Check (push) Successful in 46s
Continuous integration / Trunk (push) Successful in 37s
Continuous integration / Rustfmt (push) Successful in 38s
Continuous integration / build (push) Successful in 51s
Continuous integration / Disallow unused dependencies (push) Successful in 2m7s
2025-04-22 15:16:24 +00:00
a8819c7551 gitea: use nightly when doing trunk build
All checks were successful
Continuous integration / Test Suite (push) Successful in 44s
Continuous integration / Check (push) Successful in 1m23s
Continuous integration / Rustfmt (push) Successful in 37s
Continuous integration / Trunk (push) Successful in 3m47s
Continuous integration / Disallow unused dependencies (push) Successful in 55s
Continuous integration / build (push) Successful in 3m45s
2025-04-22 08:13:38 -07:00
6 changed files with 75 additions and 56 deletions

View File

@@ -26,7 +26,7 @@ jobs:
- uses: actions/checkout@v4
- uses: actions-rust-lang/setup-rust-toolchain@v1
with:
toolchain: stable
toolchain: nightly
target: wasm32-unknown-unknown
- run: cargo install trunk
- run: cd web; trunk build

76
Cargo.lock generated
View File

@@ -3018,37 +3018,23 @@ dependencies = [
"spin",
]
[[package]]
name = "letterbox-notmuch"
version = "0.16.0"
source = "sparse+https://git.z.xinu.tv/api/packages/wathiede/cargo/"
checksum = "f7cdd2798042f4cc63342d798f450e7152231f4f592b3142cd63a0a9f4b879d8"
dependencies = [
"log",
"mailparse",
"serde",
"serde_json",
"thiserror 2.0.12",
"tracing",
]
[[package]]
name = "letterbox-notmuch"
version = "0.17.2"
source = "sparse+https://git.z.xinu.tv/api/packages/wathiede/cargo/"
checksum = "e68cf6f69a34d9dca43cf99a850eb4eaa81632057da58541c002ba58d4026e99"
dependencies = [
"log",
"mailparse",
"serde",
"serde_json",
"thiserror 2.0.12",
"tracing",
]
[[package]]
name = "letterbox-notmuch"
version = "0.17.3"
source = "sparse+https://git.z.xinu.tv/api/packages/wathiede/cargo/"
checksum = "660e35d98139603d764aba884faea20b6ebd43864afd8a70ee0864d161cb7089"
dependencies = [
"log",
"mailparse",
"serde",
"serde_json",
"thiserror 2.0.12",
"tracing",
]
[[package]]
name = "letterbox-notmuch"
version = "0.17.5"
dependencies = [
"itertools",
"log",
@@ -3063,12 +3049,12 @@ dependencies = [
[[package]]
name = "letterbox-procmail2notmuch"
version = "0.17.3"
version = "0.17.5"
dependencies = [
"anyhow",
"clap",
"letterbox-notmuch 0.17.2",
"letterbox-shared 0.17.2",
"letterbox-notmuch 0.17.3",
"letterbox-shared 0.17.3",
"serde",
"sqlx",
"tokio 1.44.2",
@@ -3076,7 +3062,7 @@ dependencies = [
[[package]]
name = "letterbox-server"
version = "0.17.3"
version = "0.17.5"
dependencies = [
"ammonia",
"anyhow",
@@ -3094,8 +3080,8 @@ dependencies = [
"futures 0.3.31",
"headers",
"html-escape",
"letterbox-notmuch 0.17.2",
"letterbox-shared 0.17.2",
"letterbox-notmuch 0.17.3",
"letterbox-shared 0.17.3",
"linkify",
"log",
"lol_html",
@@ -3120,12 +3106,12 @@ dependencies = [
[[package]]
name = "letterbox-shared"
version = "0.17.2"
version = "0.17.3"
source = "sparse+https://git.z.xinu.tv/api/packages/wathiede/cargo/"
checksum = "0e1a634b8bbfa38f847cda9d10142c41fba727c0efef1e159de6f60c157de8de"
checksum = "e30cefa3eebb0b15b077527072a4a53dbde8dd6cb513b20e78f036a84c86329a"
dependencies = [
"build-info",
"letterbox-notmuch 0.16.0",
"letterbox-notmuch 0.17.3",
"regex",
"serde",
"sqlx",
@@ -3135,10 +3121,10 @@ dependencies = [
[[package]]
name = "letterbox-shared"
version = "0.17.3"
version = "0.17.5"
dependencies = [
"build-info",
"letterbox-notmuch 0.17.2",
"letterbox-notmuch 0.17.3",
"regex",
"serde",
"sqlx",
@@ -3148,7 +3134,7 @@ dependencies = [
[[package]]
name = "letterbox-web"
version = "0.17.3"
version = "0.17.5"
dependencies = [
"build-info",
"build-info-build",
@@ -3160,8 +3146,8 @@ dependencies = [
"graphql_client",
"human_format",
"itertools",
"letterbox-notmuch 0.17.2",
"letterbox-shared 0.17.2",
"letterbox-notmuch 0.17.3",
"letterbox-shared 0.17.3",
"log",
"seed",
"seed_hooks",
@@ -7299,7 +7285,7 @@ version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb"
dependencies = [
"windows-sys 0.59.0",
"windows-sys 0.48.0",
]
[[package]]
@@ -7647,9 +7633,9 @@ checksum = "a62ce76d9b56901b19a74f19431b0d8b3bc7ca4ad685a746dfd78ca8f4fc6bda"
[[package]]
name = "xtracing"
version = "0.3.1"
version = "0.3.2"
source = "sparse+https://git.z.xinu.tv/api/packages/wathiede/cargo/"
checksum = "bb7fe734574f346e72c8ed2d8d6d8f35b7d65ecc289ead1fa4ffcfcdee003d09"
checksum = "ef54d77517715b6cd50871e60000909c2e78bacd9a6131c2794cfad3d76abe13"
dependencies = [
"chrono",
"console-subscriber",

View File

@@ -8,7 +8,7 @@ authors = ["Bill Thiede <git@xinu.tv>"]
edition = "2021"
license = "UNLICENSED"
publish = ["xinu"]
version = "0.17.3"
version = "0.17.5"
repository = "https://git.z.xinu.tv/wathiede/letterbox"
[profile.dev]

View File

@@ -50,7 +50,7 @@ url = "2.5.4"
urlencoding = "2.1.3"
#xtracing = { git = "http://git-private.h.xinu.tv/wathiede/xtracing.git" }
#xtracing = { path = "../../xtracing" }
xtracing = { version = "0.3.1", registry = "xinu" }
xtracing = { version = "0.3.2", registry = "xinu" }
[build-dependencies]
build-info-build = "0.0.40"

View File

@@ -21,7 +21,7 @@ use letterbox_notmuch::Notmuch;
use letterbox_server::tantivy::TantivyConnection;
use letterbox_server::{
graphql::{compute_catchup_ids, Attachment, MutationRoot, QueryRoot, SubscriptionRoot},
nm::{attachment_bytes, cid_attachment_bytes},
nm::{attachment_bytes, cid_attachment_bytes, label_unprocessed},
ws::ConnectionTracker,
};
use letterbox_shared::WebsocketMessage;
@@ -29,7 +29,7 @@ use serde::Deserialize;
use sqlx::postgres::PgPool;
use tokio::{net::TcpListener, sync::Mutex};
use tower_http::trace::{DefaultMakeSpan, TraceLayer};
use tracing::info;
use tracing::{error, info};
// Make our own error that wraps `ServerError`.
struct AppError(letterbox_server::ServerError);
@@ -176,11 +176,15 @@ async fn start_ws(
#[derive(Debug, Deserialize)]
struct NotificationParams {
delay_ms: Option<u64>,
num_unprocessed: Option<usize>,
}
async fn send_refresh_websocket_handler(
State(AppState {
connection_tracker, ..
nm,
pool,
connection_tracker,
..
}): State<AppState>,
params: Query<NotificationParams>,
) -> impl IntoResponse {
@@ -190,6 +194,15 @@ async fn send_refresh_websocket_handler(
info!("sleeping {delay:?}");
tokio::time::sleep(delay).await;
}
let limit = match params.num_unprocessed {
Some(0) => None,
Some(limit) => Some(limit),
None => Some(10),
};
if let Err(err) = label_unprocessed(&nm, &pool, false, limit, "tag:unprocessed").await {
error!("Failed to label_unprocessed: {err:?}");
};
connection_tracker
.lock()
.await
@@ -204,18 +217,33 @@ async fn watch_new(
conn_tracker: Arc<Mutex<ConnectionTracker>>,
poll_time: Duration,
) -> Result<(), async_graphql::Error> {
let mut old_ids = Vec::new();
loop {
async fn watch_new_iteration(
nm: &Notmuch,
pool: &PgPool,
conn_tracker: Arc<Mutex<ConnectionTracker>>,
old_ids: &[String],
) -> Result<Vec<String>, async_graphql::Error> {
let ids = compute_catchup_ids(&nm, &pool, "is:unread").await?;
info!("old_ids: {} ids: {}", old_ids.len(), ids.len());
if old_ids != ids {
info!("old_ids: {old_ids:?}\n ids: {ids:?}");
label_unprocessed(&nm, &pool, false, Some(100), "tag:unprocessed").await?;
conn_tracker
.lock()
.await
.send_message_all(WebsocketMessage::RefreshMessages)
.await
}
old_ids = ids;
Ok(ids)
}
let mut old_ids = Vec::new();
loop {
old_ids = match watch_new_iteration(&nm, &pool, conn_tracker.clone(), &old_ids).await {
Ok(old_ids) => old_ids,
Err(err) => {
error!("watch_new_iteration failed: {err:?}");
continue;
}
};
tokio::time::sleep(poll_time).await;
}
}
@@ -223,6 +251,7 @@ async fn watch_new(
#[derive(Clone)]
struct AppState {
nm: Notmuch,
pool: PgPool,
connection_tracker: Arc<Mutex<ConnectionTracker>>,
}
@@ -263,7 +292,7 @@ async fn main() -> Result<(), Box<dyn Error>> {
let connection_tracker = Arc::new(Mutex::new(ConnectionTracker::default()));
let ct = Arc::clone(&connection_tracker);
let poll_time = Duration::from_secs(60);
let _h = tokio::spawn(watch_new(nm.clone(), pool, ct, poll_time));
let _h = tokio::spawn(watch_new(nm.clone(), pool.clone(), ct, poll_time));
let api_routes = Router::new()
.route(
@@ -288,6 +317,7 @@ async fn main() -> Result<(), Box<dyn Error>> {
.nest("/notification", notification_routes)
.with_state(AppState {
nm,
pool,
connection_tracker,
})
.layer(

View File

@@ -1005,6 +1005,9 @@ pub async fn label_unprocessed(
for t in &add_tags {
nm.tag_add(t, &id)?;
}
if add_tags.contains("spam") || add_tags.contains("Spam") {
nm.tag_remove("unread", &id)?;
}
if !add_tags.contains("inbox") {
nm.tag_remove("inbox", &id)?;
}