With the help of @ptpaterson I was able to get my upsert & delete queries to work.
The next part of my journey is:
- Read the data, during a redirect
- Select the key with the least amount of hits
- Update the hits for that key
- Redirect user
The high-level goal is: Evenly redirect users for A/B testing purposes. And eventual consistency is not enough, it has to be as even as possible, also at low volumes.
Now, @ptpaterson already let me know that this pattern will lead to contention problems, at relatively low loads even…
I would love some help on how I can make this work, without having to worry about failing redirects (The users we redirect, are from paid ad campaigns. So it would be pretty bad for me and my job, if at some point redirects start failing because of contention haha)
My schema currently looks like this:
.query(
CreateCollection({
name: "landing_page_redirects",
history_days: 0,
ttl_days: null,
})
)
.then(() => {
client.query(
CreateCollection({
name: "offer_redirects",
history_days: 0,
ttl_days: null,
})
);
})
.then(() => {
return client.query(
CreateIndex({
name: "landing_page_redirects_search_by_uuid",
source: Collection("landing_page_redirects"),
terms: [{ field: ["data", "key"] }],
unique: true,
})
);
})
.then(() => {
return client.query(
CreateIndex({
name: "offer_redirects_search_by_uuid",
source: Collection("offer_redirects"),
terms: [{ field: ["data", "key"] }],
unique: true,
})
);
})
The data for lander_redirects
looks like this:
{
"ref": Ref(Collection("landing_page_redirects"), "325031451757118028"),
"ts": 1646233296003000,
"data": {
"key": "f90b38d9-77d7-47f1-920c-79b2b4bb2c8d",
"value": {
"542e2364-5911-4b7e-b5f8-e29a5461cca0": 0
}
}
}
For offer_redirects
it looks like this:
{
"ref": Ref(Collection("offer_redirects"), "325031764682605131"),
"ts": 1646233296000000,
"data": {
"key": "542e2364-5911-4b7e-b5f8-e29a5461cca0",
"value": [
{
"key": "542e2364-5911-4b7e-b5f8-e29a5461cca1",
"value": {
"95c2cca9-b086-4e36-bda3-50096fb95711": 0
}
},
{
"key": "542e2364-5911-4b7e-b5f8-e29a5461cca2",
"value": {
"95c2cca9-b086-4e36-bda3-50096fb95711": 0
}
},
{
"key": "542e2364-5911-4b7e-b5f8-e29a5461cca3",
"value": {
"95c2cca9-b086-4e36-bda3-50096fb95711": 0
}
},
{
"key": "542e2364-5911-4b7e-b5f8-e29a5461cca4",
"value": {
"95c2cca9-b086-4e36-bda3-50096fb95711": 0
}
},
{
"key": "542e2364-5911-4b7e-b5f8-e29a5461cca5",
"value": {
"95c2cca9-b086-4e36-bda3-50096fb95711": 0
}
},
{
"key": "542e2364-5911-4b7e-b5f8-e29a5461cca6",
"value": {
"95c2cca9-b086-4e36-bda3-50096fb95711": 0
}
},
{
"key": "542e2364-5911-4b7e-b5f8-e29a5461cca7",
"value": {
"95c2cca9-b086-4e36-bda3-50096fb95711": 0
}
}
]
}
}
The int
values in my value
properties, were supposed to hold the amount of hits.
That was, until @ptpaterson explained what will happen if I do this.
Question is now, how can I achieve the goal mentioned in the beginning of this post, without running into contention issues & broken redirects.
Thank You!
PS: I’ve read the best practices, as well as the post on scaling queries. I must confess, I’m not a DB guy and mostly understood, well, nothing really. Haha.
A hands-on example would be highly appreciated.