480 lines
22 KiB
C#
480 lines
22 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.Threading.Tasks;
|
|
|
|
|
|
using StackExchange.Redis;
|
|
|
|
|
|
using ServerCore; using ServerBase;
|
|
using ServerCommon;
|
|
using ServerCommon.Cache;
|
|
|
|
|
|
using META_ID = System.UInt32;
|
|
using REQUESTOR_ID = System.String;
|
|
|
|
|
|
namespace GameServer
|
|
{
|
|
public static class LandAuctionCacheHelper
|
|
{
|
|
public static async Task<Result> trySaveToCache(this LandAuction landAuction, REQUESTOR_ID requestorId)
|
|
{
|
|
var server_logic = GameServerApp.getServerLogic();
|
|
var redis_connector = server_logic.getRedisConnector();
|
|
|
|
var result = new Result();
|
|
|
|
var land_auction_action = landAuction.getEntityAction<LandAuctionAction>();
|
|
NullReferenceCheckHelper.throwIfNull(land_auction_action, () => $"land_auction_action is null !!! - {landAuction.toBasicString()}");
|
|
|
|
var registry_attribute = landAuction.getEntityAttribute<LandAuctionRegistryAttribute>();
|
|
NullReferenceCheckHelper.throwIfNull(registry_attribute, () => $"registry_attribute is null !!! - {landAuction.toBasicString()}");
|
|
var highest_bid_user_attribute = landAuction.getEntityAttribute<LandAuctionHighestBidUserAttribute>();
|
|
NullReferenceCheckHelper.throwIfNull(highest_bid_user_attribute, () => $"highest_bid_user_attribute is null !!! - {landAuction.toBasicString()}");
|
|
|
|
var land_auction_cache = new LandAuctionCache();
|
|
land_auction_cache.LandMetaId = registry_attribute.LandMetaId;
|
|
land_auction_cache.AuctionNumber = registry_attribute.AuctionNumber;
|
|
|
|
land_auction_cache.LandAuctionState = registry_attribute.LandAuctionState;
|
|
land_auction_cache.LandAuctionResult = registry_attribute.LandAuctionResult;
|
|
land_auction_cache.ProcessVersionTime = registry_attribute.ProcessVersionTime;
|
|
|
|
var land_auction_cache_request = new LandAuctionCacheRequest(land_auction_cache, redis_connector);
|
|
result = await land_auction_cache_request.upsertLandAuction(DateTimeHelper.toRemainingTimeMin(registry_attribute.AuctionEndTime));
|
|
if (result.isFail())
|
|
{
|
|
return result;
|
|
}
|
|
|
|
if (LandAuctionState.Started == land_auction_cache.LandAuctionState)
|
|
{
|
|
await landAuction.tryRemoveLandAuctionTopBidderBlockFromCache();
|
|
}
|
|
|
|
land_auction_action.resetCacheSaveStep();
|
|
|
|
var is_success = await landAuction.tryReleaseWriteLockWithLandAuction(requestorId);
|
|
if (false == is_success)
|
|
{
|
|
var err_msg = $"Failed to tryReleaseWriteLockWithLandAuction() !!! - {landAuction.toBasicString()}";
|
|
Log.getLogger().warn(err_msg);
|
|
}
|
|
|
|
Log.getLogger().debug($"Called trySaveToCache() - {landAuction.toBasicString()}");
|
|
|
|
return result;
|
|
}
|
|
|
|
public static async Task<bool> tryAcquireWriteLockWithLandAuctionBidders(this LandAuction landAuction, REQUESTOR_ID requestorId, Int16 ttlSec)
|
|
{
|
|
var result = new Result();
|
|
|
|
var server_logic = GameServerApp.getServerLogic();
|
|
var redis_connector = server_logic.getRedisConnector();
|
|
var redis_lua_executor = server_logic.getRedisWithLuaScriptExecutor();
|
|
|
|
var land_auction_registry_attribute = landAuction.getEntityAttribute<LandAuctionRegistryAttribute>();
|
|
NullReferenceCheckHelper.throwIfNull(land_auction_registry_attribute, () => $"land_auction_registry_attribute is null !!! - requestorId:{requestorId}");
|
|
|
|
var land_meta_id = land_auction_registry_attribute.LandMetaId;
|
|
|
|
var bid_price_order_cache_request = new LandAuctionBidPriceOrderCacheRequest(land_meta_id, redis_connector);
|
|
|
|
var lock_key = $"lock:{bid_price_order_cache_request.toKey()}";
|
|
var locker_id = $"locker_id:{requestorId}";
|
|
|
|
var is_success = await redis_lua_executor.tryAcquireLock(lock_key, locker_id, ttlSec);
|
|
if (false == is_success)
|
|
{
|
|
var err_msg = $"Failed to tryAcquireLock() !!! : LockKey:{lock_key}, LockerId:{locker_id}, TTLSec:{ttlSec} - {landAuction.toBasicString()}";
|
|
Log.getLogger().error(err_msg);
|
|
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
public static async Task<bool> tryReleaseWriteLockWithLandAuctionBidders(this LandAuction landAuction, REQUESTOR_ID requestorId)
|
|
{
|
|
var result = new Result();
|
|
|
|
var server_logic = GameServerApp.getServerLogic();
|
|
var redis_connector = server_logic.getRedisConnector();
|
|
var redis_lua_executor = server_logic.getRedisWithLuaScriptExecutor();
|
|
|
|
var land_auction_attribute = landAuction.getEntityAttribute<LandAuctionRegistryAttribute>();
|
|
NullReferenceCheckHelper.throwIfNull(land_auction_attribute, () => $"land_auction_attribute is null !!! - requestorId:{requestorId}");
|
|
|
|
var land_meta_id = land_auction_attribute.LandMetaId;
|
|
|
|
var bid_price_order_cache_request = new LandAuctionBidPriceOrderCacheRequest(land_meta_id, redis_connector);
|
|
|
|
var lock_key = $"lock:{bid_price_order_cache_request.toKey()}";
|
|
var locker_id = $"locker_id:{requestorId}";
|
|
|
|
var is_success = await redis_lua_executor.tyrReleaseLock(lock_key, locker_id);
|
|
if (false == is_success)
|
|
{
|
|
var err_msg = $"Failed to tyrReleaseLock() !!! : LockKey:{lock_key}, LockerId:{locker_id} - {landAuction.toBasicString()}";
|
|
Log.getLogger().warn(err_msg);
|
|
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
public static async Task<(bool, LandAuctionTopBidderCache?, LandAuctionTopBidderCache?, bool)> tryRankLandAuctionTopBidderCache(this LandAuction landAuction, REQUESTOR_ID requestorId, double bidPrice)
|
|
{
|
|
var server_logic = GameServerApp.getServerLogic();
|
|
var redis_connector = server_logic.getRedisConnector();
|
|
var redis_lua_executor = server_logic.getRedisWithLuaScriptExecutor();
|
|
|
|
var land_auction_action = landAuction.getEntityAction<LandAuctionAction>();
|
|
NullReferenceCheckHelper.throwIfNull(land_auction_action, () => $"land_auction_action is null !!! - requestorId:{requestorId}");
|
|
|
|
var land_meta_id = land_auction_action.getLandMetaId();
|
|
|
|
var bid_price_order_cache_request = new LandAuctionBidPriceOrderCacheRequest(land_meta_id, redis_connector);
|
|
|
|
( var is_success
|
|
, var curr_ranker_id, var curr_ranker_score
|
|
, var old_ranker_id, var old_ranker_score
|
|
, var is_top_change ) = await redis_lua_executor.tryPlaceTopRankOnly( bid_price_order_cache_request.toKey()
|
|
, requestorId
|
|
, bidPrice, bid_price_order_cache_request.toBlockKey());
|
|
if (false == is_success)
|
|
{
|
|
var err_msg = $"Failed to tryPlaceTopRankOnly() !!! : {bid_price_order_cache_request.toKeyAll()} - {landAuction.toBasicString()}";
|
|
Log.getLogger().error(err_msg);
|
|
|
|
return (false, null, null, false);
|
|
}
|
|
|
|
var curr_top_bidder = new LandAuctionTopBidderCache();
|
|
curr_top_bidder.LandMetaId = land_meta_id;
|
|
curr_top_bidder.HighestBidUserGuid = curr_ranker_id;
|
|
curr_top_bidder.HighestBidPrice = curr_ranker_score;
|
|
|
|
if (true == is_top_change)
|
|
{
|
|
if(false == old_ranker_id.isNullOrWhiteSpace())
|
|
{
|
|
var old_top_bidder = new LandAuctionTopBidderCache();
|
|
old_top_bidder.LandMetaId = land_meta_id;
|
|
old_top_bidder.HighestBidUserGuid = old_ranker_id;
|
|
old_top_bidder.HighestBidPrice = old_ranker_score;
|
|
|
|
return (true, curr_top_bidder, old_top_bidder, is_top_change);
|
|
}
|
|
}
|
|
|
|
return (true, curr_top_bidder, null, is_top_change);
|
|
}
|
|
|
|
public static async Task<(bool, LandAuctionTopBidderCache?)> tryGetLandAuctionTopBidderCacheWithBlock(this LandAuction landAuction)
|
|
{
|
|
var server_logic = GameServerApp.getServerLogic();
|
|
var redis_connector = server_logic.getRedisConnector();
|
|
var redis_lua_executor = server_logic.getRedisWithLuaScriptExecutor();
|
|
|
|
var land_auction_action = landAuction.getEntityAction<LandAuctionAction>();
|
|
NullReferenceCheckHelper.throwIfNull(land_auction_action, () => $"land_auction_action is null !!! - {landAuction.toBasicString()}");
|
|
|
|
var err_msg = string.Empty;
|
|
|
|
var land_meta_id = land_auction_action.getLandMetaId();
|
|
|
|
var bid_price_order_cache_request = new LandAuctionBidPriceOrderCacheRequest(land_meta_id, redis_connector);
|
|
|
|
( var is_success
|
|
, var is_top_found
|
|
, var top_ranker_id, var top_ranker_score ) = await redis_lua_executor.tryGetTopRankAndSetBlock( bid_price_order_cache_request.toKey()
|
|
, bid_price_order_cache_request.toBlockKey() );
|
|
if (false == is_success)
|
|
{
|
|
err_msg = $"Failed to tryGetTopRankAndSetBlock() !!! : {bid_price_order_cache_request.toKeyAll()} - {landAuction.toBasicString()}";
|
|
Log.getLogger().error(err_msg);
|
|
|
|
return (false, null);
|
|
}
|
|
|
|
if (true == is_top_found)
|
|
{
|
|
var curr_top_bidder = new LandAuctionTopBidderCache();
|
|
curr_top_bidder.LandMetaId = land_meta_id;
|
|
curr_top_bidder.HighestBidUserGuid = top_ranker_id;
|
|
curr_top_bidder.HighestBidPrice = top_ranker_score;
|
|
|
|
return (true, curr_top_bidder);
|
|
}
|
|
|
|
return (true, null);
|
|
}
|
|
|
|
public static async Task<(Result, LandAuctionTopBidderCache?)> tryGetLandAuctionTopBidderCache(this LandAuction landAuction)
|
|
{
|
|
var result = new Result();
|
|
var err_msg = string.Empty;
|
|
|
|
var server_logic = GameServerApp.getServerLogic();
|
|
var redis_connector = server_logic.getRedisConnector();
|
|
var redis_db = redis_connector.getDatabase();
|
|
NullReferenceCheckHelper.throwIfNull(redis_db, () => $"redis_db is null !!!");
|
|
|
|
var land_auction_attribute = landAuction.getEntityAttribute<LandAuctionRegistryAttribute>();
|
|
NullReferenceCheckHelper.throwIfNull(land_auction_attribute, () => $"land_auction_attribute is null !!!");
|
|
|
|
var top_bidder = new LandAuctionTopBidderCache();
|
|
var land_meta_id = land_auction_attribute.LandMetaId;
|
|
|
|
var bid_price_order_cache_request = new LandAuctionBidPriceOrderCacheRequest(land_meta_id, redis_connector);
|
|
|
|
try
|
|
{
|
|
var top_ranker = await redis_db.SortedSetRangeByRankWithScoresAsync(bid_price_order_cache_request.toKey(), 0, 0, Order.Descending);
|
|
if (top_ranker.Length == 0)
|
|
{
|
|
return (result, null);
|
|
}
|
|
|
|
top_bidder.LandMetaId = land_meta_id;
|
|
top_bidder.HighestBidUserGuid = top_ranker[0].Element.ToString();
|
|
top_bidder.HighestBidPrice = top_ranker[0].Score;
|
|
|
|
return (result, top_bidder);
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
var error_code = ServerErrorCode.TryCatchException;
|
|
err_msg = $"Exception !!!, Failed to perfom in tryGetLandAuctionTopBidderCache() !!! : exception:{e}, errorCode:{error_code}, key:{bid_price_order_cache_request.toKey()} - {landAuction.toBasicString()}";
|
|
result.setFail(error_code, err_msg);
|
|
Log.getLogger().error(result.toBasicString());
|
|
}
|
|
|
|
return (result, null);
|
|
}
|
|
|
|
public static async Task<bool> tryRemoveLandAuctionTopBidderBlockFromCache(this LandAuction landAuction)
|
|
{
|
|
var server_logic = GameServerApp.getServerLogic();
|
|
var redis_connector = server_logic.getRedisConnector();
|
|
var redis_lua_executor = server_logic.getRedisWithLuaScriptExecutor();
|
|
|
|
var err_msg = string.Empty;
|
|
|
|
var land_auction_action = landAuction.getEntityAction<LandAuctionAction>();
|
|
NullReferenceCheckHelper.throwIfNull(land_auction_action, () => $"land_auction_action is null !!! - {landAuction.toBasicString()}");
|
|
|
|
var land_meta_id = land_auction_action.getLandMetaId();
|
|
|
|
var bid_price_order_cache_request = new LandAuctionBidPriceOrderCacheRequest(land_meta_id, redis_connector);
|
|
|
|
var is_success = await redis_lua_executor.tryRemoveTopRankAndBlock( bid_price_order_cache_request.toKey()
|
|
, bid_price_order_cache_request.toBlockKey() );
|
|
if (false == is_success)
|
|
{
|
|
err_msg = $"Failed to tryRemoveTopRankAndBlock() !!! : {bid_price_order_cache_request.toKeyAll()} - {landAuction.toBasicString()}";
|
|
Log.getLogger().warn(err_msg);
|
|
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
public static async Task<bool> isExistTopBidderFromCache(this LandAuction landAuction)
|
|
{
|
|
var server_logic = GameServerApp.getServerLogic();
|
|
var redis_connector = server_logic.getRedisConnector();
|
|
|
|
var land_auction_attribute = landAuction.getEntityAttribute<LandAuctionRegistryAttribute>();
|
|
NullReferenceCheckHelper.throwIfNull(land_auction_attribute, () => $"land_auction_attribute is null !!! - {landAuction.toBasicString()}");
|
|
|
|
var land_meta_id = land_auction_attribute.LandMetaId;
|
|
|
|
var bid_price_order_cache_request = new LandAuctionBidPriceOrderCacheRequest(land_meta_id, redis_connector);
|
|
|
|
var is_exist_key = await bid_price_order_cache_request.isExistKey();
|
|
if (false == is_exist_key)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
public static async Task<bool> IsExistLandAuctionFromCache(this LandAuction landAuction, REQUESTOR_ID requestorId)
|
|
{
|
|
var server_logic = GameServerApp.getServerLogic();
|
|
var redis_connector = server_logic.getRedisConnector();
|
|
var redis_lua_executor = server_logic.getRedisWithLuaScriptExecutor();
|
|
|
|
var land_auction_attribute = landAuction.getEntityAttribute<LandAuctionRegistryAttribute>();
|
|
NullReferenceCheckHelper.throwIfNull(land_auction_attribute, () => $"land_auction_attribute is null !!! - requstorId:{requestorId}");
|
|
|
|
var land_meta_id = land_auction_attribute.LandMetaId;
|
|
|
|
var land_auction_cache_request = new LandAuctionCacheRequest(land_meta_id, redis_connector);
|
|
|
|
var is_exist_key = await land_auction_cache_request.isExistKey();
|
|
if (false == is_exist_key)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
public static async Task<(bool, string)> tryGetLandAuctionWithWriteLock(this LandAuction landAuction, REQUESTOR_ID requestorId, Int16 ttlSec)
|
|
{
|
|
var result = new Result();
|
|
var err_msg = string.Empty;
|
|
|
|
var server_logic = GameServerApp.getServerLogic();
|
|
var redis_connector = server_logic.getRedisConnector();
|
|
var redis_lua_executor = server_logic.getRedisWithLuaScriptExecutor();
|
|
|
|
var land_auction_attribute = landAuction.getEntityAttribute<LandAuctionRegistryAttribute>();
|
|
NullReferenceCheckHelper.throwIfNull(land_auction_attribute, () => $"land_auction_attribute is null !!! - requstorId:{requestorId}");
|
|
|
|
var land_meta_id = land_auction_attribute.LandMetaId;
|
|
|
|
var land_auction_cache_request = new LandAuctionCacheRequest(land_meta_id, redis_connector);
|
|
|
|
var lock_key = $"lock:{land_auction_cache_request.toKey()}";
|
|
var locker_id = $"locker_id:{requestorId}";
|
|
|
|
(var is_success, var read_data) = await redis_lua_executor.tryReadWithLock( lock_key, locker_id
|
|
, land_auction_cache_request.toKey(), ttlSec );
|
|
if (false == is_success)
|
|
{
|
|
err_msg = $"Failed to tryReadWithLock() !!! : LockKey:{land_auction_cache_request.toKey()}, LockerId:{locker_id}, TTLSec:{ttlSec} - {landAuction.toBasicString()}";
|
|
Log.getLogger().warn(err_msg);
|
|
|
|
return (false, string.Empty);
|
|
}
|
|
if(null == read_data)
|
|
{
|
|
return (true, string.Empty);
|
|
}
|
|
|
|
return (true, read_data);
|
|
}
|
|
|
|
public static async Task<bool> tryAcquireWriteLockWithLandAuction(this LandAuction landAuction, REQUESTOR_ID requestorId, Int16 ttlSec)
|
|
{
|
|
var result = new Result();
|
|
var err_msg = string.Empty;
|
|
|
|
var server_logic = GameServerApp.getServerLogic();
|
|
var redis_connector = server_logic.getRedisConnector();
|
|
var redis_lua_executor = server_logic.getRedisWithLuaScriptExecutor();
|
|
|
|
var land_auction_attribute = landAuction.getEntityAttribute<LandAuctionRegistryAttribute>();
|
|
NullReferenceCheckHelper.throwIfNull(land_auction_attribute, () => $"land_auction_attribute is null !!! - requestorId:{requestorId}");
|
|
|
|
var land_meta_id = land_auction_attribute.LandMetaId;
|
|
|
|
var land_auction_cache_request = new LandAuctionCacheRequest(land_meta_id, redis_connector);
|
|
|
|
var lock_key = $"lock:{land_auction_cache_request.toKey()}";
|
|
var locker_id = $"locker_id:{requestorId}";
|
|
|
|
var is_success = await redis_lua_executor.tryAcquireLock(lock_key, locker_id, ttlSec);
|
|
if (false == is_success)
|
|
{
|
|
err_msg = $"Failed to tryAcquireLock() !!! : LockKey:{land_auction_cache_request.toKey()}, LockerId:{locker_id}, TTLSec:{ttlSec} - {landAuction.toBasicString()}";
|
|
Log.getLogger().warn(err_msg);
|
|
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
public static async Task<bool> tryReleaseWriteLockWithLandAuction(this LandAuction landAuction, REQUESTOR_ID requestorid)
|
|
{
|
|
var result = new Result();
|
|
var err_msg = string.Empty;
|
|
|
|
var server_logic = GameServerApp.getServerLogic();
|
|
var redis_connector = server_logic.getRedisConnector();
|
|
var redis_lua_executor = server_logic.getRedisWithLuaScriptExecutor();
|
|
|
|
var land_auction_attribute = landAuction.getEntityAttribute<LandAuctionRegistryAttribute>();
|
|
NullReferenceCheckHelper.throwIfNull(land_auction_attribute, () => $"land_auction_attribute is null !!! - requstorId:{requestorid}");
|
|
|
|
var land_meta_id = land_auction_attribute.LandMetaId;
|
|
|
|
var land_auction_cache_request = new LandAuctionCacheRequest(land_meta_id, redis_connector);
|
|
|
|
var lock_key = $"lock:{land_auction_cache_request.toKey()}";
|
|
var locker_id = $"locker_id:{requestorid}";
|
|
|
|
var is_success = await redis_lua_executor.tyrReleaseLock(lock_key, locker_id);
|
|
if (false == is_success)
|
|
{
|
|
err_msg = $"Failed to tyrReleaseLock() !!! : LockKey:{land_auction_cache_request.toKey()}, LockerId:{locker_id} - {landAuction.toBasicString()}";
|
|
Log.getLogger().warn(err_msg);
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
public static async Task<bool> tryAcquireWriteLockWithLandAuctionReservation(REQUESTOR_ID requestorId, Int16 ttlSec)
|
|
{
|
|
var result = new Result();
|
|
var err_msg = string.Empty;
|
|
|
|
var server_logic = GameServerApp.getServerLogic();
|
|
var redis_connector = server_logic.getRedisConnector();
|
|
var redis_lua_executor = server_logic.getRedisWithLuaScriptExecutor();
|
|
|
|
var lock_key = $"land_auction_reservation:write_lock";
|
|
var locker_id = $"land_auction_reservation:locker_id:{requestorId}";
|
|
|
|
var is_success = await redis_lua_executor.tryAcquireLock(lock_key, locker_id, ttlSec);
|
|
if (false == is_success)
|
|
{
|
|
err_msg = $"Failed to tryAcquireLock() !!! : LockKey:{lock_key}, LockerId:{locker_id}, TTLSec:{ttlSec} - requstorId:{requestorId}";
|
|
Log.getLogger().warn(err_msg);
|
|
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
public static async Task<bool> tryReleaseWriteLockWithLandAuctionReservation(REQUESTOR_ID requestorId)
|
|
{
|
|
var result = new Result();
|
|
var err_msg = string.Empty;
|
|
|
|
var server_logic = GameServerApp.getServerLogic();
|
|
var redis_connector = server_logic.getRedisDb();
|
|
var redis_lua_executor = server_logic.getRedisWithLuaScriptExecutor();
|
|
|
|
var lock_key = $"land_auction_reservation:write_lock";
|
|
var locker_id = $"land_auction_reservation:locker_id:{requestorId}";
|
|
|
|
var is_success = await redis_lua_executor.tyrReleaseLock(lock_key, locker_id);
|
|
if (false == is_success)
|
|
{
|
|
err_msg = $"Failed to tyrReleaseLock() !!! : LockKey:{lock_key}, LockerId:{locker_id} - requstorId:{requestorId}";
|
|
Log.getLogger().warn(err_msg);
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
}
|
|
}
|