using AIStudio.ConSole.Redis.Core;
using CSRedis;
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
namespace AIStudio.ConSole.Redis.Ch04
{
class TestCh04
{
/********************************************************************************************************
# <start id="_1313_14472_8342"/>
def list_item(conn, itemid, sellerid, price):
inventory = "inventory:%s"%sellerid
item = "%s.%s" % (itemid, sellerid)
end = time.time() + 5
pipe = conn.pipeline()
while time.time() < end:
try:
pipe.watch(inventory) #A
if not pipe.sismember(inventory, itemid):#B
pipe.unwatch() #E
return None
pipe.multi() #C
pipe.zadd("market:", {item: price
}) #C
pipe.srem(inventory, itemid) #C
pipe.execute() #F
return True
except redis.exceptions.WatchError: #D
pass #D
return False
# <end id="_1313_14472_8342"/>
*********************************************************************************************************/
#region list_item
public bool list_item(CSRedisClient conn, string itemid, string sellerid, decimal price)
{
var inventory = $"inventory:{sellerid}";
var item = $"{itemid}.{sellerid}";
var end = DateTime.Now.AddSeconds(5);
var pipe = conn.StartPipe();
while (DateTime.Now < end)
{
try
{
if (conn.SIsMember(inventory, itemid) != true)
continue;
pipe.ZAdd("market:", (price, item));
pipe.SRem(inventory, itemid);
pipe.EndPipe();
return true;
}
catch (Exception)
{
continue;
}
}
return false;
}
#endregion
/********************************************************************************************************
# <start id="_1313_14472_8353"/>
def purchase_item(conn, buyerid, itemid, sellerid, lprice):
buyer = "users:%s"%buyerid
seller = "users:%s" % sellerid
item = "%s.%s"%(itemid, sellerid)
inventory = "inventory:%s" % buyerid
end = time.time() + 10
pipe = conn.pipeline()
while time.time() < end:
try:
pipe.watch("market:", buyer) #A
price = pipe.zscore("market:", item) #B
funds = int (pipe.hget(buyer, "funds")) #B
if price != lprice or price > funds: #B
pipe.unwatch() #B
return None
pipe.multi() #C
pipe.hincrby(seller, "funds", int (price)) #C
pipe.hincrby(buyer, "funds", int (-price)) #C
pipe.sadd(inventory, itemid) #C
pipe.zrem("market:", item) #C
pipe.execute() #C
return True
except redis.exceptions.WatchError: #D
pass #D
return False
# <end id="_1313_14472_8353"/>
*********************************************************************************************************/
public bool purchase_item(CSRedisClient conn, string buyerid, string itemid, string sellerid, decimal lprice)
{
var buyer = $"users:{buyerid}";
var seller = $"users:{sellerid}";
var item = $"{itemid}.{sellerid}";
var inventory = $"inventory:{sellerid}";
var end = DateTime.Now.AddSeconds(10);
var pipe = conn.StartPipe();
while (DateTime.Now < end)
{
try
{
var price = conn.ZScore("market:", item);
var funds = conn.HGet(buyer, "funds");
if (price != lprice || price > decimal.Parse(funds))
{
return false;
}
pipe.HIncrBy(seller, "funds", (long)price);
pipe.HIncrBy(buyer, "funds", (long)-price);
pipe.SAdd(inventory, itemid);
pipe.ZRem("market:", item);
pipe.EndPipe();
return true;
}
catch
{
continue;
}
}
return false;
}
/********************************************************************************************************
# <start id="update-token"/>
def update_token(conn, token, user, item=None):
timestamp = time.time() #A
conn.hset('login:', token, user) #B
conn.zadd('recent:', {token: timestamp}) #C
if item:
conn.zadd('viewed:' + token, {item: timestamp}) #D
conn.zremrangebyrank('viewed:' + token, 0, -26) #E
conn.zincrby('viewed:', -1, item) #F
# <end id="update-token"/>
*********************************************************************************************************/
#region update-token
public void update_token(CSRedisClient conn, string token, string user, string item = null)
{
var timestamp = (DateTime.Now - new DateTime(1970, 1, 1)).TotalSeconds;
conn.HSet("login:", token, user);
conn.ZAdd("recent:", ((decimal)timestamp, token));
if (!string.IsNullOrEmpty(item))
{
conn.ZAdd("viewed:" + token, ((decimal)timestamp, token));
conn.ZRemRangeByRank("viewed:" + token, 0, -26);
conn.ZIncrBy("viewed:", item, -1);
}
}
#endregion
/********************************************************************************************************
# <start id="update-token-pipeline"/>
def update_token_pipeline(conn, token, user, item= None):
timestamp = time.time()
pipe = conn.pipeline(False) #A
pipe.hset('login:', token, user)
pipe.zadd('recent:', {token: timestamp
})
if item:
pipe.zadd('viewed:' + token, {item: timestamp
})
pipe.zremrangebyrank('viewed:' + token, 0, -26)
pipe.zincrby('viewed:', -1, item)
pipe.execute() #B
# <end id="update-token-pipeline"/>
*********************************************************************************************************/
#region update-token-pipeline
public void update_token_pipeline(CSRedisClient conn, string token, string user, string item = null)
{
var timestamp = (DateTime.Now - new DateTime(1970, 1, 1)).TotalSeconds;
var pipe = conn.StartPipe();
pipe.HSet("login:", token, user);
pipe.ZAdd("recent:", ((decimal)timestamp, token));
if (!string.IsNullOrEmpty(item))
{
pipe.ZAdd("viewed:" + token, ((decimal)timestamp, token));
pipe.ZRemRangeByRank("viewed:" + token, 0, -26);
pipe.ZIncrBy("viewed:", item, -1);
}
pipe.EndPipe();
}
#endregion
/********************************************************************************************************
# <start id="simple-pipeline-benchmark-code"/>
def benchmark_update_token(conn, duration):
for function in (update_token, update_token_pipeline): #A
count = 0 #B
start = time.time() #B
end = start + duration #B
while time.time() < end:
count += 1
function(conn, 'token', 'user', 'item') #C
delta = time.time() - start #D
print(function.__name__, count, delta, count / delta) #E
# <end id="simple-pipeline-benchmark-code"/>
*********************************************************************************************************/
#region simple-pipeline-benchmark-code
public void simple_pipeline_benchmark_code(CSRedisClient conn, int duration)
{
foreach (var function in new Action<CSRedisClient, string, string, string>[] { update_token, update_token_pipeline })
{
int count = 0;
var start = DateTime.Now;
var end = start.AddSeconds(duration);
while (DateTime.Now < end)
{
count += 1;
function(conn, "token", "user", "item");
}
var delta = (DateTime.Now - start).TotalSeconds;
Console.WriteLine($"{function.Method.Name}, {count}, {delta}, {count / delta}");
}
}
#endregion
/********************************************************************************************************
def test_list_item(self):
import pprint
conn = self.conn
print("We need to set up just enough state so that a user can list an item")
seller = 'userX'
item = 'itemX'
conn.sadd('inventory:' + seller, item)
i = conn.smembers('inventory:' + seller)
print("The user's inventory has:", i)
self.assertTrue(i)
print()
print("Listing the item...")
l = list_item(conn, item, seller, 10)
print("Listing the item succeeded?", l)
self.assertTrue(l)
r = conn.zrange('market:', 0, -1, withscores = True)
print("The market contains:")
pprint.pprint(r)
self.assertTrue(r)
self.assertTrue(any(x[0] == b'itemX.userX' for x in r))
*********************************************************************************************************/
public void test_list_item(CSRedisClient conn)
{
Console.WriteLine("We need to set up just enough state so that a user can list an item");
var seller = "userX";
var item = "itemX";
conn.SAdd("inventory:" + seller, item);
var i = conn.SMembers("inventory:" + seller);
Console.WriteLine("The user's inventory has:{i}");
Console.WriteLine();
Console.WriteLine("Listing the item...");
var l = list_item(conn, item, seller, 10);
Console.WriteLine($"Listing the item succeeded?{l}");
var r = conn.ZRangeWithScores("market:", 0, -1);
Console.WriteLine($"The market contains:{PrintHelper.ValueTuple2String(r)}");
}
/********************************************************************************************************
def test_purchase_item(self):
self.test_list_item()
conn = self.conn
print("We need to set up just enough state so a user can buy an item")
buyer = 'userY'
conn.hset('users:userY', 'funds', 125)
r = conn.hgetall('users:userY')
print("The user has some money:", r)
self.assertTrue(r)
self.assertTrue(r.get(b'funds'))
print()
print("Let's purchase an item")
p = purchase_item(conn, 'userY', 'itemX', 'userX', 10)
print("Purchasing an item succeeded?", p)
self.assertTrue(p)
r = conn.hgetall('users:userY')
print("Their money is now:", r)
self.assertTrue(r)
i = conn.smembers('inventory:' + buyer)
print("Their inventory is now:", i)
self.assertTrue(i)
self.assertTrue(b'itemX' in i)
self.assertEqual(conn.zscore('market:', 'itemX.userX'), None)
*********************************************************************************************************/
#region
public void test_purchase_item(CSRedisClient conn)
{
Console.WriteLine("We need to set up just enough state so a user can buy an item");
var buyer = "userY";
conn.HSet("users:userY", "funds", 125);
var r = conn.HGetAll("users:userY");
Console.WriteLine($"The user has some money:{PrintHelper.Dictionary2String(r)}");
Console.WriteLine();
Console.WriteLine("Let's purchase an item");
var p = purchase_item(conn, "userY", "itemX", "userX", 10);
Console.WriteLine($"Purchasing an item succeeded?{p}");
r = conn.HGetAll("users:userY");
Console.WriteLine($"Their money is now:{PrintHelper.Dictionary2String(r)}");
var i = conn.SMembers("inventory:" + buyer);
Console.WriteLine("Their inventory is now:", PrintHelper.StringArray2String(i));
}
#endregion
public void Test()
{
var conn = new CSRedis.CSRedisClient("127.0.0.1:6379,defaultDatabase=0,poolsize=500,ssl=false,writeBuffer=10240");
simple_pipeline_benchmark_code(conn, 5);
test_list_item(conn);
test_purchase_item(conn);
}
}
}