CoinBombs and GemBombs now queue their amounts to prevent excessive database calls.

Removed excess account row information retrieval on web api when awarding gems/coins.
Added account specific transactional locks in webapi.
This commit is contained in:
Jonathan Williams 2014-11-05 14:42:11 -08:00
parent ecad60eee3
commit 4254225462
9 changed files with 454 additions and 360 deletions

View File

@ -28,6 +28,7 @@ public class DonationManager extends MiniPlugin
private Object _donorLock = new Object();
private NautHashMap<Player, NautHashMap<String, Integer>> _gemQueue = new NautHashMap<Player, NautHashMap<String, Integer>>();
private NautHashMap<Player, NautHashMap<String, Integer>> _coinQueue = new NautHashMap<Player, NautHashMap<String, Integer>>();
public DonationManager(JavaPlugin plugin, String webAddress)
{
@ -247,4 +248,56 @@ public class DonationManager extends MiniPlugin
}
}, caller, name, uuid.toString(), amount);
}
public void RewardCoinsLater(final String caller, final Player player, final int amount)
{
if (!_coinQueue.containsKey(player))
_coinQueue.put(player, new NautHashMap<String, Integer>());
int totalAmount = amount;
if (_coinQueue.get(player).containsKey(caller))
totalAmount += _coinQueue.get(player).get(caller);
_coinQueue.get(player).put(caller, totalAmount);
//Do Temp Change
Donor donor = Get(player.getName());
if (donor != null)
donor.addCoins(amount);
}
@EventHandler
public void UpdateCoinQueue(UpdateEvent event)
{
if (event.getType() != UpdateType.SLOWER)
return;
for (Player player : _coinQueue.keySet())
{
String caller = null;
int total = 0;
for (String curCaller : _coinQueue.get(player).keySet())
{
caller = curCaller;
total += _coinQueue.get(player).get(curCaller);
}
if (caller == null)
continue;
//Actually Add Gems
RewardCoins(null, caller, player.getName(), player.getUniqueId(), total, false);
System.out.println("Queue Added [" + player + "] with Coins [" + total + "] for [" + caller + "]");
//Clean
_coinQueue.get(player).clear();
}
//Clean
_coinQueue.clear();
}
}

View File

@ -110,7 +110,7 @@ public class ItemCoinBomb extends ItemGadget
event.setCancelled(true);
event.getItem().remove();
Manager.getDonationManager().RewardCoins(null, this.GetName() + " Pickup", event.getPlayer().getName(), event.getPlayer().getUniqueId(), 4);
Manager.getDonationManager().RewardCoinsLater(GetName() + " Pickup", event.getPlayer(), 4);
event.getPlayer().getWorld().playSound(event.getPlayer().getLocation(), Sound.ORB_PICKUP, 1f, 2f);

View File

@ -189,7 +189,7 @@ public class ItemGemBomb extends ItemGadget
event.setCancelled(true);
event.getItem().remove();
Manager.getDonationManager().RewardGems(null, this.GetName() + " Pickup", event.getPlayer().getName(), event.getPlayer().getUniqueId(), 4);
Manager.getDonationManager().RewardGemsLater(GetName() + " Pickup", event.getPlayer(), 4);
event.getPlayer().getWorld().playSound(event.getPlayer().getLocation(), Sound.ORB_PICKUP, 1f, 2f);
}

View File

@ -143,7 +143,7 @@ public class MorphVillager extends MorphGadget implements IThrown
event.setCancelled(true);
event.getItem().remove();
Manager.getDonationManager().RewardGems(null, this.GetName() + " Pickup", event.getPlayer().getName(), event.getPlayer().getUniqueId(), 16);
Manager.getDonationManager().RewardGemsLater(GetName() + " Pickup", event.getPlayer(), 16);
event.getPlayer().getWorld().playSound(event.getPlayer().getLocation(), Sound.ORB_PICKUP, 1f, 2f);
}

View File

@ -2,10 +2,14 @@
{
public class GemRewardToken
{
public int OriginalBalance;
public string Name { get; set; }
public string Source { get; set; }
public int Amount { get; set; }
public int Retries { get; set; }
}
}

View File

@ -7,5 +7,7 @@
public string Rank { get; set; }
public bool Perm { get; set; }
public int Retries { get; set; }
}
}

View File

