NEST 中的时间单位

Time units

Version: 5.x

英文原文地址:Time units

与 Elasticsearch 交互,我们会遇到需要设定时间段的情况(例如:timeout 参数)。为了指定时间段,我们可以使用一个表示时间的整数(以毫秒为单位),也可以使用一个时间值(例如:2d 表示 2 天)。

NEST 使用一个 Time 类型来满足上述需求,有好几种方式来构造 Time 对象。

Constructor

最直接的方式当然是构造函数了,参数可以是列表中的任意一种:

  • 字符串
  • double 类型的毫秒值
  • 因子和间隔的组合(其实就是数字和单位)
  • TimeSpan 对象
var unitString = new Time("2d");
var unitComposed = new Time(2, Nest.TimeUnit.Day);
var unitTimeSpan = new Time(TimeSpan.FromDays(2));
var unitMilliseconds = new Time(1000 * 60 * 60 * 24 * 2);

Time 对象序列化后的结果是一个由因子和间隔构成的字符串,如:上面这段代码中的变量序列化的结果都是 2d

即使没有使用 Time(double ms) 这个构造函数,TimeMilliseconds 属性也会被计算。

unitMilliseconds.Milliseconds.Should().Be(1000*60*60*24*2);
unitComposed.Milliseconds.Should().Be(1000*60*60*24*2);
unitTimeSpan.Milliseconds.Should().Be(1000*60*60*24*2);
unitString.Milliseconds.Should().Be(1000*60*60*24*2);

Implicit conversion

NEST 提供了从 string TimeSpan doubleTime 的隐式转换,提高了易用性。

Time oneAndHalfYear = "1.5y";
Time fourteenDays = TimeSpan.FromDays(14);
Time twoDays = 1000*60*60*24*2;

Expect("1.5y").WhenSerializing(oneAndHalfYear);
Expect("14d").WhenSerializing(fourteenDays);
Expect("2d").WhenSerializing(twoDays);

Equality and Comparison

处理 年和月 的时候,是无法精确计算毫秒数的,Milliseconds 的值为 -1 。这是因为年和月不是固定的值,举个栗子

  • 一月(不是一月份)可能有 30 天、31 天、28 天、29 天
  • 一年可能有 365 天、366 天
Time oneAndHalfYear = "1.5y";
oneAndHalfYear.Milliseconds.Should().Be(-1);

你可以将两个 Time 对象做比较

Time twoDays = 1000*60*60*24*2;

oneAndHalfYear.Should().BeGreaterThan(fourteenDays);
(oneAndHalfYear > fourteenDays).Should().BeTrue();
(oneAndHalfYear >= fourteenDays).Should().BeTrue();
(twoDays != null).Should().BeTrue();
(twoDays >= new Time("2d")).Should().BeTrue();

twoDays.Should().BeLessThan(fourteenDays);
(twoDays < fourteenDays).Should().BeTrue();
(twoDays <= fourteenDays).Should().BeTrue();
(twoDays <= new Time("2d")).Should().BeTrue();

判定相等性

twoDays.Should().Be(new Time("2d"));
(twoDays == new Time("2d")).Should().BeTrue();
(twoDays != new Time("2.1d")).Should().BeTrue();
(new Time("2.1d") == new Time(TimeSpan.FromDays(2.1))).Should().BeTrue();

相等的精确度为 0.1 纳秒

Time oneNanosecond = new Time(1, Nest.TimeUnit.Nanoseconds);
Time onePointNoughtNineNanoseconds = "1.09nanos";
Time onePointOneNanoseconds = "1.1nanos";

(oneNanosecond == onePointNoughtNineNanoseconds).Should().BeTrue();
(oneNanosecond == onePointOneNanoseconds).Should().BeFalse();

Special Time Values

Elasticsearch 有两个特殊的时间值

  • 0 通过 Time.Zero 表示
  • -1 通过 Time.MinusOne 表示

下面的对象都等于 Time.MinusOne

