Skip to content

Commit 889275c

Browse files
authored
Merge branch 'playfulprogramming:main' into main
2 parents c8450a1 + e3674b7 commit 889275c

File tree

18 files changed

+629
-35
lines changed

18 files changed

+629
-35
lines changed

content/crutchcorn/posts/uuid-v6-8/UUIDv6.svg

Lines changed: 150 additions & 0 deletions
Loading

content/crutchcorn/posts/uuid-v6-8/UUIDv7.svg

Lines changed: 151 additions & 0 deletions
Loading

content/crutchcorn/posts/uuid-v6-8/UUIDv8.svg

Lines changed: 148 additions & 0 deletions
Loading
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
---
2+
{
3+
title: "UUIDv6, UUIDv7, and UUIDv8; what are they?",
4+
description: "There's new UUIDs on the block! Let's explore what's new with UUIDv6, v7, and v8.",
5+
published: '2024-11-20T21:52:59.284Z',
6+
tags: ['computer science'],
7+
license: 'cc-by-4',
8+
collection: "Explaining UUIDs",
9+
order: 3
10+
}
11+
---
12+
13+
[In our first article explaining what UUIDs are](/posts/what-are-uuids), we explored a few different variants of UUID:
14+
15+
- [UUIDv1](/posts/what-are-uuids#UUIDv1)
16+
- A machine's network card information + a timestamp
17+
- [UUIDv2](/posts/what-are-uuids#UUIDv2)
18+
- [It's a long story.](/posts/what-happened-to-uuid-v2)
19+
- [UUIDv3](/posts/what-are-uuids#UUIDv3and5)
20+
- Encode a string using MD5
21+
- [UUIDv4](/posts/what-are-uuids#UUIDv4)
22+
- Random UUID with effectively zero chance of producing the same number twice
23+
- [UUIDv5](/posts/what-are-uuids#UUIDv3and5)
24+
- UUIDv3 but more secure (uses SHA-1)
25+
26+
Since that time, however, there [was an RFC that was accepted](https://www.ietf.org/archive/id/draft-peabody-dispatch-new-uuid-format-04.html) which added 3 new standard UUID types:
27+
28+
- [UUIDv6](#UUIDv6)
29+
- UUIDv1 but better for database indexes
30+
- [UUIDv7](#UUIDv7)
31+
- UUIDv1 without network card information and with a more standard timestamp
32+
- [UUIDv8](#UUIDv8)
33+
- An intentionally broad UUID spec for all non-standard UUIDs - make up your own UUIDs
34+
35+
Let's explore each of these UUID systems individually to understand them better.
36+
37+
38+
39+
# Create a Database Index with UUIDv6 {#UUIDv6}
40+
41+
If you've worked much with UUIDv1 UUIDs, you'll see a pattern in the new UUIDv6 mechanism. If we look at the UUIDv1 example:
42+
43+
![A UUID broken down into "Low Time", a dash, "Mid Time", a dash, "Version", "High Time", a dash, "Variant", "Clock", a dash, and finally a "MAC Address". An example UUIDv1 might be "4e2b4d4c-92e8-11ed-86a8-3fdb0085247e"](../what-are-uuids/UUIDv1.svg)
44+
45+
And compare it to the UUIDv6 example:
46+
47+
![A UUID broken down into "Time High", a dash, "Time Mid", a dash, "Version", "Time Low", a dash, "Variant", "Clock", a dash, and finally a "MAC Address". An example UUIDv6 might be "1ed92e84-e2b4-6d4c-86a8-3fdb0085247e"](./UUIDv6.svg)
48+
49+
We can see how the order of the UUIDv6 is "just" a rearrangement of the bytes presented in a UUIDv1.
50+
51+
Why is this?
52+
53+
Well, this reorder allows multiple UUIDs to be sorted without having to parse them more in-depth. This helps makes databases of UUIDv6s easier to index as opposed to UUIDv1s while retaining the same base information.
54+
55+
> [Read more about the specifics of UUIDv6's sorting improvements in their draft RFC.](https://ietf-wg-uuidrev.github.io/rfc4122bis/draft-00/draft-ietf-uuidrev-rfc4122bis.html#section-6.10)
56+
57+
**Why UUIDv6?**
58+
59+
This is useful if your projects are already using UUIDv1 and you need a drop-in replacement with better database indexing.
60+
61+
**Why not UUIDv6?**
62+
63+
[According to the RFC that introduces v6, v7, and v8](https://ietf-wg-uuidrev.github.io/rfc4122bis/draft-00/draft-ietf-uuidrev-rfc4122bis.html#name-uuid-version-6):
64+
65+
> Systems that do not involve legacy UUIDv1 SHOULD consider using UUIDv7 instead.
66+
67+
Let's explore why that is by taking a look at UUIDv7 next.
68+
69+
# More Standard Timestamps with UUIDv7 {#UUIDv7}
70+
71+
If we look at the byte order of UUIDv7 without any additional context, it might start to look familiar to UUIDv1 and v6:
72+
73+
![A UUID broken down into "Time High", a dash, "Time Mid", a dash, "Version", "Random", a dash, "Variant", "Random", a dash, and finally "Random". An example UUIDv7 might be "0185aa25-112e-7cc3-98c4-dc0c0c07398f"](./UUIDv7.svg)
74+
75+
However, if we note the `input data` section of this graph, the distinction becomes clear.
76+
77+
While UUIDv1, v6, and v7 all track time; v1 and v6 use "a count of 100- nanosecond intervals since 00:00:00.00, 15 October 1582" as their time-keeping mechanism.
78+
79+
Compare and contrast that to UUIDv7 utilizing the far more standard ["Epoch time", or, "Unix time"](https://en.wikipedia.org/wiki/Unix_time).
80+
81+
See, Epoch time is broadly used in nearly every computer system that needs to keep track of time. This makes v7 the superior choice over v6 and v1 for most usages, since encoding and decoding date logic becomes far more standardized.
82+
83+
# Make your own UUID rules with UUIDv8 {#UUIDv8}
84+
85+
Now comes the fun one of the bunch of new UUID formats: UUIDv8.
86+
87+
![A UUID broken down into "Custom", a dash, "Custom", a dash, "Version", "Custom, a dash, "Variant", "Custom", a dash, and finally "Custom". An example UUIDv8 might be "01234567-89ab-8cde-8f01-23456789abcd"](./UUIDv8.svg)
88+
89+
You'll notice that outside of the encoded variant and version that UUIDv8 allows you to encode any data you'd like.
90+
91+
This is mostly useful for future-proofing UUIDs for the foreseeable future. By allowing whatever format you want as a formalized UUID standard,
92+
vendors (like APIs, databases, and more) can make their own flavors of UUIDs that extend the v8 format for their own needs.

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@
6363
"@types/hast": "^3.0.4",
6464
"@types/html-escaper": "^3.0.0",
6565
"@types/json5": "^2.2.0",
66+
"@types/lru-cache": "^7.10.10",
6667
"@types/mdast": "^4.0.3",
6768
"@types/node": "^20.5.0",
6869
"@types/uuid": "^10.0.0",
@@ -96,6 +97,7 @@
9697
"junk": "^4.0.1",
9798
"lint-staged": "^15.2.7",
9899
"live-server": "^1.2.2",
100+
"lru-cache": "^11.0.2",
99101
"msw": "^2.3.5",
100102
"npm-run-all": "^4.1.5",
101103
"octokit": "^4.0.2",

pnpm-lock.yaml

Lines changed: 20 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

public/icons/website.svg

Lines changed: 3 additions & 0 deletions
Loading

public/link.png

-1.91 KB
Binary file not shown.

src/utils/fetch-page-html.ts

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,34 @@
11
import { Element, Root } from "hast";
22
import { fromHtml } from "hast-util-from-html";
33
import { find } from "unist-util-find";
4+
import { LRUCache } from "lru-cache";
5+
6+
export async function fetchAsBrowser(input: string | URL, init?: RequestInit) {
7+
const response = await fetch(input, {
8+
...init,
9+
headers: {
10+
"User-Agent":
11+
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36",
12+
"Accept-Language": "en",
13+
...init?.headers,
14+
},
15+
});
16+
const isSuccess = `${response.status}`.startsWith("2");
17+
if (!isSuccess)
18+
throw new Error(`Request ${input} returned an error: ${response.status}`);
19+
return response;
20+
}
421

5-
const pageHtmlMap = new Map<string, Promise<Root | null>>();
22+
const pageHtmlCache = new LRUCache<string, Promise<Root | null>>({
23+
max: 50,
24+
});
625

726
export function fetchPageHtml(src: string): Promise<Root | null> {
8-
if (pageHtmlMap.has(src)) return pageHtmlMap.get(src)!;
27+
if (pageHtmlCache.has(src)) return pageHtmlCache.get(src)!;
928

1029
const promise = (async () => {
11-
const srcHTML = await fetch(src, {
12-
headers: {
13-
"User-Agent":
14-
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36",
15-
"Accept-Language": "en",
16-
},
17-
})
18-
.then((r) => (r.status === 200 ? r.text() : undefined))
30+
const srcHTML = await fetchAsBrowser(src)
31+
.then(async (r) => await r.text())
1932
.catch(() => null);
2033

2134
// if fetch fails...
@@ -26,7 +39,7 @@ export function fetchPageHtml(src: string): Promise<Root | null> {
2639
return srcHast;
2740
})();
2841

29-
pageHtmlMap.set(src, promise);
42+
pageHtmlCache.set(src, promise);
3043
return promise;
3144
}
3245

src/utils/markdown/astro-integration-copy-generated.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import * as path from "node:path";
44
import { fileURLToPath } from "node:url";
55

66
const copyFiles = async (srcDir: string, destDir: string) => {
7+
await fs.promises.mkdir(destDir, { recursive: true });
78
const readDir = await fs.promises.readdir(srcDir);
89

910
await Promise.all(

0 commit comments

Comments
 (0)