#identifier #distributed-systems #type-id #uuid

mti

一个实现了基于TypeID规范的类型安全、前缀增强标识符的Rust库

8个版本

1.0.7-beta.12024年7月15日
1.0.6-beta.12024年7月14日
1.0.5-beta.12024年7月13日
1.0.2-beta.12024年7月12日

#381解析器实现

Download history 389/week @ 2024-07-09 62/week @ 2024-07-16 1/week @ 2024-07-23 5/week @ 2024-07-30

136 每月下载量

MIT/Apache

56KB
400

魔法类型ID (MTI):用智能标识符赋予分布式系统力量

Crates.io Documentation License: MIT OR Apache-2.0

欢迎来到 mti,这是一个将类型安全、前缀增强标识符的强大功能带入您分布式系统的Rust包。它基于 TypeID规范 构建,将UUID的唯一性、前缀标识符的可读性和类型安全结合起来,为跨应用程序的标识符管理提供了一种强大的解决方案。

致谢

此包实现了由 Jetify 创建和维护的 TypeID规范 版本0.3.0。我为他们在开发和维护此规范方面所做的工作表示感激。

功能

  • 类型安全:直接在标识符中嵌入类型信息。
  • 可读性:人类可读的前缀使标识符具有自描述性。
  • 唯一性:使用UUID(包括UUIDv7)保证全局唯一性。
  • 排序性:当使用UUIDv7时,标识符具有固有的时间排序性。
  • 灵活性:支持各种UUID版本和自定义前缀。
  • 易用性:直观的API,带有扩展方法,可轻松创建和操作。
  • 性能:字符串操作的零成本抽象。
  • 可靠性:基于经过彻底测试和验证的 TypeIdPrefixTypeIdSuffix 包。

快速入门

mti 添加到您的 Cargo.toml

[dependencies]
mti = "1.0.5-beta.1"

然后,在您的Rust代码中

use mti::prelude::*;

// Create a MagicTypeId for a user
let user_id = "user".create_type_id::<V7>();
println!("New User ID: {}", user_id); // e.g., "user_01h455vb4pex5vsknk084sn02q"

// Parse an existing MagicTypeId
let order_id = MagicTypeId::from_str("order_01h455vb4pex5vsknk084sn02q").unwrap();
assert_eq!(order_id.prefix().as_str(), "order");

使用示例

创建MagicTypeIds

use mti::prelude::*;

// Create with UUIDv7 (sortable, recommended)
let product_id = "product".create_type_id::<V7>();

// Create with UUIDv4 (random)
let user_id = "user".create_type_id::<V4>();

// Create with custom suffix
let custom_suffix = TypeIdSuffix::new::<V7>();
let order_id = "order".create_type_id_with_suffix(custom_suffix);

灵活的前缀处理

use mti::prelude::*;

// Sanitized creation (always produces a valid prefix)
let sanitized_id = "Invalid Prefix!".create_type_id::<V7>();
assert!(sanitized_id.to_string().starts_with("invalidprefix_"));

// Strict creation (returns an error for invalid prefixes)
let result = "Invalid Prefix!".try_create_type_id::<V7>();
assert!(result.is_err());

字符串-like行为

use mti::prelude::*;

let id = "user".create_type_id::<V7>();
assert!(id.starts_with("user_"));
assert_eq!(id.len(), 31);

// Use in string comparisons
assert_eq!(id.as_str(), id.to_string());

解析和组件提取

use mti::prelude::*;

let id_str = "product_01h455vb4pex5vsknk084sn02q";
let magic_id = MagicTypeId::from_str(id_str).unwrap();

assert_eq!(magic_id.prefix().as_str(), "product");
assert_eq!(magic_id.suffix().to_string(), "01h455vb4pex5vsknk084sn02q");

// Extract UUID
let uuid = magic_id.suffix().to_uuid();
println!("Extracted UUID: {}", uuid);

排序

当使用MagicTypeIdV7 UUID创建时,它提供了一种自然的排序顺序

  1. 主要排序:由UUIDv7后缀中的时间戳决定。这意味着生成的较晚的标识符将出现在较早生成的标识符之后。
  2. 次要排序:如果时间戳相等,则基于前缀的字典序进行排序。这确保了即使在标识符同时创建的情况下,也能保持一致的排序顺序。
use std::str::FromStr;
use std::thread::sleep;
use std::time::Duration;

use mti::prelude::*;
use typeid_prefix::prelude::*;
use typeid_suffix::prelude::*;

let prefix1 = TypeIdPrefix::from_str("user").unwrap();
let prefix2 = TypeIdPrefix::from_str("admin").unwrap();
let id1 = MagicTypeId::new(prefix1.clone(), TypeIdSuffix::new::<V7>());

