browser-broker 0.1.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/.env.example +173 -0
- package/LICENSE +21 -0
- package/README.md +374 -0
- package/RELEASES.md +97 -0
- package/dist/package.json +58 -0
- package/dist/src/adapter/conformance/case.js +1 -0
- package/dist/src/adapter/conformance/cases.js +429 -0
- package/dist/src/adapter/conformance/discovery.js +156 -0
- package/dist/src/adapter/conformance/driver.js +1 -0
- package/dist/src/adapter/conformance/drivers.js +36 -0
- package/dist/src/adapter/conformance/run.js +224 -0
- package/dist/src/adapter/conformance/service-subject.js +165 -0
- package/dist/src/adapter/contract.js +24 -0
- package/dist/src/adapter/operations.js +114 -0
- package/dist/src/adapter/service-seam.js +1 -0
- package/dist/src/artifacts/names.js +229 -0
- package/dist/src/artifacts/store.js +174 -0
- package/dist/src/bin/broker-tool.js +63 -0
- package/dist/src/bin/broker.js +111 -0
- package/dist/src/browser/adoption.js +143 -0
- package/dist/src/browser/automation-probe.js +113 -0
- package/dist/src/browser/conformance/case.js +1 -0
- package/dist/src/browser/conformance/cases.js +192 -0
- package/dist/src/browser/conformance/run.js +102 -0
- package/dist/src/browser/conformance/subjects.js +19 -0
- package/dist/src/browser/discovery.js +226 -0
- package/dist/src/browser/driver.js +195 -0
- package/dist/src/browser/fake.js +585 -0
- package/dist/src/browser/launch.js +504 -0
- package/dist/src/browser/real.js +1425 -0
- package/dist/src/browser/setup.js +161 -0
- package/dist/src/capture/accounting.js +59 -0
- package/dist/src/capture/image.js +112 -0
- package/dist/src/capture/ladder.js +72 -0
- package/dist/src/capture/legibility.js +195 -0
- package/dist/src/capture/pipeline.js +153 -0
- package/dist/src/capture/tiers.js +166 -0
- package/dist/src/cli/adapter.js +233 -0
- package/dist/src/cli/commands.js +270 -0
- package/dist/src/cli/conformance-driver.js +119 -0
- package/dist/src/cli/diffs.js +122 -0
- package/dist/src/cli/image.js +274 -0
- package/dist/src/cli/index.js +895 -0
- package/dist/src/cli/login-command.js +401 -0
- package/dist/src/cli/operations-commands.js +186 -0
- package/dist/src/cli/reconcile-command.js +137 -0
- package/dist/src/cli/sign-in.js +134 -0
- package/dist/src/cli/telemetry.js +222 -0
- package/dist/src/config/environment.js +446 -0
- package/dist/src/diff/artifact-path.js +77 -0
- package/dist/src/diff/crops.js +102 -0
- package/dist/src/diff/geometry.js +122 -0
- package/dist/src/diff/image.js +132 -0
- package/dist/src/diff/mask.js +46 -0
- package/dist/src/diff/regions.js +263 -0
- package/dist/src/diff/settings.js +135 -0
- package/dist/src/doctor/checks.js +588 -0
- package/dist/src/doctor/report.js +152 -0
- package/dist/src/doctor/session.js +161 -0
- package/dist/src/errors.js +36 -0
- package/dist/src/feedback/read.js +119 -0
- package/dist/src/feedback/record.js +199 -0
- package/dist/src/operations/addresses.js +175 -0
- package/dist/src/operations/derive.js +109 -0
- package/dist/src/operations/ledger.js +194 -0
- package/dist/src/operations/status.js +197 -0
- package/dist/src/operations/telemetry.js +280 -0
- package/dist/src/report/document.js +419 -0
- package/dist/src/report/escape.js +68 -0
- package/dist/src/report/snapshot.js +97 -0
- package/dist/src/service/arbitration.js +537 -0
- package/dist/src/service/artifacts.js +85 -0
- package/dist/src/service/bridge.js +577 -0
- package/dist/src/service/broker.js +120 -0
- package/dist/src/service/browser-session.js +269 -0
- package/dist/src/service/capacity.js +62 -0
- package/dist/src/service/capture-seam.js +83 -0
- package/dist/src/service/capture-store.js +91 -0
- package/dist/src/service/comparison-store.js +101 -0
- package/dist/src/service/comparison.js +173 -0
- package/dist/src/service/events.js +93 -0
- package/dist/src/service/keys.js +68 -0
- package/dist/src/service/leases.js +147 -0
- package/dist/src/service/nudge.js +66 -0
- package/dist/src/service/operations/claim.js +692 -0
- package/dist/src/service/operations/give-back.js +131 -0
- package/dist/src/service/operations/pages.js +771 -0
- package/dist/src/service/operations/sign-in.js +915 -0
- package/dist/src/service/operations/status.js +62 -0
- package/dist/src/service/ownership.js +93 -0
- package/dist/src/service/pages.js +616 -0
- package/dist/src/service/pending-seeds.js +20 -0
- package/dist/src/service/queue.js +233 -0
- package/dist/src/service/reconcile.js +220 -0
- package/dist/src/service/refusals.js +262 -0
- package/dist/src/service/runtime.js +131 -0
- package/dist/src/service/signin-recovery.js +148 -0
- package/dist/src/service/storage-seed.js +239 -0
- package/dist/src/service/tabs.js +123 -0
- package/dist/src/store/budget.js +99 -0
- package/dist/src/store/location.js +42 -0
- package/dist/src/store/network-path.js +182 -0
- package/dist/src/store/network-volume.js +92 -0
- package/dist/src/store/open.js +226 -0
- package/dist/src/store/schema/step-001-initial.js +523 -0
- package/dist/src/store/schema/step-002-tab-budget.js +53 -0
- package/dist/src/store/schema/step-003-queue-order.js +110 -0
- package/dist/src/store/schema/step-004-tab-never-opened.js +100 -0
- package/dist/src/store/schema/step-005-storage-seed-event.js +90 -0
- package/dist/src/store/schema/step-006-signin-events.js +104 -0
- package/dist/src/store/schema/step-007-signin-without-process.js +92 -0
- package/dist/src/store/schema/step-008-signin-owner.js +76 -0
- package/dist/src/store/schema/step-009-named-browsers.js +138 -0
- package/dist/src/store/schema/step-010-signin-request.js +135 -0
- package/dist/src/store/schema/step.js +172 -0
- package/dist/src/store/schema/steps.js +58 -0
- package/dist/src/store/transaction.js +37 -0
- package/dist/src/tool/adapter.js +90 -0
- package/dist/src/tool/conformance-driver.js +184 -0
- package/dist/src/tool/protocol.js +310 -0
- package/dist/src/tool/session.js +351 -0
- package/dist/src/tool/tools.js +310 -0
- package/package.json +58 -0
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import { updateSweptTabs, } from "../arbitration.js";
|
|
2
|
+
import { append } from "../events.js";
|
|
3
|
+
import { hashKey } from "../keys.js";
|
|
4
|
+
import { promoteWhileCapacity } from "../queue.js";
|
|
5
|
+
import { CallRefusal } from "../refusals.js";
|
|
6
|
+
/**
|
|
7
|
+
* Release whatever the lease holds.
|
|
8
|
+
*
|
|
9
|
+
* The tab to close is **collected, not closed**. §2.4b is the hard rule and
|
|
10
|
+
* the reason is worth restating at the site rather than only in the header:
|
|
11
|
+
* closing a tab is a round trip to a browser process that can hang, and a
|
|
12
|
+
* wedged browser does not refuse — it accepts the request and never answers.
|
|
13
|
+
* Inside the transaction that blocks every arbitration call on the machine,
|
|
14
|
+
* including every caller with no interest in that browser, because they are
|
|
15
|
+
* all serialised behind the same writer.
|
|
16
|
+
*/
|
|
17
|
+
export function decideRelease(scope, input, settings) {
|
|
18
|
+
const { db, adapter, swept } = scope;
|
|
19
|
+
const now = swept.sweptAt;
|
|
20
|
+
const row = db
|
|
21
|
+
.prepare(`SELECT id AS claimId, session_id AS sessionId, browser_id AS browserId,
|
|
22
|
+
state, ended_at AS endedAt
|
|
23
|
+
FROM claims
|
|
24
|
+
WHERE key_hash = @keyHash`)
|
|
25
|
+
.get({ keyHash: hashKey(input.key) });
|
|
26
|
+
if (row === undefined) {
|
|
27
|
+
// The only refusal (§3.4). A key this store has never seen names nothing
|
|
28
|
+
// to give back, and forgiving that would mean reporting success for a
|
|
29
|
+
// lease that never existed.
|
|
30
|
+
scope.recordRefusal({
|
|
31
|
+
kind: 'claim_released',
|
|
32
|
+
outcome: 'deny',
|
|
33
|
+
guard: 'key.valid',
|
|
34
|
+
adapter,
|
|
35
|
+
});
|
|
36
|
+
throw new CallRefusal('unrecognised_key', 'That key does not match any lease in this store, so there is nothing to give back.');
|
|
37
|
+
}
|
|
38
|
+
if (row.state !== 'queued' && row.state !== 'active') {
|
|
39
|
+
// Forgiving: succeeds, and says the lease had already ended.
|
|
40
|
+
append(db, {
|
|
41
|
+
kind: 'claim_released',
|
|
42
|
+
outcome: 'allow',
|
|
43
|
+
adapter,
|
|
44
|
+
claimId: row.claimId,
|
|
45
|
+
sessionId: row.sessionId,
|
|
46
|
+
browserId: row.browserId,
|
|
47
|
+
detail: { alreadyEnded: true, state: row.state, endedAt: row.endedAt },
|
|
48
|
+
});
|
|
49
|
+
return {
|
|
50
|
+
value: {
|
|
51
|
+
released: 'nothing',
|
|
52
|
+
claimId: row.claimId,
|
|
53
|
+
alreadyEnded: true,
|
|
54
|
+
state: row.state,
|
|
55
|
+
// Nothing was held, so nothing is outstanding.
|
|
56
|
+
completeAtCommit: true,
|
|
57
|
+
promoted: 0,
|
|
58
|
+
},
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
const wasQueued = row.state === 'queued';
|
|
62
|
+
db.prepare(`UPDATE claims
|
|
63
|
+
SET state = 'released', ended_at = @now, updated_at = @now
|
|
64
|
+
WHERE id = @id`).run({ id: row.claimId, now });
|
|
65
|
+
// On a queued lease this finds nothing, which is the whole difference
|
|
66
|
+
// between the two halves: there was never a tab to collect.
|
|
67
|
+
const tabs = db
|
|
68
|
+
.prepare(`SELECT id AS tabId, claim_id AS claimId, browser_id AS browserId
|
|
69
|
+
FROM tabs
|
|
70
|
+
WHERE claim_id = @claimId AND state IN ('opening', 'open')
|
|
71
|
+
ORDER BY id`)
|
|
72
|
+
.all({ claimId: row.claimId });
|
|
73
|
+
// The same rule the sweep uses, from the same function, because two writers
|
|
74
|
+
// spelling it separately is how they come to disagree — and they did: both
|
|
75
|
+
// moved every tab to `closing`, which the schema refuses for a tab that
|
|
76
|
+
// never opened, and every tab this build creates is one of those.
|
|
77
|
+
//
|
|
78
|
+
// What comes back is the subset a browser still owes an answer about.
|
|
79
|
+
const pendingCloses = updateSweptTabs(db, tabs, now);
|
|
80
|
+
append(db, {
|
|
81
|
+
kind: 'claim_released',
|
|
82
|
+
outcome: 'allow',
|
|
83
|
+
adapter,
|
|
84
|
+
claimId: row.claimId,
|
|
85
|
+
sessionId: row.sessionId,
|
|
86
|
+
browserId: row.browserId,
|
|
87
|
+
detail: {
|
|
88
|
+
released: wasQueued ? 'queue-place' : 'tab',
|
|
89
|
+
tabs: tabs.length,
|
|
90
|
+
releasedAt: now,
|
|
91
|
+
},
|
|
92
|
+
});
|
|
93
|
+
for (const tab of pendingCloses) {
|
|
94
|
+
// Collected inside, closed outside (§2.4b). This schedules; it cannot
|
|
95
|
+
// call a browser, because the scope carries no driver to call one with.
|
|
96
|
+
scope.closeAfterCommit(tab);
|
|
97
|
+
append(db, {
|
|
98
|
+
kind: 'tab_closing',
|
|
99
|
+
outcome: 'allow',
|
|
100
|
+
adapter,
|
|
101
|
+
claimId: row.claimId,
|
|
102
|
+
tabId: tab.tabId,
|
|
103
|
+
sessionId: row.sessionId,
|
|
104
|
+
browserId: tab.browserId,
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
// **Everyone behind moves up immediately** (§2.5, #72). Releasing a queue
|
|
108
|
+
// place frees no capacity, so this promotes nobody in that case — the
|
|
109
|
+
// people behind move up because the position is a count of the queued
|
|
110
|
+
// leases ahead, and one of them just stopped being queued.
|
|
111
|
+
const promoted = promoteWhileCapacity(db, {
|
|
112
|
+
budget: settings.tabBudget,
|
|
113
|
+
leaseSeconds: settings.leaseSeconds,
|
|
114
|
+
adapter,
|
|
115
|
+
now,
|
|
116
|
+
});
|
|
117
|
+
return {
|
|
118
|
+
value: {
|
|
119
|
+
released: wasQueued ? 'queue-place' : 'tab',
|
|
120
|
+
claimId: row.claimId,
|
|
121
|
+
alreadyEnded: false,
|
|
122
|
+
state: 'released',
|
|
123
|
+
// A queued release is complete at commit, because there is no browser
|
|
124
|
+
// round trip in it — the one case where the best-effort caveat in
|
|
125
|
+
// §2.4b's step three does not apply and the response can say so
|
|
126
|
+
// without qualification.
|
|
127
|
+
completeAtCommit: wasQueued,
|
|
128
|
+
promoted: promoted.length,
|
|
129
|
+
},
|
|
130
|
+
};
|
|
131
|
+
}
|