Skip to content
Merged

#79 #83

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,4 @@ install/*
!install/*.template.yaml
config/localhost.yaml
mydb.db-journal
test_db.db-journal
2 changes: 2 additions & 0 deletions src/database/model/building-production-rate.model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,10 @@ export class BuildingProductionRateModel {

@Column({name: 'resourceId'})
public resourceId: string;

@Field({description: 'Current level production rate in seconds'})
@IsNumber()
@Column()
@Column({type: 'float', precision: 10, scale: 4})
public productionRate: number;
}
53 changes: 1 addition & 52 deletions src/database/repository/abstract.repository.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import {Inject, Injectable} from '@nestjs/common';
import {EntitySubscriberInterface, Repository} from 'typeorm';
import {Repository} from 'typeorm';

import {TransactionManagerService} from '@warp-core/database/transaction-manager.service';

Expand All @@ -10,11 +10,6 @@ export abstract class AbstractRepository<
@Inject(TransactionManagerService)
private readonly transactionManager: TransactionManagerService;

private static disabledEntityListeners: Map<
object | string,
EntitySubscriberInterface
> = new Map<object | string, EntitySubscriberInterface>();

/**
* Creates shared transaction.
* Shared transaction allows using transactions in different modules
Expand All @@ -37,50 +32,4 @@ export abstract class AbstractRepository<
public rollbackTransaction(): Promise<void> {
return this.transactionManager.rollbackTransaction();
}

public disableEntityListeners(
entityType: object | object[] | string | string[],
): void {
const entityTypesToCheck = Array.isArray(entityType)
? entityType
: [entityType];

const subscriber = this.manager.connection.subscribers;
for (let i = subscriber.length - 1; i >= 0; --i) {
const subscriberElement = subscriber[i];

// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-expect-error
if (entityTypesToCheck.includes(subscriberElement.listenTo())) {
AbstractRepository.disabledEntityListeners.set(
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-expect-error
subscriberElement.listenTo(),
subscriberElement,
);
subscriber.splice(subscriber.indexOf(subscriberElement), 1);
}
}
}

public enableEntityListeners(
entityType: object | object[] | string | string[],
): void {
const entityTypesToCheck = Array.isArray(entityType)
? entityType
: [entityType];
const subscriber = this.manager.connection.subscribers;

for (const entityTypesToCheckElement of entityTypesToCheck) {
const disabledEntity = AbstractRepository.disabledEntityListeners.get(
entityTypesToCheckElement,
);
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-expect-error
subscriber.push(disabledEntity);
AbstractRepository.disabledEntityListeners.delete(
entityTypesToCheckElement,
);
}
}
}
25 changes: 11 additions & 14 deletions src/database/repository/habitat-resource.repository.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import {Injectable} from '@nestjs/common';
import {DataSource, In, UpdateResult} from 'typeorm';
import {DataSource, In} from 'typeorm';

import {BuildingProductionRateModel} from '@warp-core/database/model/building-production-rate.model';
import {BuildingModel} from '@warp-core/database/model/building.model';
import {HabitatResourceModel} from '@warp-core/database/model/habitat-resource.model';
import {QueueElementCostModel} from '@warp-core/database/model/queue-element-cost.model';
import {AbstractRepository} from '@warp-core/database/repository/abstract.repository';

@Injectable()
Expand Down Expand Up @@ -46,6 +47,15 @@ export class HabitatResourceRepository extends AbstractRepository<HabitatResourc
return queryBuilder.getMany();
}

public getHabitatResourcesByQueueCostItems(
queueCost: QueueElementCostModel[],
habitatId: number,
): Promise<HabitatResourceModel[]> {
const requiredResourcesIds = queueCost.map(cost => cost.resource.id);

return this.getHabitatResourcesByIds(requiredResourcesIds, habitatId);
}

public getHabitatResourcesByIds(
resourcesIds: string[],
habitatId: number,
Expand All @@ -55,17 +65,4 @@ export class HabitatResourceRepository extends AbstractRepository<HabitatResourc
habitatId: habitatId,
});
}

public updateLastCalculationDateForManyResources(
resourceIds: string[],
habitatId: number,
lastCalculationTime: Date,
): Promise<UpdateResult> {
return this.createQueryBuilder()
.update(HabitatResourceModel)
.set({lastCalculationTime: lastCalculationTime})
.where('resourceId IN (:...resourceIds)', {resourceIds: resourceIds})
.andWhere('habitatId = :habitatId', {habitatId: habitatId})
.execute();
}
}
11 changes: 0 additions & 11 deletions src/user/queue/building-queue/building-queue-handler.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import {Injectable, Logger} from '@nestjs/common';
import {AuthorizedHabitatModel} from '@warp-core/auth';
import {BuildingQueueElementModel} from '@warp-core/database/model/building-queue-element.model';
import {BuildingZoneModel} from '@warp-core/database/model/building-zone.model';
import {HabitatResourceModel} from '@warp-core/database/model/habitat-resource.model';
import {BuildingQueueRepository} from '@warp-core/database/repository/building-queue.repository';
import {BuildingZoneRepository} from '@warp-core/database/repository/building-zone.repository';
import {BuildingQueueProcessingEmitter} from '@warp-core/user/queue/building-queue/exchange/emit/building-queue-processing.emitter';
Expand Down Expand Up @@ -86,11 +85,6 @@ export class BuildingQueueHandlerService {
`Queue element processed/consumed for building zone with id ${queueElement.buildingZoneId}`,
);

this.buildingQueueRepository.disableEntityListeners([
BuildingZoneModel,
HabitatResourceModel,
]);

await this.buildingQueueEmitter.beforeProcessing({queueElement});

await this.buildingZoneRepository.update(buildingZoneToProcess.id, {
Expand All @@ -102,10 +96,5 @@ export class BuildingQueueHandlerService {
});

await this.buildingQueueEmitter.afterProcessing({queueElement});

this.buildingQueueRepository.enableEntityListeners([
BuildingZoneModel,
HabitatResourceModel,
]);
}
}
12 changes: 8 additions & 4 deletions src/user/queue/building-queue/building-queue.module.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {Module} from '@nestjs/common';
import {MiddlewareConsumer, Module, NestModule} from '@nestjs/common';

import {AuthModule} from '@warp-core/auth';
import {CoreConfigModule} from '@warp-core/core/config/core-config.module';
Expand All @@ -11,7 +11,6 @@ import {SimpleCalculationService} from '@warp-core/user/queue/building-queue/add
import {PrepareSingleBuildingQueueElementService} from '@warp-core/user/queue/building-queue/add/prepare-single-building-queue-element.service';
import {BuildingQueueHandlerService} from '@warp-core/user/queue/building-queue/building-queue-handler.service';
import {BuildingQueueResolver} from '@warp-core/user/queue/building-queue/building-queue.resolver';
import {BuildingZoneUpdateByQueueSubscriber} from '@warp-core/user/queue/building-queue/entity-subscriber/building-zone-update-by-queue.subscriber';
import {BuildingQueueAddEmitter} from '@warp-core/user/queue/building-queue/exchange/emit/building-queue-add.emitter';
import {BuildingQueueProcessingEmitter} from '@warp-core/user/queue/building-queue/exchange/emit/building-queue-processing.emitter';
import {AddToQueueValidator} from '@warp-core/user/queue/building-queue/input/validator/add-to-queue.validator';
Expand All @@ -20,6 +19,7 @@ import {DraftQueueElementValidator} from '@warp-core/user/queue/building-queue/i
import {EndLevelValidator} from '@warp-core/user/queue/building-queue/input/validator/end-level.validator';
import {MaxQueueCountValidator} from '@warp-core/user/queue/building-queue/input/validator/max-queue-count.validator';
import {ValidateSingleQueueElementService} from '@warp-core/user/queue/building-queue/input/validator/validate-single-queue-element.service';
import {QueueConsumerMiddleware} from '@warp-core/user/queue/building-queue/queue-consumer.middleware';

@Module({
providers: [
Expand All @@ -31,7 +31,6 @@ import {ValidateSingleQueueElementService} from '@warp-core/user/queue/building-
BuildingQueueHandlerService,
PrepareSingleBuildingQueueElementService,
BuildingQueueResolver,
BuildingZoneUpdateByQueueSubscriber,
AddToQueueValidator,
DraftQueueElementValidator,
EndLevelValidator,
Expand All @@ -40,11 +39,16 @@ import {ValidateSingleQueueElementService} from '@warp-core/user/queue/building-
BuildingQueueAddEmitter,
BuildingQueueProcessingEmitter,
ValidateSingleQueueElementService,
QueueConsumerMiddleware,
{
provide: 'QUEUE_ADD_CALCULATION',
useClass: SimpleCalculationService,
},
],
imports: [DatabaseModule, CoreConfigModule, AuthModule],
})
export class BuildingQueueModule {}
export class BuildingQueueModule implements NestModule {
public configure(consumer: MiddlewareConsumer): void {
consumer.apply(QueueConsumerMiddleware).forRoutes('graphql');
}
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import {Test, TestingModule} from '@nestjs/testing';
import {when} from 'jest-when';

import {AuthorizedHabitatModel} from '@warp-core/auth';
import {RuntimeConfig} from '@warp-core/core/config/runtime.config';
import {BuildingZoneModel} from '@warp-core/database/model/building-zone.model';
import {BuildingModel} from '@warp-core/database/model/building.model';
Expand All @@ -19,7 +18,6 @@ jest.mock('@nestjs/config');

describe('max queue elements count validator', () => {
let buildingQueueRepository: jest.Mocked<BuildingQueueRepository>;
let habitatMock: jest.Mocked<AuthorizedHabitatModel>;
let runtimeConfig: jest.Mocked<RuntimeConfig>;
let maxQueueCountValidator: MaxQueueCountValidator;

Expand All @@ -28,30 +26,29 @@ describe('max queue elements count validator', () => {

const module: TestingModule = await Test.createTestingModule({
providers: [
BuildingQueueRepository,
AuthorizedHabitatModel,
MaxQueueCountValidator,
BuildingQueueRepository,
coreConfigMock,
],
}).compile();
buildingQueueRepository = module.get(BuildingQueueRepository);
runtimeConfig = module.get(RuntimeConfig);
habitatMock = module.get(AuthorizedHabitatModel);
maxQueueCountValidator = module.get(MaxQueueCountValidator);
});

describe('validate', () => {
it('should add error when queue count equals max elements in queue from config', async () => {
habitatMock.id = 5;
const maxQueueElements = 10;
const queueValidationInput: QueueInputValidation = {
addToQueueInput: {} as AddToQueueInput,
building: {} as BuildingModel,
buildingZone: {} as BuildingZoneModel,
buildingZone: {
habitatId: 5,
} as BuildingZoneModel,
validationError: new QueueValidationError(),
};
when(buildingQueueRepository.countActiveBuildingQueueElementsForHabitat)
.calledWith(habitatMock.id)
.calledWith(5)
.mockResolvedValue(maxQueueElements);

runtimeConfig.habitat.buildingQueue.maxElementsInQueue = maxQueueElements;
Expand All @@ -65,17 +62,18 @@ describe('max queue elements count validator', () => {
});

it('should pass validation when queue elements count does not reach max queue elements from config', async () => {
habitatMock.id = 5;
const maxQueueElements = 10;
const queueValidationInput: QueueInputValidation = {
addToQueueInput: {} as AddToQueueInput,
building: {} as BuildingModel,
buildingZone: {} as BuildingZoneModel,
buildingZone: {
habitatId: 5,
} as BuildingZoneModel,
validationError: new QueueValidationError(),
};

when(buildingQueueRepository.countActiveBuildingQueueElementsForHabitat)
.calledWith(habitatMock.id)
.calledWith(5)
.mockResolvedValue(3);

runtimeConfig.habitat.buildingQueue.maxElementsInQueue = maxQueueElements;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import {Injectable} from '@nestjs/common';

import {AuthorizedHabitatModel} from '@warp-core/auth';
import {RuntimeConfig} from '@warp-core/core/config/runtime.config';
import {BuildingQueueRepository} from '@warp-core/database/repository/building-queue.repository';
import {QueueItemValidatorInterface} from '@warp-core/user/queue/building-queue/input/validator/queue-item-validator.interface';
Expand All @@ -11,15 +10,15 @@ export class MaxQueueCountValidator implements QueueItemValidatorInterface {
constructor(
private readonly buildingQueueRepository: BuildingQueueRepository,
private readonly runtimeConfig: RuntimeConfig,
private readonly habitatModel: AuthorizedHabitatModel,
) {}

public async validate({
validationError,
buildingZone,
}: QueueInputValidation): Promise<void> {
const queueCounter =
await this.buildingQueueRepository.countActiveBuildingQueueElementsForHabitat(
this.habitatModel.id,
buildingZone.habitatId,
);
const maxElementsInQueue =
this.runtimeConfig.habitat.buildingQueue.maxElementsInQueue;
Expand Down
25 changes: 25 additions & 0 deletions src/user/queue/building-queue/queue-consumer.middleware.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import {Injectable, NestMiddleware} from '@nestjs/common';
import {NextFunction} from 'connect';

import {AuthorizedHabitatModel} from '@warp-core/auth';
import {BuildingQueueHandlerService} from '@warp-core/user/queue/building-queue/building-queue-handler.service';

@Injectable()
export class QueueConsumerMiddleware implements NestMiddleware {
public constructor(
private readonly habitatModel: AuthorizedHabitatModel,
private readonly buildingQueueHandlerService: BuildingQueueHandlerService,
) {}

public async use(
req: Request,
res: Response,
next: NextFunction,
): Promise<void> {
if (this.habitatModel.id) {
await this.buildingQueueHandlerService.resolveQueue();
}

next();
}
}
Loading
Loading