[Data Buckets] Implement scoped data buckets #3498
Merged
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
What
This PR implements scoped data buckets
This means that for common primitives such as
character
npc
orbot
that use data-buckets that we represent them as their own columns within the data model and have a unique constraints applied against them.For example, Quest API methods that use
mob:SetData(name, value)
will automatically scope thekey
to the entity under the hood without an operator needing to additionally add nested keying.This PR also is pre-cursor to other work, such as distributed data bucket caching and other features.
This PR still needs to be tested in its entirety
Goal(s)
data_buckets
as it relates to a mechanism for storing character progress and flags to copy a character, migrate a character's flags and easily select what flags are unique to a specific playerCurrent
Right now, data-buckets are arbitrary k/v pairs, which should be the case when using a k/v store and this mostly works without issue, you can store things as arbitrary k/v and key however you wish.
Challenge
The part where this breaks down is when you want to easily query what flags or buckets that are tied to a specific entity, unless you have a consistent keying convention that all servers use, it is difficult to understand what is tied to a character.
In the source we prepend identifiers, but unless you are going through the quest abstraction of using
Mob::SetBucket
your values may or may not be tied to that entity. Some servers use their own set of prefixes or sometimes even suffixes to append uniqueness to their keys and does not allow for simplicity of the API.We need a way to scope this, still keep pairs arbitrary but can be specific to at least a character.
Solution: Scoped Columns
We can add columns that scope to the player, but it will need to change how we query the data.
Instead of just having the key be the absolute unique component, it will need to extend to each scoped entity, in this case
character_id
,npc_id
andbot_id
.Schema
If we were to implement the equivalent
character_id
npc_id
bot_id
scoped entries the schema would resemble the followingWe drop the old
key_index
which only enforced uniqueness on thekey
column, we need to extend this uniqueness to other types.Testing Schema
If we were to test this schema it would end up looking something like
We're using
something
as a key and we have a unique entry globallycharacter_id
andnpc_id
are 0 while we have entries that are scoped to a specificcharacter_id
and anpc_id
separately.The moment we try to add a 4th entry that is then the same as a record previously added for the same
npc_id
we get:Similar test applies when we add the
bot_id
field, we can add akey
that is unique to thatbot_id
without issue while existing with the other flags.Migration
We'd need to have a means to migrate from the existing code-level abstraction of how flags are defined per-character or per-npc in this case. We could do so while doing a select using the code format that is listed in the code above. This would result in a one-time migration of flags and while that is done, code changes would also have to be made in the current abstractions to add a scope to what column is being selected and written to during the
Get
andSet
operations of the Quest APIConversion example query
Below we show
character_id
being pulled out of the original format we had in the code.We also pull out
bucket_name
similarly.We want to see the bucket name containing the character prefix and the ID get removed from the bucket name itself and exploded onto the new scoped column
Final Conversion