@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.7.0",
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/loader": "^6.2.1",
29
- "@quenty/math": "^2.4.0",
30
- "@quenty/promise": "^6.6.0"
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": "dc77d6de09e9eb9d3fd6dafd790c052d8393d38f"
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