构建一个rust生产应用读书笔记7-确认邮件3

news2025/1/7 13:11:38

设计架构思路

从前面的学习过程中,我们从单一文件测试套件发展到模块化测试套件,并构建了一套强大的辅助工具,这是一个非常重要的进展。个人认为测试代码和应用代码一样,是一个持续进化的过程。随着项目的不断成长,测试也需要不断地调整和扩展,以确保新功能的质量以及现有功能的稳定性。

对于接下来要实现的功能——发送确认邮件,我们可以遵循以下步骤来继续推进:

1. 定义需求

明确需要实现的确认邮件功能的具体要求,例如:

  • 在什么情况下触发邮件发送(如用户注册、密码重置等)。
  • 邮件的内容格式(包括主题、正文、签名等)。
  • 收件人的信息来源(从数据库中获取还是其他方式)。
  • 是否有特殊的业务逻辑需要考虑(如个性化内容、多语言支持等)。

2. 设计解决方案

根据需求定义,设计出合理的架构和技术方案。比如选择合适的邮件服务提供商(SMTP服务器或者第三方API),确定如何在应用程序中集成这些服务,以及怎样处理发送失败的情况。

3. 编写单元测试

为新的邮件发送功能编写单元测试。这应该涵盖所有可能的成功路径和失败场景。由于涉及到外部系统(邮件服务),可以使用mock对象或stub来模拟这些依赖,保证测试环境的隔离性和可重复性。

4. 创建集成测试

除了单元测试外,还需要创建集成测试来验证整个流程是否按预期工作。这类测试会真正调用邮件服务,所以要考虑成本和速度的问题。可以通过配置测试环境中的特定设置来控制实际发送的邮件数量,或者仅在CI/CD管道中执行这些测试。

5. 开发功能代码

