diff --git a/.github/workflows/nodejs.yml b/.github/workflows/nodejs.yml index 92626837..b350216d 100644 --- a/.github/workflows/nodejs.yml +++ b/.github/workflows/nodejs.yml @@ -9,9 +9,9 @@ jobs: matrix: node-version: [16.x] steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Install node - uses: actions/setup-node@v1 + uses: actions/setup-node@v3 with: node-version: ${{ matrix.node-version }} - name: Update version patch @@ -52,11 +52,11 @@ jobs: npm run bundle cp dist/generated/swagger.json ../casanet_bin/swagger.json cp -v bundle/* ../casanet_bin - - uses: actions/upload-artifact@v2 + - uses: actions/upload-artifact@v3 with: name: casanet_bin path: casanet_bin - - uses: actions/upload-artifact@v2 + - uses: actions/upload-artifact@v3 with: name: swagger-spec path: backend/dist/generated/swagger.json @@ -68,9 +68,9 @@ jobs: node-version: [16.x] if: github.ref != 'refs/heads/master' steps: - - uses: actions/checkout@v1 + - uses: actions/checkout@v3 - name: Install node - uses: actions/setup-node@v1 + uses: actions/setup-node@v3 with: node-version: ${{ matrix.node-version }} - name: test backend @@ -88,9 +88,9 @@ jobs: node-version: [16.x] if: github.ref == 'refs/heads/master' steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Install node - uses: actions/setup-node@v1 + uses: actions/setup-node@v3 with: node-version: ${{ matrix.node-version }} - uses: actions/download-artifact@master diff --git a/backend/package.json b/backend/package.json index bde81739..4e1866e9 100644 --- a/backend/package.json +++ b/backend/package.json @@ -94,7 +94,7 @@ "ts-events": "^3.4.0", "tsoa": "^3.6.1", "tuyapi": "^7.4.0", - "unitsnet-js": "^1.0.26", + "unitsnet-js": "^1.0.42", "winston": "^3.2.1", "yeelight-awesome": "^1.0.12" }, diff --git a/backend/src/business-layer/actionsService.ts b/backend/src/business-layer/actionsService.ts index a1f096c9..e4e100a4 100644 --- a/backend/src/business-layer/actionsService.ts +++ b/backend/src/business-layer/actionsService.ts @@ -21,13 +21,13 @@ export class ActionsService { // Subscribe to each minion change this.minionsService.minionFeed.attach((minionFeed) => { this.onMinionStatusChange(minionFeed); }); // Run in interval to force the action set, in case of ActionApply permanent. - setInterval(() => { this.forceActionsActions(); }, ACTIONS_ACTIVATION.Milliseconds); + setInterval(() => { this.forceActionsSet(); }, ACTIONS_ACTIVATION.Milliseconds); } /** * Force the permanent actions */ - private async forceActionsActions() { + private async forceActionsSet() { // Get all actions in system const actions = await this.actionsDal.getActions(); @@ -74,6 +74,11 @@ export class ActionsService { * @param minionFeed The minions feed object */ private async onMinionStatusChange(minionFeed: MinionFeed) { + if (minionFeed.event === 'removed') { + await this.deleteMinionActions(minionFeed.minion); + return; + } + // If it's not an update, do nothing if (minionFeed.event !== 'update') { return; @@ -83,6 +88,20 @@ export class ActionsService { await this.triggerMinionStatusChangedActions(minionFeed.minion); } + /** + * Delete all minion's actions + * @param minion The minion to drop all his actions + */ + private async deleteMinionActions(minion: Minion) { + logger.info(`[ActionsService.deleteMinionActions] Collecting all "${minion.minionId}" minion's actions in order to delete them all`); + const actions = await this.getMinionActions(minion.minionId); + for (const action of actions) { + logger.info(`[ActionsService.deleteMinionActions] Deleting "${action.actionId}" action`); + await this.deleteAction(action.actionId); + } + logger.info(`[ActionsService.deleteMinionActions] Deleting all "${minion.minionId}" actions done`); + } + /** Trigger 'statusChange' of a certain minion that his status updated */ private async triggerMinionStatusChangedActions(minion: Minion) { @@ -98,7 +117,7 @@ export class ActionsService { } logger.info(`[ActionsService.triggerMinionStatusChangedActions] Triggering minion ${minion.minionId} actions done"`); - await this.forceActionsActions() + await this.forceActionsSet() } /** @@ -207,7 +226,7 @@ export class ActionsService { public async setAction(actionId: string, action: Action): Promise { await this.validateActionParams(action); action.actionId = actionId; - this.forceActionsActions(); + this.forceActionsSet(); return await this.actionsDal.updateAction(action); } @@ -215,7 +234,7 @@ export class ActionsService { const action = await this.getActionById(actionId); const actionCopy = DeepCopy(action); actionCopy.active = active; - this.forceActionsActions(); + this.forceActionsSet(); return await this.actionsDal.updateAction(actionCopy); } @@ -231,7 +250,7 @@ export class ActionsService { */ action.actionId = randomstring.generate(6); await this.actionsDal.createAction(action); - this.forceActionsActions(); + this.forceActionsSet(); return action; } diff --git a/backend/src/business-layer/timingsBl.ts b/backend/src/business-layer/timingsBl.ts index 34d2011c..66ba3f2d 100644 --- a/backend/src/business-layer/timingsBl.ts +++ b/backend/src/business-layer/timingsBl.ts @@ -10,6 +10,8 @@ import { DailyTiming, DaysOptions, ErrorResponse, + Minion, + MinionFeed, OnceTiming, OperationResult, TimeoutTiming, @@ -19,6 +21,7 @@ import { import { logger } from '../utilities/logger'; import { OperationsBl, OperationsBlSingleton } from './operationsBl'; import { SyncEvent } from 'ts-events'; +import { MinionsBl, MinionsBlSingleton } from './minionsBl'; const TIMING_INTERVAL_ACTIVATION = moment.duration(5, 'seconds'); @@ -39,8 +42,9 @@ export class TimingsBl { * @param timingsDal Inject timings dal. * @param localNetworkReader Inject the reader function. */ - constructor(private timingsDal: TimingsDal, private operationBl: OperationsBl) { - + constructor(private timingsDal: TimingsDal, private operationBl: OperationsBl, private minionsService: MinionsBl) { + // Subscribe to each minion change + this.minionsService.minionFeed.attach((minionFeed) => { this.onMinionStatusChange(minionFeed); }); } /** @@ -106,6 +110,33 @@ export class TimingsBl { return await this.timingsDal.deleteTiming(timingId); } + /** + * Handle minion update event + * @param minionFeed The minions feed object + */ + private async onMinionStatusChange(minionFeed: MinionFeed) { + if (minionFeed.event === 'removed') { + await this.deleteMinionTimings(minionFeed.minion); + return; + } + } + + /** + * Delete all minion's actions + * @param minion The minion to drop all his actions + */ + private async deleteMinionTimings(minion: Minion) { + logger.info(`[TimingsService.deleteMinionTimings] Collecting all "${minion.minionId}" minion's timings in order to delete them all`); + const timings = await this.getTimings(); + + const minionTimings = timings.filter(t => t?.triggerDirectAction?.minionId === minion.minionId); + for (const timing of minionTimings) { + logger.info(`[ActionsService.deleteMinionActions] Deleting "${timing.timingId}" timing`); + await this.DeleteTiming(timing.timingId); + } + logger.info(`[TimingsService.deleteMinionTimings] Deleting all "${minion.minionId}" timings done`); + } + /** * Active timing. * @param timing timing to active. @@ -316,4 +347,4 @@ export class TimingsBl { } } -export const TimingsBlSingleton = new TimingsBl(TimingsDalSingleton, OperationsBlSingleton); +export const TimingsBlSingleton = new TimingsBl(TimingsDalSingleton, OperationsBlSingleton, MinionsBlSingleton); diff --git a/backend/yarn.lock b/backend/yarn.lock index 03e78e61..3911ac48 100644 --- a/backend/yarn.lock +++ b/backend/yarn.lock @@ -6136,10 +6136,10 @@ unique-string@^1.0.0: dependencies: crypto-random-string "^1.0.0" -unitsnet-js@^1.0.26: - version "1.0.27" - resolved "https://registry.yarnpkg.com/unitsnet-js/-/unitsnet-js-1.0.27.tgz#5ddb4cd2bfaeb21d0193d047f128acaa3cd07721" - integrity sha512-lpVk4jGyXLCCKIszx49NkpxvCg6a/lZ5olp9EFidPsAKSUw6QlQSx70oPPsYqzt/6Gdw/IpKn2l1vcoCRO7bmw== +unitsnet-js@^1.0.42: + version "1.0.42" + resolved "https://registry.yarnpkg.com/unitsnet-js/-/unitsnet-js-1.0.42.tgz#a21046a8c20ac04718389ace6a643aea165906f5" + integrity sha512-NN5qOnLpg5rC/DoLf+5GSSldNtGvfTGli37dijGedLj2t70Wt8CgGpkNd544NohCTcaL07zEDOq5lSrDQVXzEQ== universalify@^0.1.0: version "0.1.2"