Skip to content

Commit b8a37bd

Browse files
authored
Merge pull request #231 from WICG/yao-spec-transactional-batch-update
[spec] Support transactional batchUpdate()
2 parents aa9049d + 56004bb commit b8a37bd

File tree

1 file changed

+55
-42
lines changed

1 file changed

+55
-42
lines changed

spec.bs

Lines changed: 55 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1415,6 +1415,50 @@ The Shared Storage API will integrate into the [=Storage Model|Storage API=] as
14151415
1. Return the result of running [=shared storage database/store an entry in the database=] with |queue|, |databaseMap|, |environment|, |key|, and |value|.
14161416
</div>
14171417

1418+
<div algorithm>
1419+
1420+
To <dfn for="shared storage database">batch update entries in the database</dfn>, given a [=shared storage database/shared storage database queue=] |queue|, a [=storage proxy map=] |databaseMap|, an [=environment settings object=] |environment|, and a [=list=] of {{SharedStorageModifierMethod}} |methods|, run the following steps on |queue|:
1421+
1422+
1. Let |originalDatabaseMap| be |databaseMap|.
1423+
1424+
1. Let |innerMethodFailed| be false.
1425+
1. For each |method| in |methods|:
1426+
1. If |method| is a {{SharedStorageSetMethod}}:
1427+
1. Let |key| be |method|'s [=SharedStorageSetMethod/key=].
1428+
1. Let |value| be |method|'s [=SharedStorageSetMethod/value=].
1429+
1. Let |ignoreIfPresent| be |method|'s [=SharedStorageSetMethod/ignore if present=].
1430+
1. Let |result| be the result of running [=shared storage database/set an entry in the database=] with |queue|, |databaseMap|, |environment|, |key|, |value|, and |ignoreIfPresent|.
1431+
1. If |result| is false:
1432+
1. Set |innerMethodFailed| to true.
1433+
1. Break.
1434+
1. Else if |method| is a {{SharedStorageAppendMethod}}:
1435+
1. Let |key| be |method|'s [=SharedStorageAppendMethod/key=].
1436+
1. Let |value| be |method|'s [=SharedStorageAppendMethod/value=].
1437+
1. Let |result| be the result of running [=shared storage database/append an entry in the database=] with |queue|, |databaseMap|, |environment|, |key|, and |value|.
1438+
1. If |result| is false:
1439+
1. Set |innerMethodFailed| to true.
1440+
1. Break.
1441+
1. Else if |method| is a {{SharedStorageDeleteMethod}}:
1442+
1. Let |key| be |method|'s [=SharedStorageDeleteMethod/key=].
1443+
1. Let |result| be the result of running [=shared storage database/delete an entry from the database=] with |queue|, |databaseMap|, |environment|, and |key|.
1444+
1. If |result| is false:
1445+
1. Set |innerMethodFailed| to true.
1446+
1. Break.
1447+
1. Else:
1448+
1. [=Assert=]: |method| is a {{SharedStorageClearMethod}}.
1449+
1. Let |result| be the result of running [=shared storage database/clear all entries in the database=] with |queue|, |databaseMap|, and |environment|.
1450+
1. If |result| is false:
1451+
1. Set |innerMethodFailed| to true.
1452+
1. Break.
1453+
1. If |innerMethodFailed|:
1454+
1. Set |databaseMap| to |originalDatabaseMap|.
1455+
1. Return false.
1456+
1. Return true.
1457+
</div>
1458+
1459+
<div class="note">
1460+
This algorithm uses a naive rollback mechanism. For production environments, consider more efficient techniques that avoid full database copies.
1461+
</div>
14181462