sleep(Duration::from_millis(10));  // Ensure different timestamps

let id2 = MagicTypeId::new(prefix1.clone(), TypeIdSuffix::new::<V7>());
let id3 = MagicTypeId::new(prefix2.clone(), TypeIdSuffix::from_str(&id2.suffix().to_string()).unwrap());

assert!(id1 < id2, "Expected id1 to be less than id2 due to earlier timestamp");
assert_eq!(id2.suffix(), id3.suffix(), "Suffixes for id2 and id3 should be the same");
assert!(id3 < id2, "Expected id3 to be less than id2 due to lexicographically smaller prefix when timestamps are equal");

使用案例

MagicTypeId非常灵活,可应用于各种场景。

  1. 分布式系统:在微服务之间生成全局唯一、类型安全的标识符。
    let order_id = "order".create_type_id::<V7>();
    // Send to another service: "order_01h455vb4pex5vsknk084sn02q"
    
  2. 数据库记录:创建可读、可排序的主键。
let user_id = "user".create_type_id::<V7>();
// MagicTypeIds behave like strings
db.insert_user(user_id, user_data);
  1. API 开发:在 REST 或 GraphQL API 中用作资源标识符。
#[get("/users/{id}")]
async fn get_user(id: Path<MagicTypeId>) -> impl Responder {
    // Retrieve user with id
}
  1. 非唯一、可重复的 ID:使用 UUIDv5 根据输入生成一致的 ID。
let namespace = Uuid::parse_str("6ba7b810-9dad-11d1-80b4-00c04fd430c8").unwrap();
let name = "example.com";
let v5_uuid = Uuid::new_v5( & namespace, name.as_bytes());
let domain_id = MagicTypeId::new(
TypeIdPrefix::from_str("domain").unwrap(),
TypeIdSuffix::from(v5_uuid)
);
// Always produces the same ID for "example.com"
assert_eq!(domain_id.uuid_str().unwrap(), "cfbff0d1-9375-5685-968c-48ce8b15ae17");
  1. 日志和跟踪:在日志条目中嵌入类型信息,以便于调试。
log::info!("Processing order {}", "order".create_type_id::<V7>());

高级用法

自定义类型安全的 ID 类型

use mti::prelude::*;

struct UserId(MagicTypeId);

struct OrderId(MagicTypeId);

impl UserId {
    fn new() -> Self {
        Self("user".create_type_id::<V7>())
    }
}

impl OrderId {
    fn new() -> Self {
        Self("order".create_type_id::<V7>())
    }
}

// Compile-time type safety
fn process_user(id: UserId) { /* ... */ }

fn process_order(id: OrderId) { /* ... */ }

let user_id = UserId::new();
let order_id = OrderId::new();

process_user(user_id);
process_order(order_id);
// process_user(order_id); // This would cause a compile-time error!

数据库集成

use mti::prelude::*;

#[derive(Debug)]
struct User {
    id: MagicTypeId,
    name: String,
}

fn create_user(name: &str) -> User {
    User {
        id: "user".create_type_id::<V7>(),
        name: name.to_string(),
    }
}

// In your database operations
let user = create_user("Alice");
// MagicTypeId behaves like a string
db.insert(user.id, & user);

// Retrieving
let retrieved_id = MagicTypeId::from_str("user_01h455vb4pex5vsknk084sn02q").unwrap();
let retrieved_user = db.get::<User>(retrieved_id.to_string());

性能和安全

mti 的设计考虑了性能和安全

  • 字符串操作的无成本抽象。
  • 建立在经过充分测试和验证的 TypeIdPrefixTypeIdSuffix 包的基础上。
  • 广泛使用 Rust 的类型系统来防止编译时错误。
  • 全面的测试套件确保可靠性和正确性。

测试版状态

虽然这个包功能完善且经过充分测试,但它目前处于测试版,以收集更广泛的社区反馈。我鼓励您将其用于您的项目并提供反馈。如果您遇到任何问题或有一些建议,请在我的 GitHub 仓库 上提交。

贡献

我欢迎贡献!请查看我的 GitHub 仓库,以获取问题、功能请求和拉取请求。

许可

此项目受以下任一许可证的许可:

任选其一。


关于作者

我是 @rrrodzilla,一名拥有 30 年行业经验的技术人员。我曾是一名 SOA 和云架构师,也是 AWS Rust 编程语言的资深技术产品经理。目前,我是 Govcraft 的所有者和运营者,致力于构建和咨询 Rust 和 AI 解决方案。

更多信息,请访问 https://www.govcraft.ai

依赖项

~535KB