Skip to content

Commit

Permalink
Merge pull request #57 from nezuo/allow-mutable-updates
Browse files Browse the repository at this point in the history
Add `freezeData` option to allow mutable updates to documents
  • Loading branch information
nezuo authored Jul 2, 2024
2 parents 12ea6af + 27cee16 commit 1a47d2f
Show file tree
Hide file tree
Showing 8 changed files with 187 additions and 66 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,15 @@
* Migrations can now be marked as `backwardsCompatible`. This allows documents to be loaded on servers with an older version as long as they are compatible.
For more information, see the [docs](https://nezuo.github.io/lapis/docs/Migrations#backwards-compatibility). ([#54])
* The `validate` option for collections is now optional. ([#56])
* Add `freezeData` option to collections to allow mutable updates to documents. ([#57])

[#50]: https://github.com/nezuo/lapis/pull/50
[#51]: https://github.com/nezuo/lapis/pull/51
[#52]: https://github.com/nezuo/lapis/pull/52
[#53]: https://github.com/nezuo/lapis/pull/53
[#54]: https://github.com/nezuo/lapis/pull/54
[#56]: https://github.com/nezuo/lapis/pull/56
[#57]: https://github.com/nezuo/lapis/pull/57

### 0.3.0 - April 14, 2024
* **BREAKING CHANGE**: `Collection:load` no longer caches promises. Each call will now return a unique promise and attempt to load the document separately. This is to fix an edge case that can result in data loss. More information can be found in the pull request. ([#48])
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ A Roblox DataStore abstraction that offers:
- **Retries** - Failed DataStore requests will be retried.
- **Throttling** - DataStore requests will never exceed their budget and throw an error.
- **Promise-based API** - Promises are used instead of yielding.
- **Immutability** - Documents must be updated immutably.
- **Immutability** - By default, documents are deep frozen must be updated immutably. This can be disabled.
- **Save Batching** - Pending `Document:save()` and `Document:close()` calls are combined into one DataStore request when possible.
- **Auto Save** - Documents are automatically saved every 5 minutes.
- **BindToClose** - All documents are automatically closed when the game shuts down.
Expand Down
2 changes: 1 addition & 1 deletion docs/intro.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ sidebar_position: 1
- **Retries** - Failed DataStore requests will be retried.
- **Throttling** - DataStore requests will never exceed their budget and throw an error.
- **Promise-based API** - Promises are used instead of yielding.
- **Immutability** - Documents must be updated immutably.
- **Immutability** - By default, documents are deep frozen must be updated immutably. This can be disabled.
- **Save Batching** - Pending `Document:save()` and `Document:close()` calls are combined into one DataStore request when possible.
- **Auto Save** - Documents are automatically saved every 5 minutes.
- **BindToClose** - All documents are automatically closed when the game shuts down.
14 changes: 10 additions & 4 deletions src/Collection.lua
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,6 @@ function Collection.new(name, options, data, autoSave, config)
assert(options.validate(options.defaultData))
end

freezeDeep(options.defaultData)

local migrations = {}
if options.migrations ~= nil then
for _, migration in options.migrations do
Expand All @@ -35,6 +33,10 @@ function Collection.new(name, options, data, autoSave, config)
end
options.migrations = migrations

options.freezeData = if options.freezeData ~= nil then options.freezeData else true

freezeDeep(options)

return setmetatable({
dataStore = config:get("dataStoreService"):GetDataStore(name),
options = options,
Expand Down Expand Up @@ -86,7 +88,9 @@ function Collection:load(key, defaultUserIds)
defaultData = copyDeep(tailoredDefaultData)
else
-- The data was validated when the collection was created.
defaultData = self.options.defaultData
defaultData = if self.options.freezeData
then self.options.defaultData
else copyDeep(self.options.defaultData)
end

local data = {
Expand Down Expand Up @@ -139,7 +143,9 @@ function Collection:load(key, defaultUserIds)

local data = value.data

freezeDeep(data)
if self.options.freezeData then
freezeDeep(data)
end

local document = Document.new(self, key, self.options.validate, lockId, data, keyInfo)

Expand Down
24 changes: 23 additions & 1 deletion src/Document.lua
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ end
--[=[
Writes the document's data.
If [`CollectionOptions.freezeData`](Lapis#CollectionOptions<T>) is `true`, `data` will be deep frozen.
:::warning
Throws an error if the document was closed or if the data is invalid.
:::
Expand All @@ -65,7 +67,9 @@ function Document:write(data)
assert(self.validate(data))
end

freezeDeep(data)
if self.collection.options.freezeData then
freezeDeep(data)
end

self.data = data
end
Expand Down Expand Up @@ -135,6 +139,15 @@ function Document:save()
return "fail", "The session lock was stolen"
end

if not self.collection.options.freezeData and self.validate ~= nil then
local validateOk, valid, message = pcall(self.validate, self.data)
if not validateOk then
return "fail", `'validate' threw an error: {valid}`
elseif not valid then
return "fail", `Invalid data: {message}`
end
end

value.data = self.data

return "succeed", value, self.userIds
Expand Down Expand Up @@ -174,6 +187,15 @@ function Document:close()
return "fail", "The session lock was stolen"
end

if not self.collection.options.freezeData and self.validate ~= nil then
local validateOk, valid, message = pcall(self.validate, self.data)
if not validateOk then
return "fail", `'validate' threw an error: {valid}`
elseif not valid then
return "fail", `Invalid data: {message}`
end
end

value.data = self.data
value.lockId = nil

Expand Down
Loading

0 comments on commit 1a47d2f

Please sign in to comment.