Forum teuk.org

πŸ›‘οΈ *Protego Cursonem!* β€” Karma PM Context and DB Cursor Hardening

in Mediabot Β· started by TeuK Β· 4w ago

TeuK Β· 4w ago

This Mediabot v3 pass was a focused cleanup round after a broader debug session.

The main theme was simple:

make karma helpers behave correctly in private messages
close DB cursors cleanly
avoid undef statement-handle crashes

No schema change.


🧭 The root pattern: karma helpers in PM

Several karma-related commands were using _karma_log{$channel}.

That is correct in a public channel:

#boulets
#phat
#quebec

But in private messages, the IRC framework does not provide a real channel context. Depending on the path, $channel may be the caller nick or not a #channel at all.

That means code like this silently returns empty data:

$self->{_karma_log}{$channel}

because _karma_log is indexed by channel names, not by nicknames.

So commands that should have worked in PM reported empty results even when karma activity existed on real channels.


πŸ“Œ karmainfo fixed in private messages

!karmainfo <nick> in PM could previously say there was no karma activity, even for an active nick.

The fix is now context-aware:

public channel -> inspect only this channel
private message -> aggregate known _karma_log entries across all channels

It also replies to the right target:

channel command -> reply to the channel
private command -> reply to the nick

This makes PM usage useful instead of misleading.


πŸ“ˆ karmgraph protected in private messages

A karma graph/sparkline is channel-contextual.

In PM, the command does not have a meaningful channel width or channel-specific activity context.

So !karmgraph now refuses cleanly in PM:

!karmgraph requires a channel context. Use it in a channel.

That is better than reading the wrong key or showing nonsense.


πŸ” karmadiff fixed in private messages

!karmadiff <nick> had the same context problem.

In PM it looked at the wrong _karma_log key, found nothing, and reported no changes.

Now it aggregates across known channels when no public channel context exists.

It also guards missing delta values so old or partial in-memory entries do not trigger Perl warnings.


πŸ•˜ karmahist fixed in private messages

!karmahist <nick> in PM could report history for the caller nickname as if it were a channel.

Now it behaves more sensibly:

public channel -> use that channel
private message -> aggregate in-memory karma history across channels

The database-backed path remains preferred when available, and the in-memory fallback is used when the PM context does not map to a real channel.


🧹 Lexical scope regression fixed

One intermediate patch introduced a strict-mode compile error:

Global symbol "$klog" requires explicit package name

The cause was a variable declared inside an if block and then reused outside that block.

That was fixed by collecting entries into a properly scoped array before later filtering.

Simple bug, but exactly the sort of thing perl -c catches before runtime.


🧯 DB cursor leak fixed in checkResponder

checkResponder() had a frequent cursor leak.

When a responder matched, it returned immediately:

return $iChance;

before closing the statement handle.

Since checkResponder() can run on public messages, this is not a theoretical leak. Over time, it can leave DBI cursors open and cause trouble on long-running instances.

The fix closes the cursor before returning the matched chance.

The final fallback path was also hardened:

$sth->finish if $sth;

so a failed prepare() does not lead to undef->finish.


🧱 mbDbModCommand cursor and execute guards

mbDbModCommand() had early returns inside a block where the main statement handle needed to be closed.

Those returns now close the cursor before leaving.

The update query was also hardened from:

$sth_upd->execute(...)

to the safer pattern:

$sth_upd && $sth_upd->execute(...)

and its statement handle is closed when execution fails.

This matches the broader DB hardening direction in Mediabot v3:

prepare may fail
execute may fail
finish what was opened
return cleanly
do not crash dispatchers on undef statement handles

βœ… Audit results

The debug pass also confirmed several suspected issues were false positives.

Examples:

trivia PM scope is coherent
remindsnooze has row guards
karmawatch case handling is consistent
Claude history/persona keys are aligned
timer random quote finishes its cursor
poll voter access remains Master-level
displayUrlTitle eval scope is correct

The important recurring issue was narrowed down to _karma_log{$channel} in PM contexts.

That pattern is now handled explicitly in the affected karma commands.


Validation

Minimum validation for this pass:

perl -I. -c Mediabot/UserCommands.pm
perl -I. -c Mediabot/DBCommands.pm
perl -c mediabot.pl

A broader sanity check remains recommended after this kind of cleanup:

perl -c mediabot.pl
find Mediabot -name '*.pm' -print -exec perl -I. -c {} \;

Result

This pass improves long-running reliability and command correctness:

karmainfo works in PM
karmadiff works in PM
karmahist works in PM
karmgraph refuses PM cleanly
karma delta warnings are guarded
lexical scope regression fixed
checkResponder cursor leak fixed
mbDbModCommand early-return cursor leaks fixed
update execute guards improved

No schema change.


Spell of the day

Protego Cursonem!

The karma logs now know the difference between a channel and a private message.

And the database cursors have been politely escorted to the exit.

Mischief closed. πŸ§™β€β™‚οΈπŸ›‘οΈ

You must be logged in to reply.