@axpecter/lync 2.3.2 → 3.0.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/LICENSE +21 -0
- package/README.md +302 -299
- package/Types.luau +215 -0
- package/api/Define.luau +154 -0
- package/api/Lifecycle.luau +119 -0
- package/api/Packet.luau +108 -0
- package/api/Query.luau +149 -0
- package/api/Set.luau +189 -0
- package/channel/Blocks.luau +124 -0
- package/channel/Group.luau +118 -0
- package/channel/Link.luau +135 -0
- package/channel/Outbox.luau +261 -0
- package/channel/Recipients.luau +129 -0
- package/channel/Transport.luau +138 -0
- package/codec/Base.luau +236 -0
- package/codec/Composites.luau +128 -0
- package/codec/Datatypes.luau +162 -0
- package/codec/Legality.luau +61 -0
- package/codec/Scalars.luau +72 -0
- package/codec/Text.luau +89 -0
- package/codec/init.luau +39 -0
- package/index.d.ts +285 -0
- package/init.luau +91 -0
- package/kernel/Bits.luau +16 -0
- package/kernel/Catalog.luau +121 -0
- package/kernel/Heap.luau +80 -0
- package/kernel/Listeners.luau +95 -0
- package/kernel/Log.luau +197 -0
- package/kernel/Tally.luau +128 -0
- package/kernel/Threads.luau +44 -0
- package/kernel/Wide.luau +267 -0
- package/package.json +15 -32
- package/runtime/Boundary.luau +180 -0
- package/runtime/Dispatch.luau +91 -0
- package/runtime/Handles.luau +114 -0
- package/runtime/Handshake.luau +90 -0
- package/runtime/Pending.luau +196 -0
- package/runtime/Router.luau +379 -0
- package/runtime/Session.luau +731 -0
- package/shape/Compile.luau +340 -0
- package/shape/Folds.luau +332 -0
- package/shape/Frames.luau +170 -0
- package/shape/Grid.luau +169 -0
- package/shape/Ir.luau +540 -0
- package/shape/Joins.luau +125 -0
- package/shape/Legality.luau +273 -0
- package/shape/Lower.luau +419 -0
- package/shape/Order.luau +64 -0
- package/shape/Regions.luau +113 -0
- package/shape/Rotation.luau +472 -0
- package/shape/Serial.luau +258 -0
- package/shape/Words.luau +89 -0
- package/shape/emit/Block.luau +453 -0
- package/shape/emit/Column.luau +338 -0
- package/shape/emit/Leaf.luau +462 -0
- package/shape/emit/Word.luau +234 -0
- package/shape/emit/init.luau +222 -0
- package/shape/init.luau +78 -0
- package/state/Apply.luau +330 -0
- package/state/Audience.luau +126 -0
- package/state/Catchup.luau +218 -0
- package/state/Coalesce.luau +43 -0
- package/state/Fieldset.luau +177 -0
- package/state/Newest.luau +339 -0
- package/state/Plan.luau +441 -0
- package/state/Sections.luau +468 -0
- package/state/Store.luau +188 -0
- package/state/Sync.luau +762 -0
- package/wire/Bytes.luau +118 -0
- package/wire/Clock.luau +37 -0
- package/wire/Protocol.luau +110 -0
- package/wire/Sequence.luau +40 -0
- package/wire/Varint.luau +124 -0
- package/src/Types.luau +0 -180
- package/src/api/Group.luau +0 -156
- package/src/api/Packet.luau +0 -319
- package/src/api/Query.luau +0 -338
- package/src/api/Scope.luau +0 -90
- package/src/api/Signal.luau +0 -188
- package/src/codec/Base.luau +0 -136
- package/src/codec/composite/Array.luau +0 -456
- package/src/codec/composite/Map.luau +0 -469
- package/src/codec/composite/Optional.luau +0 -54
- package/src/codec/composite/Shared.luau +0 -291
- package/src/codec/composite/Struct.luau +0 -494
- package/src/codec/composite/Tagged.luau +0 -103
- package/src/codec/composite/Tuple.luau +0 -143
- package/src/codec/datatype/Buffer.luau +0 -66
- package/src/codec/datatype/CFrame.luau +0 -109
- package/src/codec/datatype/Color.luau +0 -32
- package/src/codec/datatype/Instance.luau +0 -52
- package/src/codec/datatype/IntVector.luau +0 -39
- package/src/codec/datatype/NumberRange.luau +0 -39
- package/src/codec/datatype/Ray.luau +0 -36
- package/src/codec/datatype/Rect.luau +0 -31
- package/src/codec/datatype/Region.luau +0 -62
- package/src/codec/datatype/Sequence.luau +0 -184
- package/src/codec/datatype/String.luau +0 -94
- package/src/codec/datatype/UDim.luau +0 -46
- package/src/codec/datatype/Vector.luau +0 -130
- package/src/codec/meta/Auto.luau +0 -318
- package/src/codec/meta/Bitfield.luau +0 -147
- package/src/codec/meta/Custom.luau +0 -33
- package/src/codec/meta/DeltaScalar.luau +0 -390
- package/src/codec/meta/Enum.luau +0 -50
- package/src/codec/meta/Float.luau +0 -38
- package/src/codec/meta/Nothing.luau +0 -13
- package/src/codec/meta/Unknown.luau +0 -41
- package/src/codec/primitive/Bool.luau +0 -26
- package/src/codec/primitive/Float16.luau +0 -99
- package/src/codec/primitive/Int.luau +0 -59
- package/src/codec/primitive/Number.luau +0 -24
- package/src/codec/primitive/Signed.luau +0 -32
- package/src/codec/primitive/Varint.luau +0 -165
- package/src/codec/primitive/Zint.luau +0 -99
- package/src/index.d.ts +0 -423
- package/src/init.luau +0 -362
- package/src/internal/Baseline.luau +0 -57
- package/src/internal/Channel.luau +0 -390
- package/src/internal/Middleware.luau +0 -100
- package/src/internal/Pool.luau +0 -65
- package/src/internal/Registry.luau +0 -119
- package/src/internal/Transport.luau +0 -28
- package/src/transport/Bridge.luau +0 -110
- package/src/transport/Client.luau +0 -97
- package/src/transport/Gate.luau +0 -488
- package/src/transport/Reader.luau +0 -331
- package/src/transport/Server.luau +0 -211
- package/src/util/Array.luau +0 -18
- package/src/util/Buffer.luau +0 -90
- package/src/util/Constants.luau +0 -30
- package/src/util/Log.luau +0 -68
- package/src/util/Player.luau +0 -14
- package/src/util/Quantize.luau +0 -84
- package/src/util/Quat.luau +0 -124
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
--!strict
|
|
2
|
+
--!optimize 2
|
|
3
|
+
-- What a handle is bound to, and what it was asked to do before there was anything to bind it to.
|
|
4
|
+
|
|
5
|
+
local Types = require (script.Parent.Parent.Types)
|
|
6
|
+
|
|
7
|
+
local Handles = {}
|
|
8
|
+
|
|
9
|
+
-- Types ---------------------------------------------------------------
|
|
10
|
+
|
|
11
|
+
-- What a handle knows about where it ended up, which is nothing until it is told.
|
|
12
|
+
export type Live = {
|
|
13
|
+
space: string?,
|
|
14
|
+
name: string?,
|
|
15
|
+
id: number?,
|
|
16
|
+
def: any,
|
|
17
|
+
session: any,
|
|
18
|
+
isServer: boolean,
|
|
19
|
+
waiting: { (any) -> () },
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
-- An attachment made before there was anything to attach to.
|
|
23
|
+
export type Waiting = {
|
|
24
|
+
connected: boolean,
|
|
25
|
+
held: Types.Connection?,
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
-- Private -------------------------------------------------------------
|
|
29
|
+
|
|
30
|
+
--[[
|
|
31
|
+
A connection to something that does not exist yet, ended the same way as one that does.
|
|
32
|
+
|
|
33
|
+
A metatable rather than a closure per attachment, because a handle may be listened to as often
|
|
34
|
+
as a caller likes and the pair of fields is the whole of what one of these is.
|
|
35
|
+
]]
|
|
36
|
+
local Attached = {}
|
|
37
|
+
Attached.__index = Attached
|
|
38
|
+
|
|
39
|
+
function Attached.disconnect (self: Waiting)
|
|
40
|
+
self.connected = false
|
|
41
|
+
|
|
42
|
+
local held = self.held
|
|
43
|
+
if held ~= nil then held:disconnect () end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
-- Public --------------------------------------------------------------
|
|
47
|
+
|
|
48
|
+
--[[
|
|
49
|
+
A fresh binding, which every handle is made holding one of.
|
|
50
|
+
|
|
51
|
+
Made by the handle rather than here, and typed here, because what fills it is the calls below
|
|
52
|
+
and nothing a caller can reach.
|
|
53
|
+
]]
|
|
54
|
+
function Handles.live (): Live
|
|
55
|
+
return {
|
|
56
|
+
space = nil,
|
|
57
|
+
name = nil,
|
|
58
|
+
id = nil,
|
|
59
|
+
def = nil,
|
|
60
|
+
session = nil,
|
|
61
|
+
isServer = false,
|
|
62
|
+
waiting = {},
|
|
63
|
+
}
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
--[[
|
|
67
|
+
Something to do to this handle once there is a session to do it with.
|
|
68
|
+
|
|
69
|
+
Run now where there is one and held where there is not, so a caller who attaches before a
|
|
70
|
+
namespace opens and one who attaches after are asking for the same thing and get it.
|
|
71
|
+
]]
|
|
72
|
+
function Handles.waiting (of: Live, run: (any) -> ())
|
|
73
|
+
local session = of.session
|
|
74
|
+
if session ~= nil then
|
|
75
|
+
run (session)
|
|
76
|
+
return
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
table.insert (of.waiting, run)
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
-- A listener attached whenever the caller liked, and the connection that ends it either way.
|
|
83
|
+
function Handles.later (of: Live, bind: (any) -> Types.Connection): Types.Connection
|
|
84
|
+
local session = of.session
|
|
85
|
+
if session ~= nil then return bind (session) end
|
|
86
|
+
|
|
87
|
+
local held: Waiting = setmetatable ({ connected = true, held = nil }, Attached) :: any
|
|
88
|
+
table.insert (of.waiting, function (opened: any)
|
|
89
|
+
if not held.connected then return end
|
|
90
|
+
held.held = bind (opened)
|
|
91
|
+
end)
|
|
92
|
+
|
|
93
|
+
return (held :: any) :: Types.Connection
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
--[[
|
|
97
|
+
A handle, bound to what its namespace compiled it into, and everything it was owed since.
|
|
98
|
+
|
|
99
|
+
The binding is written before anything waiting runs, because what waits is listeners and
|
|
100
|
+
responders and both of them reach back through the handle for the id they attach under.
|
|
101
|
+
]]
|
|
102
|
+
function Handles.opened (of: Live, def: any, session: any, isServer: boolean)
|
|
103
|
+
of.id = def.id
|
|
104
|
+
of.def = def
|
|
105
|
+
of.session = session
|
|
106
|
+
of.isServer = isServer
|
|
107
|
+
|
|
108
|
+
for _, run in of.waiting do
|
|
109
|
+
run (session)
|
|
110
|
+
end
|
|
111
|
+
table.clear (of.waiting)
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
return table.freeze (Handles)
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
--!strict
|
|
2
|
+
--!optimize 2
|
|
3
|
+
-- The two messages the handshake lane carries, and the judgement each one earns.
|
|
4
|
+
|
|
5
|
+
local Catalog = require (script.Parent.Parent.kernel.Catalog)
|
|
6
|
+
local Log = require (script.Parent.Parent.kernel.Log)
|
|
7
|
+
local Protocol = require (script.Parent.Parent.wire.Protocol)
|
|
8
|
+
local Wide = require (script.Parent.Parent.kernel.Wide)
|
|
9
|
+
|
|
10
|
+
local Handshake = {}
|
|
11
|
+
|
|
12
|
+
-- Constants -----------------------------------------------------------
|
|
13
|
+
|
|
14
|
+
-- What each message weighs, which is the whole of what tells the two apart, and where a field sits.
|
|
15
|
+
const HELLO = Protocol.HELLO_BYTES
|
|
16
|
+
const VERDICT = Protocol.VERDICT_BYTES
|
|
17
|
+
const FIELD = Protocol.VERDICT_FIELD
|
|
18
|
+
|
|
19
|
+
-- Private -------------------------------------------------------------
|
|
20
|
+
|
|
21
|
+
--[[
|
|
22
|
+
One code for both sides. A hello reaching a client and a verdict reaching a server are one event
|
|
23
|
+
told from two ends, and neither end has anything to say about the bytes past that.
|
|
24
|
+
]]
|
|
25
|
+
local function unspoken ()
|
|
26
|
+
local facts: Log.Facts = { code = Catalog.HELLO }
|
|
27
|
+
Log.warn (Log.line (Catalog.HELLO, facts), facts)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
-- Two builds that cannot speak to one another, as the one sentence both machines read it as.
|
|
31
|
+
local function mismatch (ours: Wide.Word, theirs: Wide.Word): (string, Log.Facts)
|
|
32
|
+
local facts: Log.Facts =
|
|
33
|
+
{ code = Catalog.MISMATCH, ours = Wide.text (ours), theirs = Wide.text (theirs) }
|
|
34
|
+
return Log.line (Catalog.MISMATCH, facts), facts
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
-- Public --------------------------------------------------------------
|
|
38
|
+
|
|
39
|
+
function Handshake.hello (ours: Wide.Word): buffer
|
|
40
|
+
local out = buffer.create (HELLO)
|
|
41
|
+
Wide.write (out, 0, ours)
|
|
42
|
+
return out
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
-- The verdict a hello has earned, and whether the machine that sent it may be spoken to.
|
|
46
|
+
function Handshake.verdict (ours: Wide.Word, epoch: number, bytes: buffer): (buffer?, boolean)
|
|
47
|
+
if buffer.len (bytes) ~= HELLO then
|
|
48
|
+
unspoken ()
|
|
49
|
+
return nil, false
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
local theirs = Wide.read (bytes, 0)
|
|
53
|
+
local out = buffer.create (VERDICT)
|
|
54
|
+
|
|
55
|
+
if Wide.same (theirs, ours) then
|
|
56
|
+
buffer.writeu8 (out, 0, Protocol.VERDICT_ACCEPT)
|
|
57
|
+
buffer.writef64 (out, FIELD, epoch)
|
|
58
|
+
return out, true
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
Log.warn (mismatch (ours, theirs))
|
|
62
|
+
|
|
63
|
+
buffer.writeu8 (out, 0, Protocol.VERDICT_REJECT)
|
|
64
|
+
Wide.write (out, FIELD, ours)
|
|
65
|
+
return out, false
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
--[[
|
|
69
|
+
The namespace epoch, or nothing where the lane carried no verdict yet. A refusal is the third
|
|
70
|
+
way out and never comes back: two builds that disagree cannot be made to agree at run time, so
|
|
71
|
+
it raises where a message nobody can read only warns.
|
|
72
|
+
]]
|
|
73
|
+
function Handshake.judged (ours: Wide.Word, bytes: buffer): number?
|
|
74
|
+
if buffer.len (bytes) ~= VERDICT then
|
|
75
|
+
unspoken ()
|
|
76
|
+
return nil
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
local said = buffer.readu8 (bytes, 0)
|
|
80
|
+
if said == Protocol.VERDICT_ACCEPT then return buffer.readf64 (bytes, FIELD) end
|
|
81
|
+
|
|
82
|
+
if said ~= Protocol.VERDICT_REJECT then
|
|
83
|
+
unspoken ()
|
|
84
|
+
return nil
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
return Log.error (mismatch (ours, Wide.read (bytes, FIELD)))
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
return table.freeze (Handshake)
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
--!strict
|
|
2
|
+
--!optimize 2
|
|
3
|
+
-- Requests in flight: the id each waits under, the deadline it waits to, and every way out.
|
|
4
|
+
|
|
5
|
+
local Heap = require (script.Parent.Parent.kernel.Heap)
|
|
6
|
+
local Log = require (script.Parent.Parent.kernel.Log)
|
|
7
|
+
local Protocol = require (script.Parent.Parent.wire.Protocol)
|
|
8
|
+
local Types = require (script.Parent.Parent.Types)
|
|
9
|
+
|
|
10
|
+
local Pending = {}
|
|
11
|
+
Pending.__index = Pending
|
|
12
|
+
|
|
13
|
+
-- Constants -----------------------------------------------------------
|
|
14
|
+
|
|
15
|
+
-- Twice the live ceiling, so the walk for a free id always has somewhere to go and cannot fail.
|
|
16
|
+
const SPACE = Protocol.QUERY_CAP * 2
|
|
17
|
+
|
|
18
|
+
-- Types ---------------------------------------------------------------
|
|
19
|
+
|
|
20
|
+
--[[
|
|
21
|
+
One request nobody has answered. Its deadline is here as well as in the heap, since a heap entry
|
|
22
|
+
outlives its request: an id comes round a lap later and the entry popping then belongs to the
|
|
23
|
+
one before it.
|
|
24
|
+
]]
|
|
25
|
+
type Entry = {
|
|
26
|
+
read definition: string,
|
|
27
|
+
read player: Player?,
|
|
28
|
+
read opened: number,
|
|
29
|
+
read at: number,
|
|
30
|
+
read complete: Types.Outcome<any>,
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export type Pending = {
|
|
34
|
+
read open: (
|
|
35
|
+
self: Pending,
|
|
36
|
+
now: number,
|
|
37
|
+
definition: string,
|
|
38
|
+
player: Player?,
|
|
39
|
+
timeout: number?,
|
|
40
|
+
complete: Types.Outcome<any>
|
|
41
|
+
) -> number,
|
|
42
|
+
read answer: (self: Pending, id: number, value: any) -> boolean,
|
|
43
|
+
read fail: (self: Pending, id: number, code: Types.OutcomeCode, now: number) -> boolean,
|
|
44
|
+
read sweep: (self: Pending, now: number) -> (),
|
|
45
|
+
read rejectFor: (self: Pending, player: Player, now: number) -> (),
|
|
46
|
+
read rejectAll: (self: Pending, now: number) -> (),
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
type Self = {
|
|
50
|
+
namespace: string,
|
|
51
|
+
live: { [number]: Entry },
|
|
52
|
+
count: number,
|
|
53
|
+
next: number,
|
|
54
|
+
deadlines: Heap.Heap,
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
-- Private -------------------------------------------------------------
|
|
58
|
+
|
|
59
|
+
-- A request lifted out of the live set. Every way out goes through here, so one resolves once.
|
|
60
|
+
local function taken (self: Self, id: number): Entry?
|
|
61
|
+
local entry = self.live[id]
|
|
62
|
+
if entry == nil then return nil end
|
|
63
|
+
|
|
64
|
+
self.live[id] = nil
|
|
65
|
+
self.count -= 1
|
|
66
|
+
return entry
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
-- Public --------------------------------------------------------------
|
|
70
|
+
|
|
71
|
+
function Pending.new (namespace: string): Pending
|
|
72
|
+
local self: Self = {
|
|
73
|
+
namespace = namespace,
|
|
74
|
+
live = {},
|
|
75
|
+
count = 0,
|
|
76
|
+
next = 0,
|
|
77
|
+
deadlines = Heap.new (),
|
|
78
|
+
}
|
|
79
|
+
return (setmetatable (self, Pending) :: any) :: Pending
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
-- A request, under the first id nothing is waiting on.
|
|
83
|
+
function Pending.open (
|
|
84
|
+
self: Self,
|
|
85
|
+
now: number,
|
|
86
|
+
definition: string,
|
|
87
|
+
player: Player?,
|
|
88
|
+
timeout: number?,
|
|
89
|
+
complete: Types.Outcome<any>
|
|
90
|
+
): number
|
|
91
|
+
if self.count == Protocol.QUERY_CAP then
|
|
92
|
+
Log.refuse (
|
|
93
|
+
`{self.namespace} has {Protocol.QUERY_CAP} requests in flight, which is the ceiling`
|
|
94
|
+
)
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
local id = self.next
|
|
98
|
+
while self.live[id] ~= nil do
|
|
99
|
+
id = (id + 1) % SPACE
|
|
100
|
+
end
|
|
101
|
+
self.next = (id + 1) % SPACE
|
|
102
|
+
|
|
103
|
+
local at = now + (timeout or Protocol.QUERY_TIMEOUT)
|
|
104
|
+
self.live[id] = {
|
|
105
|
+
definition = definition,
|
|
106
|
+
player = player,
|
|
107
|
+
opened = now,
|
|
108
|
+
at = at,
|
|
109
|
+
complete = complete,
|
|
110
|
+
}
|
|
111
|
+
self.count += 1
|
|
112
|
+
|
|
113
|
+
Heap.push (self.deadlines, at, id)
|
|
114
|
+
return id
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
--[[
|
|
118
|
+
The reply arrived. Answers whether anybody was waiting, an id nobody waits on being a reply to a
|
|
119
|
+
request that already ended or a frame nobody here sent for.
|
|
120
|
+
]]
|
|
121
|
+
function Pending.answer (self: Self, id: number, value: any): boolean
|
|
122
|
+
local entry = taken (self, id)
|
|
123
|
+
if entry == nil then return false end
|
|
124
|
+
|
|
125
|
+
entry.complete (true, value, nil)
|
|
126
|
+
return true
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
--[[
|
|
130
|
+
The request ended as one of the four outcomes. The elapsed time rides on all of them, a caller
|
|
131
|
+
reading how long a leave took being owed the same number as one reading a timeout.
|
|
132
|
+
]]
|
|
133
|
+
function Pending.fail (self: Self, id: number, code: Types.OutcomeCode, now: number): boolean
|
|
134
|
+
local entry = taken (self, id)
|
|
135
|
+
if entry == nil then return false end
|
|
136
|
+
|
|
137
|
+
entry.complete (
|
|
138
|
+
false,
|
|
139
|
+
code,
|
|
140
|
+
table.freeze ({ definition = entry.definition, elapsed = now - entry.opened })
|
|
141
|
+
)
|
|
142
|
+
return true
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
-- Every deadline that has passed, and only the requests still waiting on one of them.
|
|
146
|
+
function Pending.sweep (self: Self, now: number)
|
|
147
|
+
local heap = self.deadlines
|
|
148
|
+
|
|
149
|
+
while true do
|
|
150
|
+
local at, id = Heap.peek (heap)
|
|
151
|
+
if at == nil or at > now then return end
|
|
152
|
+
Heap.pop (heap)
|
|
153
|
+
|
|
154
|
+
local entry = self.live[id :: number]
|
|
155
|
+
if entry ~= nil and entry.at <= now then
|
|
156
|
+
Pending.fail (self, id :: number, "timeout", now)
|
|
157
|
+
end
|
|
158
|
+
end
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
--[[
|
|
162
|
+
Everything owed by somebody who has gone, named for what happened: a caller branching on a leave
|
|
163
|
+
knows not to retry, where one told it timed out would.
|
|
164
|
+
]]
|
|
165
|
+
function Pending.rejectFor (self: Self, player: Player, now: number)
|
|
166
|
+
local taking: { number } = {}
|
|
167
|
+
for id, entry in self.live do
|
|
168
|
+
if entry.player == player then table.insert (taking, id) end
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
for _, id in taking do
|
|
172
|
+
Pending.fail (self, id, "leave", now)
|
|
173
|
+
end
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
--[[
|
|
177
|
+
Everything at once, which is a namespace closing. The live set is replaced before anything is
|
|
178
|
+
answered, so a completion opening a request of its own lands in the new one and nothing in the
|
|
179
|
+
old can be answered twice.
|
|
180
|
+
]]
|
|
181
|
+
function Pending.rejectAll (self: Self, now: number)
|
|
182
|
+
local live = self.live
|
|
183
|
+
|
|
184
|
+
self.live = {}
|
|
185
|
+
self.count = 0
|
|
186
|
+
|
|
187
|
+
for _, entry in live do
|
|
188
|
+
entry.complete (
|
|
189
|
+
false,
|
|
190
|
+
"shutdown",
|
|
191
|
+
table.freeze ({ definition = entry.definition, elapsed = now - entry.opened })
|
|
192
|
+
)
|
|
193
|
+
end
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
return table.freeze (Pending)
|