按照设计方案开始编码实现。确保遵循良好的编程实践,如DRY原则(Don't Repeat Yourself)、SOLID原则等,使代码易于维护和扩展。

6. 实施监控与日志记录

为了跟踪邮件发送的状态并及时发现潜在问题,在关键点添加适当的日志记录是非常必要的。此外,还可以考虑建立一个简单的监控系统,用于检测异常情况并报警。

7. 文档化

不要忘记更新相关文档,描述新增加的功能及其使用方法。这对于未来的维护和支持非常重要。

8. 回顾与优化

完成初步实现后,组织一次代码审查会议,邀请团队成员参与讨论,寻找改进的机会。同时也可以回顾一下现有的测试套件,看看是否有地方可以进一步增强其稳定性和覆盖率。

零停机部署的关键要素

  1. 负载均衡器:使用负载均衡器来分配流量到不同的应用实例。负载均衡器可以在不同版本的应用程序之间切换流量,而不会影响正在处理的请求。

  2. 蓝绿部署(Blue-Green Deployment)

    • 创建两个完全相同的环境,即蓝色环境(当前生产环境)和绿色环境(新版本部署环境)。
    • 当新版本准备就绪后,将流量从蓝色环境切换到绿色环境。
    • 如果出现问题,可以迅速回滚到蓝色环境,确保最小化风险。
  3. 滚动更新(Rolling Update)

    • 逐步替换旧版本的应用实例为新版本,而不是一次性全部替换。
    • 在每次迭代中只更新一部分实例,并监控其健康状态。
    • 如果出现任何问题,可以暂停或回滚更新过程。
  4. 金丝雀发布(Canary Release)

    • 先将新版本部署给一小部分用户(如5%的流量),并密切监控这些用户的体验和系统性能。
    • 如果一切正常,则逐渐增加新版本的流量比例,直到完全取代旧版本。
  5. 数据库迁移

    • 对于涉及数据库模式变更的情况,需要特别小心处理以避免数据丢失或不一致。
    • 可以采用分阶段的方式进行迁移,先引入向后兼容的新字段或表,再逐步移除旧结构。
  6. 自动伸缩:根据实际需求动态调整实例数量,保证有足够的资源来应对流量变化。

  7. 健康检查与自我修复机制:确保有健全的健康检查机制来检测实例的状态,并且能够自动重启故障实例或者重新分配流量。

  8. CI/CD管道:构建持续集成和持续交付(CI/CD)管道,自动化测试、构建和部署过程,减少人为错误的风险。

  9. 配置管理:使用配置管理系统(如Ansible、Puppet、Chef等)来管理和同步配置文件,确保所有实例的一致性。

实施步骤

  • 评估现有架构:首先了解目前使用的云服务提供商、网络设置、容器编排工具(如Kubernetes)、微服务框架等信息。

  • 选择合适的部署策略:基于业务需求和技术栈选择最适合的零停机部署方式,如蓝绿部署、滚动更新或金丝雀发布等。

  • 设计详细的部署计划:包括每个阶段的任务列表、时间安排、责任人以及应急预案。

  • 执行前的准备工作:确保所有必要的基础设施组件已经到位,例如额外的服务器容量、更新后的镜像、修改过的配置文件等。

  • 实施部署:按照预定的计划执行部署,同时密切关注系统的响应情况和服务质量指标。

  • 验证结果:确认新版本已成功上线并且稳定运行,同时收集反馈用于后续改进。

给表添加一个新的列

 sqlx migrate add add_status_to_subscriptions

20241226080004_add_status_to_subscriptions.sql内容

-- Add migration script here
ALTER TABLE subscriptions ADD COLUMN status TEXT NULL;

执行命令 : sqlx migrate run 

新的列入库

//!src/routers/subscriptions.rs
pub async fn insert_subscriber(
    pool: &PgPool,
    new_subscriber: &NewSubscriber,
) -> Result<(), sqlx::Error> {
    sqlx::query!(
        r#"insert into subscriptions (id,email,name,subscribed_at,status) values($1,$2,$3,$4,'confirmed')"#,
        Uuid::new_v4(),
        new_subscriber.email.as_ref(),
        new_subscriber.name.as_ref(),
        Utc::now()
    )
    .execute(pool)
    .await
    .map_err(|e| {
        tracing::error!("Failed to execute query :{:?}", e);
        e
    })?;
    Ok(())
}

 历史数据补全

执行新的SQL

sqlx migrate add make_status_not_null_in_subscriptions

20241226083956_make_status_not_null_in_subscriptions.sql 

-- Add migration script here
BEGIN;
    -- Backfill `status` for historical entries
    UPDATE subscriptions
        SET status = 'confirmed'
        WHERE status IS NULL;
    -- Make `status` mandatory
    ALTER TABLE subscriptions ALTER COLUMN status SET NOT NULL;
COMMIT;

执行命令 : sqlx migrate run 

执行结果显示

当我们处理 subscription_tokens 数据库表时,尤其是在部署新功能(如订阅确认邮件)的背景下,遵循一个结构化的流程来最小化停机时间并确保数据完整性是非常重要的。

可以通过如下步骤处理:

  1. 创建迁移脚本:首先,生成一个新的迁移脚本,用于在数据库中添加subscription_tokens 表。这个表可能包括字段如令牌值、用户ID(或订阅ID)、创建时间戳以及该令牌是否已被使用等。

  2. 独立部署迁移:在这个阶段,运行此迁移以在数据库中添加新的表。此时,你的应用程序应该仍然能正常工作,因为它被设计为忽略或不使用它不认识的表。

  3. 更新应用程序代码:开发并部署应用程序的新版本,使其开始使用 subscription_tokens 表。这将涉及更新代码库以处理令牌的生成、发送确认邮件和验证用户确认订阅时的令牌。

  4. 彻底测试:在全面推出该特性之前,确保你已经测试了从令牌生成到电子邮件确认的整个流程,以防止任何问题发生。

  5. 部署后监控:一旦部署完成,密切监控系统,以便尽早捕捉任何未预见的问题。

让我们执行以下脚本

sqlx migrate add create_subscription_tokens_table

--sql 内容
CREATE TABLE subscription_tokens(
   subscription_token TEXT NOT NULL,
   subscriber_id uuid NOT NULL REFERENCES subscriptions (id),
   PRIMARY KEY (subscription_token)
);
-- 执行
sqlx migrate run

总结

书中的第七章内容比较多,这周调代码好了好长时间,下一节就记录我代码重构的过程吧

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2271674.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

默认ip无法访问,利用dhcp功能获取ip进行访问的方法

应用场景&#xff1a; ac的默认ip如192.168.1.1在pc与ac的eth2以后网口直连无法ping通&#xff0c;而且pc改为dhcp自动获取ip也获取不到ip地址&#xff0c;无法进行web配置和命令行操作。 原因是ac或其他设备被修改了默认ip或者对应端口所属vlanid&#xff0c;现在的端口vlan…

redis的集群模式与ELK基础

一、redis的集群模式 1.主从复制 &#xff08;1&#xff09;概述 主从模式&#xff1a;这是redis高可用的基础&#xff0c;哨兵和集群都是建立在此基础之上。 主从模式和数据库的主从模式是一样的&#xff0c;主负责写入&#xff0c;然后把写入的数据同步到从服务器&#xff…

大脑特训,自信 “满格”

编辑&#xff1a;念小艺 在追求自信的漫漫长路上&#xff0c;诸多因素如同闪耀的星光&#xff0c;为人们指引着方向。保持良好的饮食习惯&#xff0c;让身体摄取充足且均衡的营养&#xff0c;为精神的饱满提供坚实后盾&#xff1b;持续投身于锻炼之中&#xff0c;在挥洒汗水的…

渗透测试-非寻常漏洞案例

声明 本文章所分享内容仅用于网络安全技术讨论&#xff0c;切勿用于违法途径&#xff0c;所有渗透都需获取授权&#xff0c;违者后果自行承担&#xff0c;与本号及作者无关&#xff0c;请谨记守法. 此文章不允许未经授权转发至除先知社区以外的其它平台&#xff01;&#xff0…

计算机的发展、计算机基本组成原理

计算机系统 软件 硬件 硬件的发展 软件的发展 低级语言&#xff1a;机器语言、汇编语言 一、早期冯诺依曼机的结构 存储程序&#xff1a;将指令以二进制代码事先输入计算机的主存储器 在计算机系统软件和硬件是等效的 软件&#xff1a;数据 程序 硬件&#xff1a; 存储器、…

公共数据授权运营系统建设手册(附下载)

在全球范围内&#xff0c;许多国家和地区已经开始探索公共数据授权运营的路径和模式。通过建立公共数据平台&#xff0c;推动数据的开放共享&#xff0c;促进数据的创新应用&#xff0c;不仅能够提高政府决策的科学性和公共服务的效率&#xff0c;还能够激发市场活力&#xff0…

[极客大挑战 2019]HardSQL 1

看了大佬的wp&#xff0c;没用字典爆破&#xff0c;手动试出来的&#xff0c;屏蔽了常用的关键字&#xff0c;例如&#xff1a;order select union and 最搞的是&#xff0c;空格也有&#xff0c;这个空格后面让我看了好久&#xff0c;该在哪里加括号。 先传入1’ 1试试&#…

iOS 逆向学习 - iOS Architecture Cocoa Touch Layer

iOS 逆向学习 - iOS Architecture Cocoa Touch Layer 一、Cocoa Touch Layer 简介二、Cocoa Touch Layer 的核心功能1. UIKit2. Event Handling&#xff08;事件处理&#xff09;3. Multitasking&#xff08;多任务处理&#xff09;4. Push Notifications&#xff08;推送通知&…

STM32烧写失败之Contents mismatch at: 0800005CH (Flash=FFH Required=29H) !

一&#xff09;问题&#xff1a;用ULINK2给STM32F103C8T6下载程序&#xff0c;下载方式设置如下&#xff1a; 出现下面两个问题&#xff1a; 1&#xff09;下载问题界面如下&#xff1a; 这个错误的信息大概可以理解为&#xff0c;在0x08000063地址上读取到flash存储为FF&am…

使用命令行管理git项目

# 初始化一个新的Git仓库 git init # 添加文件到暂存区 git add <file> # 提交暂存区的更改到仓库 git commit -m "commit message" # 查看当前仓库的状态 git status # 查看提交历史 git log # 查看文件的改动 git diff <file> # 创建一个新…

论文笔记PhotoReg: Photometrically Registering 3D Gaussian Splatting Models

1.abstract 最近推出的3D高斯飞溅(3DGS)&#xff0c;它用多达数百万个原始椭球体来描述场景&#xff0c;可以实时渲染。3DGS迅速声名鹊起。然而&#xff0c;一个关键的悬而未决的问题仍然存在&#xff1a;我们如何将多个3DG融合到一个连贯的模型中&#xff1f;解决这个问题将使…

javaEE-网络原理-1初识

目录 一.网络发展史 1.独立模式 2.网络互联 二.局域网LAN 1.基于网线直连&#xff1a; 2.基于集线器组件&#xff1a; 3.基于交换机组件&#xff1a; 4.基于交换机和路由器组件 ​编辑 三、广域网WAN 四、网络通信基础 1.ip地址 2.端口号&#xff1a; 3.协议 4.五…

电子电气架构 --- 整车整车网络管理浅析

我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 所谓鸡汤,要么蛊惑你认命,要么怂恿你拼命,但都是回避问题的根源,以现象替代逻辑,以情绪代替思考,把消极接受现实的懦弱,伪装成乐观面对不幸的…

xml格式化(3):增加头部声明

前言 这篇文章&#xff0c;是用来增加头部声明。 正文 from lxml import etreedef pretty_print(element, level0, indent" "):result ""# 判断元素是否为注释节点if isinstance(element, etree._Comment):result f"{indent * level}<!--{el…

STM32 高级 物联网通讯之LoRa通讯

目录 LoRa通讯基础知识 常见的3种通讯协议 远距离高速率的传输协议 近距离高速率传输技术 近距离低功耗传输技术 低功耗广域网 采用授权频段技术 非授权频段 LoRa简介 LoRa的特点 远距离 低功耗 安全 标准化 地理定位 移动性 高性能 低成本 LoRa应用 LoRa组…

【FlutterDart】 拖动改变 widget 的窗口尺寸大小GestureDetector~简单实现(10 /100)

上效果 预期的是通过拖动一条边界线改变窗口大小&#xff0c;类似vscode里拖动效果。这个是简单的拖动实现 上代码&#xff1a; import package:flutter/material.dart;class MyDraggableViewDemo extends StatelessWidget {const MyDraggableViewDemo({super.key});override…

Luma AI 简单几步生成视频

简单几步生成视频 登录我们的 AceDataPlatform 网站&#xff0c;按照下图所示即可生成高质量的视频&#xff0c;同时&#xff0c;我们也提供了简单易用的 API 方便集成调用&#xff0c;可以查看 Luma API了解详情 技术介绍 我们使用了 Luma 的技术&#xff0c;实现了上面的图…

如何免费解锁 IPhone 网络

您是否担心 iPhone 上的网络锁定&#xff1f;如果您的 iPhone 被锁定到特定运营商&#xff0c;解锁它可以连接到不同的运营商。好吧&#xff0c;我们为您准备了一份指南。 iPhone运营商免费解锁将是小菜一碟。在我们的解锁运营商 iphone 免费指南中。我们为您提供了一份简介&am…

[读书日志]8051软核处理器设计实战(基于FPGA)第三篇:8051 keil编程配置 C语言开发流程 中断程序实例

第一篇https://blog.csdn.net/m0_74021449/article/details/144796689 第二篇https://blog.csdn.net/m0_74021449/article/details/144813103 3.8051中断与keil开发流程 3.1 keil的下载与概述 关于keil&#xff0c;大家都并不陌生&#xff0c;它是开发51单片机和ARM架构的32…

音视频-----RTSP协议 音视频编解码

流媒体协议详解&#xff1a;RTSP、RTP、RTCP、SIP、SDP、RTMP、WebRTC、WebSocket-CSDN博客 上文讲解比较清楚 多媒体编解码基础知识 一文详解WebRTC、RTSP、RTMP、SRT-腾讯云开发者社区-腾讯云 RTP :(Real-time Transport Protocol)是用于Internet上针对多媒体数据流的一种传…