This commit is contained in:
2026-05-13 22:35:24 +02:00
parent 1ae4734e81
commit c2e6466022
18 changed files with 311 additions and 317 deletions

View File

@@ -0,0 +1,17 @@
# frozen_string_literal: true
class BoardService
def initialize(repo) = @repo = repo
def boards = @repo.boards
def board(id) = @repo.boards.find { |b| b.id == id }
def messages(id, n = 30) = @repo.last(id, n)
def count(id) = @repo.count(id)
def total_count = @repo.total_count
def post(board_id, username, text)
return :empty if text.to_s.strip.empty?
@repo.append(board_id, username, text.strip[0...1000])
:ok
end
end

View File

@@ -0,0 +1,55 @@
# frozen_string_literal: true
# Tiny in-memory chat hub. Each session subscribes to receive broadcast
# messages from other sessions. Backed by a per-session Queue so the
# Application's idle tick can drain pending messages.
class ChatService
ChatLine = Struct.new(:timestamp, :username, :text)
def initialize
@subs = {}
@mu = Mutex.new
@history = []
@history_limit = 200
end
def subscribe(session_id)
@mu.synchronize do
@subs[session_id] = Queue.new
@history.last(50).each { |line| @subs[session_id] << line }
end
end
def unsubscribe(session_id)
@mu.synchronize { @subs.delete(session_id) }
end
def broadcast(username, text)
line = ChatLine.new(Time.now.strftime('%H:%M:%S'), username, text)
@mu.synchronize do
@history << line
@history.shift while @history.size > @history_limit
@subs.each_value { |q| q << line }
end
line
end
# Returns Array<ChatLine> of pending messages for the given session.
def drain(session_id)
queue = @mu.synchronize { @subs[session_id] }
return [] unless queue
pending = []
pending << queue.pop(true) while !queue.empty?
pending
rescue ThreadError
pending
end
def history(n = 50)
@mu.synchronize { @history.last(n).dup }
end
def subscriber_count
@mu.synchronize { @subs.size }
end
end

View File

@@ -0,0 +1,7 @@
# frozen_string_literal: true
class GamesService
def initialize(repo) = @repo = repo
def all = @repo.fetch
end

View File

@@ -0,0 +1,8 @@
# frozen_string_literal: true
class LastCallersService
def initialize(repo) = @repo = repo
def record(username, session_id) = @repo.record(username, session_id)
def recent(n = 10) = @repo.recent(n)
end

View File

@@ -0,0 +1,10 @@
# frozen_string_literal: true
class OnlineService
def initialize(repo) = @repo = repo
def add(session_id, username) = @repo.add(session_id, username)
def remove(session_id) = @repo.remove(session_id)
def count = @repo.count
def user_list = @repo.snapshot.sort.map { |_, name| name }
end

View File

@@ -0,0 +1,8 @@
# frozen_string_literal: true
class ProfileService
def initialize(repo) = @repo = repo
def find(username) = @repo.find(username)
def update(username, **f) = @repo.upsert(username: username, **f)
end

View File

@@ -0,0 +1,9 @@
# frozen_string_literal: true
class WikiService
def initialize(repo) = @repo = repo
def list(category) = @repo.list(category)
def content(page_id) = @repo.content(page_id)
def page_url(locale, path) = @repo.page_url(locale, path)
end