Time.MinusOne.Should().Be(Time.MinusOne);
new Time("-1").Should().Be(Time.MinusOne);
new Time(-1).Should().Be(Time.MinusOne);
((Time) (-1)).Should().Be(Time.MinusOne);
((Time) "-1").Should().Be(Time.MinusOne);
((Time) (-1)).Should().Be((Time) "-1");

下面的对象都等于 Time.Zero

Time.Zero.Should().Be(Time.Zero);
new Time("0").Should().Be(Time.Zero);
new Time(0).Should().Be(Time.Zero);
((Time) 0).Should().Be(Time.Zero);
((Time) "0").Should().Be(Time.Zero);
((Time) 0).Should().Be((Time) "0");

特殊的时间值 0-1 可以和其他 Time 值做比较,尽管这看起来很荒谬。

var twoDays = new Time(2, Nest.TimeUnit.Day);
Time.MinusOne.Should().BeLessThan(Time.Zero);
Time.Zero.Should().BeGreaterThan(Time.MinusOne);
Time.Zero.Should().BeLessThan(twoDays);
Time.MinusOne.Should().BeLessThan(twoDays);

如果需要构造一个 -1ms 或者 0ms 的时间,使用接收因子和间隔的构造函数,或者指定一个 ms 字符串

(new Time(-1, Nest.TimeUnit.Millisecond) == new Time("-1ms")).Should().BeTrue();
(new Time(0, Nest.TimeUnit.Millisecond) == new Time("0ms")).Should().BeTrue();

Units of Time

可以使用一个 DateIntervalTime 构成的共用体 Union<DateInterval, Time> 来指定一个 Time 的单位,它支持 TimeDateInterval 的隐式转换

Expect("month").WhenSerializing<Union<DateInterval, Time>>(DateInterval.Month);
Expect("day").WhenSerializing<Union<DateInterval, Time>>(DateInterval.Day);
Expect("hour").WhenSerializing<Union<DateInterval, Time>>(DateInterval.Hour);
Expect("minute").WhenSerializing<Union<DateInterval, Time>>(DateInterval.Minute);
Expect("quarter").WhenSerializing<Union<DateInterval, Time>>(DateInterval.Quarter);
Expect("second").WhenSerializing<Union<DateInterval, Time>>(DateInterval.Second);
Expect("week").WhenSerializing<Union<DateInterval, Time>>(DateInterval.Week);
Expect("year").WhenSerializing<Union<DateInterval, Time>>(DateInterval.Year);

Expect("2d").WhenSerializing<Union<DateInterval, Time>>((Time)"2d");
Expect("11664m").WhenSerializing<Union<DateInterval, Time>>((Time)TimeSpan.FromDays(8.1));

转载于:https://www.cnblogs.com/WessonStar/p/8312804.html

