Skip to content

Commit

Permalink
fix(server): fix billing miss on old app (#1659)
Browse files Browse the repository at this point in the history
* fix(server): fix billing miss on old app

* fix
  • Loading branch information
0fatal authored Nov 9, 2023
1 parent c1f0cdc commit 4e5b8d4
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 18 deletions.
2 changes: 2 additions & 0 deletions server/src/application/entities/application.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@ export class Application {

billingLockedAt: Date

latestBillingTime?: Date

constructor(partial: Partial<Application>) {
Object.assign(this, partial)
}
Expand Down
57 changes: 39 additions & 18 deletions server/src/billing/billing-creation-task.service.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import { Injectable, Logger } from '@nestjs/common'
import { Cron, CronExpression } from '@nestjs/schedule'
import { Application } from 'src/application/entities/application'
import {
Application,
ApplicationState,
} from 'src/application/entities/application'
import { ServerConfig, TASK_LOCK_INIT_TIME } from 'src/constants'
import { SystemDatabase } from 'src/system-database'
import {
Expand All @@ -15,17 +18,15 @@ import { BundleService } from 'src/application/bundle.service'
@Injectable()
export class BillingCreationTaskService {
private readonly logger = new Logger(BillingCreationTaskService.name)
private readonly lockTimeout = 60 * 60 // in second
private readonly lockTimeout = 15 // in second
private readonly billingInterval = 60 * 60 // in second
private lastTick = TASK_LOCK_INIT_TIME

constructor(
private readonly billing: BillingService,
private readonly bundleService: BundleService,
) {}

/**
* Cron job method that runs every 10 minute
*/
@Cron(CronExpression.EVERY_MINUTE)
async tick() {
// If billing creation task is disabled, return
Expand Down Expand Up @@ -58,8 +59,12 @@ export class BillingCreationTaskService {
billingLockedAt: {
$lt: new Date(Date.now() - 1000 * this.lockTimeout),
},
latestBillingTime: {
$lt: new Date(Date.now() - 1000 * this.billingInterval),
},
state: ApplicationState.Running,
},
{ $set: { billingLockedAt: this.getHourTime() } },
{ $set: { billingLockedAt: new Date() } },
)

if (!res.value) {
Expand All @@ -78,17 +83,29 @@ export class BillingCreationTaskService {
}

// unlock billing if billing time is not the latest
if (Date.now() - billingTime.getTime() > 1000 * this.lockTimeout) {
if (Date.now() - billingTime.getTime() > 1000 * this.billingInterval) {
this.logger.warn(
`Unlocking billing for application: ${app.appid} since billing time is not the latest`,
)

await db
.collection<Application>('Application')
.updateOne(
{ appid: app.appid },
{ $set: { billingLockedAt: TASK_LOCK_INIT_TIME } },
)
await db.collection<Application>('Application').updateOne(
{ appid: app.appid },
{
$set: {
billingLockedAt: TASK_LOCK_INIT_TIME,
latestBillingTime: billingTime,
},
},
)
} else {
await db.collection<Application>('Application').updateOne(
{ appid: app.appid },
{
$set: {
latestBillingTime: billingTime,
},
},
)
}
} catch (err) {
this.logger.error(
Expand All @@ -101,16 +118,18 @@ export class BillingCreationTaskService {
}
}

private async createApplicationBilling(app: Application) {
private async createApplicationBilling(app: Application): Promise<Date> {
this.logger.debug(`Start creating billing for application: ${app.appid}`)

const appid = app.appid
const db = SystemDatabase.db

// determine latest billing time & next metering time
const latestBillingTime = await this.getLatestBillingTime(appid)
const latestBillingTime = app.latestBillingTime
? app.latestBillingTime
: await this.getLatestBillingTime(appid)
const nextMeteringTime = new Date(
latestBillingTime.getTime() + 1000 * 60 * 60,
latestBillingTime.getTime() + 1000 * this.billingInterval,
)

if (nextMeteringTime > new Date()) {
Expand All @@ -124,7 +143,7 @@ export class BillingCreationTaskService {
)
if (!meteringData) {
this.logger.warn(`No metering data found for application: ${appid}`)
return
return nextMeteringTime
}

// get application bundle
Expand All @@ -145,7 +164,9 @@ export class BillingCreationTaskService {
}

// create billing
const startAt = new Date(nextMeteringTime.getTime() - 1000 * 60 * 60)
const startAt = new Date(
nextMeteringTime.getTime() - 1000 * this.billingInterval,
)
const inserted = await db
.collection<ApplicationBilling>('ApplicationBilling')
.insertOne({
Expand Down

0 comments on commit 4e5b8d4

Please sign in to comment.