Fix up resend logic to be cleaner

This commit is contained in:
Jack Kingsman
2026-03-13 22:07:16 -07:00
parent 39a687da58
commit b4962d39f0
5 changed files with 32 additions and 25 deletions

View File

@@ -180,7 +180,7 @@ RESEND_WINDOW_SECONDS = 30
async def resend_channel_message(
message_id: int,
new_timestamp: bool = Query(default=False),
) -> dict[str, object]:
) -> ResendChannelMessageResponse:
"""Resend a channel message.
When new_timestamp=False (default): byte-perfect resend using the original timestamp.

View File

@@ -8,6 +8,7 @@ from typing import Any
from fastapi import HTTPException
from meshcore import EventType
from app.models import ResendChannelMessageResponse
from app.region_scope import normalize_region_scope
from app.repository import AppSettingsRepository, ContactRepository, MessageRepository
from app.services.messages import (
@@ -437,7 +438,7 @@ async def resend_channel_message_record(
now_fn: NowFn,
temp_radio_slot: int,
message_repository=MessageRepository,
) -> dict[str, Any]:
) -> ResendChannelMessageResponse:
"""Resend a stored outgoing channel message."""
try:
key_bytes = bytes.fromhex(message.conversation_key)
@@ -530,7 +531,11 @@ async def resend_channel_message_record(
new_message.id,
channel.name,
)
return {"status": "ok", "message_id": new_message.id, "message": new_message}
return ResendChannelMessageResponse(
status="ok",
message_id=new_message.id,
message=new_message,
)
logger.info("Resent channel message %d to %s", message.id, channel.name)
return {"status": "ok", "message_id": message.id}
return ResendChannelMessageResponse(status="ok", message_id=message.id)

View File

@@ -20,6 +20,7 @@ import type {
RadioDiscoveryResponse,
RadioDiscoveryTarget,
PathDiscoveryResponse,
ResendChannelMessageResponse,
RepeaterAclResponse,
RepeaterAdvertIntervalsResponse,
RepeaterLoginResponse,
@@ -34,12 +35,6 @@ import type {
UnreadCounts,
} from './types';
export interface ResendChannelMessageResponse {
status: string;
message_id: number;
message?: Message;
}
const API_BASE = '/api';
async function fetchJson<T>(url: string, options?: RequestInit): Promise<T> {

View File

@@ -247,6 +247,12 @@ export interface MessagesAroundResponse {
has_newer: boolean;
}
export interface ResendChannelMessageResponse {
status: string;
message_id: number;
message?: Message;
}
type ConversationType = 'contact' | 'channel' | 'raw' | 'map' | 'visualizer' | 'search';
export interface Conversation {

View File

@@ -632,8 +632,8 @@ class TestResendChannelMessage:
):
result = await resend_channel_message(msg_id, new_timestamp=False)
assert result["status"] == "ok"
assert result["message_id"] == msg_id
assert result.status == "ok"
assert result.message_id == msg_id
# Verify radio was called with correct timestamp bytes
mc.commands.send_chan_msg.assert_awaited_once()
@@ -731,7 +731,7 @@ class TestResendChannelMessage:
):
result = await resend_channel_message(msg_id, new_timestamp=False)
assert result["status"] == "ok"
assert result.status == "ok"
mock_broadcast_error.assert_called_once()
assert "restore failed" in mock_broadcast_error.call_args.args[0].lower()
@@ -762,15 +762,16 @@ class TestResendChannelMessage:
mock_time.time.return_value = float(now)
result = await resend_channel_message(msg_id, new_timestamp=True)
assert result["status"] == "ok"
assert result["message_id"] != msg_id
resent = await MessageRepository.get_by_id(result["message_id"])
assert result.status == "ok"
assert result.message_id != msg_id
resent = await MessageRepository.get_by_id(result.message_id)
assert resent is not None
assert result["message"].id == resent.id
assert result["message"].conversation_key == resent.conversation_key
assert result["message"].text == resent.text
assert result["message"].sender_timestamp == resent.sender_timestamp
assert result["message"].outgoing is True
assert result.message is not None
assert result.message.id == resent.id
assert result.message.conversation_key == resent.conversation_key
assert result.message.text == resent.text
assert result.message.sender_timestamp == resent.sender_timestamp
assert result.message.outgoing is True
assert resent.sender_timestamp == now + 1
assert resent.received_at == now
sent_timestamp = int.from_bytes(
@@ -896,9 +897,9 @@ class TestResendChannelMessage:
):
result = await resend_channel_message(msg_id, new_timestamp=True)
assert result["status"] == "ok"
assert result.status == "ok"
# Should return a NEW message id, not the original
assert result["message_id"] != msg_id
assert result.message_id != msg_id
@pytest.mark.asyncio
async def test_resend_new_timestamp_creates_new_message(self, test_db):
@@ -925,7 +926,7 @@ class TestResendChannelMessage:
):
result = await resend_channel_message(msg_id, new_timestamp=True)
new_msg_id = result["message_id"]
new_msg_id = result.message_id
new_msg = await MessageRepository.get_by_id(new_msg_id)
original_msg = await MessageRepository.get_by_id(msg_id)
@@ -963,7 +964,7 @@ class TestResendChannelMessage:
mock_broadcast.assert_called_once()
event_type, event_data = mock_broadcast.call_args.args
assert event_type == "message"
assert event_data["id"] == result["message_id"]
assert event_data["id"] == result.message_id
assert event_data["outgoing"] is True
assert event_data["channel_name"] == "#broadcast"