Add SyncUtils#vertxWrap. This is something we wrap all mongo callbacks with so all business logic is ran on vertx worker threads. This is important for 2 reasons:

1. Running all of our logic on the vertx threads makes sense, as we're a vertx application. (This also allows us to utilize vertx's thread pool logic + config, instead of relying on mongo's thread pool)
2. The more important one, it allows exceptions to be processed (instead of swallowed by mongo) with relevant context information.

There is an overhead to the thread switching we'll be doing because of this, but doing all of our work on a better thought out thread pool and (more importantly) having stack traces completely make this change worth the overhead.
This commit is contained in:
Colin McDonald 2016-07-09 17:19:20 -04:00
parent 5de25c498b
commit d55325d255
14 changed files with 118 additions and 82 deletions

View File

@ -11,6 +11,7 @@ import lombok.AllArgsConstructor;
import lombok.Getter; import lombok.Getter;
import net.frozenorb.apiv3.APIv3; import net.frozenorb.apiv3.APIv3;
import net.frozenorb.apiv3.actor.ActorType; import net.frozenorb.apiv3.actor.ActorType;
import net.frozenorb.apiv3.util.SyncUtils;
import org.bson.Document; import org.bson.Document;
import java.time.Instant; import java.time.Instant;
@ -32,15 +33,15 @@ public final class AccessToken {
@Getter private Instant lastUpdatedAt; @Getter private Instant lastUpdatedAt;
public static void findAll(SingleResultCallback<List<AccessToken>> callback) { public static void findAll(SingleResultCallback<List<AccessToken>> callback) {
accessTokensCollection.find().into(new LinkedList<>(), callback); accessTokensCollection.find().into(new LinkedList<>(), SyncUtils.vertxWrap(callback));
} }
public static void findById(String id, SingleResultCallback<AccessToken> callback) { public static void findById(String id, SingleResultCallback<AccessToken> callback) {
accessTokensCollection.find(new Document("_id", id)).first(callback); accessTokensCollection.find(new Document("_id", id)).first(SyncUtils.vertxWrap(callback));
} }
public static void findByNameAndType(String actorName, ActorType actorType, SingleResultCallback<AccessToken> callback) { public static void findByNameAndType(String actorName, ActorType actorType, SingleResultCallback<AccessToken> callback) {
accessTokensCollection.find(new Document("actorName", actorName).append("actorType", actorType.name())).first(callback); accessTokensCollection.find(new Document("actorName", actorName).append("actorType", actorType.name())).first(SyncUtils.vertxWrap(callback));
} }
private AccessToken() {} // For Jackson private AccessToken() {} // For Jackson
@ -60,15 +61,15 @@ public final class AccessToken {
} }
public void insert(SingleResultCallback<Void> callback) { public void insert(SingleResultCallback<Void> callback) {
accessTokensCollection.insertOne(this, callback); accessTokensCollection.insertOne(this, SyncUtils.vertxWrap(callback));
} }
public void save(SingleResultCallback<UpdateResult> callback) { public void save(SingleResultCallback<UpdateResult> callback) {
accessTokensCollection.replaceOne(new Document("_id", id), this, callback); accessTokensCollection.replaceOne(new Document("_id", id), this, SyncUtils.vertxWrap(callback));
} }
public void delete(SingleResultCallback<DeleteResult> callback) { public void delete(SingleResultCallback<DeleteResult> callback) {
accessTokensCollection.deleteOne(new Document("_id", id), callback); accessTokensCollection.deleteOne(new Document("_id", id), SyncUtils.vertxWrap(callback));
} }
} }

View File

@ -10,6 +10,7 @@ import net.frozenorb.apiv3.APIv3;
import net.frozenorb.apiv3.actor.Actor; import net.frozenorb.apiv3.actor.Actor;
import net.frozenorb.apiv3.actor.ActorType; import net.frozenorb.apiv3.actor.ActorType;
import net.frozenorb.apiv3.auditLog.AuditLogActionType; import net.frozenorb.apiv3.auditLog.AuditLogActionType;
import net.frozenorb.apiv3.util.SyncUtils;
import org.bson.Document; import org.bson.Document;
import org.bson.types.ObjectId; import org.bson.types.ObjectId;
@ -38,15 +39,15 @@ public final class AuditLogEntry {
@Getter private Map<String, Object> metadata; @Getter private Map<String, Object> metadata;
public static void findPaginated(Document query, int skip, int pageSize, SingleResultCallback<List<AuditLogEntry>> callback) { public static void findPaginated(Document query, int skip, int pageSize, SingleResultCallback<List<AuditLogEntry>> callback) {
auditLogCollection.find(query).sort(new Document("performedAt", -1)).skip(skip).limit(pageSize).into(new LinkedList<>(), callback); auditLogCollection.find(query).sort(new Document("performedAt", -1)).skip(skip).limit(pageSize).into(new LinkedList<>(), SyncUtils.vertxWrap(callback));
} }
public static void findById(String id, SingleResultCallback<AuditLogEntry> callback) { public static void findById(String id, SingleResultCallback<AuditLogEntry> callback) {
auditLogCollection.find(new Document("_id", id)).first(callback); auditLogCollection.find(new Document("_id", id)).first(SyncUtils.vertxWrap(callback));
} }
public static void find(Document query, SingleResultCallback<List<AuditLogEntry>> callback) { public static void find(Document query, SingleResultCallback<List<AuditLogEntry>> callback) {
auditLogCollection.find(query).into(new LinkedList<>(), callback); auditLogCollection.find(query).into(new LinkedList<>(), SyncUtils.vertxWrap(callback));
} }
private AuditLogEntry() {} // For Jackson private AuditLogEntry() {} // For Jackson
@ -65,7 +66,7 @@ public final class AuditLogEntry {
} }
public void insert(SingleResultCallback<Void> callback) { public void insert(SingleResultCallback<Void> callback) {
auditLogCollection.insertOne(this, callback); auditLogCollection.insertOne(this, SyncUtils.vertxWrap(callback));
} }
} }

