-
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathatomic.ts
137 lines (120 loc) · 3.31 KB
/
atomic.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
import { deleteAllRecords, showAllRecords } from "./util.ts";
/**
* The `atomic` method is transactional, assuring the synchronization between multiple
* related KV indexes.
*/
const kv = await Deno.openKv();
interface BaseUser {
id: string;
name: string;
email: string;
}
interface User extends BaseUser {
age: number;
address?: Address;
phones?: Phone;
}
type Address = {
userId?: string;
streetNumber: string;
street: string;
city: string;
state: string;
zipCode?: string;
};
type Phone = {
cell?: string;
home?: string;
work?: string;
};
const KeyRoot = {
users: "users",
userEmail: "userEmail",
UserAddresses: "userAddress",
phones: "phones",
};
const createUserWithAddressAndPhone = async (
user: User,
address: Address,
phone: Phone,
): Promise<Deno.KvCommitResult | Deno.KvCommitError> => {
const userId = crypto.randomUUID();
user.id = userId;
// get data for atomic check
const guser = await kv.get([KeyRoot.users, userId]);
const userEmail = await kv.get([KeyRoot.userEmail, user.email]);
const userAddress = await kv.get([KeyRoot.UserAddresses, userId]);
const userPhone = await kv.get([KeyRoot.phones, userId]);
const result = await kv.atomic()
.check(guser)
.check(userEmail)
.check(userAddress)
.check(userPhone)
.set([KeyRoot.users, userId], user)
.set([KeyRoot.userEmail, user.email], user)
.set([KeyRoot.UserAddresses, userId], address)
.set([KeyRoot.phones, userId], phone)
.commit();
return result;
};
const findUserByEmail = async (email: string): Promise<BaseUser> => {
const key = [KeyRoot.userEmail, email];
const user = await kv.get(key);
const userVal = user.value as BaseUser;
return userVal;
};
const findUserWithAddressAndPhone = async (userId: string): Promise<User> => {
const userKv = await kv.get([KeyRoot.users, userId]);
kv.atomic()
.check(userKv);
const user = userKv.value as User;
const addressKv = await kv.get([KeyRoot.UserAddresses, userId]);
const address = addressKv.value as Address;
user.address = address;
const phoneKv = await kv.get([KeyRoot.phones, userId]);
user.phones = phoneKv.value as Phone;
return user;
};
// Add some data
const user1: User = {
id: "",
name: "John Doe",
age: 32,
email: "jdoe@foo.com",
};
const addr1: Address = {
streetNumber: "100",
street: "Main Street",
city: "Bethel",
state: "ME",
zipCode: "04260",
};
const phone1: Phone = { cell: "2071231234" };
const createResult = await createUserWithAddressAndPhone(user1, addr1, phone1);
// make sure commit() succeeds
if (!createResult.ok) {
console.error(
"There was a problem! User, address & phone persistence did not work.",
);
}
// const user2: User = {
// id: "",
// name: "Bill Smith",
// age: 34,
// email: "bsmith@foo.com",
// };
// const addr2: Address = {
// streetNumber: "1001",
// street: "Mass Avenue",
// city: "Boston",
// state: "MA",
// zipCode: "02108",
// };
// const phone2: Phone = { cell: "5180987654", home: "2123456789" };
// await createUserWithAddressAndPhone(user2, addr2, phone2);
// const user = await findUserByEmail("bsmith@foo.com");
// const userAddress = await findUserWithAddressAndPhone(user.id);
// console.log(`USER FOUND: ${JSON.stringify(userAddress)}`);
console.log("Records inserted");
await showAllRecords();
await deleteAllRecords();