@quenty/userserviceutils 3.7.0 → 3.8.0-canary.398.cbf5f4f.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,17 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
5
|
|
|
6
|
+
# [3.8.0-canary.398.cbf5f4f.0](https://github.com/Quenty/NevermoreEngine/compare/@quenty/userserviceutils@3.7.0...@quenty/userserviceutils@3.8.0-canary.398.cbf5f4f.0) (2023-07-25)
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
### Features
|
|
10
|
+
|
|
11
|
+
* Add UserInfoService to aggregate user info in a de-duplicated request format ([deb1a79](https://github.com/Quenty/NevermoreEngine/commit/deb1a7914f753f8835ce407a2f94b3f8eac7d812))
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
|
|
6
17
|
# [3.7.0](https://github.com/Quenty/NevermoreEngine/compare/@quenty/userserviceutils@3.6.0...@quenty/userserviceutils@3.7.0) (2023-06-17)
|
|
7
18
|
|
|
8
19
|
**Note:** Version bump only for package @quenty/userserviceutils
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@quenty/userserviceutils",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.8.0-canary.398.cbf5f4f.0",
|
|
4
4
|
"description": "Utilities involving UserService in Roblox",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"Roblox",
|
|
@@ -25,12 +25,15 @@
|
|
|
25
25
|
"Quenty"
|
|
26
26
|
],
|
|
27
27
|
"dependencies": {
|
|
28
|
-
"@quenty/
|
|
29
|
-
"@quenty/
|
|
30
|
-
"@quenty/
|
|
28
|
+
"@quenty/baseobject": "6.2.1",
|
|
29
|
+
"@quenty/loader": "6.2.1",
|
|
30
|
+
"@quenty/maid": "2.5.0",
|
|
31
|
+
"@quenty/math": "2.4.0",
|
|
32
|
+
"@quenty/promise": "6.6.0",
|
|
33
|
+
"@quenty/servicebag": "6.8.0"
|
|
31
34
|
},
|
|
32
35
|
"publishConfig": {
|
|
33
36
|
"access": "public"
|
|
34
37
|
},
|
|
35
|
-
"gitHead": "
|
|
38
|
+
"gitHead": "cbf5f4f4211156144e150dd960d9e2225cf9c5f5"
|
|
36
39
|
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
--[=[
|
|
2
|
+
Centralized provider for user info so we can coordinate web requests.
|
|
3
|
+
|
|
4
|
+
@class UserInfoServiceClient
|
|
5
|
+
]=]
|
|
6
|
+
|
|
7
|
+
local require = require(script.Parent.loader).load(script)
|
|
8
|
+
|
|
9
|
+
local UserInfoAggregator = require("UserInfoAggregator")
|
|
10
|
+
local Maid = require("Maid")
|
|
11
|
+
|
|
12
|
+
local UserInfoServiceClient = {}
|
|
13
|
+
UserInfoServiceClient.ServiceName = "UserInfoServiceClient"
|
|
14
|
+
|
|
15
|
+
function UserInfoServiceClient:Init(serviceBag)
|
|
16
|
+
assert(not self._serviceBag, "Already initialized")
|
|
17
|
+
self._serviceBag = assert(serviceBag, "No serviceBag")
|
|
18
|
+
self._maid = Maid.new()
|
|
19
|
+
|
|
20
|
+
self._aggregator = UserInfoAggregator.new()
|
|
21
|
+
self._maid:GiveTask(self._aggregator)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
--[=[
|
|
25
|
+
Promises the user info for the given user, aggregating all requests to reduce
|
|
26
|
+
calls into Roblox.
|
|
27
|
+
|
|
28
|
+
@param userId number
|
|
29
|
+
@return Promise<UserInfo>
|
|
30
|
+
]=]
|
|
31
|
+
function UserInfoServiceClient:PromiseUserInfo(userId)
|
|
32
|
+
assert(type(userId) == "number", "Bad userId")
|
|
33
|
+
|
|
34
|
+
return self._aggregator:PromiseUserInfo(userId)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
--[=[
|
|
38
|
+
Promises the user display name for the userId
|
|
39
|
+
|
|
40
|
+
@param userId number
|
|
41
|
+
@return Promise<string>
|
|
42
|
+
]=]
|
|
43
|
+
function UserInfoServiceClient:PromiseDisplayName(userId)
|
|
44
|
+
assert(type(userId) == "number", "Bad userId")
|
|
45
|
+
|
|
46
|
+
return self._aggregator:PromiseDisplayName(userId)
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
function UserInfoServiceClient:Destroy()
|
|
50
|
+
self._maid:DoCleaning()
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
return UserInfoServiceClient
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
--[=[
|
|
2
|
+
Centralized provider for user info so we can coordinate web requests.
|
|
3
|
+
|
|
4
|
+
@class UserInfoService
|
|
5
|
+
]=]
|
|
6
|
+
|
|
7
|
+
local require = require(script.Parent.loader).load(script)
|
|
8
|
+
|
|
9
|
+
local UserInfoAggregator = require("UserInfoAggregator")
|
|
10
|
+
local Maid = require("Maid")
|
|
11
|
+
|
|
12
|
+
local UserInfoService = {}
|
|
13
|
+
UserInfoService.ServiceName = "UserInfoService"
|
|
14
|
+
|
|
15
|
+
function UserInfoService:Init(serviceBag)
|
|
16
|
+
assert(not self._serviceBag, "Already initialized")
|
|
17
|
+
self._serviceBag = assert(serviceBag, "No serviceBag")
|
|
18
|
+
self._maid = Maid.new()
|
|
19
|
+
|
|
20
|
+
self._aggregator = UserInfoAggregator.new()
|
|
21
|
+
self._maid:GiveTask(self._aggregator)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
--[=[
|
|
25
|
+
Promises the user info for the given user, aggregating all requests to reduce
|
|
26
|
+
calls into Roblox.
|
|
27
|
+
|
|
28
|
+
@param userId number
|
|
29
|
+
@return Promise<UserInfo>
|
|
30
|
+
]=]
|
|
31
|
+
function UserInfoService:PromiseUserInfo(userId)
|
|
32
|
+
assert(type(userId) == "number", "Bad userId")
|
|
33
|
+
|
|
34
|
+
return self._aggregator:PromiseUserInfo(userId)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
--[=[
|
|
38
|
+
Promises the user display name for the userId
|
|
39
|
+
|
|
40
|
+
@param userId number
|
|
41
|
+
@return Promise<string>
|
|
42
|
+
]=]
|
|
43
|
+
function UserInfoService:PromiseDisplayName(userId)
|
|
44
|
+
assert(type(userId) == "number", "Bad userId")
|
|
45
|
+
|
|
46
|
+
return self._aggregator:PromiseDisplayName(userId)
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
function UserInfoService:Destroy()
|
|
50
|
+
self._maid:DoCleaning()
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
return UserInfoService
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
--[=[
|
|
2
|
+
Aggregates all requests into one big send request
|
|
3
|
+
|
|
4
|
+
@class UserInfoAggregator
|
|
5
|
+
]=]
|
|
6
|
+
|
|
7
|
+
local require = require(script.Parent.loader).load(script)
|
|
8
|
+
|
|
9
|
+
local BaseObject = require("BaseObject")
|
|
10
|
+
local Promise = require("Promise")
|
|
11
|
+
local UserServiceUtils = require("UserServiceUtils")
|
|
12
|
+
|
|
13
|
+
local UserInfoAggregator = setmetatable({}, BaseObject)
|
|
14
|
+
UserInfoAggregator.ClassName = "UserInfoAggregator"
|
|
15
|
+
UserInfoAggregator.__index = UserInfoAggregator
|
|
16
|
+
|
|
17
|
+
function UserInfoAggregator.new()
|
|
18
|
+
local self = setmetatable(BaseObject.new(), UserInfoAggregator)
|
|
19
|
+
|
|
20
|
+
-- TODO: LRU cache this? Limit to 1k or something?
|
|
21
|
+
self._promises = {}
|
|
22
|
+
self._unsentPromises = {}
|
|
23
|
+
|
|
24
|
+
return self
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
--[=[
|
|
28
|
+
Promises the user info for the given user, aggregating all requests to reduce
|
|
29
|
+
calls into Roblox.
|
|
30
|
+
|
|
31
|
+
@param userId number
|
|
32
|
+
@return Promise<UserInfo>
|
|
33
|
+
]=]
|
|
34
|
+
function UserInfoAggregator:PromiseUserInfo(userId)
|
|
35
|
+
assert(type(userId) == "number", "Bad userId")
|
|
36
|
+
|
|
37
|
+
if self._promises[userId] then
|
|
38
|
+
return self._promises[userId]
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
local promise = Promise.new()
|
|
42
|
+
|
|
43
|
+
self._unsentPromises[userId] = promise
|
|
44
|
+
self._promises[userId] = promise
|
|
45
|
+
|
|
46
|
+
self:_queueAggregatedPromises()
|
|
47
|
+
|
|
48
|
+
return promise
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
--[=[
|
|
52
|
+
Promises the user display name for the userId
|
|
53
|
+
|
|
54
|
+
@param userId number
|
|
55
|
+
@return Promise<string>
|
|
56
|
+
]=]
|
|
57
|
+
function UserInfoAggregator:PromiseDisplayName(userId)
|
|
58
|
+
assert(type(userId) == "number", "Bad userId")
|
|
59
|
+
|
|
60
|
+
return self:PromiseUserInfo(userId)
|
|
61
|
+
:Then(function(userInfo)
|
|
62
|
+
return userInfo.DisplayName
|
|
63
|
+
end)
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
function UserInfoAggregator:_sendAggregatedPromises()
|
|
67
|
+
local promiseMap = self._unsentPromises
|
|
68
|
+
self._unsentPromises = {}
|
|
69
|
+
|
|
70
|
+
local userIds = {}
|
|
71
|
+
local unresolvedMap = {}
|
|
72
|
+
for userId, promise in pairs(promiseMap) do
|
|
73
|
+
table.insert(userIds, userId)
|
|
74
|
+
unresolvedMap[userId] = promise
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
if #userIds == 0 then
|
|
78
|
+
return
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
self._maid:GivePromise(UserServiceUtils.promiseUserInfosByUserIds(userIds))
|
|
82
|
+
:Then(function(result)
|
|
83
|
+
assert(type(result) == "table", "Bad result")
|
|
84
|
+
|
|
85
|
+
for _, data in pairs(result) do
|
|
86
|
+
assert(type(data.Id) == "number", "Bad result[?].Id")
|
|
87
|
+
|
|
88
|
+
if unresolvedMap[data.Id] then
|
|
89
|
+
unresolvedMap[data.Id]:Resolve(data)
|
|
90
|
+
unresolvedMap[data.Id] = nil
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
-- Reject other ones
|
|
95
|
+
for userId, promise in pairs(unresolvedMap) do
|
|
96
|
+
promise:Reject(string.format("Failed to get result for userId %d", userId))
|
|
97
|
+
end
|
|
98
|
+
end, function(...)
|
|
99
|
+
for _, item in pairs(promiseMap) do
|
|
100
|
+
item:Reject(...)
|
|
101
|
+
end
|
|
102
|
+
end)
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
function UserInfoAggregator:_queueAggregatedPromises()
|
|
106
|
+
if self._queued then
|
|
107
|
+
return
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
self._queued = true
|
|
111
|
+
self._maid._queue = task.delay(0.05, function()
|
|
112
|
+
self._queued = false
|
|
113
|
+
self:_sendAggregatedPromises()
|
|
114
|
+
end)
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
return UserInfoAggregator
|