Skip to content

Commit

Permalink
Fitbit sync task adjustments and readme update.
Browse files Browse the repository at this point in the history
  • Loading branch information
douglasrafael committed Sep 20, 2019
1 parent 700be9d commit 7b1bb2e
Show file tree
Hide file tree
Showing 6 changed files with 40 additions and 43 deletions.
2 changes: 1 addition & 1 deletion .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ FITBIT_SUBSCRIBER_ID=SUBSCRIBER_ID_HERE
#################################################################################################

# EXPRESSION_AUTO_SYNC Frequency time that the application will sync the users data in
# background, according with the time format defined on node-cron library.
# background according to the crontab expression.
# For example, the value 0 0 * * 0, means that the sync it will occurs
# every sunday at 00:00.
# default value: 0 0 * * 0
Expand Down
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ Application settings are defined by environment variables. To define the setting
| `FITBIT_CLIENT_SECRET` | Client Secret for Fitbit Application resposible to manage user data. | `CIENT_SECRET_HERE` |
| `FITBIT_CLIENT_SUBSCRIBER` | Client Subscriber code for automatically get notification from new sync data. | `CLIENT_SUBSCRIBER_HERE` |
| `FITBIT_SUBSCRIBER_ID` | Customer Subscriber ID, used to manage the subscriber who will receive notification of a user resource. | `FITBIT_SUBSCRIBER_ID` |
| `EXPRESSION_AUTO_SYNC` | Defines how often the application will automatically sync user data in the background according to the crontab expression. | `0 0 * * 0` |

