Skip to content

Commit

Permalink
Simply load all logs and remove navigation
Browse files Browse the repository at this point in the history
I realized the code for navigation was most likely premature optimization which even resulted in worse UX:
Using the buttons to load logs from 5m, 1h, 6h ago sometimes meant that nothing happened at all since there were no logs from 5m, 1h, 6h ago.
That's why I added a time string as "start of logs" so it's at least visible that it changed but that looked bad so I removed it.

But all of this was not necessary: I can simply load all logs at once and then the user can scroll around however they like.

I was worried that it would be bad for performance to load all logs at once since we might store a lot of logs but as mentioned, that's probably premature optimization.

WHEN a lot of logs are stored AND this becomes a problem (What problem even? Slow page load?), THEN we can think about this.

If page load ever becomes slow because of loading logs, we could probably simply not load the logs at page load but only when /wallet/logs is visited.

But for now, this works fine.
  • Loading branch information
ekzyis committed Mar 31, 2024
1 parent cc0f67e commit cb1f1a6
Show file tree
Hide file tree
Showing 2 changed files with 9 additions and 72 deletions.
51 changes: 5 additions & 46 deletions components/logger.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { createContext, useCallback, useContext, useEffect, useMemo, useRef, useState } from 'react'
import { useMe } from './me'
import fancyNames from '@/lib/fancy-names.json'
import { datePivot } from '@/lib/time'

const generateFancyName = () => {
// 100 adjectives * 100 nouns * 10000 = 100M possible names
Expand Down Expand Up @@ -134,6 +133,7 @@ const initIndexedDB = async (storeName) => {

let db
request.onupgradeneeded = () => {
// this only runs if version was changed during open
db = request.result
if (!db.objectStoreNames.contains(storeName)) {
const objectStore = db.createObjectStore(storeName, { autoIncrement: true })
Expand All @@ -159,7 +159,6 @@ const WalletLoggerProvider = ({ children }) => {
const idbStoreName = 'wallet_logs'
const idb = useRef()
const logQueue = useRef([])
const [logStart, setLogStart] = useState(0)

const saveLog = useCallback((log) => {
if (!idb.current) {
Expand All @@ -176,17 +175,11 @@ const WalletLoggerProvider = ({ children }) => {
.then(db => {
idb.current = db

// load logs from IDB
// -- open index sorted by timestamps
// load all logs from IDB
const tx = idb.current.transaction(idbStoreName, 'readonly')
const store = tx.objectStore(idbStoreName)
const index = store.index('ts')
// -- check if there is an open request for past logs else default to last 5m
const sinces = logQueue.current?.filter(q => !!q.since).map(({ since }) => since).sort((a, b) => a - b)
const sinceRounded = sinces?.[0] || +datePivot(new Date(), { minutes: -5 })
const rounded = Math.floor(sinceRounded / 1e3) * 1e3
// -- fetch rows from index
const request = index.getAll(window.IDBKeyRange.lowerBound(rounded))
const request = index.getAll()
request.onsuccess = () => {
const logs = request.result
setLogs((prevLogs) => {
Expand All @@ -202,18 +195,6 @@ const WalletLoggerProvider = ({ children }) => {
})

logQueue.current = []

// get timestamp of first log for pagination
const request2 = index.openCursor()
request2.onsuccess = () => {
const cursor = request2.result
if (cursor) {
const log = cursor.value
if (log) {
setLogStart(log.ts)
}
}
}
})
.catch(console.error)
return () => idb.current?.close()
Expand All @@ -225,35 +206,15 @@ const WalletLoggerProvider = ({ children }) => {
setLogs((prevLogs) => [...prevLogs, log])
}, [setLogs, saveLog])

const loadLogs = useCallback((lower) => {
const upper = logs[0]?.ts || +new Date()

if (!lower || !upper || lower >= upper) return

if (!idb.current) {
// queue loading logs until IDB is ready
return logQueue.current.push({ since: lower })
}

const tx = idb.current.transaction(idbStoreName, 'readonly')
const store = tx.objectStore(idbStoreName)
const index = store.index('ts')
const request = index.getAll(window.IDBKeyRange.bound(lower, upper, false, true))
request.onsuccess = () => {
const logs = request.result
setLogs((prevLogs) => [...logs, ...prevLogs])
}
}, [logs, setLogs])

return (
<WalletLoggerContext.Provider value={{ logs, appendLog, loadLogs, logStart }}>
<WalletLoggerContext.Provider value={{ logs, appendLog }}>
{children}
</WalletLoggerContext.Provider>
)
}

export function useWalletLogger (wallet) {
const { logs, appendLog: _appendLog, loadLogs, logStart } = useContext(WalletLoggerContext)
const { logs, appendLog: _appendLog } = useContext(WalletLoggerContext)

const log = useCallback(level => message => {
// TODO:
Expand All @@ -270,8 +231,6 @@ export function useWalletLogger (wallet) {
}), [log, wallet])

return {
logStart,
loadLogs,
logs: logs.filter(log => !wallet || log.wallet === wallet),
...logger
}
Expand Down
30 changes: 4 additions & 26 deletions pages/wallet/logs.js
Original file line number Diff line number Diff line change
@@ -1,49 +1,27 @@
import { createContext, useEffect } from 'react'
import { createContext } from 'react'
import { CenterLayout } from '@/components/layout'
import LogMessage from '@/components/log-message'
import { useWalletLogger } from '@/components/logger'
import { getGetServerSideProps } from '@/api/ssrApollo'
import Link from 'next/link'
import { useRouter } from 'next/router'
import { datePivot } from '@/lib/time'
import styles from '@/styles/log.module.css'

export const getServerSideProps = getGetServerSideProps({ query: null })

export const WalletLogsContext = createContext()

export default function WalletLogs () {
const { logs, loadLogs, logStart } = useWalletLogger()

const more = logs.length > 0 ? logStart < logs[0].ts : false

const router = useRouter()
// TODO add filter by wallet, add sort by timestamp
const since = router.query.since ? parseInt(router.query.since, 10) : +datePivot(new Date(), { minutes: -5 })
const sinceRounded = Math.floor(since / 60e3) * 60e3
const earlierTs5m = more ? +datePivot(new Date(since), { minutes: -5 }) : logStart
const earlierTs1h = more ? +datePivot(new Date(since), { hours: -1 }) : logStart
const earlierTs6h = more ? +datePivot(new Date(since), { hours: -6 }) : logStart

useEffect(() => {
loadLogs(sinceRounded)
}, [sinceRounded])
const { logs } = useWalletLogger()

// TODO add filter by wallet
return (
<>
<CenterLayout>
<h2 className='text-center'>wallet logs</h2>
<div>
<div className={styles.logNav}>
<span>show earlier logs:</span>
<Link href={`/wallet/logs?since=${earlierTs5m}`} className='mx-1 text-muted text-underline'>5m</Link>
<Link href={`/wallet/logs?since=${earlierTs1h}`} className='mx-1 text-muted text-underline'>1h</Link>
<Link href={`/wallet/logs?since=${earlierTs6h}`} className='mx-1 text-muted text-underline'>6h</Link>
</div>
<div className={styles.logTable}>
<table>
<tbody>
{!more && <tr><td colSpan='4' className='text-center'>------ start of logs ------</td></tr>}
<tr><td colSpan='4' className='text-center'>------ start of logs ------</td></tr>
{logs.map((log, i) => <LogMessage key={i} {...log} />)}
</tbody>
</table>
Expand Down

0 comments on commit cb1f1a6

Please sign in to comment.