require 'redis' require 'securerandom' require 'json' class CommentsRepository def initialize @redis = Redis.new end def save itemId, comment, parentId = nil now = Time.now.utc.to_i id = @redis.incr 1 comment = {id: id, comment: comment, time: now} childsOfKey = parentId ? subCommentsKey(parentId) : commentsKey(itemId) @redis.multi do |multi| @redis.del jsonKey itemId @redis.hmset commentKey(id), comment.map{|k,v| [k,v]}.flatten(1) @redis.zadd childsOfKey, now, id end id end def get id jsonId = jsonKey id jsonComments = @redis.get jsonId if jsonComments JSON.parse jsonComments else comments = multiFetch commentsKey id @redis.set jsonId, comments.to_json comments end end def leaf id comment = @redis.hgetall commentKey id comment['comments'] = multiFetch subCommentsKey id comment end def delete comment, parentId, itemId, isMainThread = true innerDelete comment, parentId, isMainThread @redis.del jsonKey itemId end private def multiFetch key commentIds = @redis.zrange key, 0, -1 comments = @redis.multi do |multi| commentIds.map { |id| multi.hgetall(commentKey id)} end processComments comments end def processComments comments comments.each do |comment| subCommentsId = subCommentsKey comment['id'] if @redis.zcard(subCommentsId) > 0 comment['comments'] = multiFetch subCommentsId end end end def innerDelete comment, parentId, isMainThread if comment.kind_of? Array comment.each {|c| innerDelete c, parentId, isMainThread} else id = comment['id'] comments = comment['comments'] childsKey = isMainThread ? commentsKey(parentId) : subCommentsKey(parentId) @redis.del commentKey id @redis.zrem childsKey, id innerDelete comments, id, false if comments end end def jsonKey id "comment:#{id}:json" end def commentKey id "comment:#{id}" end def commentsKey id "comments:#{id}" end def subCommentsKey id "comment:#{id}:sub" end end def printComments comments, tabs = 0 comments.each do |comment| tabs.times { putc "\t" } puts "#{comment['comment']}" if comment['comments'] printComments comment['comments'], tabs + 1 end end end def saveDummy cr, id tree = cr.save id, 'Tree' root = cr.save id, 'Root', tree trunk = cr.save id, 'Trunk', tree branch = cr.save id, 'Branch', trunk leaf = cr.save id, 'Leaf', branch top = cr.save id, 'Top', tree end command = ARGV[0] id = ARGV[1] cr = CommentsRepository.new case command when 's' saveDummy cr, id when 'p' printComments cr.get id when 'l' printComments [cr.leaf(id)] when 'd' cr.delete cr.get(id), id, id when 'r' cr.delete cr.leaf(ARGV[2]), ARGV[3], id, false when 'j' puts cr.get(id).to_json end