## Generate Certificates
For development and testing environments the easiest and fastest way is to generate your own self-signed certificates. These certificates can be used to encrypt data as well as certificates signed by a CA, but users will receive a warning that the certificate is not trusted for their computer or browser. Therefore, self-signed certificates should only be used in non-production environments, that is, development and testing environments. To do this, run the `create-self-signed-certs.sh` script in the root of the repository.
Expand Down Expand Up @@ -120,6 +121,7 @@ docker run --rm \
-e FITBIT_CLIENT_SECRET="YOUR_FITBIT_CLIENT_SECRET" \
-e FITBIT_CLIENT_SUBSCRIBER="YOUR_FITBIT_CLIENT_SUBSCRIBER" \
-e FITBIT_SUBSCRIBER_ID="SUBSCRIBER_ID_HERE" \
-e EXPRESSION_AUTO_SYNC="0 0 * * 0" \
ocariot/ds-agent
```
If the MongoDB or RabbitMQ instance is in the host local, add the `--net=host` statement when creating the container, this will cause the docker container to communicate with its local host.
Expand All @@ -132,6 +134,7 @@ docker run --rm \
-e FITBIT_CLIENT_SECRET="YOUR_FITBIT_CLIENT_SECRET" \
-e FITBIT_CLIENT_SUBSCRIBER="YOUR_FITBIT_CLIENT_SUBSCRIBER" \
-e FITBIT_SUBSCRIBER_ID="SUBSCRIBER_ID_HERE" \
-e EXPRESSION_AUTO_SYNC="0 0 * * 0" \
ocariot/ds-agent
```
To generate your own docker image, run the following command:
Expand Down
20 changes: 10 additions & 10 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "data-sync-agent",
"version": "1.2.0",
"version": "1.3.0",
"description": "Service responsible for data synchronization of FitBit and CVE platform with OCARIoT platform.",
"main": "dist/server.js",
"scripts": {
Expand Down
42 changes: 19 additions & 23 deletions src/background/task/collect.fitbit.user.data.task.ts
Original file line number Diff line number Diff line change
@@ -1,54 +1,50 @@
import { inject, injectable } from 'inversify'
import { Identifier } from '../../di/identifiers'
import { ILogger } from '../../utils/custom.logger'
import { IConnectionDB } from '../../infrastructure/port/connection.db.interface'
import { IBackgroundTask } from '../../application/port/background.task.interface'
import { IFitbitDataRepository } from '../../application/port/fitbit.auth.data.repository.interface'
import { IUserAuthDataRepository } from '../../application/port/user.auth.data.repository.interface'
import { Query } from '../../infrastructure/repository/query/query'
import { UserAuthData } from '../../application/domain/model/user.auth.data'
import cron from 'node-cron'
import moment from 'moment'

@injectable()
export class CollectFitbitUserDataTask implements IBackgroundTask {
private schedule: any

constructor(
@inject(Identifier.MONGODB_CONNECTION) private readonly _mongodb: IConnectionDB,
@inject(Identifier.FITBIT_DATA_REPOSITORY) private readonly _fitbitAuthDataRepo: IFitbitDataRepository,
@inject(Identifier.USER_AUTH_DATA_REPOSITORY) private readonly _userAuthDataRepo: IUserAuthDataRepository,
@inject(Identifier.LOGGER) private readonly _logger: ILogger
) {
this.createSchedule(`${process.env.EXPRESSION_AUTO_SYNC}`)
this.schedule = cron.schedule(`${process.env.EXPRESSION_AUTO_SYNC}`, () => this.getFitbitUsersData())
}

public async run(): Promise<void> {
this._mongodb.eventConnection.on('connected', async () => {
this.schedule.start()
})
this.schedule.start()
}

public async createSchedule(expression: string): Promise<void> {
this.schedule = cron.schedule(expression, async () => {
console.log('running a task every minute -', moment().format('HH:mm:ss'))
this.getFitbitUsersData()
})
}
private getFitbitUsersData(): void {
const query = new Query()
query.filters = { 'fitbit.is_valid': true }

private async getFitbitUsersData(): Promise<void> {
return new Promise<void>(async (resolve, reject) => {
const usersData: Array<UserAuthData> = await this._userAuthDataRepo.find(new Query())
for await (const data of usersData) {
this._fitbitAuthDataRepo.syncFitbitUserData(data.fitbit!, data.fitbit!.last_sync!, 1, data.user_id!)
.then(() => this._logger.info(`Data from ${data.user_id} successful synchronized!`))
.catch(err => this._logger.error(err.message))
}
})
this._userAuthDataRepo
.find(query)
.then((usersData: Array<UserAuthData>) => {
for (const data of usersData) {
this._fitbitAuthDataRepo
.syncFitbitUserData(data.fitbit!, data.fitbit!.last_sync!, 1, data.user_id!)
.then(() => this._logger.info(`Fitbit sync task for child ${data.user_id} finished!`))
.catch(err => this._logger.error(err.message))
}
})
.catch(err => {
this._logger.error(`An error occurred while performing Fitbit sync. ${err.message}`)
})
}

public stop(): Promise<void> {
this.schedule.stop()
this.schedule.destroy()
return Promise.resolve()
}
}
14 changes: 6 additions & 8 deletions test/unit/repositories/fitbit.data.repository.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import { DefaultEntityMock } from '../../mocks/models/default.entity.mock'
import { UserAuthData } from '../../../src/application/domain/model/user.auth.data'
import { assert } from 'chai'
import sinon from 'sinon'
import jwt from 'jsonwebtoken'

require('sinon-mongoose')

Expand Down Expand Up @@ -192,7 +191,6 @@ describe('Repositories: FitbitDataRepository', () => {
describe('syncFitbitUserData', () => {
context('when token is expired', () => {
it('should reject an error', () => {
console.log(generateTokenWithoutScope('none'))
data.fitbit!.access_token = 'expired'
sinon
.mock(modelFake)
Expand Down Expand Up @@ -292,9 +290,9 @@ describe('Repositories: FitbitDataRepository', () => {
})
})

function generateTokenWithoutScope(scope: string): any {
const payload: any = { ...DefaultEntityMock.PAYLOAD }
payload.scopes = payload.scopes === 'none' ? '' :
payload.scopes.split(' ').filter(item => item !== scope).join(' ')
return jwt.sign(payload, 'shhhhh')
}
// function generateTokenWithoutScope(scope: string): any {
// const payload: any = { ...DefaultEntityMock.PAYLOAD }
// payload.scopes = payload.scopes === 'none' ? '' :
// payload.scopes.split(' ').filter(item => item !== scope).join(' ')
// return jwt.sign(payload, 'shhhhh')
// }

0 comments on commit 7b1bb2e

Please sign in to comment.