Skip to content

Commit

Permalink
Feature/redis (#34)
Browse files Browse the repository at this point in the history
  • Loading branch information
hebertzin authored Jun 23, 2024
1 parent b7fc387 commit a363202
Show file tree
Hide file tree
Showing 13 changed files with 164 additions and 22 deletions.
5 changes: 4 additions & 1 deletion .env.exemple
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
ACCESS_KEY='your_aws_access_key'
SECRET_KEY='your_aws_acess_key'
REGION='your_aws_region'
PORT=3000
PORT=3000
REDIS_PORT=53821
REDIS_HOST="redis_host"
REDIS_PASSWORD="redis_password"
100 changes: 100 additions & 0 deletions package-lock.json

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

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
"compression": "^1.7.4",
"dotenv": "^16.4.5",
"helmet": "^7.1.0",
"ioredis": "^5.4.1",
"k6": "^0.0.0",
"morgan": "^1.10.0",
"multer": "^1.4.5-lts.1",
Expand Down
2 changes: 1 addition & 1 deletion src/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ export class ExpressApp {

public start(port: number) {
return this.expressApp.listen(port, () => {
loggerService.info('Sever is running !')
loggerService.info(`Sever is running on por ${port}!`)
})
}

Expand Down
3 changes: 3 additions & 0 deletions src/config/env/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ const envSchema = z.object({
ACCESS_KEY: z.string(),
SECRET_KEY: z.string(),
REGION: z.string(),
REDIS_PORT: z.coerce.number(),
REDIS_HOST: z.string(),
REDIS_PASSWORD: z.string(),
})

const _env = envSchema.safeParse(process.env)
Expand Down
4 changes: 3 additions & 1 deletion src/controllers/list-all-files-controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import { Request, Response } from 'express'
import { ListFilesService } from '../services/list-all-files-service'
import { s3 } from '../aws'
import { HttpStatusCode } from '../utils/http-status'
import { loggerService } from '../config/logger/winston'
import { redis } from '../redis'

export class ListFilesController {
private listFilesService: ListFilesService
Expand All @@ -27,5 +29,5 @@ export class ListFilesController {
}

export const listFilesControllerHandler = new ListFilesController(
new ListFilesService(s3),
new ListFilesService(s3, loggerService, redis),
)
7 changes: 6 additions & 1 deletion src/controllers/list-file-by-id-controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { ListFileByIdService } from '../services/list-file-by-id-service'
import { s3 } from '../aws'
import { HttpStatusCode } from '../utils/http-status'
import { loggerService } from '../config/logger/winston'
import { redis } from '../redis'

export class ListFileByIdController {
private listFileByIdService: ListFileByIdService
Expand All @@ -27,7 +28,11 @@ export class ListFileByIdController {
}
}

export const listFileByIdService = new ListFileByIdService(s3, loggerService)
export const listFileByIdService = new ListFileByIdService(
s3,
loggerService,
redis,
)

export const listFileByIdControllerHandler = new ListFileByIdController(
listFileByIdService,
Expand Down
8 changes: 8 additions & 0 deletions src/redis/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import Redis from 'ioredis'
import { env } from '../config/env'

export const redis = new Redis({
password: env.REDIS_PASSWORD,
host: env.REDIS_HOST,
port: env.REDIS_PORT,
})
15 changes: 14 additions & 1 deletion src/services/list-all-files-service.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,31 @@
import { S3Client, ListObjectsV2Command, _Object } from '@aws-sdk/client-s3'
import { Redis } from 'ioredis'
import { Logger } from 'winston'

export class ListFilesService {
private s3: S3Client
private redisService: Redis
private logger: Logger

constructor(s3: S3Client) {
constructor(s3: S3Client, logger: Logger, redisService: Redis) {
this.s3 = s3
this.redisService = redisService
this.logger = logger
}

public async invoke(): Promise<_Object[]> {
const params = {
Bucket: 'storage-app',
}
try {
const cacheData = await this.redisService.get('data')
if (cacheData) {
this.logger.info('Returning data from cache...')
return JSON.parse(cacheData)
}
const data = await this.s3.send(new ListObjectsV2Command(params))

await this.redisService.set('data', JSON.stringify(data), 'EX', 3000)
return data.Contents
} catch (error) {
throw new Error('Some error has been ocurred')
Expand Down
16 changes: 14 additions & 2 deletions src/services/list-file-by-id-service.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { S3Client, HeadObjectCommand } from '@aws-sdk/client-s3'
import { Redis } from 'ioredis'
import { Logger } from 'winston'

type ReturnTypeListFileById = {
Expand All @@ -11,13 +12,20 @@ type ReturnTypeListFileById = {
export class ListFileByIdService {
private s3: S3Client
private logger: Logger
private redisService: Redis

constructor(s3: S3Client, logger: Logger) {
constructor(s3: S3Client, logger: Logger, redisService: Redis) {
this.s3 = s3
this.logger = logger
this.redisService = redisService
}

public async invoke(file_id: string): Promise<ReturnTypeListFileById> {
const cacheData = await this.redisService.get(file_id)
if (cacheData) {
this.logger.info('Returning file in cache...')
return JSON.parse(cacheData)
}
if (!file_id || file_id.trim() == '') {
this.logger.warn('Provide a file file id...')
throw new Error('Please provide a file id')
Expand All @@ -29,12 +37,16 @@ export class ListFileByIdService {

try {
const data = await this.s3.send(new HeadObjectCommand(params))
return {

const result: ReturnTypeListFileById = {
key: file_id,
size: data.ContentLength,
lastModified: data.LastModified,
contentType: data.ContentType,
}

await this.redisService.set(file_id, JSON.stringify(result), 'EX', 600)
return result
} catch (error) {
throw new Error('Some error while get a file...')
}
Expand Down
2 changes: 1 addition & 1 deletion src/services/upload-file-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,5 +36,5 @@ export class UploadFileService {
this.logger.error('Error uploading file:', error)
throw new Error('An error occurred while uploading the file')
}
}
}
}
16 changes: 3 additions & 13 deletions src/tests/unit/list-all-files-services.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { S3Client, ListObjectsV2Command } from '@aws-sdk/client-s3'
import { ListFilesService } from '../../services/list-all-files-service'
import { env } from '../../config/env'
import { loggerService } from '../../config/logger/winston'
import { redis } from '../../redis'
describe('ListFilesService', () => {
let s3Client: S3Client
let listFilesService: ListFilesService
Expand All @@ -13,24 +15,12 @@ describe('ListFilesService', () => {
secretAccessKey: env.SECRET_KEY,
},
})
listFilesService = new ListFilesService(s3Client)
listFilesService = new ListFilesService(s3Client, loggerService, redis)
})

it('should list files from S3 bucket', async () => {
const result = await listFilesService.invoke()
expect(result).toBeDefined()
result.map((file) => {
expect(file).toHaveProperty('Key')
expect(file).toHaveProperty('LastModified')
expect(file).toHaveProperty('ETag')
expect(file).toHaveProperty('Size')
expect(file).toHaveProperty('StorageClass')

expect(typeof file.Key).toBe('string')
expect(typeof file.ETag).toBe('string')
expect(typeof file.Size).toBe('number')
expect(typeof file.StorageClass).toBe('string')
})
})

afterAll(async () => {
Expand Down
7 changes: 6 additions & 1 deletion src/tests/unit/list-file-by-id-service.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { S3Client, ListObjectsV2Command } from '@aws-sdk/client-s3'
import { ListFileByIdService } from '../../services/list-file-by-id-service'
import { env } from '../../config/env'
import { loggerService } from '../../config/logger/winston'
import { redis } from '../../redis'

describe('ListFileByIdService', () => {
let s3Client: S3Client
Expand All @@ -16,7 +17,11 @@ describe('ListFileByIdService', () => {
},
})

listFileByIdService = new ListFileByIdService(s3Client, loggerService)
listFileByIdService = new ListFileByIdService(
s3Client,
loggerService,
redis,
)
})

it('should list file from S3 bucket', async () => {
Expand Down

0 comments on commit a363202

Please sign in to comment.