feat: 修改项目后自动删除项目工作区相关目录

This commit is contained in:
Ivan Li
2021-06-27 19:35:49 +08:00
parent 7e17de0f15
commit a231a02c28
14 changed files with 201 additions and 24 deletions

View File

@ -1,8 +1,10 @@
import { Module } from '@nestjs/common';
import { PasswordConverter } from './services/password-converter';
import { RedisMutexModule } from './redis-mutex/redis-mutex.module';
@Module({
providers: [PasswordConverter],
exports: [PasswordConverter],
exports: [PasswordConverter, RedisMutexModule],
imports: [RedisMutexModule],
})
export class CommonsModule {}

View File

@ -0,0 +1,10 @@
import { Module } from '@nestjs/common';
import { RedisMutexService } from './redis-mutex.service';
import { RedisModule } from 'nestjs-redis';
@Module({
imports: [RedisModule],
providers: [RedisMutexService],
exports: [RedisMutexService],
})
export class RedisMutexModule {}

View File

@ -0,0 +1,18 @@
import { Test, TestingModule } from '@nestjs/testing';
import { RedisMutexService } from './redis-mutex.service';
describe('RedisMutexService', () => {
let service: RedisMutexService;
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [RedisMutexService],
}).compile();
service = module.get<RedisMutexService>(RedisMutexService);
});
it('should be defined', () => {
expect(service).toBeDefined();
});
});

View File

@ -0,0 +1,71 @@
import { Injectable } from '@nestjs/common';
import { RedisService } from 'nestjs-redis';
import * as uuid from 'uuid';
import { ApplicationException } from '../exceptions/application.exception';
export interface RedisMutexOption {
/**
* seconds
*/
expires?: number;
/**
* seconds
*/
timeout?: number | null;
/**
* milliseconds
*/
retryDelay?: number;
}
@Injectable()
export class RedisMutexService {
constructor(private readonly redisClient: RedisService) {}
public async lock(
key: string,
{ expires = 100, timeout = 10, retryDelay = 100 }: RedisMutexOption = {
expires: 100,
timeout: 10,
retryDelay: 100,
},
) {
const redisKey = `${'mutex-lock'}:${key}`;
const redis = this.redisClient.getClient();
const value = uuid.v4();
const timeoutAt = timeout ? Date.now() + timeout * 1000 : null;
while (
!(await redis
.set(redisKey, value, 'EX', expires, 'NX')
.then(() => true)
.catch(() => false))
) {
if (timeoutAt && timeoutAt > Date.now()) {
throw new ApplicationException('lock timeout');
}
await new Promise((resolve) => setTimeout(resolve, retryDelay));
}
const renewTimer = setInterval(() => {
redis.expire(redisKey, expires);
}, (expires * 1000) / 2);
return async () => {
clearInterval(renewTimer);
await redis.eval(
`
if redis.call("get", KEYS[1]) == ARGV[1]
then
return redis.call("del", KEYS[1])
else
return 0
end
`,
1,
redisKey,
value,
);
};
}
}