Skip to content

Commit

Permalink
[GUI/CORE] Better log spam resistance
Browse files Browse the repository at this point in the history
  • Loading branch information
Bwc9876 committed Jul 28, 2023
1 parent 53c7f28 commit 398bb96
Show file tree
Hide file tree
Showing 13 changed files with 219 additions and 141 deletions.
12 changes: 8 additions & 4 deletions owmods_core/src/socket.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use anyhow::{anyhow, Result};
use log::{error, info};
use log::{error, info, warn};
use serde::{Deserialize, Serialize};
use serde_repr::{Deserialize_repr, Serialize_repr};
use tokio::{
Expand Down Expand Up @@ -105,9 +105,13 @@ impl LogServer {

// Give a log to the tx channel
async fn yield_log(tx: &LogServerSender, message: SocketMessage) {
let res = tx.send(message).await;
if let Err(why) = res {
error!("Couldn't Yield Log: {why:?}")
if tx.capacity() == 0 {
warn!("Logs incoming too fast! Logs may be dropped!");
} else {
let res = tx.send(message).await;
if let Err(why) = res {
error!("Couldn't Yield Log: {why:?}")
}
}
}

Expand Down
22 changes: 20 additions & 2 deletions owmods_gui/backend/src/commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,10 @@ use tauri::{api::dialog, async_runtime, AppHandle, Manager, WindowEvent};
use time::{macros::format_description, OffsetDateTime};
use tokio::{sync::mpsc, try_join};

use crate::events::{CustomEventEmitter, CustomEventEmitterAll, CustomEventTriggerGlobal, Event};
use crate::events::{
CustomEventEmitter, CustomEventEmitterAll, CustomEventTriggerGlobal, Event,
LogLineCountUpdatePayload,
};
use crate::progress::ProgressBar;
use crate::protocol::{ProtocolInstallType, ProtocolPayload};
use crate::{
Expand Down Expand Up @@ -721,6 +724,21 @@ pub async fn run_game(
let window_handle = window.app_handle();
let mut game_log = state.game_log.write().await;
if let Some((lines, writer)) = game_log.get_mut(&port) {
if let Some(last_message) = lines.last_mut() {
if msg == last_message.message {
last_message.amount += 1;
let res = window_handle.typed_emit_all(&Event::LogLineCountUpdate(
LogLineCountUpdatePayload {
port,
line: (lines.len() - 1).try_into().unwrap_or(u32::MAX),
},
));
if let Err(why) = res {
error!("Couldn't Emit Game Log: {}", why)
}
continue;
}
}
let res = write_log(writer, &msg);
if let Err(why) = res {
error!("Couldn't Write Game Log: {}", why);
Expand Down Expand Up @@ -773,7 +791,7 @@ pub async fn get_log_lines(
filter_type: Option<SocketMessageType>,
search: &str,
state: tauri::State<'_, State>,
) -> Result<Vec<(usize, usize)>> {
) -> Result<Vec<usize>> {
let logs = state.game_log.read().await;
if let Some((lines, _)) = logs.get(&port) {
let lines = get_logs_indices(lines, filter_type, search)?;
Expand Down
9 changes: 9 additions & 0 deletions owmods_gui/backend/src/events.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,14 @@ fn map_emit_err(e: tauri::Error) -> anyhow::Error {
#[typeshare]
pub type EmptyParams = ();

// Typeshare doesn't allow tuples, I cry
#[typeshare]
#[derive(Deserialize, Serialize, Clone)]
pub struct LogLineCountUpdatePayload {
pub port: LogPort,
pub line: u32,
}

#[typeshare]
#[derive(Deserialize, Serialize, Clone)]
#[serde(tag = "name", content = "params", rename_all = "camelCase")]
Expand All @@ -26,6 +34,7 @@ pub enum Event {
OwmlConfigReload(EmptyParams),
GameStart(LogPort),
LogUpdate(LogPort),
LogLineCountUpdate(LogLineCountUpdatePayload),
LogFatal(GameMessage),
ProtocolInvoke(ProtocolPayload),
ProgressUpdate(EmptyParams),
Expand Down
56 changes: 23 additions & 33 deletions owmods_gui/backend/src/game.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,16 @@ use crate::LogPort;
pub struct GameMessage {
pub port: LogPort,
pub message: SocketMessage,
pub amount: u32,
}

impl GameMessage {
pub fn new(port: LogPort, message: SocketMessage) -> Self {
Self { port, message }
Self {
port,
message,
amount: 1,
}
}
}

Expand Down Expand Up @@ -79,43 +84,28 @@ pub fn get_logs_indices(
lines: &[GameMessage],
filter_type: Option<SocketMessageType>,
search: &str,
) -> Result<Vec<(usize, usize)>> {
) -> Result<Vec<usize>> {
let mut indices = Vec::with_capacity(lines.len());
let search = search.to_ascii_lowercase();
let mut count = 1;
for (line_number, line) in lines.iter().enumerate() {
let mut same = false;
if let Some(next_line) = lines.get(line_number + 1) {
if next_line.message.message == line.message.message
&& next_line.message.message_type == line.message.message_type
&& next_line.message.sender_name == line.message.sender_name
{
same = true;
let mut include = true;
if filter_type.is_some() || !search.trim().is_empty() {
let matches_type = filter_type.is_none()
|| line.message.message_type == *filter_type.as_ref().unwrap();
let matches_search = search.is_empty()
|| line.message.message.to_ascii_lowercase().contains(&search)
|| line
.message
.sender_name
.as_ref()
.map(|v| v.to_ascii_lowercase().contains(&search))
.unwrap_or(false);
if !(matches_type && matches_search) {
include = false;
}
}
if same {
count += 1;
} else {
let mut include = true;
if filter_type.is_some() || !search.trim().is_empty() {
let matches_type = filter_type.is_none()
|| line.message.message_type == *filter_type.as_ref().unwrap();
let matches_search = search.is_empty()
|| line.message.message.to_ascii_lowercase().contains(&search)
|| line
.message
.sender_name
.as_ref()
.map(|v| v.to_ascii_lowercase().contains(&search))
.unwrap_or(false);
if !(matches_type && matches_search) {
include = false;
}
}
if include {
indices.push((line_number, count));
}
count = 1;
if include {
indices.push(line_number);
}
}
Ok(indices)
Expand Down
12 changes: 8 additions & 4 deletions owmods_gui/frontend/src/commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ const commandInfo = {
filterType?: number | undefined;
search: string;
},
[number, number][]
number[]
>
>("get_log_lines"),
exportMods: $<ActionCommand<{ path: string }>>("export_mods"),
Expand Down Expand Up @@ -111,9 +111,12 @@ const makeInvoke = (key: Command, forceNoDisplayErr?: boolean) => {

const makeHook = (key: Command) => {
const name = commandInfo[key];
return (eventName: Event["name"] | Event["name"][], payload?: (typeof name)[0]) => {
return <E extends Event["name"]>(
eventName: E | Event["name"][],
payload?: (typeof name)[0]
) => {
const fn = makeInvoke(key, true);
return useTauri<(typeof name)[1]>(
return useTauri<(typeof name)[1], E>(
eventName,
() => fn(payload ?? {}) as unknown as Promise<(typeof name)[1]>,
payload
Expand All @@ -131,7 +134,8 @@ export type Commands = {
export type Hooks = {
[T in Command]: (
eventName: Event["name"] | Event["name"][],
payload?: (typeof commandInfo)[T][0]
payload?: (typeof commandInfo)[T][0],
shouldChangeFn?: (params: unknown) => boolean
) => [LoadState, (typeof commandInfo)[T][1] | null, Error | null];
};

Expand Down
2 changes: 1 addition & 1 deletion owmods_gui/frontend/src/components/logs/LogApp.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import { listen } from "@events";
import { simpleOnError } from "@components/common/StyledErrorBoundary";

export type LogFilter = keyof typeof SocketMessageType | "Any";
export type LogLines = [number, number][];
export type LogLines = number[];

const thisWindow = getCurrent();

Expand Down
27 changes: 19 additions & 8 deletions owmods_gui/frontend/src/components/logs/LogRow.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
import { hooks } from "@commands";
import ODTooltip from "@components/common/ODTooltip";
import { Box, Chip, Palette, Skeleton, TableCell, Typography, useTheme } from "@mui/material";
import { SocketMessageType } from "@types";
import { LogLineCountUpdatePayload, SocketMessageType } from "@types";
import { Fragment, MutableRefObject, memo, useLayoutEffect, useMemo } from "react";
import { VirtuosoHandle } from "react-virtuoso";

export interface LogRowProps {
port: number;
index: number;
count: number;
virtuosoRef?: MutableRefObject<VirtuosoHandle | null>;
}

Expand All @@ -33,10 +32,16 @@ const getColor = (palette: Palette, messageType: SocketMessageType) => {
const LogRow = memo(function LogRow(props: LogRowProps) {
const theme = useTheme();

const [status, logLine] = hooks.getLogLine("none", {
port: props.port,
line: props.index
});
const [status, logLine] = hooks.getLogLine(
"logLineCountUpdate",
{
port: props.port,
line: props.index
},
(params) => {
return (params as LogLineCountUpdatePayload).line === props.index;
}
);

const messageType = useMemo(() => {
return Object.values(SocketMessageType)[
Expand All @@ -59,6 +64,8 @@ const LogRow = memo(function LogRow(props: LogRowProps) {
props.virtuosoRef?.current?.autoscrollToBottom?.();
}, [status, props.virtuosoRef]);

console.debug(logLine?.amount ?? 1);

return (
<>
<TableCell sx={cellStyle}>
Expand Down Expand Up @@ -95,9 +102,13 @@ const LogRow = memo(function LogRow(props: LogRowProps) {
</Typography>
)}{" "}
</Box>
{props.count > 1 && (
{(logLine?.amount ?? 1) > 1 && (
<Box justifySelf="end">
<Chip size="small" label={`x${props.count}`} />
<Chip
color={logLine?.amount === 65535 ? "error" : "default"}
size="small"
label={`x${logLine?.amount}`}
/>
</Box>
)}
</Box>
Expand Down
4 changes: 2 additions & 2 deletions owmods_gui/frontend/src/components/logs/LogTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ const LogTable = memo(function LogTable(props: LogTableProps) {
<TableVirtuoso
ref={virtuoso}
components={LogTableComponents}
computeItemKey={(index) => `${index}-${props.logLines[index][0]}`}
computeItemKey={(index) => `${index}-${props.logLines[index]}`}
increaseViewportBy={500}
atBottomThreshold={1000}
data={props.logLines}
Expand All @@ -60,7 +60,7 @@ const LogTable = memo(function LogTable(props: LogTableProps) {
</TableRow>
)}
itemContent={(_, data) => (
<LogRow port={props.port} index={data[0]} count={data[1]} virtuosoRef={virtuoso} />
<LogRow port={props.port} index={data} virtuosoRef={virtuoso} />
)}
followOutput
alignToBottom
Expand Down
2 changes: 1 addition & 1 deletion owmods_gui/frontend/src/events.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { simpleOnError } from "@components/common/StyledErrorBoundary";
import { listen as tauriListen, emit as tauriEmit } from "@tauri-apps/api/event";
import { Event } from "@types";

type Params<E extends Event["name"]> = Extract<Event, { name: E }>["params"];
export type Params<E extends Event["name"]> = Extract<Event, { name: E }>["params"];

type EventSubscriptions = {
[E in Event["name"]]: Array<(params: Params<E>) => void>;
Expand Down
14 changes: 9 additions & 5 deletions owmods_gui/frontend/src/hooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,18 @@ import {
} from "@components/common/TranslationContext";
import { Event, FailedMod, LocalMod, RemoteMod, UnsafeLocalMod } from "@types";
import { useErrorBoundary } from "react-error-boundary";
import { listen } from "@events";
import { Params, listen } from "@events";

export type LoadState = "Loading" | "Done";

/**
* Use @commands:hooks if possible
*/
export const useTauri = <T>(
export const useTauri = <T, E extends Event["name"]>(
eventName: Event["name"] | Event["name"][],
commandFn: () => Promise<T>,
payload: unknown
payload: unknown,
shouldChangeFn?: (params: Params<E>) => boolean
): [LoadState, T | null] => {
const [status, setStatus] = useState<LoadState>("Loading");
const [data, setData] = useState<T | null>(null);
Expand All @@ -27,7 +28,10 @@ export const useTauri = <T>(
useEffect(() => {
if (status !== "Loading") {
for (const eventToSubscribe of events) {
listen(eventToSubscribe, () => setStatus("Loading"));
listen(eventToSubscribe, (params) => {
if (shouldChangeFn && !shouldChangeFn(params)) return;
setStatus("Loading");
});
}
} else {
commandFn()
Expand All @@ -40,7 +44,7 @@ export const useTauri = <T>(
})
.finally(() => setStatus("Done"));
}
}, [commandFn, errorBound, events, status]);
}, [commandFn, shouldChangeFn, errorBound, events, status]);

useEffect(() => {
if (status === "Done") {
Expand Down
Loading

0 comments on commit 398bb96

Please sign in to comment.