Created
May 25, 2012 15:37
-
-
Save Loupi/2788831 to your computer and use it in GitHub Desktop.
Redis nested comments in C#
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.IO; | |
using System.Xml.Serialization; | |
using ServiceStack.Redis; | |
namespace RedisNestedComments | |
{ | |
public class CommentsRepository | |
{ | |
readonly IRedisClientsManager _RedisFactory; | |
public CommentsRepository(IRedisClientsManager redisFactory) | |
{ | |
_RedisFactory = redisFactory; | |
} | |
public string Save(string itemId, string comment, string parentId = null) | |
{ | |
CommentModel data; | |
using (var redis = _RedisFactory.GetClient()) | |
{ | |
var now = DateTime.UtcNow.ToFileTimeUtc(); | |
var id = redis.Increment("1", 1); | |
data = new CommentModel(){Id = id, Comment = comment, Time = DateTime.UtcNow}; | |
var k = parentId != null ? SubCommentsKey(parentId) : CommentsKey(itemId); | |
redis.Remove(JsonKey(itemId)); | |
redis.AddItemToSortedSet(k, id.ToString(), now); | |
redis.StoreAsHash(data); | |
} | |
return data.Id.ToString(); | |
} | |
public List<NestedComment> Get(string itemId) | |
{ | |
List<NestedComment> result = null; | |
using (var redis = _RedisFactory.GetReadOnlyClient()) | |
{ | |
var jsonId = JsonKey(itemId); | |
var jsonComments = redis.Get<byte[]>(jsonId); | |
var xs = new XmlSerializer(typeof(List<NestedComment>)); | |
if (jsonComments == null) | |
{ | |
result = MultiFetch(CommentsKey(itemId), redis); | |
using (var ms = new MemoryStream()) | |
{ | |
xs.Serialize(ms, result); | |
redis.Set(jsonId, ms.ToArray()); | |
} | |
} | |
else | |
{ | |
using (var ms = new MemoryStream(jsonComments)) | |
{ | |
result = xs.Deserialize(ms) as List<NestedComment>; | |
} | |
} | |
} | |
return result; | |
} | |
public List<NestedComment> Leaf(string id) | |
{ | |
List<NestedComment> result = null; | |
using (var redis = _RedisFactory.GetReadOnlyClient()) | |
{ | |
var nestedComment = new NestedComment(redis.GetFromHash<CommentModel>(CommentKey(id))); | |
nestedComment.SubComments = MultiFetch(SubCommentsKey(id), redis); | |
} | |
return result; | |
} | |
public void Delete(IList<NestedComment> comments, string parentId, string itemId, bool isMainThread = false) | |
{ | |
using (var redis = _RedisFactory.GetClient()) | |
{ | |
InnerDelete(comments, parentId, isMainThread, redis); | |
redis.Remove(JsonKey(itemId)); | |
} | |
} | |
List<NestedComment> MultiFetch(string keyName, IRedisClient redis) | |
{ | |
var result = new List<CommentModel>(); | |
var commentIds = redis.GetRangeFromSortedSet(keyName, 0, -1); | |
foreach (var commentId in commentIds) | |
{ | |
result.Add(redis.GetFromHash<CommentModel>(commentId)); | |
} | |
return ProcessComments(result, redis); | |
} | |
List<NestedComment> ProcessComments(IList<CommentModel> comments, IRedisClient redis) | |
{ | |
var result = new List<NestedComment>(); | |
foreach (var comment in comments) | |
{ | |
var nestedComment = new NestedComment(comment); | |
var subCommentsId = SubCommentsKey(comment.Id.ToString()); | |
if (redis.GetSortedSetCount(subCommentsId) > 0) | |
{ | |
nestedComment.SubComments = MultiFetch(subCommentsId, redis); | |
} | |
result.Add(nestedComment); | |
} | |
return result; | |
} | |
void InnerDelete(IList<NestedComment> comments, string parentId, bool isMainThread, IRedisClient redis) | |
{ | |
foreach (var comment in comments) | |
{ | |
InnerDelete(comment, parentId, isMainThread, redis); | |
} | |
} | |
void InnerDelete(NestedComment comment, string parentId, bool isMainThread, IRedisClient redis) | |
{ | |
var id = comment.Comment.Id.ToString(); | |
var k = isMainThread ? CommentKey(parentId) : SubCommentsKey(parentId); | |
redis.Remove(CommentKey(id)); | |
redis.RemoveItemFromSortedSet(k, id); | |
if (comment.SubComments != null) | |
InnerDelete(comment.SubComments, id, false, redis); | |
} | |
string JsonKey(string id) | |
{ | |
return string.Format("comment:{0}:json", id); | |
} | |
string CommentKey(string id) | |
{ | |
return string.Format("comment:{0}", id); | |
} | |
string CommentsKey(string id) | |
{ | |
return string.Format("comments:{0}", id); | |
} | |
string SubCommentsKey(string id) | |
{ | |
return string.Format("comment:{0}:sub", id); | |
} | |
} | |
public class CommentModel | |
{ | |
public long Id {get; set;} | |
public DateTime Time {get; set;} | |
public string Comment {get; set;} | |
} | |
public class NestedComment | |
{ | |
public NestedComment() | |
{ | |
} | |
public NestedComment(CommentModel comment) | |
{ | |
this.Comment = comment; | |
} | |
public CommentModel Comment { get; set; } | |
public List<NestedComment> SubComments { get; set; } | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment