107 lines
3.6 KiB
GDScript
107 lines
3.6 KiB
GDScript
extends RefCounted
|
|
class_name GedisPubSub
|
|
|
|
var _gedis: Gedis
|
|
|
|
signal pubsub_message(channel, message)
|
|
signal psub_message(pattern, channel, message)
|
|
|
|
signal subscribed(channel, subscriber)
|
|
signal unsubscribed(channel, subscriber)
|
|
|
|
func _init(gedis: Gedis):
|
|
_gedis = gedis
|
|
|
|
# --------
|
|
# Pub/Sub
|
|
# --------
|
|
func publish(channel: String, message) -> void:
|
|
# Backwards-compatible delivery:
|
|
# 1) If subscriber objects registered via subscribe/psubscribe expect direct signals,
|
|
# call their 'pubsub_message'/'psub_message' on the subscriber object.
|
|
# 2) Emit a single Gedis-level signal so external code can connect to this Gedis instance.
|
|
# This avoids emitting the same Gedis signal multiple times (which would cause duplicate callbacks).
|
|
# Direct subscribers (back-compat)
|
|
if _gedis._core._subscribers.has(channel):
|
|
for subscriber in _gedis._core._subscribers[channel]:
|
|
if is_instance_valid(subscriber):
|
|
# deliver directly to subscriber object if it exposes the signal
|
|
if subscriber.has_signal("pubsub_message"):
|
|
subscriber.pubsub_message.emit(channel, message)
|
|
# Emit a single Gedis-level pubsub notification for all listeners connected to this Gedis instance.
|
|
if _gedis._core._subscribers.has(channel) and _gedis._core._subscribers[channel].size() > 0:
|
|
pubsub_message.emit(channel, message)
|
|
# Pattern subscribers (back-compat + Gedis-level)
|
|
for pattern in _gedis._core._psubscribers.keys():
|
|
# Use simple glob matching: convert to RegEx
|
|
var rx = _gedis._utils._glob_to_regex(pattern)
|
|
if rx.search(channel) != null:
|
|
for subscriber in _gedis._core._psubscribers[pattern]:
|
|
if is_instance_valid(subscriber):
|
|
if subscriber.has_signal("psub_message"):
|
|
subscriber.psub_message.emit(pattern, channel, message)
|
|
# Emit one Gedis-level pattern message for this matching pattern
|
|
psub_message.emit(pattern, channel, message)
|
|
|
|
func subscribe(channel: String, subscriber: Object) -> void:
|
|
var arr: Array = _gedis._core._subscribers.get(channel, [])
|
|
# avoid duplicates
|
|
for s in arr:
|
|
if s == subscriber:
|
|
return
|
|
arr.append(subscriber)
|
|
_gedis._core._subscribers[channel] = arr
|
|
subscribed.emit(channel, subscriber)
|
|
|
|
func unsubscribe(channel: String, subscriber: Object) -> void:
|
|
if not _gedis._core._subscribers.has(channel):
|
|
return
|
|
var arr: Array = _gedis._core._subscribers[channel]
|
|
for i in range(arr.size()):
|
|
if arr[i] == subscriber:
|
|
arr.remove_at(i)
|
|
unsubscribed.emit(channel, subscriber)
|
|
break
|
|
if arr.is_empty():
|
|
_gedis._core._subscribers.erase(channel)
|
|
else:
|
|
_gedis._core._subscribers[channel] = arr
|
|
|
|
func psubscribe(pattern: String, subscriber: Object) -> void:
|
|
var arr: Array = _gedis._core._psubscribers.get(pattern, [])
|
|
for s in arr:
|
|
if s == subscriber:
|
|
return
|
|
arr.append(subscriber)
|
|
_gedis._core._psubscribers[pattern] = arr
|
|
subscribed.emit(pattern, subscriber)
|
|
|
|
func punsubscribe(pattern: String, subscriber: Object) -> void:
|
|
if not _gedis._core._psubscribers.has(pattern):
|
|
return
|
|
var arr: Array = _gedis._core._psubscribers[pattern]
|
|
for i in range(arr.size()):
|
|
if arr[i] == subscriber:
|
|
arr.remove_at(i)
|
|
unsubscribed.emit(pattern, subscriber)
|
|
break
|
|
if arr.is_empty():
|
|
_gedis._core._psubscribers.erase(pattern)
|
|
else:
|
|
_gedis._core._psubscribers[pattern] = arr
|
|
|
|
# -----------
|
|
# Introspection
|
|
# -----------
|
|
func list_channels() -> Array:
|
|
return _gedis._core._subscribers.keys()
|
|
|
|
func list_subscribers(channel: String) -> Array:
|
|
return _gedis._core._subscribers.get(channel, [])
|
|
|
|
func list_patterns() -> Array:
|
|
return _gedis._core._psubscribers.keys()
|
|
|
|
func list_pattern_subscribers(pattern: String) -> Array:
|
|
return _gedis._core._psubscribers.get(pattern, [])
|