Skip to content

Instantly share code, notes, and snippets.

View jjn1056's full-sized avatar

John Napiorkowski jjn1056

View GitHub Profile
@jjn1056
jjn1056 / question.txt
Created August 26, 2026 20:33
Using Future::OP with _DefaultImpl or not?
Hit this working on an async redis client - a pubsub message handler
disconnects two connections, which cancels both their in-flight reads,
and with the default impl that dies:
Can't call method "fh" on an undefined value at Future/IO.pm line 890
Best I can tell the poll loop caches $npollers and then completes ready
futures inside the loop, so when a continuation cancels other pending
reads, on_cancel splices them out of @pollers behind the loop's back and
the index runs off the end.
@jjn1056
jjn1056 / gist:aede08e810778190fdc9059409bc7f04
Last active August 26, 2026 20:08
FAA COW issue details

Folded string constants corrupted across await on threaded perls — full detail

Summary

Inside an async sub, a loop that (a) assigns from a constant-folded string literal at or above perl's SV_COWBUF_THRESHOLD (1250 bytes) (e.g. my $p = 'x' x 20_000; — folded at compile time) and (b) genuinely suspends via await, produces undef from a later assignment onward (deterministically the third, in every minimal shape tested; a larger real program failed from

Future::IO 0.23 — cancelling a pending read from inside another read's continuation walks off the end of @pollers

Module: Future::IO 0.23 (current CPAN release), default impl (Future::IO::_DefaultImpl) Symptom: Can't call method "fh" on an undefined value at Future/IO.pm line 890. Not affected: Future::IO::Impl::IOAsync 0.805

The issue

_DefaultImpl's poll loop caches the poller count before iterating, then completes ready futures inside that loop. Completing a future runs its continuation synchronously, and if

Middleware in PAGI

A port of the sample app from What Is Middleware? — which builds the same three-layer stack in Plack/PSGI (Perl) and Starlette/ASGI (Python) — to PAGI, an async, ASGI-style application interface for Perl.

The app is deliberately tiny but exercises the three things middleware exists to do:

  1. Logger — wrap the request, time it, log method/path in and status/duration out.
  2. Authenticator — inspect a header, inject context for downstream layers on
#!/usr/bin/env perl
# future-io-cancel-bug.pl
#
# Demonstrates a bug in Future::IO::Impl::IOAsync where cancelling a future
# that's waiting on a socket read doesn't properly clean up internal state.
#
# This is SELF-CONTAINED - no Redis or external server required.
#
# Run with different backends:
# perl future-io-cancel-bug.pl # defaults to IOAsync
@jjn1056
jjn1056 / perl.pm
Last active July 11, 2025 20:11
another form builder model example
Sketch to see if we can just use AUTOLOAD to inject into the
display object methods as needed ad hoc
# in this approach you have some named methods like $args
# and other methods use AUTOLOAD, defautl behavior is to call
# resolve_method_for_proxy($method) or if that doesn't exist
# dfaults to $obj->method.
# if you pass args to an AUTOLOADED method, that sets that
# method to have that value.
use Future::AsyncAwait;
# Define an ASGI-like application as an anonymous async sub.
# This app checks the request scope and sends a response.
my $asgi_app = async sub ($scope, $receive, $send) {
if ($scope->{type} eq 'http') {
# Send the response start message.
await $send->({
type => "http.response.start",
#!/usr/bin/env perl
use strictures;
use PSGI::Syntax; #(signatures, etc. for example code)
use Future::AsyncAwait;
use Future;
### Basic ASGI App Implementation
async sub app($scope, $receive, $send) {
if ($scope->{type} eq 'http') {
import asyncio
# A simple logging middleware
class LoggingMiddleware:
def __init__(self, app):
self.app = app
async def __call__(self, scope, receive, send):
# Only handle HTTP requests for this example.
if scope["type"] == "http":
package MyApp::Model::Components::Counter;
use Moose;
extends 'CatalystX::Components:::DisplayModel';
has count => (is=>'rw', required=>1, default=>0, live=>1); #lifecycle=>'request|session'
sub increment($self) {
my $current = $self->count;
$self->count($current++);