new framework

This commit is contained in:
2026-05-12 22:36:19 +02:00
parent d92768dd23
commit 9d52a2e2c6
29 changed files with 1240 additions and 400 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,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

@@ -1,14 +0,0 @@
# frozen_string_literal: true
class MessageService
def initialize(repo) = @repo = repo
def recent(count = 30) = @repo.last(count)
def count = @repo.count
def post(username, text)
return :empty if text.strip.empty?
@repo.append(username, text.strip[0...200])
:ok
end
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