Skip to content

Commit

Permalink
Merge pull request #150 from Dartanlla/bugfix/fix-connection-leaking
Browse files Browse the repository at this point in the history
Some of the repository methods were not using Using and so it is poss…
  • Loading branch information
Dartanlla authored Feb 5, 2025
2 parents a397d75 + 1be3cc5 commit a8ffc04
Show file tree
Hide file tree
Showing 10 changed files with 195 additions and 168 deletions.
12 changes: 6 additions & 6 deletions src/OWSCharacterPersistence/Startup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -138,16 +138,16 @@ private void InitializeContainer(IServiceCollection services)
switch (dbBackend)
{
case "postgres":
container.Register<ICharactersRepository, OWSData.Repositories.Implementations.Postgres.CharactersRepository>(Lifestyle.Scoped);
container.Register<IUsersRepository, OWSData.Repositories.Implementations.Postgres.UsersRepository>(Lifestyle.Scoped);
container.Register<ICharactersRepository, OWSData.Repositories.Implementations.Postgres.CharactersRepository>(Lifestyle.Singleton);
container.Register<IUsersRepository, OWSData.Repositories.Implementations.Postgres.UsersRepository>(Lifestyle.Singleton);
break;
case "mysql":
container.Register<ICharactersRepository, OWSData.Repositories.Implementations.MySQL.CharactersRepository>(Lifestyle.Scoped);
container.Register<IUsersRepository, OWSData.Repositories.Implementations.MySQL.UsersRepository>(Lifestyle.Scoped);
container.Register<ICharactersRepository, OWSData.Repositories.Implementations.MySQL.CharactersRepository>(Lifestyle.Singleton);
container.Register<IUsersRepository, OWSData.Repositories.Implementations.MySQL.UsersRepository>(Lifestyle.Singleton);
break;
default: // Default to MSSQL
container.Register<ICharactersRepository, OWSData.Repositories.Implementations.MSSQL.CharactersRepository>(Lifestyle.Scoped);
container.Register<IUsersRepository, OWSData.Repositories.Implementations.MSSQL.UsersRepository>(Lifestyle.Scoped);
container.Register<ICharactersRepository, OWSData.Repositories.Implementations.MSSQL.CharactersRepository>(Lifestyle.Singleton);
container.Register<IUsersRepository, OWSData.Repositories.Implementations.MSSQL.UsersRepository>(Lifestyle.Singleton);
break;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@ public async Task<IEnumerable<DefaultCustomData>> GetDefaultCustomCharacterData(
parameters.Add("@CustomerGUID", customerGUID);
parameters.Add("@DefaultSetName", defaultSetName);

outputDefaultCustomCharacterDataRows = await Connection.QueryAsync<DefaultCustomData>(GenericQueries.GetDefaultCharacterCustomDataByName,
outputDefaultCustomCharacterDataRows = await Connection.QueryAsync<DefaultCustomData>(GenericQueries.GetDefaultCustomCharacterDataByDefaultSetName,
parameters,
commandType: CommandType.Text);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,7 @@ public async Task<IEnumerable<DefaultCustomData>> GetDefaultCustomCharacterData(
parameters.Add("@CustomerGUID", customerGUID);
parameters.Add("@DefaultSetName", defaultSetName);

outputDefaultCustomCharacterDataRows = await Connection.QueryAsync<DefaultCustomData>(GenericQueries.GetDefaultCharacterCustomDataByName,
outputDefaultCustomCharacterDataRows = await Connection.QueryAsync<DefaultCustomData>(GenericQueries.GetDefaultCustomCharacterDataByDefaultSetName,
parameters,
commandType: CommandType.Text);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,47 +30,52 @@ public CharactersRepository(IOptions<StorageOptions> storageOptions)

public async Task AddCharacterToMapInstanceByCharName(Guid customerGUID, string characterName, int mapInstanceID)
{
IDbConnection conn = Connection;
conn.Open();
using IDbTransaction transaction = conn.BeginTransaction();
try
using (Connection)
{
var parameters = new DynamicParameters();
parameters.Add("@CustomerGUID", customerGUID);
parameters.Add("@CharName", characterName);
parameters.Add("@MapInstanceID", mapInstanceID);
using (IDbTransaction transaction = Connection.BeginTransaction())
{
try
{
var parameters = new DynamicParameters();
parameters.Add("@CustomerGUID", customerGUID);
parameters.Add("@CharName", characterName);
parameters.Add("@MapInstanceID", mapInstanceID);

var outputCharacter = await Connection.QuerySingleOrDefaultAsync<Characters>(GenericQueries.GetCharacterIDByName,
parameters,
commandType: CommandType.Text);
var outputCharacter = await Connection.QuerySingleOrDefaultAsync<Characters>(
GenericQueries.GetCharacterIDByName,
parameters,
commandType: CommandType.Text);

var outputZone = await Connection.QuerySingleOrDefaultAsync<Maps>(GenericQueries.GetZoneName,
parameters,
commandType: CommandType.Text);
var outputZone = await Connection.QuerySingleOrDefaultAsync<Maps>(GenericQueries.GetZoneName,
parameters,
commandType: CommandType.Text);

if (outputCharacter.CharacterId > 0)
{
parameters.Add("@CharacterID", outputCharacter.CharacterId);
parameters.Add("@ZoneName", outputZone.ZoneName);
if (outputCharacter.CharacterId > 0)
{
parameters.Add("@CharacterID", outputCharacter.CharacterId);
parameters.Add("@ZoneName", outputZone.ZoneName);

await Connection.ExecuteAsync(GenericQueries.RemoveCharacterFromAllInstances,
parameters,
commandType: CommandType.Text);
await Connection.ExecuteAsync(GenericQueries.RemoveCharacterFromAllInstances,
parameters,
commandType: CommandType.Text);

await Connection.ExecuteAsync(GenericQueries.AddCharacterToInstance,
parameters,
commandType: CommandType.Text);
await Connection.ExecuteAsync(GenericQueries.AddCharacterToInstance,
parameters,
commandType: CommandType.Text);

await Connection.ExecuteAsync(GenericQueries.UpdateCharacterZone,
parameters,
commandType: CommandType.Text);
await Connection.ExecuteAsync(GenericQueries.UpdateCharacterZone,
parameters,
commandType: CommandType.Text);
}

transaction.Commit();
}
catch
{
transaction.Rollback();
throw new Exception("Database Exception in AddCharacterToMapInstanceByCharName!");
}
}
transaction.Commit();
}
catch
{
transaction.Rollback();
throw new Exception("Database Exception in AddCharacterToMapInstanceByCharName!");
}
}

Expand Down Expand Up @@ -135,43 +140,48 @@ public async Task<MapInstances> CheckMapInstanceStatus(Guid customerGUID, int ma

public async Task CleanUpInstances(Guid customerGUID)
{
IDbConnection conn = Connection;
conn.Open();
using IDbTransaction transaction = conn.BeginTransaction();
try
using (Connection)
{
var parameters = new DynamicParameters();
parameters.Add("@CustomerGUID", customerGUID);
parameters.Add("@CharacterMinutes", 1); // TODO Add Configuration Parameter
parameters.Add("@MapMinutes", 2); // TODO Add Configuration Parameter
using (IDbTransaction transaction = Connection.BeginTransaction())
{
try
{
var parameters = new DynamicParameters();
parameters.Add("@CustomerGUID", customerGUID);
parameters.Add("@CharacterMinutes", 1); // TODO Add Configuration Parameter
parameters.Add("@MapMinutes", 2); // TODO Add Configuration Parameter

await transaction.ExecuteAsync(PostgresQueries.RemoveCharactersFromAllInactiveInstances,
parameters,
commandType: CommandType.Text);
await transaction.ExecuteAsync(PostgresQueries.RemoveCharactersFromAllInactiveInstances,
parameters,
commandType: CommandType.Text);

var outputMapInstances = await transaction.QueryAsync<int>(PostgresQueries.GetAllInactiveMapInstances,
parameters,
commandType: CommandType.Text);
var outputMapInstances = await transaction.QueryAsync<int>(
PostgresQueries.GetAllInactiveMapInstances,
parameters,
commandType: CommandType.Text);

if (outputMapInstances.Any())
{
parameters.Add("@MapInstances", outputMapInstances);
if (outputMapInstances.Any())
{
parameters.Add("@MapInstances", outputMapInstances);

await transaction.ExecuteAsync(PostgresQueries.RemoveCharacterFromInstances,
parameters,
commandType: CommandType.Text);
await transaction.ExecuteAsync(PostgresQueries.RemoveCharacterFromInstances,
parameters,
commandType: CommandType.Text);

await transaction.ExecuteAsync(PostgresQueries.RemoveMapInstances,
parameters,
commandType: CommandType.Text);
await transaction.ExecuteAsync(PostgresQueries.RemoveMapInstances,
parameters,
commandType: CommandType.Text);

}

transaction.Commit();
}
catch
{
transaction.Rollback();
throw new Exception("Database Exception in CleanUpInstances!");
}
}
transaction.Commit();
}
catch
{
transaction.Rollback();
throw new Exception("Database Exception in CleanUpInstances!");
}
}

Expand Down Expand Up @@ -247,6 +257,21 @@ public async Task<JoinMapByCharName> JoinMapByCharName(Guid customerGUID, string
bool enableAutoLoopback = false;
bool noPortForwarding = false;

outputObject = new JoinMapByCharName()
{
ServerIP = serverIp,
Port = port,
WorldServerID = -1,
WorldServerIP = worldServerIp,
WorldServerPort = worldServerPort,
MapInstanceID = mapInstanceID,
MapNameToStart = mapNameToStart,
MapInstanceStatus = -1,
NeedToStartupMap = false,
EnableAutoLoopback = false,
NoPortForwarding = false
};

using (Connection)
{
var parameters = new DynamicParameters();
Expand All @@ -259,29 +284,31 @@ public async Task<JoinMapByCharName> JoinMapByCharName(Guid customerGUID, string
parameters,
commandType: CommandType.Text);

if (outputMap == null)
{
Console.WriteLine($"CharactersRepository: JoinMapByCharName - Unable to find Zone Name: {zoneName} for CustomerGUID: {customerGUID} Check your Maps table for this row!");

return outputObject;
}

Characters outputCharacter = await Connection.QuerySingleOrDefaultAsync<Characters>(GenericQueries.GetCharacterByName,
parameters,
commandType: CommandType.Text);

if (outputCharacter == null)
{
Console.WriteLine($"CharactersRepository: JoinMapByCharName - Unable to find Character by Name: {characterName} for CustomerGUID: {customerGUID}");

return outputObject;
}

Customers outputCustomer = await Connection.QuerySingleOrDefaultAsync<Customers>(GenericQueries.GetCustomer,
parameters,
commandType: CommandType.Text);

if (outputCharacter == null)
if (outputCustomer == null)
{
outputObject = new JoinMapByCharName() {
ServerIP = serverIp,
Port = port,
WorldServerID = -1,
WorldServerIP = worldServerIp,
WorldServerPort = worldServerPort,
MapInstanceID = mapInstanceID,
MapNameToStart = mapNameToStart,
MapInstanceStatus = -1,
NeedToStartupMap = false,
EnableAutoLoopback = enableAutoLoopback,
NoPortForwarding = noPortForwarding
};
Console.WriteLine($"CharactersRepository: JoinMapByCharName - Unable to find Customer for CustomerGUID: {customerGUID}");

return outputObject;
}
Expand Down Expand Up @@ -372,14 +399,13 @@ public async Task<MapInstances> SpinUpInstance(Guid customerGUID, string zoneNam

if (outputWorldServers.Any())
{
int? firstAvailable = null;
foreach (var worldServer in outputWorldServers)
{
var portsInUse = await Connection.QueryAsync<int>(GenericQueries.GetPortsInUseByWorldServer,
parameters,
commandType: CommandType.Text);

firstAvailable = Enumerable.Range(worldServer.StartingMapInstancePort, worldServer.StartingMapInstancePort + worldServer.MaxNumberOfInstances)
int? firstAvailable = Enumerable.Range(worldServer.StartingMapInstancePort, worldServer.StartingMapInstancePort + worldServer.MaxNumberOfInstances)
.Except(portsInUse)
.FirstOrDefault();

Expand All @@ -394,11 +420,11 @@ public async Task<MapInstances> SpinUpInstance(Guid customerGUID, string zoneNam
parameters.Add("@MapID", outputMaps.MapId);
parameters.Add("@Port", firstAvailable);

int outputMapInstanceID = await Connection.QuerySingleOrDefaultAsync<int>(PostgresQueries.AddMapInstance,
int outputMapInstanceId = await Connection.QuerySingleOrDefaultAsync<int>(PostgresQueries.AddMapInstance,
parameters,
commandType: CommandType.Text);

parameters.Add("@MapInstanceID", outputMapInstanceID);
parameters.Add("@MapInstanceID", outputMapInstanceId);

MapInstances outputMapInstances = await Connection.QuerySingleOrDefaultAsync<MapInstances>(GenericQueries.GetMapInstance,
parameters,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -121,34 +121,37 @@ await Connection.QueryFirstOrDefaultAsync(GenericQueries.UpdateMapInstanceStatus

public async Task<SuccessAndErrorMessage> ShutDownWorldServer(Guid customerGUID, int worldServerID)
{
IDbConnection conn = Connection;
conn.Open();
using IDbTransaction transaction = conn.BeginTransaction();
try
{
var parameter = new DynamicParameters();
parameter.Add("@CustomerGUID", customerGUID);
parameter.Add("@WorldServerID", worldServerID);
parameter.Add("@ServerStatus", 0);

await Connection.ExecuteAsync(GenericQueries.RemoveAllCharactersFromAllInstancesByWorldID,
parameter,
commandType: CommandType.Text);

await Connection.ExecuteAsync(GenericQueries.RemoveAllMapInstancesForWorldServer,
parameter,
commandType: CommandType.Text);

await Connection.ExecuteAsync(GenericQueries.UpdateWorldServerStatus,
parameter,
commandType: CommandType.Text);

transaction.Commit();
}
catch
using (Connection)
{
transaction.Rollback();
throw new Exception("Database Exception in ShutDownWorldServer!");
using (IDbTransaction transaction = Connection.BeginTransaction())
{
try
{
var parameter = new DynamicParameters();
parameter.Add("@CustomerGUID", customerGUID);
parameter.Add("@WorldServerID", worldServerID);
parameter.Add("@ServerStatus", 0);

await Connection.ExecuteAsync(GenericQueries.RemoveAllCharactersFromAllInstancesByWorldID,
parameter,
commandType: CommandType.Text);

await Connection.ExecuteAsync(GenericQueries.RemoveAllMapInstancesForWorldServer,
parameter,
commandType: CommandType.Text);

await Connection.ExecuteAsync(GenericQueries.UpdateWorldServerStatus,
parameter,
commandType: CommandType.Text);

transaction.Commit();
}
catch
{
transaction.Rollback();
throw new Exception("Database Exception in ShutDownWorldServer!");
}
}
}

SuccessAndErrorMessage output = new SuccessAndErrorMessage()
Expand Down
Loading

0 comments on commit a8ffc04

Please sign in to comment.