Added timer controllers for managing usage stats

This commit is contained in:
Chris Troutner
2025-06-05 18:25:10 -07:00
parent fcb4acb11d
commit f0f6970a08
5 changed files with 90 additions and 34 deletions
+35 -17
View File
@@ -23,58 +23,76 @@ class TimerControllers {
this.debugLevel = localConfig.debugLevel
// Constants
this.cleanUsageInterval = 60000 * 60 // 1 hour
this.backupUsageInterval = 60000 * 1 // 1 minute
// Encapsulate dependencies
this.config = config
// Bind 'this' object to all subfunctions.
this.exampleTimerFunc = this.exampleTimerFunc.bind(this)
this.cleanUsage = this.cleanUsage.bind(this)
// this.startTimers()
this.backupUsage = this.backupUsage.bind(this)
}
// Start all the time-based controllers.
startTimers () {
// Any new timer control functions can be added here. They will be started
// when the server starts.
this.optimizeWalletHandle = setInterval(this.exampleTimerFunc, 60000 * 60)
this.cleanUsageHandle = setInterval(this.cleanUsage, 60000 * 60) // 1 hour
this.cleanUsageHandle = setInterval(this.cleanUsage, this.cleanUsageInterval)
this.backupUsageHandle = setInterval(this.backupUsage, this.backupUsageInterval)
return true
}
stopTimers () {
clearInterval(this.optimizeWalletHandle)
clearInterval(this.cleanUsageHandle)
clearInterval(this.backupUsageHandle)
}
// Replace this example function with your own timer handler.
exampleTimerFunc (negativeTest) {
// Clean the usage state so that stats reflect the last 24 hours.
cleanUsage () {
try {
console.log('Example timer controller executed.')
clearInterval(this.cleanUsageHandle)
if (negativeTest) throw new Error('test error')
const now = new Date()
console.log(`cleanUsage() Timer Controller executing at ${now.toLocaleString()}`)
this.useCases.usage.cleanUsage()
this.cleanUsageHandle = setInterval(this.cleanUsage, this.cleanUsageInterval)
return true
} catch (err) {
console.error('Error in exampleTimerFunc(): ', err)
console.error('Error in time-controller.js/cleanUsage(): ', err)
this.cleanUsageHandle = setInterval(this.cleanUsage, this.cleanUsageInterval)
// Note: Do not throw an error. This is a top-level function.
return false
}
}
// Clean the usage state so that stats reflect the last 24 hours.
cleanUsage () {
// Backup the usage stats to the database
async backupUsage () {
try {
const now = new Date()
console.log(`cleanUsage() Timer Controller executing at ${now.toLocaleString()}`)
clearInterval(this.backupUsageHandle)
this.useCases.usage.cleanUsage()
console.log('backupUsage() Timer Controller executing at ', new Date().toLocaleString())
// Clear the database of old usage data.
await this.useCases.usage.clearUsage()
// Save the current usage snapshot to the database.
await this.useCases.usage.saveUsage()
this.backupUsageHandle = setInterval(this.backupUsage, this.backupUsageInterval)
return true
} catch (err) {
console.error('Error in time-controller.js/cleanUsage(): ', err)
console.error('Error in time-controller.js/backupUsage(): ', err)
this.backupUsageHandle = setInterval(this.backupUsage, this.backupUsageInterval)
// Note: Do not throw an error. This is a top-level function.
return false
+3
View File
@@ -24,6 +24,9 @@ class UseCases {
// Run any startup Use Cases at the start of the app.
async start () {
// Load the usage stats from the database
await this.usage.loadUsage()
console.log('Async Use Cases have been started.')
return true
+17 -7
View File
@@ -23,6 +23,9 @@ class UsageUseCases {
)
}
// Encapsulate dependencies
this.UsageModel = this.adapters.localdb.Usage
// Bind 'this' object to all subfunctions
this.cleanUsage = this.cleanUsage.bind(this)
this.getRestSummary = this.getRestSummary.bind(this)
@@ -119,12 +122,12 @@ class UsageUseCases {
// Clear the usage database data
async clearUsage () {
try {
await this.adapters.Usage.deleteMany({})
await this.UsageModel.deleteMany({})
// Debugging: verify the database is empty
// Delete this code after debugging
const usage = await this.adapters.Usage.find({})
console.log('usage: ', usage)
const usage = await this.UsageModel.find({})
console.log('clearUsage() usage: ', usage)
} catch (err) {
console.error('Error in usage-use-cases.js/clearUsage()')
throw err
@@ -142,7 +145,14 @@ class UsageUseCases {
console.log('saveUsage() thisRestCall: ', thisRestCall)
}
const usage = new this.UsageModel(thisRestCall)
const usageData = {
ip: thisRestCall.ip,
url: thisRestCall.url,
method: thisRestCall.method,
timestamp: thisRestCall.timestamp
}
const usage = new this.UsageModel(usageData)
await usage.save()
}
} catch (err) {
@@ -154,7 +164,7 @@ class UsageUseCases {
// Load usage data from the database
async loadUsage () {
try {
const usage = await this.adapters.Usage.find({})
const usage = await this.UsageModel.find({})
// console.log('usage: ', usage)
if (usage[5]) {
@@ -163,8 +173,8 @@ class UsageUseCases {
restCalls = usage
} catch (err) {
console.error('Error in usage-use-cases.js/loadUsage()')
throw err
console.error('Error in usage-use-cases.js/loadUsage(): ', err)
// throw err
}
}
}
+27 -10
View File
@@ -66,19 +66,19 @@ describe('#Timer-Controllers', () => {
})
})
describe('#exampleTimerFunc', () => {
it('should kick off the Use Case', async () => {
const result = await uut.exampleTimerFunc()
// describe('#exampleTimerFunc', () => {
// it('should kick off the Use Case', async () => {
// const result = await uut.exampleTimerFunc()
assert.equal(result, true)
})
// assert.equal(result, true)
// })
it('should return false on error', async () => {
const result = await uut.exampleTimerFunc(true)
// it('should return false on error', async () => {
// const result = await uut.exampleTimerFunc(true)
assert.equal(result, false)
})
})
// assert.equal(result, false)
// })
// })
describe('#cleanUsage', () => {
it('should kick off the Use Case', async () => {
@@ -94,4 +94,21 @@ describe('#Timer-Controllers', () => {
assert.equal(result, false)
})
})
describe('#backupUsage', () => {
it('should kick off the Use Case', async () => {
const result = await uut.backupUsage()
assert.equal(result, true)
})
it('should return false on error', async () => {
sandbox.stub(uut.useCases.usage, 'clearUsage').throws(new Error('test error'))
// sandbox.stub(uut.useCases.usage, 'saveUsage').throws(new Error('test error'))
const result = await uut.backupUsage()
assert.equal(result, false)
})
})
})
+8
View File
@@ -47,6 +47,14 @@ class UsageUseCaseMock {
async getTopEndpoints(existingUser, newData) {
return true
}
async clearUsage() {
return true
}
async saveUsage() {
return true
}
}
class UseCasesMock {