simple-web-app

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README

commit f07178234252bb5e961a6306b6419bd2bcb0e0ae
parent d925b61c660e64e8445d519c5ea3fa4ea6e4f044
Author: Silas Brack <silasbrack@gmail.com>
Date:   Sun,  7 Jun 2026 21:55:05 +0200

fix: revert realtime polling, add error logging for API failures

- Remove HTMX polling on comments section (trailbase doesn't
  support table-level subscriptions)
- Add tracing::error! to all silent API failures (votes, tags,
  profile lookups) so errors show in logs instead of being swallowed

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

Diffstat:
Msrc/handlers/comment.rs | 2++
Msrc/handlers/feed.rs | 4+++-
Msrc/handlers/story.rs | 8+++++---
Msrc/handlers/tag.rs | 4+++-
Msrc/handlers/user.rs | 2++
Mtemplates/story.html | 6+-----
6 files changed, 16 insertions(+), 10 deletions(-)

diff --git a/src/handlers/comment.rs b/src/handlers/comment.rs @@ -75,6 +75,7 @@ pub async fn get_comments( let voted_comment_ids = if tokens.is_some() && !comment_ids.is_empty() { trailbase::get_user_votes(&client, trailbase::TARGET_TYPE_COMMENT, &comment_ids) .await + .inspect_err(|e| tracing::error!("Failed to get comment votes: {}", e)) .unwrap_or_default() } else { vec![] @@ -84,6 +85,7 @@ pub async fn get_comments( for comment in comments { let author = trailbase::get_user_profile_by_id(&client, &comment.created_by) .await + .inspect_err(|e| tracing::error!("Failed to get profile for {}: {}", comment.created_by, e)) .ok() .flatten() .map(|p| p.username); diff --git a/src/handlers/feed.rs b/src/handlers/feed.rs @@ -81,6 +81,7 @@ async fn fetch_feed( let voted_ids = if tokens.is_some() { trailbase::get_user_votes(&client, TARGET_TYPE_STORY, &story_ids) .await + .inspect_err(|e| tracing::error!("Failed to get user votes: {}", e)) .unwrap_or_default() } else { vec![] @@ -93,12 +94,13 @@ async fn fetch_feed( for (idx, story) in stories.into_iter().enumerate() { let tags = trailbase::get_categories_for_story(&client, story.id) .await + .inspect_err(|e| tracing::error!("Failed to get tags for story {}: {}", story.id, e)) .unwrap_or_default(); - // Get author username if available let author_username = if let Some(ref created_by) = story.created_by { trailbase::get_user_profile_by_id(&client, created_by) .await + .inspect_err(|e| tracing::error!("Failed to get profile for {}: {}", created_by, e)) .ok() .flatten() .map(|p| p.username) diff --git a/src/handlers/story.rs b/src/handlers/story.rs @@ -36,12 +36,13 @@ pub async fn show_story( // Get tags for the story let tags = trailbase::get_categories_for_story(&client, id) .await + .inspect_err(|e| tracing::error!("Failed to get tags for story {}: {}", id, e)) .unwrap_or_default(); - // Get author username let author_username = if let Some(ref created_by) = story.created_by { trailbase::get_user_profile_by_id(&client, created_by) .await + .inspect_err(|e| tracing::error!("Failed to get profile for {}: {}", created_by, e)) .ok() .flatten() .map(|p| p.username) @@ -49,21 +50,21 @@ pub async fn show_story( None }; - // Check if user voted on the story let story_voted = if tokens.is_some() { trailbase::get_user_votes(&client, TARGET_TYPE_STORY, &[id]) .await + .inspect_err(|e| tracing::error!("Failed to get votes: {}", e)) .map(|v| v.contains(&id)) .unwrap_or(false) } else { false }; - // Check which comments the user voted on let comment_ids: Vec<i64> = comments.iter().map(|c| c.id).collect(); let voted_comment_ids = if tokens.is_some() && !comment_ids.is_empty() { trailbase::get_user_votes(&client, TARGET_TYPE_COMMENT, &comment_ids) .await + .inspect_err(|e| tracing::error!("Failed to get comment votes: {}", e)) .unwrap_or_default() } else { vec![] @@ -78,6 +79,7 @@ pub async fn show_story( for comment in comments { let comment_author = trailbase::get_user_profile_by_id(&client, &comment.created_by) .await + .inspect_err(|e| tracing::error!("Failed to get profile for {}: {}", comment.created_by, e)) .ok() .flatten() .map(|p| p.username); diff --git a/src/handlers/tag.rs b/src/handlers/tag.rs @@ -53,23 +53,25 @@ pub async fn show_tag( let voted_ids = if tokens.is_some() && !story_ids.is_empty() { trailbase::get_user_votes(&client, TARGET_TYPE_STORY, &story_ids) .await + .inspect_err(|e| tracing::error!("Failed to get votes: {}", e)) .unwrap_or_default() } else { vec![] }; - // Enrich stories let mut enriched_stories = Vec::with_capacity(stories.len()); let base_rank = query.page * PAGE_LIMIT; for (idx, story) in stories.into_iter().enumerate() { let tags = trailbase::get_categories_for_story(&client, story.id) .await + .inspect_err(|e| tracing::error!("Failed to get tags for story {}: {}", story.id, e)) .unwrap_or_default(); let author_username = if let Some(ref created_by) = story.created_by { trailbase::get_user_profile_by_id(&client, created_by) .await + .inspect_err(|e| tracing::error!("Failed to get profile for {}: {}", created_by, e)) .ok() .flatten() .map(|p| p.username) diff --git a/src/handlers/user.rs b/src/handlers/user.rs @@ -53,6 +53,7 @@ pub async fn show_user( let voted_ids = if tokens.is_some() && !story_ids.is_empty() { trailbase::get_user_votes(&client, TARGET_TYPE_STORY, &story_ids) .await + .inspect_err(|e| tracing::error!("Failed to get votes: {}", e)) .unwrap_or_default() } else { vec![] @@ -61,6 +62,7 @@ pub async fn show_user( for (idx, story) in stories.into_iter().enumerate() { let tags = trailbase::get_categories_for_story(&client, story.id) .await + .inspect_err(|e| tracing::error!("Failed to get tags for story {}: {}", story.id, e)) .unwrap_or_default(); let time_ago = trailbase::time_ago(&story.published); let user_voted = voted_ids.contains(&story.id); diff --git a/templates/story.html b/templates/story.html @@ -82,11 +82,7 @@ <p class="login-prompt"><a href="/login">Log in</a> to comment.</p> {% endif %} - <section class="comments" - hx-get="/story/{{ story.id }}/comments" - hx-trigger="every 10s" - hx-swap="innerHTML" - > + <section class="comments"> {% include "comments.html" %} </section> </div>