View File

@ -10,6 +10,7 @@ import fr.javatic.mongo.jacksonCodec.objectId.Id;
import lombok.Getter; import lombok.Getter;
import lombok.Setter; import lombok.Setter;
import net.frozenorb.apiv3.APIv3; import net.frozenorb.apiv3.APIv3;
import net.frozenorb.apiv3.util.SyncUtils;
import org.bson.Document; import org.bson.Document;
import java.time.Instant; import java.time.Instant;
@ -45,7 +46,7 @@ public final class BannedAsn {
} }
public static void updateCache() { public static void updateCache() {
bannedAsnsCollection.find().into(new LinkedList<>(), (bannedAsns, error) -> { bannedAsnsCollection.find().into(new LinkedList<>(), SyncUtils.vertxWrap((bannedAsns, error) -> {
if (error != null) { if (error != null) {
error.printStackTrace(); error.printStackTrace();
return; return;
@ -59,7 +60,7 @@ public final class BannedAsn {
bannedAsnIdCache = working; bannedAsnIdCache = working;
bannedAsnCache = bannedAsns; bannedAsnCache = bannedAsns;
}); }));
} }
private BannedAsn() {} // For Jackson private BannedAsn() {} // For Jackson
@ -79,17 +80,17 @@ public final class BannedAsn {
public void insert(SingleResultCallback<Void> callback) { public void insert(SingleResultCallback<Void> callback) {
bannedAsnCache.add(this); bannedAsnCache.add(this);
bannedAsnIdCache.put(id, this); bannedAsnIdCache.put(id, this);
bannedAsnsCollection.insertOne(this, callback); bannedAsnsCollection.insertOne(this, SyncUtils.vertxWrap(callback));
} }
public void save(SingleResultCallback<UpdateResult> callback) { public void save(SingleResultCallback<UpdateResult> callback) {
bannedAsnsCollection.replaceOne(new Document("_id", id), this, callback); bannedAsnsCollection.replaceOne(new Document("_id", id), this, SyncUtils.vertxWrap(callback));
} }
public void delete(SingleResultCallback<DeleteResult> callback) { public void delete(SingleResultCallback<DeleteResult> callback) {
bannedAsnCache.remove(this); bannedAsnCache.remove(this);
bannedAsnIdCache.remove(id); bannedAsnIdCache.remove(id);
bannedAsnsCollection.deleteOne(new Document("_id", id), callback); bannedAsnsCollection.deleteOne(new Document("_id", id), SyncUtils.vertxWrap(callback));
} }
} }

View File

@ -11,6 +11,7 @@ import fr.javatic.mongo.jacksonCodec.objectId.Id;
import lombok.Getter; import lombok.Getter;
import lombok.Setter; import lombok.Setter;
import net.frozenorb.apiv3.APIv3; import net.frozenorb.apiv3.APIv3;
import net.frozenorb.apiv3.util.SyncUtils;
import org.bson.Document; import org.bson.Document;
import java.time.Instant; import java.time.Instant;
@ -46,7 +47,7 @@ public final class BannedCellCarrier {
} }
public static void updateCache() { public static void updateCache() {
bannedCellCarriersCollection.find().into(new LinkedList<>(), (bannedCellCarriers, error) -> { bannedCellCarriersCollection.find().into(new LinkedList<>(), SyncUtils.vertxWrap((bannedCellCarriers, error) -> {
if (error != null) { if (error != null) {
error.printStackTrace(); error.printStackTrace();
return; return;
@ -60,7 +61,7 @@ public final class BannedCellCarrier {
bannedCellCarrierIdCache = working; bannedCellCarrierIdCache = working;
bannedCellCarrierCache = bannedCellCarriers; bannedCellCarrierCache = bannedCellCarriers;
}); }));
} }
private BannedCellCarrier() {} // For Jackson private BannedCellCarrier() {} // For Jackson
@ -80,17 +81,17 @@ public final class BannedCellCarrier {
public void insert(SingleResultCallback<Void> callback) { public void insert(SingleResultCallback<Void> callback) {
bannedCellCarrierCache.add(this); bannedCellCarrierCache.add(this);
bannedCellCarrierIdCache.put(id, this); bannedCellCarrierIdCache.put(id, this);
bannedCellCarriersCollection.insertOne(this, callback); bannedCellCarriersCollection.insertOne(this, SyncUtils.vertxWrap(callback));
} }
public void save(SingleResultCallback<UpdateResult> callback) { public void save(SingleResultCallback<UpdateResult> callback) {
bannedCellCarriersCollection.replaceOne(new Document("_id", id), this, callback); bannedCellCarriersCollection.replaceOne(new Document("_id", id), this, SyncUtils.vertxWrap(callback));
} }
public void delete(SingleResultCallback<DeleteResult> callback) { public void delete(SingleResultCallback<DeleteResult> callback) {
bannedCellCarrierCache.remove(this); bannedCellCarrierCache.remove(this);
bannedCellCarrierIdCache.remove(id); bannedCellCarrierIdCache.remove(id);
bannedCellCarriersCollection.deleteOne(new Document("_id", id), callback); bannedCellCarriersCollection.deleteOne(new Document("_id", id), SyncUtils.vertxWrap(callback));
} }
} }

View File

@ -10,6 +10,7 @@ import lombok.Getter;
import net.frozenorb.apiv3.APIv3; import net.frozenorb.apiv3.APIv3;
import net.frozenorb.apiv3.actor.Actor; import net.frozenorb.apiv3.actor.Actor;
import net.frozenorb.apiv3.actor.ActorType; import net.frozenorb.apiv3.actor.ActorType;
import net.frozenorb.apiv3.util.SyncUtils;
import net.frozenorb.apiv3.util.TimeUtils; import net.frozenorb.apiv3.util.TimeUtils;
import org.bson.Document; import org.bson.Document;
import org.bson.types.ObjectId; import org.bson.types.ObjectId;
@ -38,19 +39,19 @@ public final class IpBan {
@Getter private String removalReason; @Getter private String removalReason;
public static void findPaginated(Document query, int skip, int pageSize, SingleResultCallback<List<IpBan>> callback) { public static void findPaginated(Document query, int skip, int pageSize, SingleResultCallback<List<IpBan>> callback) {
ipBansCollection.find(query).sort(new Document("addedAt", -1)).skip(skip).limit(pageSize).into(new LinkedList<>(), callback); ipBansCollection.find(query).sort(new Document("addedAt", -1)).skip(skip).limit(pageSize).into(new LinkedList<>(), SyncUtils.vertxWrap(callback));
} }
public static void findById(String id, SingleResultCallback<IpBan> callback) { public static void findById(String id, SingleResultCallback<IpBan> callback) {
ipBansCollection.find(new Document("_id", id)).first(callback); ipBansCollection.find(new Document("_id", id)).first(SyncUtils.vertxWrap(callback));
} }
public static void findByIp(String userIp, SingleResultCallback<List<IpBan>> callback) { public static void findByIp(String userIp, SingleResultCallback<List<IpBan>> callback) {
ipBansCollection.find(new Document("userIp", userIp)).into(new LinkedList<>(), callback); ipBansCollection.find(new Document("userIp", userIp)).into(new LinkedList<>(), SyncUtils.vertxWrap(callback));
} }
public static void findByIpGrouped(Iterable<String> userIps, SingleResultCallback<Map<String, List<IpBan>>> callback) { public static void findByIpGrouped(Iterable<String> userIps, SingleResultCallback<Map<String, List<IpBan>>> callback) {
ipBansCollection.find(new Document("userIp", new Document("$in", userIps))).into(new LinkedList<>(), (ipBans, error) -> { ipBansCollection.find(new Document("userIp", new Document("$in", userIps))).into(new LinkedList<>(), SyncUtils.vertxWrap((ipBans, error) -> {
if (error != null) { if (error != null) {
callback.onResult(null, error); callback.onResult(null, error);
} else { } else {
@ -66,7 +67,7 @@ public final class IpBan {
callback.onResult(result, null); callback.onResult(result, null);
} }
}); }));
} }
private IpBan() {} // For Jackson private IpBan() {} // For Jackson
@ -145,7 +146,7 @@ public final class IpBan {
} }
public void insert(SingleResultCallback<Void> callback) { public void insert(SingleResultCallback<Void> callback) {
ipBansCollection.insertOne(this, callback); ipBansCollection.insertOne(this, SyncUtils.vertxWrap(callback));
} }
public void delete(User removedBy, String reason, SingleResultCallback<UpdateResult> callback) { public void delete(User removedBy, String reason, SingleResultCallback<UpdateResult> callback) {
@ -153,7 +154,7 @@ public final class IpBan {
this.removedAt = Instant.now(); this.removedAt = Instant.now();
this.removalReason = reason; this.removalReason = reason;
ipBansCollection.replaceOne(new Document("_id", id), this, callback); ipBansCollection.replaceOne(new Document("_id", id), this, SyncUtils.vertxWrap(callback));
} }
} }

View File

@ -11,6 +11,7 @@ import lombok.Getter;
import net.frozenorb.apiv3.APIv3; import net.frozenorb.apiv3.APIv3;
import net.frozenorb.apiv3.maxmind.MaxMindResult; import net.frozenorb.apiv3.maxmind.MaxMindResult;
import net.frozenorb.apiv3.util.MaxMindUtils; import net.frozenorb.apiv3.util.MaxMindUtils;
import net.frozenorb.apiv3.util.SyncUtils;
import org.bson.Document; import org.bson.Document;
import java.time.Instant; import java.time.Instant;
@ -28,11 +29,11 @@ public final class IpIntel {
@Getter private MaxMindResult result; @Getter private MaxMindResult result;
public static void findAll(SingleResultCallback<List<IpIntel>> callback) { public static void findAll(SingleResultCallback<List<IpIntel>> callback) {
ipIntelCollection.find().sort(new Document("lastSeenAt", -1)).into(new LinkedList<>(), callback); ipIntelCollection.find().sort(new Document("lastSeenAt", -1)).into(new LinkedList<>(), SyncUtils.vertxWrap(callback));
} }
public static void findById(String id, SingleResultCallback<IpIntel> callback) { public static void findById(String id, SingleResultCallback<IpIntel> callback) {
ipIntelCollection.find(new Document("_id", id)).first(callback); ipIntelCollection.find(new Document("_id", id)).first(SyncUtils.vertxWrap(callback));
} }
public static void findOrCreateById(String id, SingleResultCallback<IpIntel> callback) { public static void findOrCreateById(String id, SingleResultCallback<IpIntel> callback) {
@ -65,7 +66,7 @@ public final class IpIntel {
} }
public static void findOrCreateByIdGrouped(Collection<String> search, SingleResultCallback<Map<String, IpIntel>> callback) { public static void findOrCreateByIdGrouped(Collection<String> search, SingleResultCallback<Map<String, IpIntel>> callback) {
ipIntelCollection.find(new Document("_id", new Document("$in", search))).into(new LinkedList<>(), (existingIntel, error) -> { ipIntelCollection.find(new Document("_id", new Document("$in", search))).into(new LinkedList<>(), SyncUtils.vertxWrap((existingIntel, error) -> {
if (error != null) { if (error != null) {
callback.onResult(null, error); callback.onResult(null, error);
return; return;
@ -101,14 +102,14 @@ public final class IpIntel {
IpIntel newIpIntel = new IpIntel(ip, maxMindResult); IpIntel newIpIntel = new IpIntel(ip, maxMindResult);
ipIntelCollection.insertOne(newIpIntel, (ignored, error3) -> { ipIntelCollection.insertOne(newIpIntel, SyncUtils.vertxWrap((ignored, error3) -> {
if (error3 != null) { if (error3 != null) {
createNewIntelFuture.fail(error3); createNewIntelFuture.fail(error3);
} else { } else {
result.put(ip, newIpIntel); result.put(ip, newIpIntel);
createNewIntelFuture.complete(); createNewIntelFuture.complete();
} }
}); }));
}); });
}); });
@ -119,7 +120,7 @@ public final class IpIntel {
callback.onResult(result, null); callback.onResult(result, null);
} }
}); });
}); }));
} }
private IpIntel() {} // For Jackson private IpIntel() {} // For Jackson

View File

@ -8,6 +8,7 @@ import fr.javatic.mongo.jacksonCodec.objectId.Id;
import lombok.Getter; import lombok.Getter;
import lombok.Setter; import lombok.Setter;
import net.frozenorb.apiv3.APIv3; import net.frozenorb.apiv3.APIv3;
import net.frozenorb.apiv3.util.SyncUtils;
import org.bson.Document; import org.bson.Document;
import java.util.LinkedList; import java.util.LinkedList;
@ -24,11 +25,11 @@ public final class NotificationTemplate {
@Getter @Setter private String body; @Getter @Setter private String body;
public static void findAll(SingleResultCallback<List<NotificationTemplate>> callback) { public static void findAll(SingleResultCallback<List<NotificationTemplate>> callback) {
notificationTemplatesCollection.find().into(new LinkedList<>(), callback); notificationTemplatesCollection.find().into(new LinkedList<>(), SyncUtils.vertxWrap(callback));
} }
public static void findById(String id, SingleResultCallback<NotificationTemplate> callback) { public static void findById(String id, SingleResultCallback<NotificationTemplate> callback) {
notificationTemplatesCollection.find(new Document("_id", id)).first(callback); notificationTemplatesCollection.find(new Document("_id", id)).first(SyncUtils.vertxWrap(callback));
} }
private NotificationTemplate() {} // For Jackson private NotificationTemplate() {} // For Jackson
@ -59,11 +60,11 @@ public final class NotificationTemplate {
} }
public void insert(SingleResultCallback<Void> callback) { public void insert(SingleResultCallback<Void> callback) {
notificationTemplatesCollection.insertOne(this, callback); notificationTemplatesCollection.insertOne(this, SyncUtils.vertxWrap(callback));
} }
public void delete(SingleResultCallback<DeleteResult> callback) { public void delete(SingleResultCallback<DeleteResult> callback) {
notificationTemplatesCollection.deleteOne(new Document("_id", id), callback); notificationTemplatesCollection.deleteOne(new Document("_id", id), SyncUtils.vertxWrap(callback));
} }
} }

View File

@ -7,6 +7,7 @@ import fr.javatic.mongo.jacksonCodec.objectId.Id;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Getter; import lombok.Getter;
import net.frozenorb.apiv3.APIv3; import net.frozenorb.apiv3.APIv3;
import net.frozenorb.apiv3.util.SyncUtils;
import net.frozenorb.apiv3.util.ZangUtils; import net.frozenorb.apiv3.util.ZangUtils;
import net.frozenorb.apiv3.zang.ZangResult; import net.frozenorb.apiv3.zang.ZangResult;
import org.bson.Document; import org.bson.Document;
@ -26,11 +27,11 @@ public final class PhoneIntel {
@Getter private ZangResult result; @Getter private ZangResult result;
public static void findAll(SingleResultCallback<List<PhoneIntel>> callback) { public static void findAll(SingleResultCallback<List<PhoneIntel>> callback) {
phoneIntelCollection.find().sort(new Document("lastSeenAt", -1)).into(new LinkedList<>(), callback); phoneIntelCollection.find().sort(new Document("lastSeenAt", -1)).into(new LinkedList<>(), SyncUtils.vertxWrap(callback));
} }
public static void findById(String id, SingleResultCallback<PhoneIntel> callback) { public static void findById(String id, SingleResultCallback<PhoneIntel> callback) {
phoneIntelCollection.find(new Document("_id", id)).first(callback); phoneIntelCollection.find(new Document("_id", id)).first(SyncUtils.vertxWrap(callback));
} }
public static void findOrCreateById(String id, SingleResultCallback<PhoneIntel> callback) { public static void findOrCreateById(String id, SingleResultCallback<PhoneIntel> callback) {
@ -46,13 +47,13 @@ public final class PhoneIntel {
} else { } else {
PhoneIntel newPhoneIntel = new PhoneIntel(id, zangResult); PhoneIntel newPhoneIntel = new PhoneIntel(id, zangResult);
phoneIntelCollection.insertOne(newPhoneIntel, (ignored, error3) -> { phoneIntelCollection.insertOne(newPhoneIntel, SyncUtils.vertxWrap((ignored, error3) -> {
if (error3 != null) { if (error3 != null) {
callback.onResult(null, error3); callback.onResult(null, error3);
} else { } else {
callback.onResult(newPhoneIntel, null); callback.onResult(newPhoneIntel, null);
} }
}); }));
} }
}); });
} }