@ -16,6 +16,7 @@
using LOC.Website.Common.Contexts;
using System.Data.Entity.Infrastructure;
using System.Transactions;
using System.Runtime.CompilerServices;
public class AccountAdministrator : IAccountAdministrator
{
@ -23,7 +24,7 @@
private readonly IGameServerMonitor _gameServerMonitor;
private readonly ILogger _logger;
private readonly object _transactionLock = new object();
private static ConditionalWeakTable<string, object> _accountLocks = new ConditionalWeakTable<string, object>();
public AccountAdministrator(INautilusRepositoryFactory nautilusRepositoryFactory, ILogger logger)
{
@ -64,14 +65,32 @@
}
}
private object getAccountLock(string name)
{
object lockObject = null;
if (!_accountLocks.TryGetValue(name, out lockObject))
{
lockObject = new object();
_accountLocks.Add(name, lockObject);
}
return lockObject;
}
public Account Login(LoginRequestToken loginToken)
{
lock (getAccountLock(loginToken.Name))
{
using (var repository = _repositoryFactory.CreateRepository())
{
var account = repository.Where<Account>(x => x.Uuid == loginToken.Uuid).FirstOrDefault() ?? CreateAccount(loginToken, repository);
var account = repository.Where<Account>(x => x.Uuid == loginToken.Uuid).FirstOrDefault() ?? (repository.Where<Account>(x => x.Name == loginToken.Name).FirstOrDefault() ?? CreateAccount(loginToken, repository));
account.LoadNavigationProperties(repository.Context);
account.LastLogin = DateTime.Now.Ticks;
if (String.IsNullOrEmpty(account.Uuid))
account.Uuid = loginToken.Uuid;
// Expire punishments
if (account.Punishments != null)
{
@ -107,6 +126,7 @@
return account;
}
}
}
public void Logout(string name)
{
@ -193,11 +213,12 @@
}
public bool GemReward(GemRewardToken token)
{
lock (getAccountLock(token.Name))
{
using (var repository = _repositoryFactory.CreateRepository())
{
var account = repository.Where<Account>(x => x.Name == token.Name).FirstOrDefault();
account.LoadNavigationProperties(repository.Context);
if (account == null)
return false;
@ -220,20 +241,23 @@
repository.Edit(account);
repository.CommitChanges();
}
}
return true;
}
public bool CoinReward(GemRewardToken token)
{
lock (getAccountLock(token.Name))
{
using (var repository = _repositoryFactory.CreateRepository())
{
var account = repository.Where<Account>(x => x.Name == token.Name).FirstOrDefault();
account.LoadNavigationProperties(repository.Context);
if (account == null)
return false;
token.OriginalBalance = account.Coins;
account.Coins += token.Amount;
if (!token.Source.Contains("Earned") && !token.Source.Contains("Tutorial") && !token.Source.Contains("Parkour"))
@ -251,6 +275,8 @@
repository.Edit(account);
repository.CommitChanges();
}
}
return true;
@ -357,10 +383,10 @@
}
public string PurchaseGameSalesPackage(PurchaseToken token)
{
lock (_transactionLock)
{
try
{
lock (getAccountLock(token.AccountName))
{
using (var repository = _repositoryFactory.CreateRepository())
{
@ -390,7 +416,7 @@
repository.Edit(account);
if (account.PvpTransactions == null)
account.PvpTransactions = new List<GameTransaction> {accountTransaction};
account.PvpTransactions = new List<GameTransaction> { accountTransaction };
else
{
account.PvpTransactions.Add(accountTransaction);
@ -403,12 +429,12 @@
return TransactionResponse.Success.ToString();
}
}
}
catch (Exception exception)
{
return TransactionResponse.Failed.ToString() + ":" + exception.Message;
}
}
}
public bool AccountExists(string name)
{
@ -419,6 +445,8 @@
}
public void SaveCustomBuild(CustomBuildToken token)
{
lock (getAccountLock(token.PlayerName))
{
using (var repository = _repositoryFactory.CreateRepository())
{
@ -459,6 +487,7 @@
repository.CommitChanges();
}
}
}
public void Ignore(string accountName, string ignoredPlayer)
{
@ -485,10 +514,10 @@
}
public string PurchaseUnknownSalesPackage(UnknownPurchaseToken token)
{
lock (_transactionLock)
{
try
{
lock (getAccountLock(token.AccountName))
{
using (var repository = _repositoryFactory.CreateRepository())
{
@ -532,16 +561,17 @@
return TransactionResponse.Success.ToString();
}
}
}
catch (Exception exception)
{
return TransactionResponse.Failed.ToString() + ":" + exception.Message;
}
}
}
public string UpdateRank(RankUpdateToken token)
{
Rank rank = null;
var expire = DateTime.Now.AddMonths(1).AddMilliseconds(-DateTime.Now.Millisecond);
try
{
@ -559,8 +589,6 @@
if (rank == null)
return account.Rank.ToString();
var expire = DateTime.Now.AddMonths(1).AddMilliseconds(-DateTime.Now.Millisecond);
account.Rank = rank;
account.RankExpire = expire;
account.RankPerm = token.Perm;
@ -574,7 +602,14 @@
using (var repository = _repositoryFactory.CreateRepository())
{
var account = repository.Where<Account>(x => String.Equals(x.Name, token.Name)).Include(x => x.Rank).FirstOrDefault();
_logger.Log("INFO", "ACCOUNT " + account.Name + "'s rank is " + account.Rank.Name + " " + (account.RankPerm ? "Permanently" : "Monthly") + "." + " Rank expire : " + account.RankExpire.ToString());
if (token.Retries >= 3)
_logger.Log("ERROR", "Applying UpdateRank, retried 3 times and something didn't stick.");
else if (!account.Rank.Name.Equals(token.Rank) || account.RankPerm != token.Perm || account.RankExpire != expire)
{
token.Retries++;
UpdateRank(token);
}
}
}
catch (Exception ex)

File diff suppressed because it is too large Load Diff

Binary file not shown.