### 使用 BullMQ 实现 NestJS 队列功能 BullMQ 是一个现代的、基于 Redis 的任务队列系统,专为 Node.js 应用设计,适用于 NestJS 项目。它提供了丰富的功能,如延迟任务、计划任务、作业优先级、失败重试机制等[^5]。以下是实现 NestJS 队列功能的步骤: #### 安装依赖 在项目中使用 BullMQ,首先需要安装相关的依赖包: ```bash npm install --save bullmq ``` 此外,确保 Redis 服务正在运行,并可以被应用访问。 #### 定义队列服务 创建一个服务类来管理队列的添加和处理任务。例如: ```typescript import { Injectable } from '@nestjs/common'; import { Queue, Worker } from 'bullmq'; @Injectable() export class QueueService { private readonly queue: Queue; constructor() { this.queue = new Queue('myQueue', { connection: { host: 'localhost', port: 6379, }, }); } async addJob(data: any) { await this.queue.add('myJob', data); } startWorker() { new Worker( 'myQueue', async (job) => { console.log(`Processing job ${job.id} with data ${JSON.stringify(job.data)}`); // 在这里执行任务逻辑 }, { connection: { host: 'localhost', port: 6379, }, }, ); } } ``` #### 调用队列服务 在控制器或其他服务中调用 `QueueService` 来提交任务: ```typescript import { Controller, Post, Body } from '@nestjs/common'; import { QueueService } from './queue.service'; @Controller('jobs') export class JobController { constructor(private readonly queueService: QueueService) {} @Post() async createJob(@Body() data: any) { await this.queueService.addJob(data); return { message: 'Job added to queue' }; } } ``` #### 配置延迟任务 BullMQ 支持延迟任务,可以通过 `delay` 参数指定任务延迟执行的时间单位为毫秒): ```typescript await this.queue.add('delayedJob', { foo: 'bar' }, { delay: 5000 }); // 延迟 5 秒执行 ``` #### 设置计划任务 BullMQ 支持通过 `cron` 表达式定义周期性任务: ```typescript await this.queue.add( 'repeatingJob', { type: 'daily' }, { repeat: { cron: '0 0 * * *', // 每天执行一次 }, }, ); ``` #### 失败重试机制 可以通过设置 `attempts` 和 `backoff` 来定义任务失败后的重试策略: ```typescript await this.queue.add( 'retryJob', { attempts: 3 }, { attempts: 3, backoff: { type: 'fixed', delay: 2000, // 每次失败后等待 2 秒重试 }, }, ); ``` #### 父子任务与依赖关系 BullMQ 支持父子任务模型,可以在任务之间建立依赖关系: ```typescript const parentJob = await this.queue.add('parentJob', { parentId: null }); const childJob = await this.queue.add('childJob', { parentId: parentJob.id }); ``` ### 使用 RabbitMQ 实现队列功能 除了 BullMQ,NestJS 也可以通过 `@nestjs/microservices` 集成 RabbitMQ 实现队列功能。以下是一个基础配置示例: #### 安装依赖 ```bash npm install --save amqplib amqp-connection-manager @nestjs/microservices ``` #### 配置 RabbitMQ 客户端 ```typescript import { Module } from '@nestjs/common'; import { ClientsModule, Transport } from '@nestjs/microservices'; @Module({ imports: [ ClientsModule.register([ { name: 'RABBITMQ_CLIENT', transport: Transport.RMQ, options: { urls: ['amqp://localhost:5672'], queue: 'task_queue', queueOptions: { durable: true, // 队列持久化 }, }, }, ]), ], }) export class RabbitMQModule {} ``` #### 发送和接收消息 在服务中注入 `ClientProxy` 并发送消息: ```typescript import { Injectable } from '@nestjs/common'; import { ClientProxy } from '@nestjs/microservices'; @Injectable() export class RabbitMQService { constructor(private readonly client: ClientProxy) {} sendMessage(pattern: string, data: any) { return this.client.send(pattern, data); } } ``` 在控制器中调用: ```typescript import { Controller, Post, Body } from '@nestjs/common'; import { RabbitMQService } from './rabbitmq.service'; @Controller('messages') export class MessageController { constructor(private readonly rabbitMQService: RabbitMQService) {} @Post() sendMessage(@Body() data: any) { this.rabbitMQService.sendMessage('task_queue', data); return { message: 'Message sent to RabbitMQ' }; } } ``` #### 消费者端监听消息 创建一个消费者服务来监听并处理消息: ```typescript import { Controller } from '@nestjs/common'; import { MessagePattern } from '@nestjs/microservices'; @Controller() export class RabbitMQConsumer { @MessagePattern('task_queue') handleMessage(data: any) { console.log(`Received message: ${JSON.stringify(data)}`); // 处理消息逻辑 } } ``` ### 总结 NestJS 提供了多种实现队列功能的方式,其中 BullMQ 和 RabbitMQ 是两种主流方案。BullMQ 更适合基于 Redis 的分布式任务队列,支持延迟任务、计划任务和失败重试;而 RabbitMQ 则适用于需要高可靠消息传递的场景,尤其适合跨服务通信[^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值