Fix communities queries having the ability to lock the server mysql connections due to nesting, improve RepositoryBase by allowing all the methods to be passed a Connection object to reuse it, and fix duplicate invites throwing an sql error

This commit is contained in:
AlexTheCoder 2016-12-17 00:06:23 -05:00 committed by cnr
parent cc3842f019
commit 1190d4a427
3 changed files with 208 additions and 132 deletions

View File

@ -470,7 +470,10 @@ public class CommunityManager extends MiniDbClientPlugin<CommunityMemberData>
{ {
if (_repo.deleteInviteToCommunity(community.getId(), target)) if (_repo.deleteInviteToCommunity(community.getId(), target))
{ {
UtilPlayer.message(sender, F.main(getName(), "You have revoked " + F.name(target) + "'s invitation to join " + F.name(community.getName()) + "!")); if (!community.getMembers().containsKey(sender.getUniqueId()))
{
UtilPlayer.message(sender, F.main(getName(), "You have revoked " + F.name(target) + "'s invitation to join " + F.name(community.getName()) + "!"));
}
new CommunityUnInvite(community.getId(), sender.getName(), target, Managers.get(CoreClientManager.class).loadUUIDFromDB(target).toString(), true).publish(); new CommunityUnInvite(community.getId(), sender.getName(), target, Managers.get(CoreClientManager.class).loadUUIDFromDB(target).toString(), true).publish();
} }
else else

View File

@ -40,7 +40,7 @@ public class CommunityRepository extends MinecraftRepository
private static final String ADD_TO_COMMUNITY = "INSERT INTO communityMembers (accountId, communityId, communityRole, readingChat) VALUES (?, ?, ?, true);"; private static final String ADD_TO_COMMUNITY = "INSERT INTO communityMembers (accountId, communityId, communityRole, readingChat) VALUES (?, ?, ?, true);";
private static final String UPDATE_COMMUNITY_SETTING = "INSERT INTO communitySettings (settingId, communityId, settingValue) VALUES (?, ?, ?) ON DUPLICATE KEY UPDATE settingValue=VALUES(settingValue);"; private static final String UPDATE_COMMUNITY_SETTING = "INSERT INTO communitySettings (settingId, communityId, settingValue) VALUES (?, ?, ?) ON DUPLICATE KEY UPDATE settingValue=VALUES(settingValue);";
private static final String UPDATE_COMMUNITY_NAME = "UPDATE communities SET name=? WHERE id=?;"; private static final String UPDATE_COMMUNITY_NAME = "UPDATE communities SET name=? WHERE id=?;";
private static final String INVITE_TO_COMMUNITY = "INSERT INTO communityInvites (accountId, communityId) SELECT a.id AS accountId, ? FROM accounts as a WHERE a.name = ? ORDER BY a.lastLogin DESC LIMIT 1;"; private static final String INVITE_TO_COMMUNITY = "INSERT INTO communityInvites (accountId, communityId) SELECT a.id AS accountId, ? FROM accounts as a WHERE a.name = ? ORDER BY a.lastLogin DESC LIMIT 1 ON DUPLICATE KEY UPDATE communityInvites.id=communityInvites.id;";
private static final String DELETE_INVITE_TO_COMMUNITY = "DELETE i FROM communityInvites AS i INNER JOIN accounts as a ON i.accountId = a.id WHERE a.name = ? AND i.communityId=?;"; private static final String DELETE_INVITE_TO_COMMUNITY = "DELETE i FROM communityInvites AS i INNER JOIN accounts as a ON i.accountId = a.id WHERE a.name = ? AND i.communityId=?;";
private static final String ADD_JOIN_REQUEST = "INSERT INTO communityJoinRequests (accountId, communityId) VALUES (?, ?);"; private static final String ADD_JOIN_REQUEST = "INSERT INTO communityJoinRequests (accountId, communityId) VALUES (?, ?);";
private static final String REMOVE_JOIN_REQUEST = "DELETE FROM communityJoinRequests WHERE accountId=? AND communityId=?;"; private static final String REMOVE_JOIN_REQUEST = "DELETE FROM communityJoinRequests WHERE accountId=? AND communityId=?;";
@ -62,136 +62,150 @@ public class CommunityRepository extends MinecraftRepository
public void loadCommunity(int communityId, final Map<Integer, Community> communityMap) public void loadCommunity(int communityId, final Map<Integer, Community> communityMap)
{ {
executeQuery(GET_COMMUNITY_BY_ID, resultSet -> try (Connection connection = getConnection())
{ {
if (resultSet.next()) executeQuery(connection, GET_COMMUNITY_BY_ID, resultSet ->
{ {
final int id = resultSet.getInt("id"); if (resultSet.next())
final String cName = resultSet.getString("name");
final Community community = new Community(id, cName);
executeQuery(GET_COMMUNITY_MEMBERS, memberSet ->
{ {
while (memberSet.next()) final int id = resultSet.getInt("id");
final String cName = resultSet.getString("name");
final Community community = new Community(id, cName);
executeQuery(connection, GET_COMMUNITY_MEMBERS, memberSet ->
{ {
final int accountId = memberSet.getInt("accountId"); while (memberSet.next())
final String name = memberSet.getString("name");
final UUID uuid = UUID.fromString(memberSet.getString("uuid"));
final CommunityRole role = CommunityRole.parseRole(memberSet.getString("communityRole"));
final long timeSinceOnline = memberSet.getTimestamp(6).getTime() - memberSet.getTimestamp(5).getTime();
boolean readingChat = memberSet.getBoolean("readingChat");
final int owns = memberSet.getInt(8);
CommunityMemberInfo info = new CommunityMemberInfo(name, uuid, accountId, role, timeSinceOnline);
PlayerStatus status = _repo.getElement(name);
if (status != null)
{ {
info.update(name, role, timeSinceOnline, true, status.getServer()); final int accountId = memberSet.getInt("accountId");
final String name = memberSet.getString("name");
final UUID uuid = UUID.fromString(memberSet.getString("uuid"));
final CommunityRole role = CommunityRole.parseRole(memberSet.getString("communityRole"));
final long timeSinceOnline = memberSet.getTimestamp(6).getTime() - memberSet.getTimestamp(5).getTime();
boolean readingChat = memberSet.getBoolean("readingChat");
final int owns = memberSet.getInt(8);
CommunityMemberInfo info = new CommunityMemberInfo(name, uuid, accountId, role, timeSinceOnline);
PlayerStatus status = _repo.getElement(name);
if (status != null)
{
info.update(name, role, timeSinceOnline, true, status.getServer());
}
info.ReadingChat = readingChat;
info.OwnsCommunity = owns > 0;
community.getMembers().put(info.UUID, info);
} }
info.ReadingChat = readingChat; }, new ColumnInt("communityId", community.getId()));
info.OwnsCommunity = owns > 0;
community.getMembers().put(info.UUID, info);
}
}, new ColumnInt("communityId", community.getId()));
executeQuery(GET_COMMUNITY_JOIN_REQUESTS, requestSet -> executeQuery(connection, GET_COMMUNITY_JOIN_REQUESTS, requestSet ->
{
while (requestSet.next())
{ {
final int accountId = requestSet.getInt("accountId"); while (requestSet.next())
final UUID uuid = UUID.fromString(requestSet.getString("uuid"));
final String name = requestSet.getString("name");
community.getJoinRequests().put(uuid, new CommunityJoinRequestInfo(name, uuid, accountId));
}
}, new ColumnInt("communityId", community.getId()));
executeQuery(GET_COMMUNITY_SETTINGS, settingSet ->
{
while (settingSet.next())
{
final int settingId = settingSet.getInt("settingId");
final String value = settingSet.getString("settingValue");
CommunitySetting setting = CommunitySetting.getSetting(settingId);
if (setting != null)
{ {
setting.parseValueInto(value, community); final int accountId = requestSet.getInt("accountId");
} final UUID uuid = UUID.fromString(requestSet.getString("uuid"));
} final String name = requestSet.getString("name");
}, new ColumnInt("communityId", community.getId()));
communityMap.put(community.getId(), community); community.getJoinRequests().put(uuid, new CommunityJoinRequestInfo(name, uuid, accountId));
} }
}, new ColumnInt("id", communityId)); }, new ColumnInt("communityId", community.getId()));
executeQuery(connection, GET_COMMUNITY_SETTINGS, settingSet ->
{
while (settingSet.next())
{
final int settingId = settingSet.getInt("settingId");
final String value = settingSet.getString("settingValue");
CommunitySetting setting = CommunitySetting.getSetting(settingId);
if (setting != null)
{
setting.parseValueInto(value, community);
}
}
}, new ColumnInt("communityId", community.getId()));
communityMap.put(community.getId(), community);
}
}, new ColumnInt("id", communityId));
}
catch (SQLException e)
{
e.printStackTrace();
}
} }
public void loadCommunities(final Map<Integer, Community> communityMap) public void loadCommunities(final Map<Integer, Community> communityMap)
{ {
executeQuery(GET_ALL_COMMUNITIES, resultSet -> try (Connection connection = getConnection())
{ {
Map<Integer, Community> resultant = new HashMap<>(); executeQuery(connection, GET_ALL_COMMUNITIES, resultSet ->
while (resultSet.next())
{ {
final int id = resultSet.getInt("id"); Map<Integer, Community> resultant = new HashMap<>();
final String cName = resultSet.getString("name"); while (resultSet.next())
final Community community = new Community(id, cName);
executeQuery(GET_COMMUNITY_MEMBERS, memberSet ->
{ {
while (memberSet.next()) final int id = resultSet.getInt("id");
final String cName = resultSet.getString("name");
final Community community = new Community(id, cName);
executeQuery(connection, GET_COMMUNITY_MEMBERS, memberSet ->
{ {
final int accountId = memberSet.getInt("accountId"); while (memberSet.next())
final String name = memberSet.getString("name");
final UUID uuid = UUID.fromString(memberSet.getString("uuid"));
final CommunityRole role = CommunityRole.parseRole(memberSet.getString("communityRole"));
final long timeSinceOnline = memberSet.getTimestamp(6).getTime() - memberSet.getTimestamp(5).getTime();
boolean readingChat = memberSet.getBoolean("readingChat");
final int owns = memberSet.getInt(8);
CommunityMemberInfo info = new CommunityMemberInfo(name, uuid, accountId, role, timeSinceOnline);
PlayerStatus status = _repo.getElement(name);
if (status != null)
{ {
info.update(name, role, timeSinceOnline, true, status.getServer()); final int accountId = memberSet.getInt("accountId");
final String name = memberSet.getString("name");
final UUID uuid = UUID.fromString(memberSet.getString("uuid"));
final CommunityRole role = CommunityRole.parseRole(memberSet.getString("communityRole"));
final long timeSinceOnline = memberSet.getTimestamp(6).getTime() - memberSet.getTimestamp(5).getTime();
boolean readingChat = memberSet.getBoolean("readingChat");
final int owns = memberSet.getInt(8);
CommunityMemberInfo info = new CommunityMemberInfo(name, uuid, accountId, role, timeSinceOnline);
PlayerStatus status = _repo.getElement(name);
if (status != null)
{
info.update(name, role, timeSinceOnline, true, status.getServer());
}
info.ReadingChat = readingChat;
info.OwnsCommunity = owns > 0;
community.getMembers().put(info.UUID, info);
} }
info.ReadingChat = readingChat; }, new ColumnInt("communityId", community.getId()));
info.OwnsCommunity = owns > 0;
community.getMembers().put(info.UUID, info);
}
}, new ColumnInt("communityId", community.getId()));
executeQuery(GET_COMMUNITY_JOIN_REQUESTS, requestSet -> executeQuery(connection, GET_COMMUNITY_JOIN_REQUESTS, requestSet ->
{
while (requestSet.next())
{ {
final int accountId = requestSet.getInt("accountId"); while (requestSet.next())
final UUID uuid = UUID.fromString(requestSet.getString("uuid"));
final String name = requestSet.getString("name");
community.getJoinRequests().put(uuid, new CommunityJoinRequestInfo(name, uuid, accountId));
}
}, new ColumnInt("communityId", community.getId()));
executeQuery(GET_COMMUNITY_SETTINGS, settingSet ->
{
while (settingSet.next())
{
final int settingId = settingSet.getInt("settingId");
final String value = settingSet.getString("settingValue");
CommunitySetting setting = CommunitySetting.getSetting(settingId);
if (setting != null)
{ {
setting.parseValueInto(value, community); final int accountId = requestSet.getInt("accountId");
final UUID uuid = UUID.fromString(requestSet.getString("uuid"));
final String name = requestSet.getString("name");
community.getJoinRequests().put(uuid, new CommunityJoinRequestInfo(name, uuid, accountId));
} }
} }, new ColumnInt("communityId", community.getId()));
}, new ColumnInt("communityId", community.getId()));
resultant.put(community.getId(), community); executeQuery(connection, GET_COMMUNITY_SETTINGS, settingSet ->
} {
while (settingSet.next())
{
final int settingId = settingSet.getInt("settingId");
final String value = settingSet.getString("settingValue");
communityMap.clear(); CommunitySetting setting = CommunitySetting.getSetting(settingId);
communityMap.putAll(resultant); if (setting != null)
}, new ColumnVarChar("region", 5, _us ? "US" : "EU")); {
setting.parseValueInto(value, community);
}
}
}, new ColumnInt("communityId", community.getId()));
resultant.put(community.getId(), community);
}
communityMap.clear();
communityMap.putAll(resultant);
}, new ColumnVarChar("region", 5, _us ? "US" : "EU"));
}
catch (SQLException e)
{
e.printStackTrace();
}
} }
public void updateMembersAndJoinRequests(LinkedList<Community> communities) public void updateMembersAndJoinRequests(LinkedList<Community> communities)
@ -372,28 +386,42 @@ public class CommunityRepository extends MinecraftRepository
public void createCommunity(String name, int leaderAccount, Callback<Integer> idCallback) public void createCommunity(String name, int leaderAccount, Callback<Integer> idCallback)
{ {
executeInsert(CREATE_COMMUNITY, resultSet -> try (Connection connection = getConnection())
{ {
if (resultSet.next()) executeInsert(connection, CREATE_COMMUNITY, resultSet ->
{ {
int id = resultSet.getInt(1); if (resultSet.next())
executeUpdate(ADD_TO_COMMUNITY, new ColumnInt("accountId", leaderAccount), new ColumnInt("communityId", id), new ColumnVarChar("communityRole", 20, CommunityRole.LEADER.toString())); {
idCallback.run(id); int id = resultSet.getInt(1);
} executeUpdate(connection, ADD_TO_COMMUNITY, new ColumnInt("accountId", leaderAccount), new ColumnInt("communityId", id), new ColumnVarChar("communityRole", 20, CommunityRole.LEADER.toString()));
else idCallback.run(id);
{ }
idCallback.run(-1); else
} {
}, new ColumnVarChar("name", 15, name), new ColumnVarChar("region", 5, _us ? "US" : "EU")); idCallback.run(-1);
}
}, new ColumnVarChar("name", 15, name), new ColumnVarChar("region", 5, _us ? "US" : "EU"));
}
catch (SQLException e)
{
e.printStackTrace();
}
} }
public void deleteCommunity(int communityId) public void deleteCommunity(int communityId)
{ {
executeUpdate("DELETE FROM communities WHERE id=?;", new ColumnInt("id", communityId)); try (Connection connection = getConnection())
executeUpdate("DELETE FROM communitySettings WHERE communityId=?;", new ColumnInt("communityId", communityId)); {
executeUpdate("DELETE FROM communityMembers WHERE communityId=?;", new ColumnInt("communityId", communityId)); executeUpdate(connection, "DELETE FROM communities WHERE id=?;", new ColumnInt("id", communityId));
executeUpdate("DELETE FROM communityInvites WHERE communityId=?;", new ColumnInt("communityId", communityId)); executeUpdate(connection, "DELETE FROM communitySettings WHERE communityId=?;", new ColumnInt("communityId", communityId));
executeUpdate("DELETE FROM communityJoinRequests WHERE communityId=?", new ColumnInt("communityId", communityId)); executeUpdate(connection, "DELETE FROM communityMembers WHERE communityId=?;", new ColumnInt("communityId", communityId));
executeUpdate(connection, "DELETE FROM communityInvites WHERE communityId=?;", new ColumnInt("communityId", communityId));
executeUpdate(connection, "DELETE FROM communityJoinRequests WHERE communityId=?", new ColumnInt("communityId", communityId));
}
catch (SQLException e)
{
e.printStackTrace();
}
} }
public void setReadingChat(int accountId, int communityId, boolean reading) public void setReadingChat(int accountId, int communityId, boolean reading)

View File

@ -76,6 +76,11 @@ public abstract class RepositoryBase
} }
} }
protected int executeUpdate(Connection connection, String query, Column<?>...columns)
{
return executeInsert(connection, query, null, columns);
}
/** /**
* Execute a query against the repository. * Execute a query against the repository.
* @param query - the concatenated query to execute in string form. * @param query - the concatenated query to execute in string form.
@ -87,13 +92,12 @@ public abstract class RepositoryBase
return executeInsert(query, null, columns); return executeInsert(query, null, columns);
} }
protected int executeInsert(String query, ResultSetCallable callable, Column<?>...columns) protected int executeInsert(Connection connection, String query, ResultSetCallable callable, Column<?>...columns)
{ {
int affectedRows = 0; int affectedRows = 0;
// Automatic resource management for handling/closing objects. // Automatic resource management for handling/closing objects.
try ( try (
Connection connection = getConnection();
PreparedStatement preparedStatement = connection.prepareStatement(query, Statement.RETURN_GENERATED_KEYS) PreparedStatement preparedStatement = connection.prepareStatement(query, Statement.RETURN_GENERATED_KEYS)
) )
{ {
@ -121,6 +125,29 @@ public abstract class RepositoryBase
return affectedRows; return affectedRows;
} }
protected int executeInsert(String query, ResultSetCallable callable, Column<?>...columns)
{
int affectedRows = 0;
// Automatic resource management for handling/closing objects.
try (
Connection connection = getConnection();
)
{
affectedRows = executeInsert(connection, query, callable, columns);
}
catch (SQLException exception)
{
exception.printStackTrace();
}
catch (Exception exception)
{
exception.printStackTrace();
}
return affectedRows;
}
protected void executeQuery(PreparedStatement statement, ResultSetCallable callable, Column<?>...columns) protected void executeQuery(PreparedStatement statement, ResultSetCallable callable, Column<?>...columns)
{ {
try try
@ -148,11 +175,10 @@ public abstract class RepositoryBase
} }
} }
protected void executeQuery(String query, ResultSetCallable callable, Column<?>...columns) protected void executeQuery(Connection connection, String query, ResultSetCallable callable, Column<?>...columns)
{ {
// Automatic resource management for handling/closing objects. // Automatic resource management for handling/closing objects.
try ( try (
Connection connection = getConnection();
PreparedStatement preparedStatement = connection.prepareStatement(query) PreparedStatement preparedStatement = connection.prepareStatement(query)
) )
{ {
@ -167,4 +193,23 @@ public abstract class RepositoryBase
exception.printStackTrace(); exception.printStackTrace();
} }
} }
protected void executeQuery(String query, ResultSetCallable callable, Column<?>...columns)
{
// Automatic resource management for handling/closing objects.
try (
Connection connection = getConnection();
)
{
executeQuery(connection, query, callable, columns);
}
catch (SQLException exception)
{
exception.printStackTrace();
}
catch (Exception exception)
{
exception.printStackTrace();
}
}
} }