14191463
Extension to the {{Window}} interface {#window-extension}
14201464
=====================================================
@@ -1712,57 +1756,26 @@ Note: The [=determine if a navigable has fully revoked network=] algorithm ensur
17121756
1. If the result of running [=SharedStorageWorkletGlobalScope/check whether addModule is finished=] for {{SharedStorage}}'s associated {{SharedStorageWorkletGlobalScope}} is false, return a [=promise rejected=] with a {{TypeError}}.
17131757
1. If |context| is null, return a [=promise rejected=] with a {{TypeError}}.
17141758
1. If |context|'s [=active window=]'s [=associated document=] is not [=fully active=], return a [=promise rejected=] with a {{TypeError}}.
1759+
1. For each |method| in |methods|:
1760+
1. If |method|["{{SharedStorageModifierMethodOptions/withLock}}"] [=map/exists=]:
1761+
1. Return a [=promise rejected=] with a {{TypeError}}.
1762+
1763+
Note: `batchUpdate()` executes as a transactional operation. To avoid potential deadlocks from finer-grained locking, inner methods within `batchUpdate()` cannot utilize the `withLock` option. Instead of ignoring this option, an error is thrown to enforce the restriction and prevent misuse.
17151764
1. Let |environment| be |context|'s [=active window=]'s [=relevant settings object=].
17161765
1. Let |databaseMap| be the result of running [=obtain a shared storage bottle map=] given |environment| and |environment|'s [=environment settings object/origin=].
17171766
1. If |databaseMap| is failure, then return a [=promise rejected=] with a {{TypeError}}.
1718-
1. Let |unfinishedUpdatesCount| be |methods|'s [=list/size=].
1719-
1. Let |hasFailure| be false.
17201767
1. Let |onLockGrantedCallback| be an algorithm to perform the following steps:
1721-
1. For each |method| in |methods|:
1722-
1. Let |methodResultPromise| be a new [=promise=].
1723-
1. If |method| is a {{SharedStorageSetMethod}}:
1724-
1. Let |key| be |method|'s [=SharedStorageSetMethod/key=].
1725-
1. Let |value| be |method|'s [=SharedStorageSetMethod/value=].
1726-
1. Let |methodOptions| be a new {{SharedStorageSetMethodOptions}}.
1727-
1. Set |methodOptions|["{{SharedStorageSetMethodOptions/ignoreIfPresent}}"] to |method|'s [=SharedStorageSetMethod/ignore if present=].
1728-
1. If |method|'s [=SharedStorageModifierMethod/with lock=] is not null, set |methodOptions|["{{SharedStorageModifierMethodOptions/withLock}}"] to |method|'s [=SharedStorageModifierMethod/with lock=].
1729-
1. Set |methodResultPromise| to the result of invoking {{SharedStorage/set()|set}}(|key|, |value|, |methodOptions|).
1730-
1. Else if |method| is a {{SharedStorageAppendMethod}}:
1731-
1. Let |key| be |method|'s [=SharedStorageAppendMethod/key=].
1732-
1. Let |value| be |method|'s [=SharedStorageAppendMethod/value=].
1733-
1. Let |methodOptions| be a new {{SharedStorageModifierMethodOptions}}.
1734-
1. If |method|'s [=SharedStorageModifierMethod/with lock=] is not null, set |methodOptions|["{{SharedStorageModifierMethodOptions/withLock}}"] to |method|'s [=SharedStorageModifierMethod/with lock=].
1735-
1. Set |methodResultPromise| to the result of invoking {{SharedStorage/append()|append}}(|key|, |value|, |methodOptions|).
1736-
1. Else if |method| is a {{SharedStorageDeleteMethod}}:
1737-
1. Let |key| be |method|'s [=SharedStorageDeleteMethod/key=].
1738-
1. Let |methodOptions| be a new {{SharedStorageModifierMethodOptions}}.
1739-
1. If |method|'s [=SharedStorageModifierMethod/with lock=] is not null, set |methodOptions|["{{SharedStorageModifierMethodOptions/withLock}}"] to |method|'s [=SharedStorageModifierMethod/with lock=].
1740-
1. Set |methodResultPromise| to the result of invoking {{SharedStorage/delete()|delete}}(|key|, |methodOptions|).
1741-
1. Else:
1742-
1. [=Assert=]: |method| is a {{SharedStorageClearMethod}}.
1743-
1. Let |methodOptions| be a new {{SharedStorageModifierMethodOptions}}.
1744-
1. If |method|'s [=SharedStorageModifierMethod/with lock=] is not null, set |methodOptions|["{{SharedStorageModifierMethodOptions/withLock}}"] to |method|'s [=SharedStorageModifierMethod/with lock=].
1745-
1. Set |methodResultPromise| to the result of invoking {{SharedStorage/clear()|clear}}(|methodOptions|).
1746-
1. [=Upon fulfillment=] of |methodResultPromise|:
1747-
1. Decrement |unfinishedUpdatesCount| by 1.
1748-
1. If |unfinishedUpdatesCount| is 0, run [=finish a batch update=] given |promise| and |hasFailure|.
1749-
1. [=Upon rejection=] of |methodResultPromise|:
1750-
1. Decrement |unfinishedUpdatesCount| by 1.
1751-
1. Set |hasFailure| to true.
1752-
1. If |unfinishedUpdatesCount| is 0, run [=finish a batch update=] given |promise| and |hasFailure|.
1753-
1. If |unfinishedUpdatesCount| is 0, run [=finish a batch update=] given |promise| and |hasFailure|.
1768+
1. [=Enqueue the following steps=] on |queue|:
1769+
1. Let |result| be the result of running [=shared storage database/batch update entries in the database=] with |queue|, |databaseMap|, |environment|, and |methods|.
1770+
1. If |result| is false and if |globalObject| is a {{SharedStorageWorkletGlobalScope}}:
1771+
1. [=Queue a global task=] on the [=DOM manipulation task source=], given |realm|'s [=global object=], to [=reject=] |promise| with a {{TypeError}}.
1772+
1. Abort these steps.
1773+
1. [=Queue a global task=] on the [=DOM manipulation task source=], given |realm|'s [=global object=], to [=resolve=] |promise| with undefined.
17541774
1. If |options|["{{SharedStorageModifierMethodOptions/withLock}}"] [=map/exists=], run [=handle callback within a shared storage lock=] given |environment|'s [=environment settings object/origin=], |options|["{{SharedStorageModifierMethodOptions/withLock}}"], |onLockGrantedCallback|.
17551775
1. Else, run |onLockGrantedCallback|.
17561776
1. Return |promise|.
17571777
</div>
17581778

1759-
<div algorithm>
1760-
To <dfn>finish a batch update</dfn>, given a [=promise=] |promise| and a [=/boolean=] |hasFailure|, perform the following steps:
1761-
1762-
1. If |hasFailure| is true, [=reject=] |promise| with a {{TypeError}}.
1763-
1. Else, [=resolve=] |promise| with undefined.
1764-
</div>
1765-
17661779
## Setter/Deleter Methods ## {#setter}
17671780

17681781
<div algorithm>

0 commit comments

Comments
 (0)