Commit fbec82db authored by Jyrki's avatar Jyrki 🐾

Add Redis connection + watch targets repository

parent 38a8add9
......@@ -4,6 +4,14 @@ shards:
github: mamantoha/crest
version: 0.14.0
pool:
github: ysbaddaden/pool
version: 0.2.3
redis:
github: stefanwille/crystal-redis
version: 2.1.0
telegram_bot:
github: hangyas/telegram_bot
commit: 722bab24876d13a661f513b09c4569916f7a81c1
......
......@@ -11,6 +11,9 @@ targets:
dependencies:
crest:
github: mamantoha/crest
redis:
github: stefanwille/crystal-redis
version: ~> 2.1.0
telegram_bot:
github: hangyas/telegram_bot
......
require "redis"
require "redis/pooled_client"
module Connection
class Redis
def self.connection
@@redis ||= begin
Application.logger.info "Connecting to Redis"
::Redis::PooledClient.new
end
end
end
end
require "../../connection/redis"
require "json"
module Repository
# The WatchTargets repository manages the watchers of a certain toy/size
# combination.
#
# Redis considerations
# --------------------
#
# - Redis key prefix: `ddw:wt:`
# - A redis key for the toy `rex` would be e.g. `ddw:wt:rex`
# - The keys of that hash are the toy sizes, e.g. `extralarge`
# - The value is a JSON array containing the Telegram user IDs
#
# This way, we can simply iterate over all toys, and get the watchers for a
# given toy/size combination.
class WatchTargets
KEY_BASE = "ddw:wt"
private macro redis_key(key)
"#{KEY_BASE}:#{{{key}}}"
end
def self.add(user_id : Int64, toy_sku, toy_size)
Application.logger.info "adding watch #{toy_sku}/#{toy_size} for #{user_id}"
key = redis_key(toy_sku)
loop do
Application.logger.debug "[redis] WATCH #{key.inspect}"
redis.watch(key) # optimistic locking
users = watchers(toy_sku, toy_size)
users << user_id
users.uniq!
Application.logger.debug "[redis] HSET #{key.inspect} #{users.to_json.inspect}"
response = redis.multi(&.hset(key, toy_size, users.to_json))
break unless response.empty?
end
end
def self.remove(user_id, toy_sku, toy_size)
Application.logger.info "removing watch #{toy_sku}:#{toy_size} for #{user_id}"
key = redis_key(toy_sku)
loop do
redis.watch(key) # optimistic locking
users = watchers(toy_sku, toy_size)
users.delete(user_id)
users.uniq!
Application.logger.debug "[redis] HSET #{key.inspect} #{users.to_json.inspect}"
response = redis.multi(&.hset(key, toy_size, users.to_json))
break unless response.empty?
end
end
def self.watchers(toy_sku, toy_size)
Application.logger.debug "[redis] HGET #{redis_key(toy_sku).inspect} #{toy_size.inspect}"
JSON.parse(
redis.hget(redis_key(toy_sku), toy_size) || "[]"
).as_a.map(&.as_i64)
end
private def self.redis
Connection::Redis.connection
end
end
end
require "./base"
require "../../../bad_dragon/api/client"
require "../../../repository/watch_targets"
module UseCase
module CliCommands
......@@ -13,6 +14,15 @@ module UseCase
end
def call(_argv)
Repository::WatchTargets.add(2, "nova", "extralarge")
Repository::WatchTargets.add(2, "nova", "extralarge")
Repository::WatchTargets.add(3, "nova", "extralarge")
Repository::WatchTargets.remove(2, "nova", "extralarge")
Repository::WatchTargets.remove(2, "nova", "extralarge")
Repository::WatchTargets.remove(3, "nova", "extralarge")
end
def _call(_argv)
client = BadDragon::API::Client.new
toys = client.inventory_toys
pp toys.map(&.type).uniq
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment