Added new service ProfileActivityService
Maintains a timestamp of when each profile was last active on the server. Timestamp is refreshed on two events: `game/start and `game/keepalive` Timestamp is used to determine if a profiles hideout should be processed. If a profile has a timestamp older than 90 minutes, it is not processed. (could be set lower but its a conservative value) This has the side effects of not adjusting the `sptUpdateLastRunTimestamp` property, resulting in `saveProfile()` not running for every profile. My testing shows a 20x perf increase for every profile in SPT not in use. Service could likely be used in other scenarios to avoid doing unnecessary work
This commit is contained in:
parent
73a1dd9511
commit
a9d89695f0
@ -7,5 +7,6 @@
|
||||
},
|
||||
"expCraftAmount": 10,
|
||||
"overrideCraftTimeSeconds": -1,
|
||||
"overrideBuildTimeSeconds": -1
|
||||
"overrideBuildTimeSeconds": -1,
|
||||
"updateProfileHideoutWhenActiveWithinMinutes": 90
|
||||
}
|
@ -39,6 +39,7 @@ import { GiftService } from "@spt-aki/services/GiftService";
|
||||
import { ItemBaseClassService } from "@spt-aki/services/ItemBaseClassService";
|
||||
import { LocalisationService } from "@spt-aki/services/LocalisationService";
|
||||
import { OpenZoneService } from "@spt-aki/services/OpenZoneService";
|
||||
import { ProfileActivityService } from "@spt-aki/services/ProfileActivityService";
|
||||
import { ProfileFixerService } from "@spt-aki/services/ProfileFixerService";
|
||||
import { RaidTimeAdjustmentService } from "@spt-aki/services/RaidTimeAdjustmentService";
|
||||
import { SeasonalEventService } from "@spt-aki/services/SeasonalEventService";
|
||||
@ -78,6 +79,7 @@ export class GameController
|
||||
@inject("ItemBaseClassService") protected itemBaseClassService: ItemBaseClassService,
|
||||
@inject("GiftService") protected giftService: GiftService,
|
||||
@inject("RaidTimeAdjustmentService") protected raidTimeAdjustmentService: RaidTimeAdjustmentService,
|
||||
@inject("ProfileActivityService") protected profileActivityService: ProfileActivityService,
|
||||
@inject("ApplicationContext") protected applicationContext: ApplicationContext,
|
||||
@inject("ConfigServer") protected configServer: ConfigServer,
|
||||
)
|
||||
@ -109,6 +111,8 @@ export class GameController
|
||||
// Store client start time in app context
|
||||
this.applicationContext.addValue(ContextVariableType.CLIENT_START_TIMESTAMP, startTimeStampMS);
|
||||
|
||||
this.profileActivityService.setActivityTimestamp(sessionID);
|
||||
|
||||
if (this.coreConfig.fixes.fixShotgunDispersion)
|
||||
{
|
||||
this.fixShotgunDispersions();
|
||||
@ -504,6 +508,7 @@ export class GameController
|
||||
*/
|
||||
public getKeepAlive(sessionId: string): IGameKeepAliveResponse
|
||||
{
|
||||
this.profileActivityService.setActivityTimestamp(sessionId);
|
||||
return { msg: "OK", utc_time: new Date().getTime() / 1000 };
|
||||
}
|
||||
|
||||
|
@ -48,6 +48,7 @@ import { SaveServer } from "@spt-aki/servers/SaveServer";
|
||||
import { FenceService } from "@spt-aki/services/FenceService";
|
||||
import { LocalisationService } from "@spt-aki/services/LocalisationService";
|
||||
import { PlayerService } from "@spt-aki/services/PlayerService";
|
||||
import { ProfileActivityService } from "@spt-aki/services/ProfileActivityService";
|
||||
import { HashUtil } from "@spt-aki/utils/HashUtil";
|
||||
import { HttpResponseUtil } from "@spt-aki/utils/HttpResponseUtil";
|
||||
import { JsonUtil } from "@spt-aki/utils/JsonUtil";
|
||||
@ -79,6 +80,7 @@ export class HideoutController
|
||||
@inject("HideoutHelper") protected hideoutHelper: HideoutHelper,
|
||||
@inject("ScavCaseRewardGenerator") protected scavCaseRewardGenerator: ScavCaseRewardGenerator,
|
||||
@inject("LocalisationService") protected localisationService: LocalisationService,
|
||||
@inject("ProfileActivityService") protected profileActivityService: ProfileActivityService,
|
||||
@inject("ConfigServer") protected configServer: ConfigServer,
|
||||
@inject("JsonUtil") protected jsonUtil: JsonUtil,
|
||||
@inject("FenceService") protected fenceService: FenceService,
|
||||
@ -1323,7 +1325,13 @@ export class HideoutController
|
||||
{
|
||||
for (const sessionID in this.saveServer.getProfiles())
|
||||
{
|
||||
if ("Hideout" in this.saveServer.getProfile(sessionID).characters.pmc)
|
||||
if (
|
||||
"Hideout" in this.saveServer.getProfile(sessionID).characters.pmc
|
||||
&& this.profileActivityService.activeWithinLastMinutes(
|
||||
sessionID,
|
||||
this.hideoutConfig.updateProfileHideoutWhenActiveWithinMinutes,
|
||||
)
|
||||
)
|
||||
{
|
||||
this.hideoutHelper.updatePlayerHideout(sessionID);
|
||||
}
|
||||
|
@ -213,6 +213,7 @@ import { OpenZoneService } from "@spt-aki/services/OpenZoneService";
|
||||
import { PaymentService } from "@spt-aki/services/PaymentService";
|
||||
import { PlayerService } from "@spt-aki/services/PlayerService";
|
||||
import { PmcChatResponseService } from "@spt-aki/services/PmcChatResponseService";
|
||||
import { ProfileActivityService } from "@spt-aki/services/ProfileActivityService";
|
||||
import { ProfileFixerService } from "@spt-aki/services/ProfileFixerService";
|
||||
import { ProfileSnapshotService } from "@spt-aki/services/ProfileSnapshotService";
|
||||
import { RagfairCategoriesService } from "@spt-aki/services/RagfairCategoriesService";
|
||||
@ -747,6 +748,10 @@ export class Container
|
||||
depContainer.register<GiftService>("GiftService", GiftService);
|
||||
depContainer.register<MailSendService>("MailSendService", MailSendService);
|
||||
depContainer.register<RaidTimeAdjustmentService>("RaidTimeAdjustmentService", RaidTimeAdjustmentService);
|
||||
|
||||
depContainer.register<ProfileActivityService>("ProfileActivityService", ProfileActivityService, {
|
||||
lifecycle: Lifecycle.Singleton,
|
||||
});
|
||||
}
|
||||
|
||||
private static registerServers(depContainer: DependencyContainer): void
|
||||
|
@ -11,4 +11,6 @@ export interface IHideoutConfig extends IBaseConfig
|
||||
expCraftAmount: number;
|
||||
overrideCraftTimeSeconds: number;
|
||||
overrideBuildTimeSeconds: number;
|
||||
/** Only process a profiles hideout crafts when it has been active in the last x minutes */
|
||||
updateProfileHideoutWhenActiveWithinMinutes: number;
|
||||
}
|
||||
|
36
project/src/services/ProfileActivityService.ts
Normal file
36
project/src/services/ProfileActivityService.ts
Normal file
@ -0,0 +1,36 @@
|
||||
import { injectable } from "tsyringe";
|
||||
|
||||
@injectable()
|
||||
export class ProfileActivityService
|
||||
{
|
||||
protected profileActivityTimestamps: Record<string, number> = {};
|
||||
|
||||
/**
|
||||
* Was the requested profile active in the last requested minutes
|
||||
* @param sessionId Profile to check
|
||||
* @param minutes Minutes to check for activity in
|
||||
* @returns True when profile was active within past x minutes
|
||||
*/
|
||||
public activeWithinLastMinutes(sessionId: string, minutes: number): boolean
|
||||
{
|
||||
const currentTimestamp = new Date().getTime() / 1000;
|
||||
const storedActivityTimestamp = this.profileActivityTimestamps[sessionId];
|
||||
if (!storedActivityTimestamp)
|
||||
{
|
||||
// No value, no assumed activity (server offline?)
|
||||
return false;
|
||||
}
|
||||
|
||||
// True if difference since last timestamp to now is below desired amount
|
||||
return (currentTimestamp - storedActivityTimestamp) < (minutes * 60); // convert minutes to seconds to compare
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the timestamp a profile was last observed active
|
||||
* @param sessionId Profile to update
|
||||
*/
|
||||
public setActivityTimestamp(sessionId: string): void
|
||||
{
|
||||
this.profileActivityTimestamps[sessionId] = new Date().getTime() / 1000;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user