View File

@ -10,6 +10,7 @@ import lombok.Getter;
import net.frozenorb.apiv3.APIv3; import net.frozenorb.apiv3.APIv3;
import net.frozenorb.apiv3.actor.Actor; import net.frozenorb.apiv3.actor.Actor;
import net.frozenorb.apiv3.actor.ActorType; import net.frozenorb.apiv3.actor.ActorType;
import net.frozenorb.apiv3.util.SyncUtils;
import net.frozenorb.apiv3.util.TimeUtils; import net.frozenorb.apiv3.util.TimeUtils;
import org.bson.Document; import org.bson.Document;
import org.bson.types.ObjectId; import org.bson.types.ObjectId;
@ -44,19 +45,19 @@ public final class Punishment {
public static void findByType(Collection<PunishmentType> types, SingleResultCallback<List<Punishment>> callback) { public static void findByType(Collection<PunishmentType> types, SingleResultCallback<List<Punishment>> callback) {
Collection<String> convertedTypes = types.stream().map(PunishmentType::name).collect(Collectors.toList()); Collection<String> convertedTypes = types.stream().map(PunishmentType::name).collect(Collectors.toList());
punishmentsCollection.find(new Document("type", new Document("$in", convertedTypes))).into(new LinkedList<>(), callback); punishmentsCollection.find(new Document("type", new Document("$in", convertedTypes))).into(new LinkedList<>(), SyncUtils.vertxWrap(callback));
} }
public static void findPaginated(Document query, int skip, int pageSize, SingleResultCallback<List<Punishment>> callback) { public static void findPaginated(Document query, int skip, int pageSize, SingleResultCallback<List<Punishment>> callback) {
punishmentsCollection.find(query).sort(new Document("addedAt", -1)).skip(skip).limit(pageSize).into(new LinkedList<>(), callback); punishmentsCollection.find(query).sort(new Document("addedAt", -1)).skip(skip).limit(pageSize).into(new LinkedList<>(), SyncUtils.vertxWrap(callback));
} }
public static void findById(String id, SingleResultCallback<Punishment> callback) { public static void findById(String id, SingleResultCallback<Punishment> callback) {
punishmentsCollection.find(new Document("_id", id)).first(callback); punishmentsCollection.find(new Document("_id", id)).first(SyncUtils.vertxWrap(callback));
} }
public static void findByLinkedIpBanId(String id, SingleResultCallback<Punishment> callback) { public static void findByLinkedIpBanId(String id, SingleResultCallback<Punishment> callback) {
punishmentsCollection.find(new Document("linkedIpBanId", id)).first(callback); punishmentsCollection.find(new Document("linkedIpBanId", id)).first(SyncUtils.vertxWrap(callback));
} }
public static void findByUser(User user, SingleResultCallback<List<Punishment>> callback) { public static void findByUser(User user, SingleResultCallback<List<Punishment>> callback) {
@ -64,11 +65,11 @@ public final class Punishment {
} }
public static void findByUser(UUID user, SingleResultCallback<List<Punishment>> callback) { public static void findByUser(UUID user, SingleResultCallback<List<Punishment>> callback) {
punishmentsCollection.find(new Document("user", user)).into(new LinkedList<>(), callback); punishmentsCollection.find(new Document("user", user)).into(new LinkedList<>(), SyncUtils.vertxWrap(callback));
} }
public static void findByUserGrouped(Iterable<UUID> users, SingleResultCallback<Map<UUID, List<Punishment>>> callback) { public static void findByUserGrouped(Iterable<UUID> users, SingleResultCallback<Map<UUID, List<Punishment>>> callback) {
punishmentsCollection.find(new Document("user", new Document("$in", users))).into(new LinkedList<>(), (punishments, error) -> { punishmentsCollection.find(new Document("user", new Document("$in", users))).into(new LinkedList<>(), SyncUtils.vertxWrap((punishments, error) -> {
if (error != null) { if (error != null) {
callback.onResult(null, error); callback.onResult(null, error);
} else { } else {
@ -84,7 +85,7 @@ public final class Punishment {
callback.onResult(result, null); callback.onResult(result, null);
} }
}); }));
} }
public static void findByUserAndType(User user, Collection<PunishmentType> types, SingleResultCallback<List<Punishment>> callback) { public static void findByUserAndType(User user, Collection<PunishmentType> types, SingleResultCallback<List<Punishment>> callback) {
@ -93,7 +94,7 @@ public final class Punishment {
public static void findByUserAndType(UUID user, Collection<PunishmentType> types, SingleResultCallback<List<Punishment>> callback) { public static void findByUserAndType(UUID user, Collection<PunishmentType> types, SingleResultCallback<List<Punishment>> callback) {
Collection<String> convertedTypes = types.stream().map(PunishmentType::name).collect(Collectors.toList()); Collection<String> convertedTypes = types.stream().map(PunishmentType::name).collect(Collectors.toList());
punishmentsCollection.find(new Document("user", user).append("type", new Document("$in", convertedTypes))).into(new LinkedList<>(), callback); punishmentsCollection.find(new Document("user", user).append("type", new Document("$in", convertedTypes))).into(new LinkedList<>(), SyncUtils.vertxWrap(callback));
} }
private Punishment() {} // For Jackson private Punishment() {} // For Jackson
@ -148,7 +149,7 @@ public final class Punishment {
} }
public void insert(SingleResultCallback<Void> callback) { public void insert(SingleResultCallback<Void> callback) {
punishmentsCollection.insertOne(this, callback); punishmentsCollection.insertOne(this, SyncUtils.vertxWrap(callback));
} }
public void delete(User removedBy, String reason, SingleResultCallback<UpdateResult> callback) { public void delete(User removedBy, String reason, SingleResultCallback<UpdateResult> callback) {
@ -157,7 +158,7 @@ public final class Punishment {
this.removalReason = reason; this.removalReason = reason;
if (linkedIpBanId == null) { if (linkedIpBanId == null) {
punishmentsCollection.replaceOne(new Document("_id", id), this, callback); punishmentsCollection.replaceOne(new Document("_id", id), this, SyncUtils.vertxWrap(callback));
return; return;
} }
@ -172,11 +173,11 @@ public final class Punishment {
if (error2 != null) { if (error2 != null) {
callback.onResult(null, error2); callback.onResult(null, error2);
} else { } else {
punishmentsCollection.replaceOne(new Document("_id", id), this, callback); punishmentsCollection.replaceOne(new Document("_id", id), this, SyncUtils.vertxWrap(callback));
} }
}); });
} else { } else {
punishmentsCollection.replaceOne(new Document("_id", id), this, callback); punishmentsCollection.replaceOne(new Document("_id", id), this, SyncUtils.vertxWrap(callback));
} }
}); });
} }

