mirror of
https://github.com/psforever/PSF-LoginServer.git
synced 2026-01-19 18:44:45 +00:00
A Bad Filter (#763)
* comment out most of apply-cooldown-to... filter to find out which part of it causes issues with the PR * fixed resource silo tests * everything but starting the scheduled task * shutdown now * cleaning schedule managed by simple time check
This commit is contained in:
parent
8c34a55530
commit
f5ef0a9674
|
|
@ -8,9 +8,6 @@ import ch.qos.logback.core.spi.FilterReply;
|
|||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* Disrupts a variety of logging messages that would otherwise repeat within a certain frame of time.
|
||||
|
|
@ -21,9 +18,9 @@ import java.util.concurrent.TimeUnit;
|
|||
*/
|
||||
public class ApplyCooldownToDuplicateLoggingFilter extends Filter<ILoggingEvent> {
|
||||
private long cooldown;
|
||||
private ConcurrentHashMap<String, Long> messageMap;
|
||||
private long cleaning = 900000L; //default: 15min
|
||||
private ScheduledExecutorService housecleaning;
|
||||
private ConcurrentHashMap<String, Long> messageMap;
|
||||
private long housecleaningTime = System.currentTimeMillis() + cleaning;
|
||||
|
||||
@Override
|
||||
public FilterReply decide(ILoggingEvent event) {
|
||||
|
|
@ -33,43 +30,36 @@ public class ApplyCooldownToDuplicateLoggingFilter extends Filter<ILoggingEvent>
|
|||
if (previousTime != null && previousTime + cooldown > currTime) {
|
||||
return FilterReply.DENY;
|
||||
} else {
|
||||
if (currTime > housecleaningTime) {
|
||||
runCleaning();
|
||||
housecleaningTime = currTime + cleaning;
|
||||
}
|
||||
return FilterReply.NEUTRAL;
|
||||
}
|
||||
}
|
||||
|
||||
public void setCooldown(Long duration) {
|
||||
this.cooldown = duration;
|
||||
cooldown = duration;
|
||||
}
|
||||
|
||||
public void setCleaning(Long duration) {
|
||||
this.cleaning = duration;
|
||||
cleaning = duration;
|
||||
housecleaningTime = System.currentTimeMillis() + cleaning;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start() {
|
||||
if (this.cooldown != 0L) {
|
||||
messageMap = new ConcurrentHashMap<>(1000);
|
||||
housecleaning = Executors.newScheduledThreadPool(1);
|
||||
Runnable task = () -> {
|
||||
//being "concurrent" should be enough
|
||||
//the worst that can happen is two of the same message back-to-back in the log once in a while
|
||||
if (!messageMap.isEmpty()) {
|
||||
long currTime = System.currentTimeMillis();
|
||||
Iterator<String> oldLogMessages = messageMap.entrySet().stream()
|
||||
.filter( entry -> entry.getValue() + cooldown < currTime )
|
||||
.map( Map.Entry::getKey )
|
||||
.iterator();
|
||||
oldLogMessages.forEachRemaining(key -> messageMap.remove(key));
|
||||
}
|
||||
};
|
||||
housecleaning.scheduleWithFixedDelay(task, cleaning, cleaning, TimeUnit.MILLISECONDS);
|
||||
super.start();
|
||||
private void runCleaning() {
|
||||
if (!messageMap.isEmpty()) {
|
||||
long currTime = System.currentTimeMillis();
|
||||
Iterator<String> oldLogMessages = messageMap.entrySet().stream()
|
||||
.filter( entry -> entry.getValue() + cooldown < currTime )
|
||||
.map( Map.Entry::getKey )
|
||||
.iterator();
|
||||
oldLogMessages.forEachRemaining(key -> messageMap.remove(key));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stop() {
|
||||
housecleaning.shutdown();
|
||||
messageMap.clear();
|
||||
messageMap = null;
|
||||
super.stop();
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package objects
|
||||
|
||||
import akka.actor.{Actor, Props}
|
||||
import akka.actor.Props
|
||||
import akka.testkit.TestProbe
|
||||
import base.{ActorTest, FreedContextActorTest}
|
||||
import net.psforever.actors.zone.BuildingActor
|
||||
|
|
@ -18,7 +18,7 @@ import net.psforever.types._
|
|||
import org.specs2.mutable.Specification
|
||||
import net.psforever.services.avatar.{AvatarAction, AvatarServiceMessage}
|
||||
import net.psforever.objects.avatar.Avatar
|
||||
import net.psforever.services.{InterstellarClusterService, ServiceManager}
|
||||
import net.psforever.services.{InterstellarClusterService, Service, ServiceManager}
|
||||
import net.psforever.services.galaxy.GalaxyService
|
||||
|
||||
import scala.collection.concurrent.TrieMap
|
||||
|
|
@ -35,9 +35,9 @@ class ResourceSiloTest extends Specification {
|
|||
val obj = ResourceSilo()
|
||||
obj.Definition mustEqual GlobalDefinitions.resource_silo
|
||||
obj.MaxNtuCapacitor mustEqual 1000
|
||||
obj.NtuCapacitor mustEqual 0
|
||||
obj.NtuCapacitor mustEqual 1000
|
||||
obj.LowNtuWarningOn mustEqual true
|
||||
obj.CapacitorDisplay mustEqual 0
|
||||
obj.CapacitorDisplay mustEqual 10
|
||||
//
|
||||
obj.NtuCapacitor = 50
|
||||
obj.LowNtuWarningOn = false
|
||||
|
|
@ -48,7 +48,7 @@ class ResourceSiloTest extends Specification {
|
|||
|
||||
"charge level can not exceed limits(0 to maximum)" in {
|
||||
val obj = ResourceSilo()
|
||||
obj.NtuCapacitor mustEqual 0
|
||||
obj.NtuCapacitor mustEqual 1000
|
||||
obj.NtuCapacitor = -5
|
||||
obj.NtuCapacitor mustEqual 0
|
||||
|
||||
|
|
@ -90,7 +90,7 @@ class ResourceSiloControlStartupTest extends ActorTest {
|
|||
|
||||
"Resource silo" should {
|
||||
"startup properly" in {
|
||||
obj.Actor ! "startup"
|
||||
obj.Actor ! Service.Startup()
|
||||
expectNoMessage(max = 1000 milliseconds)
|
||||
}
|
||||
}
|
||||
|
|
@ -110,8 +110,9 @@ class ResourceSiloControlStartupMessageNoneTest extends ActorTest {
|
|||
|
||||
"Resource silo" should {
|
||||
"report if it has no NTU on startup" in {
|
||||
obj.NtuCapacitor = 0
|
||||
assert(obj.NtuCapacitor == 0)
|
||||
obj.Actor ! "startup"
|
||||
obj.Actor ! Service.Startup()
|
||||
val ownerMsg = buildingEvents.receiveOne(200 milliseconds)
|
||||
assert(ownerMsg match {
|
||||
case BuildingActor.NtuDepleted() => true
|
||||
|
|
@ -137,7 +138,7 @@ class ResourceSiloControlStartupMessageSomeTest extends ActorTest {
|
|||
"report if it has any NTU on startup" in {
|
||||
obj.NtuCapacitor = 1
|
||||
assert(obj.NtuCapacitor == 1)
|
||||
obj.Actor ! "startup"
|
||||
obj.Actor ! Service.Startup()
|
||||
val ownerMsg = buildingEvents.receiveOne(200 milliseconds)
|
||||
assert(ownerMsg match {
|
||||
case BuildingActor.SuppliedWithNtu() => true
|
||||
|
|
@ -195,7 +196,7 @@ class ResourceSiloControlUseTest extends FreedContextActorTest {
|
|||
ant.DeploymentState = DriveState.Deployed
|
||||
building.Amenities = silo
|
||||
silo.Actor = system.actorOf(Props(classOf[ResourceSiloControl], silo), "test-silo")
|
||||
silo.Actor ! "startup"
|
||||
silo.Actor ! Service.Startup()
|
||||
|
||||
"Resource silo" should {
|
||||
"respond when being used" in {
|
||||
|
|
@ -224,7 +225,9 @@ class ResourceSiloControlNtuWarningTest extends ActorTest {
|
|||
|
||||
val zoneEvents = TestProbe("zone-events")
|
||||
zone.AvatarEvents = zoneEvents.ref
|
||||
obj.Actor ! "startup"
|
||||
obj.Actor ! Service.Startup()
|
||||
obj.Actor ! ResourceSilo.UpdateChargeLevel(-obj.NtuCapacitor)
|
||||
zoneEvents.receiveN(3, 500.milliseconds) //events from setup
|
||||
|
||||
"Resource silo" should {
|
||||
"announce high ntu" in {
|
||||
|
|
@ -232,30 +235,10 @@ class ResourceSiloControlNtuWarningTest extends ActorTest {
|
|||
obj.Actor ! ResourceSilo.LowNtuWarning(false)
|
||||
|
||||
val reply = zoneEvents.receiveOne(5000 milliseconds)
|
||||
assert(reply.isInstanceOf[AvatarServiceMessage])
|
||||
assert(reply.asInstanceOf[AvatarServiceMessage].forChannel == "nowhere")
|
||||
assert(reply.asInstanceOf[AvatarServiceMessage].actionMessage.isInstanceOf[AvatarAction.PlanetsideAttribute])
|
||||
assert(
|
||||
reply
|
||||
.asInstanceOf[AvatarServiceMessage]
|
||||
.actionMessage
|
||||
.asInstanceOf[AvatarAction.PlanetsideAttribute]
|
||||
.player_guid == PlanetSideGUID(6)
|
||||
)
|
||||
assert(
|
||||
reply
|
||||
.asInstanceOf[AvatarServiceMessage]
|
||||
.actionMessage
|
||||
.asInstanceOf[AvatarAction.PlanetsideAttribute]
|
||||
.attribute_type == 47
|
||||
)
|
||||
assert(
|
||||
reply
|
||||
.asInstanceOf[AvatarServiceMessage]
|
||||
.actionMessage
|
||||
.asInstanceOf[AvatarAction.PlanetsideAttribute]
|
||||
.attribute_value == 0
|
||||
)
|
||||
reply match {
|
||||
case AvatarServiceMessage("nowhere", AvatarAction.PlanetsideAttribute(PlanetSideGUID(6), 47, 0)) => ;
|
||||
case _ => assert(false, s"$reply is wrong")
|
||||
}
|
||||
assert(!obj.LowNtuWarningOn)
|
||||
}
|
||||
}
|
||||
|
|
@ -274,32 +257,33 @@ class ResourceSiloControlUpdate1Test extends ActorTest {
|
|||
val buildingEvents = TestProbe("building-events")
|
||||
zone.AvatarEvents = zoneEvents.ref
|
||||
bldg.Actor = buildingEvents.ref
|
||||
obj.Actor ! "startup"
|
||||
obj.Actor ! Service.Startup()
|
||||
buildingEvents.receiveOne(500 milliseconds) //message caused by "startup"
|
||||
obj.Actor ! ResourceSilo.UpdateChargeLevel(-obj.NtuCapacitor)
|
||||
zoneEvents.receiveN(3, 500.milliseconds) //events from setup
|
||||
buildingEvents.receiveN(3, 500.milliseconds) //events from setup
|
||||
|
||||
"Resource silo" should {
|
||||
"update the charge level and capacitor display (report high ntu, power restored)" in {
|
||||
buildingEvents.receiveOne(500 milliseconds) //message caused by "startup"
|
||||
assert(obj.NtuCapacitor == 0)
|
||||
assert(obj.CapacitorDisplay == 0)
|
||||
assert(obj.LowNtuWarningOn)
|
||||
obj.Actor ! ResourceSilo.UpdateChargeLevel(305)
|
||||
|
||||
val reply1 = zoneEvents.receiveOne(500 milliseconds)
|
||||
val reply1 = zoneEvents.receiveN(2,500 milliseconds)
|
||||
val reply2 = buildingEvents.receiveOne(500 milliseconds)
|
||||
assert(obj.NtuCapacitor == 305)
|
||||
assert(obj.CapacitorDisplay == 3)
|
||||
assert(reply1 match {
|
||||
case AvatarServiceMessage("nowhere", AvatarAction.PlanetsideAttribute(PlanetSideGUID(1), 45, 3)) => true
|
||||
case _ => false
|
||||
})
|
||||
assert(reply2.isInstanceOf[BuildingActor.MapUpdate])
|
||||
|
||||
val reply3 = zoneEvents.receiveOne(500 milliseconds)
|
||||
reply1.head match {
|
||||
case AvatarServiceMessage("nowhere", AvatarAction.PlanetsideAttribute(PlanetSideGUID(1), 45, 3)) => ;
|
||||
case _ => assert(false, s"$reply1 is wrong")
|
||||
}
|
||||
assert(reply2.isInstanceOf[BuildingActor.MapUpdate], s"$reply2 is wrong")
|
||||
reply1(1) match {
|
||||
case AvatarServiceMessage("nowhere", AvatarAction.PlanetsideAttribute(PlanetSideGUID(6), 47, 0)) => ;
|
||||
case _ => assert(false, s"${reply1(1)} is wrong")
|
||||
}
|
||||
assert(!obj.LowNtuWarningOn)
|
||||
assert(reply3 match {
|
||||
case AvatarServiceMessage("nowhere", AvatarAction.PlanetsideAttribute(PlanetSideGUID(6), 47, 0)) => true
|
||||
case _ => false
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -317,75 +301,33 @@ class ResourceSiloControlUpdate2Test extends ActorTest {
|
|||
val buildingEvents = TestProbe("building-events")
|
||||
zone.AvatarEvents = zoneEvents.ref
|
||||
bldg.Actor = buildingEvents.ref
|
||||
obj.Actor ! "startup"
|
||||
obj.Actor ! Service.Startup()
|
||||
buildingEvents.receiveOne(500 milliseconds) //message caused by "startup"
|
||||
obj.Actor ! ResourceSilo.UpdateChargeLevel(-obj.NtuCapacitor + 100)
|
||||
zoneEvents.receiveN(3, 500.milliseconds) //events from setup
|
||||
buildingEvents.receiveN(1, 500.milliseconds) //events from setup
|
||||
|
||||
"Resource silo" should {
|
||||
"update the charge level and capacitor display (report good ntu)" in {
|
||||
buildingEvents.receiveOne(500 milliseconds) //message caused by "startup"
|
||||
obj.NtuCapacitor = 100
|
||||
obj.LowNtuWarningOn = true
|
||||
assert(obj.NtuCapacitor == 100)
|
||||
assert(obj.CapacitorDisplay == 1)
|
||||
assert(obj.LowNtuWarningOn)
|
||||
obj.Actor ! ResourceSilo.UpdateChargeLevel(105)
|
||||
|
||||
val reply1 = zoneEvents.receiveOne(1000 milliseconds)
|
||||
val reply1 = zoneEvents.receiveN(2, 1000 milliseconds)
|
||||
val reply2 = buildingEvents.receiveOne(1000 milliseconds)
|
||||
assert(obj.NtuCapacitor == 205)
|
||||
assert(obj.CapacitorDisplay == 2)
|
||||
assert(reply1.isInstanceOf[AvatarServiceMessage])
|
||||
assert(reply1.asInstanceOf[AvatarServiceMessage].forChannel == "nowhere")
|
||||
assert(reply1.asInstanceOf[AvatarServiceMessage].actionMessage.isInstanceOf[AvatarAction.PlanetsideAttribute])
|
||||
assert(
|
||||
reply1
|
||||
.asInstanceOf[AvatarServiceMessage]
|
||||
.actionMessage
|
||||
.asInstanceOf[AvatarAction.PlanetsideAttribute]
|
||||
.player_guid == PlanetSideGUID(1)
|
||||
)
|
||||
assert(
|
||||
reply1
|
||||
.asInstanceOf[AvatarServiceMessage]
|
||||
.actionMessage
|
||||
.asInstanceOf[AvatarAction.PlanetsideAttribute]
|
||||
.attribute_type == 45
|
||||
)
|
||||
assert(
|
||||
reply1
|
||||
.asInstanceOf[AvatarServiceMessage]
|
||||
.actionMessage
|
||||
.asInstanceOf[AvatarAction.PlanetsideAttribute]
|
||||
.attribute_value == 2
|
||||
)
|
||||
|
||||
reply1.head match {
|
||||
case AvatarServiceMessage("nowhere", AvatarAction.PlanetsideAttribute(PlanetSideGUID(1), 45, 2)) => ;
|
||||
case _ => assert(false, s"$reply1 is wrong")
|
||||
}
|
||||
assert(reply2.isInstanceOf[BuildingActor.MapUpdate])
|
||||
|
||||
val reply3 = zoneEvents.receiveOne(500 milliseconds)
|
||||
reply1(1) match {
|
||||
case AvatarServiceMessage("nowhere", AvatarAction.PlanetsideAttribute(PlanetSideGUID(6), 47, 0)) => ;
|
||||
case _ => assert(false, s"${reply1(1)} is wrong")
|
||||
}
|
||||
assert(!obj.LowNtuWarningOn)
|
||||
assert(reply3.isInstanceOf[AvatarServiceMessage])
|
||||
assert(reply3.asInstanceOf[AvatarServiceMessage].forChannel == "nowhere")
|
||||
assert(reply3.asInstanceOf[AvatarServiceMessage].actionMessage.isInstanceOf[AvatarAction.PlanetsideAttribute])
|
||||
assert(
|
||||
reply3
|
||||
.asInstanceOf[AvatarServiceMessage]
|
||||
.actionMessage
|
||||
.asInstanceOf[AvatarAction.PlanetsideAttribute]
|
||||
.player_guid == PlanetSideGUID(6)
|
||||
)
|
||||
assert(
|
||||
reply3
|
||||
.asInstanceOf[AvatarServiceMessage]
|
||||
.actionMessage
|
||||
.asInstanceOf[AvatarAction.PlanetsideAttribute]
|
||||
.attribute_type == 47
|
||||
)
|
||||
assert(
|
||||
reply3
|
||||
.asInstanceOf[AvatarServiceMessage]
|
||||
.actionMessage
|
||||
.asInstanceOf[AvatarAction.PlanetsideAttribute]
|
||||
.attribute_value == 0
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -403,12 +345,15 @@ class ResourceSiloControlNoUpdateTest extends ActorTest {
|
|||
val buildingEvents = TestProbe("building-events")
|
||||
zone.AvatarEvents = zoneEvents.ref
|
||||
bldg.Actor = buildingEvents.ref
|
||||
obj.Actor ! "startup"
|
||||
obj.Actor ! Service.Startup()
|
||||
obj.NtuCapacitor = 0
|
||||
|
||||
"Resource silo" should {
|
||||
"update, but not sufficiently to change the capacitor display" in {
|
||||
buildingEvents.receiveOne(500 milliseconds) //message caused by "startup"
|
||||
obj.NtuCapacitor = 250
|
||||
obj.Actor ! ResourceSilo.UpdateChargeLevel(250)
|
||||
zoneEvents.receiveN(2, 500.milliseconds) //events from setup
|
||||
buildingEvents.receiveN(3, 500.milliseconds) //events from setup
|
||||
obj.LowNtuWarningOn = false
|
||||
assert(obj.NtuCapacitor == 250)
|
||||
assert(obj.CapacitorDisplay == 2)
|
||||
|
|
@ -429,26 +374,4 @@ object ResourceSiloTest {
|
|||
val player = Player(
|
||||
new Avatar(0, "TestCharacter", PlanetSideEmpire.TR, CharacterSex.Male, 0, CharacterVoice.Mute)
|
||||
)
|
||||
|
||||
class ProbedAvatarService(probe: TestProbe) extends Actor {
|
||||
override def receive: Receive = {
|
||||
case msg =>
|
||||
probe.ref ! msg
|
||||
}
|
||||
}
|
||||
|
||||
class ProbedBuildingControl(probe: TestProbe) extends Actor {
|
||||
override def receive: Receive = {
|
||||
case msg =>
|
||||
probe.ref ! msg
|
||||
}
|
||||
}
|
||||
|
||||
class ProbedResourceSiloControl(silo: ResourceSilo, probe: TestProbe) extends ResourceSiloControl(silo) {
|
||||
override def receive: Receive = {
|
||||
case msg =>
|
||||
super.receive.apply(msg)
|
||||
probe.ref ! msg
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue