Async-Redis
view release on metacpan or search on metacpan
examples/pagi-chat/public/css/style.css view on Meta::CPAN
.btn-secondary:hover {
background: var(--border-color);
}
.btn-icon {
width: 32px;
height: 32px;
padding: 0;
border: none;
border-radius: 6px;
background: transparent;
color: var(--text-secondary);
cursor: pointer;
font-size: 1.2rem;
transition: all 0.2s;
}
.btn-icon:hover {
background: var(--bg-tertiary);
color: var(--text-primary);
}
examples/pagi-chat/public/css/style.css view on Meta::CPAN
align-self: center;
background: var(--message-system-bg);
font-size: 0.85rem;
color: var(--text-secondary);
padding: 0.5rem 1rem;
max-width: 90%;
}
.message.action {
align-self: center;
background: transparent;
font-style: italic;
color: var(--text-secondary);
}
.message.pm {
border-left: 3px solid var(--accent-color);
}
.message-header {
display: flex;
lib/Async/Redis.pm view on Meta::CPAN
$pipe->run_script('atomic_incr', 'counter:b', 1);
$pipe->set('other:key', 'value');
my $results = await $pipe->execute;
Scripts are automatically preloaded before pipeline execution.
=head2 EVALSHA Optimization
Scripts automatically use EVALSHA (by SHA1 hash) for efficiency.
If the script isn't cached on the server, it falls back to EVAL
and caches for future calls. This is transparent to your code.
=head2 scan_iter
my $iter = $redis->scan_iter(match => 'user:*', count => 100);
while (my $keys = await $iter->next) {
for my $key (@$keys) { ... }
}
Create an iterator for SCAN. Also available:
lib/Async/Redis/AutoPipeline.pm view on Meta::CPAN
1;
__END__
=head1 NAME
Async::Redis::AutoPipeline - Automatic command batching
=head1 DESCRIPTION
AutoPipeline transparently batches Redis commands issued in the same
event loop tick into a single pipeline, reducing network round-trips
without changing the caller's API.
=head2 How It Works
# These three commands are batched automatically
my $f1 = $redis->set('a', 1);
my $f2 = $redis->set('b', 2);
my $f3 = $redis->get('a');
lib/Async/Redis/Script.pm view on Meta::CPAN
my $redis = $script->redis;
Returns the default Redis connection associated with the script, if any.
=head1 EVALSHA OPTIMIZATION
Scripts automatically use EVALSHA for efficiency. If the script isn't
cached on the Redis server (NOSCRIPT error), it falls back to EVAL
which also loads the script for future calls.
This is transparent - you don't need to manually load scripts.
=head1 SEE ALSO
L<Async::Redis> - Main client with C<script()> and C<define_command()> methods
=cut
lib/Async/Redis/Subscription.pm view on Meta::CPAN
channel => 'channel_name',
pattern => 'pattern', # defined for pmessage, undef otherwise
data => 'payload',
}
The C<pattern> key is always present. It is defined for C<pmessage>
frames (the matching glob pattern) and C<undef> for C<message> and
C<smessage> frames. Consumers do not need C<exists $msg-E<gt>{pattern}>
checks.
C<next()> always returns real pub/sub messages. Reconnection is transparent.
=head1 RECONNECTION
When C<reconnect> is enabled on the Redis connection, subscriptions are
automatically re-established after a connection drop. To be notified:
$sub->on_reconnect(sub {
my ($sub) = @_;
warn "Reconnected, may have lost messages";
# re-poll state, log, etc.
t/30-pipeline/auto-pipeline.t view on Meta::CPAN
is(scalar @results, 100, 'all 100 completed');
ok((grep { $_ eq 'OK' } @results) == 100, 'all returned OK');
# Verify values
my @get_futures = map { $redis->get("ap:$_") } (1..10);
my @values = await_f(Future->needs_all(@get_futures));
is(\@values, [1..10], 'values stored correctly');
};
subtest 'auto-pipeline transparent API' => sub {
# Same API as non-pipelined
my $result = run { $redis->set('ap:single', 'value') };
is($result, 'OK', 'single command works');
my $value = run { $redis->get('ap:single') };
is($value, 'value', 'GET works');
};
subtest 'auto-pipeline faster than sequential' => sub {
# Compare auto-pipelined to non-pipelined
t/50-pubsub/reconnect.t view on Meta::CPAN
# Server-initiated disconnect via KILL from pub connection.
eval { run { $pub->client('KILL', 'ID', $sub_client_id) } };
# Publish after reconnect window
my $post_future = (async sub {
await Future::IO->sleep(0.3);
await $pub->publish('reconnect:test', 'after');
})->();
# next() should reconnect transparently and return real message
my $next_f = $subscription->next;
my $timeout_f = Future::IO->sleep($TEST_TIMEOUT)->then(sub {
Future->fail("Timed out waiting for message after reconnect");
});
my $msg2 = eval { await_f(Future->wait_any($next_f, $timeout_f)); $next_f->get };
if ($@) {
fail("received message after reconnect: $@");
} else {
is($msg2->{type}, 'message', 'got real message type after reconnect');
( run in 2.027 seconds using v1.01-cache-2.11-cpan-ba708fea25c )