using CommandLine;
using StackExchange.Redis;
using System;
using System.Collections.Generic;
using System.Threading;
using RedisManager.Utils;
namespace RedisManager.Commands
{
///
/// Contains command line options and implementations for Redis Pub/Sub operations.
/// Provides functionality for PUBLISH, SUBSCRIBE, and UNSUBSCRIBE commands.
///
[Verb("publish", HelpText = "Publish a message to a channel.")]
public class PublishOptions
{
[Option('i', "instance", Required = true, HelpText = "Instance name.")]
public string Instance { get; set; }
[Value(0, MetaName = "channel", Required = true, HelpText = "Channel name.")]
public string Channel { get; set; }
[Value(1, MetaName = "message", Required = true, HelpText = "Message to publish.")]
public string Message { get; set; }
[Option("table", Required = false, HelpText = "Output as table.")]
public bool Table { get; set; }
}
[Verb("subscribe", HelpText = "Subscribe to one or more channels.")]
public class SubscribeOptions
{
[Option('i', "instance", Required = true, HelpText = "Instance name.")]
public string Instance { get; set; }
[Value(0, MetaName = "channels", Min = 1, Required = true, HelpText = "Channels to subscribe to.")]
public IEnumerable Channels { get; set; }
}
[Verb("unsubscribe", HelpText = "Unsubscribe from one or more channels.")]
public class UnsubscribeOptions
{
[Option('i', "instance", Required = true, HelpText = "Instance name.")]
public string Instance { get; set; }
[Value(0, MetaName = "channels", Min = 1, Required = true, HelpText = "Channels to unsubscribe from.")]
public IEnumerable Channels { get; set; }
}
public static class PubSubCommands
{
///
/// Executes the PUBLISH command to publish a message to a channel.
///
/// The PublishOptions containing instance, channel, and message.
/// The RedisManager configuration.
/// Exit code (0 for success, non-zero for failure).
public static int RunPublish(PublishOptions opts, Config config)
{
var instance = RedisUtils.GetInstance(config, opts.Instance);
using var redis = RedisUtils.ConnectRedis(instance);
var sub = redis.GetSubscriber();
var count = sub.Publish(opts.Channel, opts.Message);
if (opts.Table)
RedisUtils.PrintTable(new[] { "Channel", "Receivers" }, new List { new[] { opts.Channel, count.ToString() } });
else
Console.WriteLine(Output.Green($"Published to {opts.Channel}, receivers: {count}"));
return 0;
}
///
/// Executes the SUBSCRIBE command to subscribe to one or more channels.
///
/// The SubscribeOptions containing instance and channels.
/// The RedisManager configuration.
/// Exit code (0 for success, non-zero for failure).
public static int RunSubscribe(SubscribeOptions opts, Config config)
{
var instance = RedisUtils.GetInstance(config, opts.Instance);
using var redis = RedisUtils.ConnectRedis(instance);
var sub = redis.GetSubscriber();
var channels = opts.Channels;
Console.WriteLine(Output.Yellow($"Subscribed to: {string.Join(", ", channels)}. Press Ctrl+C to exit."));
using var cts = new CancellationTokenSource();
Console.CancelKeyPress += (s, e) => { e.Cancel = true; cts.Cancel(); };
foreach (var channel in channels)
{
sub.Subscribe(channel, (ch, msg) =>
{
Console.WriteLine(Output.Cyan($"[{ch}] {msg}"));
});
}
try
{
while (!cts.IsCancellationRequested)
{
Thread.Sleep(100);
}
}
catch (OperationCanceledException) { }
Console.WriteLine(Output.Yellow("Unsubscribed and exiting."));
return 0;
}
///
/// Executes the UNSUBSCRIBE command to unsubscribe from one or more channels.
///
/// The UnsubscribeOptions containing instance and channels.
/// The RedisManager configuration.
/// Exit code (0 for success, non-zero for failure).
public static int RunUnsubscribe(UnsubscribeOptions opts, Config config)
{
var instance = RedisUtils.GetInstance(config, opts.Instance);
using var redis = RedisUtils.ConnectRedis(instance);
var sub = redis.GetSubscriber();
foreach (var channel in opts.Channels)
{
sub.Unsubscribe(channel);
Console.WriteLine(Output.Yellow($"Unsubscribed from {channel}"));
}
return 0;
}
}
}