View File

@ -8,6 +8,7 @@ import fr.javatic.mongo.jacksonCodec.Entity;
import fr.javatic.mongo.jacksonCodec.objectId.Id; import fr.javatic.mongo.jacksonCodec.objectId.Id;
import lombok.Getter; import lombok.Getter;
import net.frozenorb.apiv3.APIv3; import net.frozenorb.apiv3.APIv3;
import net.frozenorb.apiv3.util.SyncUtils;
import org.bson.Document; import org.bson.Document;
import java.util.HashMap; import java.util.HashMap;
@ -46,7 +47,7 @@ public final class Rank {
} }
public static void updateCache() { public static void updateCache() {
ranksCollection.find().into(new LinkedList<>(), (ranks, error) -> { ranksCollection.find().into(new LinkedList<>(), SyncUtils.vertxWrap((ranks, error) -> {
if (error != null) { if (error != null) {
error.printStackTrace(); error.printStackTrace();
return; return;
@ -60,7 +61,7 @@ public final class Rank {
rankIdCache = working; rankIdCache = working;
rankCache = ranks; rankCache = ranks;
}); }));
} }
private Rank() {} // For Jackson private Rank() {} // For Jackson
@ -79,13 +80,13 @@ public final class Rank {
public void insert(SingleResultCallback<Void> callback) { public void insert(SingleResultCallback<Void> callback) {
rankCache.add(this); rankCache.add(this);
rankIdCache.put(id, this); rankIdCache.put(id, this);
ranksCollection.insertOne(this, callback); ranksCollection.insertOne(this, SyncUtils.vertxWrap(callback));
} }
public void delete(SingleResultCallback<DeleteResult> callback) { public void delete(SingleResultCallback<DeleteResult> callback) {
rankCache.remove(this); rankCache.remove(this);
rankIdCache.remove(id); rankIdCache.remove(id);
ranksCollection.deleteOne(new Document("_id", id), callback); ranksCollection.deleteOne(new Document("_id", id), SyncUtils.vertxWrap(callback));
} }
} }

View File

@ -11,6 +11,7 @@ import fr.javatic.mongo.jacksonCodec.objectId.Id;
import lombok.Getter; import lombok.Getter;
import net.frozenorb.apiv3.APIv3; import net.frozenorb.apiv3.APIv3;
import net.frozenorb.apiv3.serialization.gson.ExcludeFromReplies; import net.frozenorb.apiv3.serialization.gson.ExcludeFromReplies;
import net.frozenorb.apiv3.util.SyncUtils;
import org.bson.Document; import org.bson.Document;
import java.time.Instant; import java.time.Instant;
@ -47,7 +48,7 @@ public final class Server {
} }
public static void updateCache() { public static void updateCache() {
serversCollection.find().into(new LinkedList<>(), (servers, error) -> { serversCollection.find().into(new LinkedList<>(), SyncUtils.vertxWrap((servers, error) -> {
if (error != null) { if (error != null) {
error.printStackTrace(); error.printStackTrace();
return; return;
@ -61,7 +62,7 @@ public final class Server {
serverIdCache = working; serverIdCache = working;
serverCache = servers; serverCache = servers;
}); }));
} }
// TODO: This code isn't multi-instance safe AND will send more // TODO: This code isn't multi-instance safe AND will send more
@ -121,17 +122,17 @@ public final class Server {
public void insert(SingleResultCallback<Void> callback) { public void insert(SingleResultCallback<Void> callback) {
serverCache.add(this); serverCache.add(this);
serverIdCache.put(id, this); serverIdCache.put(id, this);
serversCollection.insertOne(this, callback); serversCollection.insertOne(this, SyncUtils.vertxWrap(callback));
} }
public void save(SingleResultCallback<UpdateResult> callback) { public void save(SingleResultCallback<UpdateResult> callback) {
serversCollection.replaceOne(new Document("_id", id), this, callback); serversCollection.replaceOne(new Document("_id", id), this, SyncUtils.vertxWrap(callback));
} }
public void delete(SingleResultCallback<DeleteResult> callback) { public void delete(SingleResultCallback<DeleteResult> callback) {
serverCache.remove(this); serverCache.remove(this);
serverIdCache.remove(id); serverIdCache.remove(id);
serversCollection.deleteOne(new Document("_id", id), callback); serversCollection.deleteOne(new Document("_id", id), SyncUtils.vertxWrap(callback));
} }
} }

View File

@ -12,6 +12,7 @@ import lombok.Setter;
import net.frozenorb.apiv3.APIv3; import net.frozenorb.apiv3.APIv3;
import net.frozenorb.apiv3.serialization.gson.ExcludeFromReplies; import net.frozenorb.apiv3.serialization.gson.ExcludeFromReplies;
import net.frozenorb.apiv3.util.PermissionUtils; import net.frozenorb.apiv3.util.PermissionUtils;
import net.frozenorb.apiv3.util.SyncUtils;
import org.bson.Document; import org.bson.Document;
import java.util.*; import java.util.*;
@ -43,7 +44,7 @@ public final class ServerGroup {
} }
public static void updateCache() { public static void updateCache() {
serverGroupsCollection.find().into(new LinkedList<>(), (serverGroups, error) -> { serverGroupsCollection.find().into(new LinkedList<>(), SyncUtils.vertxWrap((serverGroups, error) -> {
if (error != null) { if (error != null) {
error.printStackTrace(); error.printStackTrace();
return; return;
@ -57,7 +58,7 @@ public final class ServerGroup {
serverGroupIdCache = working; serverGroupIdCache = working;
serverGroupCache = serverGroups; serverGroupCache = serverGroups;
}); }));
} }
private ServerGroup() {} // For Jackson private ServerGroup() {} // For Jackson
@ -74,17 +75,17 @@ public final class ServerGroup {
public void insert(SingleResultCallback<Void> callback) { public void insert(SingleResultCallback<Void> callback) {
serverGroupCache.add(this); serverGroupCache.add(this);
serverGroupIdCache.put(id, this); serverGroupIdCache.put(id, this);
serverGroupsCollection.insertOne(this, callback); serverGroupsCollection.insertOne(this, SyncUtils.vertxWrap(callback));
} }
public void save(SingleResultCallback<UpdateResult> callback) { public void save(SingleResultCallback<UpdateResult> callback) {
serverGroupsCollection.replaceOne(new Document("_id", id), this, callback); serverGroupsCollection.replaceOne(new Document("_id", id), this, SyncUtils.vertxWrap(callback));
} }
public void delete(SingleResultCallback<DeleteResult> callback) { public void delete(SingleResultCallback<DeleteResult> callback) {
serverGroupCache.remove(this); serverGroupCache.remove(this);
serverGroupIdCache.remove(id); serverGroupIdCache.remove(id);
serverGroupsCollection.deleteOne(new Document("_id", id), callback); serverGroupsCollection.deleteOne(new Document("_id", id), SyncUtils.vertxWrap(callback));
} }
} }

View File

@ -18,6 +18,7 @@ import io.vertx.core.Future;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Getter; import lombok.Getter;
import lombok.Setter; import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import net.frozenorb.apiv3.APIv3; import net.frozenorb.apiv3.APIv3;
import net.frozenorb.apiv3.maxmind.MaxMindResult; import net.frozenorb.apiv3.maxmind.MaxMindResult;
import net.frozenorb.apiv3.maxmind.MaxMindUserType; import net.frozenorb.apiv3.maxmind.MaxMindUserType;
@ -37,6 +38,7 @@ import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@Slf4j
@Entity @Entity
@AllArgsConstructor @AllArgsConstructor
public final class User { public final class User {
@ -75,30 +77,30 @@ public final class User {
public static void findById(UUID id, SingleResultCallback<User> callback) { public static void findById(UUID id, SingleResultCallback<User> callback) {
if (UuidUtils.isAcceptableUuid(id)) { if (UuidUtils.isAcceptableUuid(id)) {
usersCollection.find(new Document("_id", id)).first(callback); usersCollection.find(new Document("_id", id)).first(SyncUtils.vertxWrap(callback));
} else { } else {
callback.onResult(null, null); callback.onResult(null, null);
} }
} }
public static void findByPhone(String phoneNumber, SingleResultCallback<User> callback) { public static void findByPhone(String phoneNumber, SingleResultCallback<User> callback) {
usersCollection.find(new Document("phone", phoneNumber)).first(callback); usersCollection.find(new Document("phone", phoneNumber)).first(SyncUtils.vertxWrap(callback));
} }
public static void findByEmail(String email, SingleResultCallback<User> callback) { public static void findByEmail(String email, SingleResultCallback<User> callback) {
usersCollection.find(new Document("email", email)).first(callback); usersCollection.find(new Document("email", email)).first(SyncUtils.vertxWrap(callback));
} }
public static void findByEmailToken(String emailToken, SingleResultCallback<User> callback) { public static void findByEmailToken(String emailToken, SingleResultCallback<User> callback) {
usersCollection.find(new Document("emailToken", emailToken)).first(callback); usersCollection.find(new Document("emailToken", emailToken)).first(SyncUtils.vertxWrap(callback));
} }
public static void findByLastUsername(String lastUsername, SingleResultCallback<User> callback) { public static void findByLastUsername(String lastUsername, SingleResultCallback<User> callback) {
usersCollection.find(new Document("lastUsername", lastUsername)).first(callback); usersCollection.find(new Document("lastUsername", lastUsername)).first(SyncUtils.vertxWrap(callback));
} }
public static void findOrCreateByIdGrouped(Map<UUID, String> search, SingleResultCallback<Map<UUID, User>> callback) { public static void findOrCreateByIdGrouped(Map<UUID, String> search, SingleResultCallback<Map<UUID, User>> callback) {
usersCollection.find(new Document("_id", new Document("$in", search.keySet()))).into(new LinkedList<>(), (users, error) -> { usersCollection.find(new Document("_id", new Document("$in", search.keySet()))).into(new LinkedList<>(), SyncUtils.vertxWrap((users, error) -> {
if (error != null) { if (error != null) {
callback.onResult(null, error); callback.onResult(null, error);
return; return;
@ -146,7 +148,7 @@ public final class User {
callback.onResult(result, null); callback.onResult(result, null);
} }
}); });
}); }));
} }
private User() {} // For Jackson private User() {} // For Jackson
@ -551,7 +553,7 @@ public final class User {
} }
private List<Rank> getRanksScoped(ServerGroup serverGroup, Iterable<Grant> grants) { private List<Rank> getRanksScoped(ServerGroup serverGroup, Iterable<Grant> grants) {
List<Rank> grantedRanks = new LinkedList<>(); Set<Rank> grantedRanks = new HashSet<>();
for (Grant grant : grants) { for (Grant grant : grants) {
if (!grant.isActive() || (serverGroup != null && !grant.appliesOn(serverGroup))) { if (!grant.isActive() || (serverGroup != null && !grant.appliesOn(serverGroup))) {
@ -563,11 +565,11 @@ public final class User {
} }
if (grantedRanks.isEmpty()) { if (grantedRanks.isEmpty()) {
grantedRanks.add(Rank.findById("default")); return ImmutableList.of(Rank.findById("default"));
return grantedRanks;
} }
Iterator<Rank> iterator = grantedRanks.iterator(); Iterator<Rank> iterator = grantedRanks.iterator();
Set<Rank> copiedRanks = ImmutableSet.copyOf(grantedRanks);
// This is to remove redundant ranks. Say they have mod, mod-plus, admin, and youtuber, // This is to remove redundant ranks. Say they have mod, mod-plus, admin, and youtuber,
// we should remove mod and mod-plus as it'll be made redundant by the higher ranked admin. // we should remove mod and mod-plus as it'll be made redundant by the higher ranked admin.
@ -575,7 +577,7 @@ public final class User {
Rank rank = iterator.next(); Rank rank = iterator.next();
// Check all other ranks for inherited collision // Check all other ranks for inherited collision
for (Rank otherRank : grantedRanks) { for (Rank otherRank : copiedRanks) {
if (otherRank == rank) { if (otherRank == rank) {
continue; continue;
} }
@ -593,16 +595,17 @@ public final class User {
} }
} }
grantedRanks.sort((a, b) -> Ints.compare(b.getWeight(), a.getWeight())); List<Rank> grantedRanksList = new ArrayList<>(grantedRanks);
return grantedRanks; grantedRanksList.sort((a, b) -> Ints.compare(b.getWeight(), a.getWeight()));
return ImmutableList.copyOf(grantedRanksList);
} }
public void insert(SingleResultCallback<Void> callback) { public void insert(SingleResultCallback<Void> callback) {
usersCollection.insertOne(this, callback); usersCollection.insertOne(this, SyncUtils.vertxWrap(callback));
} }
public void save(SingleResultCallback<UpdateResult> callback) { public void save(SingleResultCallback<UpdateResult> callback) {
usersCollection.replaceOne(new Document("_id", id), this, callback); usersCollection.replaceOne(new Document("_id", id), this, SyncUtils.vertxWrap(callback));
} }
} }

View File

@ -0,0 +1,21 @@
package net.frozenorb.apiv3.util;
import com.mongodb.async.SingleResultCallback;
import io.vertx.core.Context;
import lombok.experimental.UtilityClass;
import net.frozenorb.apiv3.APIv3;
@UtilityClass
public class SyncUtils {
public static <T> SingleResultCallback<T> vertxWrap(SingleResultCallback<T> callback) {
Context context = APIv3.getVertxInstance().getOrCreateContext();
return (result, error) -> {
context.runOnContext((ignored) -> {
callback.onResult(result, error);
});
};
}
}