Skip to content

Commit b4bb434

Browse files
Initial sketch of manual commit
fix/add 'new in this edition' hints version history invert flag check don't let tx go inactive post-rebase cleanup
1 parent ff8346e commit b4bb434

File tree

1 file changed

+125
-17
lines changed

1 file changed

+125
-17
lines changed

index.bs

Lines changed: 125 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -934,6 +934,8 @@ following:
934934
instead is created automatically when an
935935
<a event>`upgradeneeded`</a> event is fired.
936936

937+
A [=/transaction=] has an <dfn>manual commit flag</dfn>, which is initially false. By default, transactions commit automatically when all outstanding requests have been processed. This can be behavior can be modified by options set when creating the transaction.
938+
937939
A [=/transaction=] has a <dfn>durability hint</dfn>. This is a hint to the user agent of whether to prioritize performance or durability when committing the transaction. The [=transaction/durability hint=] is one of the following:
938940

939941
: {{"strict"}}
@@ -1041,10 +1043,11 @@ The <dfn>lifetime</dfn> of a
10411043
</aside>
10421044

10431045
1. When each [=/request=] associated with a transaction is [=request/processed=],
1044-
a <a event>`success`</a> or <a event>`error`</a> [=event=] will be
1045-
fired. While the event is being [=dispatched=], the transaction
1046+
a <a event>`success`</a> or <a event>`error`</a> [=event=] will be fired.
1047+
If the transaction's [=transaction/manual commit flag=] is false (the default), then
1048+
while the event is being [=dispatched=], the transaction
10461049
[=transaction/state=] is set to [=transaction/active=], allowing
1047-
additional requests to be made against the transaction. Once the
1050+
additional requests to be made against the transaction; once the
10481051
event dispatch is complete, the transaction's
10491052
[=transaction/state=] is set to [=transaction/inactive=] again.
10501053

@@ -1063,11 +1066,12 @@ The <dfn>lifetime</dfn> of a
10631066
[=/object stores=] as well as additions and removals of [=/object
10641067
stores=] and [=/indexes=].
10651068

1066-
1. The implementation must attempt to <dfn lt="commit|committed">commit</dfn>
1067-
a transaction when all [=/requests=] placed against the
1069+
1. If a transaction's [=transaction/manual commit flag=] is false, then
1070+
the implementation must attempt to <dfn lt="commit|committed">commit</dfn>
1071+
it when all [=/requests=] placed against the
10681072
transaction have completed and their returned results handled, no
10691073
new requests have been placed against the transaction, and the
1070-
transaction has not been [=transaction/aborted=]
1074+
transaction has not been [=transaction/aborted=].
10711075

10721076
An explicit call to {{IDBTransaction/commit()}} will initiate a
10731077
[=transaction/commit=] without waiting for request results to be
@@ -1103,7 +1107,7 @@ They will return true if any transactions were cleaned up, or false otherwise.
11031107
1. For each [=/transaction=] |transaction| with [=transaction/cleanup event loop=]
11041108
matching the current [=/event loop=]:
11051109

1106-
1. Set |transaction|'s [=transaction/state=] to [=transaction/inactive=].
1110+
1. If |transaction|'s [=transaction/manual commit flag=] is false, then set |transaction|'s [=transaction/state=] to [=transaction/inactive=].
11071111

11081112
1. Clear |transaction|'s [=transaction/cleanup event loop=].
11091113

@@ -1124,6 +1128,78 @@ a [=/transaction=] that has successfully [=transaction/committed=].
11241128
An event with type <dfn event>`abort`</dfn> is fired at
11251129
a [=/transaction=] that has [=transaction/aborted=].
11261130

1131+
1132+
<aside class=example id=example-transaction-autocommit>
1133+
1134+
The following example uses requests within a transaction to increment a counter value.
1135+
Event handlers log various state changes during the request and transaction lifecycles.
1136+
1137+
```js
1138+
const transaction = connection.transaction('my_data', 'readwrite');
1139+
const store = transaction.objectStore('my_data');
1140+
const get_request = store.get('counter');
1141+
get_request.onerror = e => {
1142+
console.warn(`get failed: ${get_request.error}`);
1143+
};
1144+
get_request.onsuccess = e => {
1145+
console.log(`get succeeded`);
1146+
const old_value = get_request.result;
1147+
const put_request = store.put(old_value + 1, 'counter');
1148+
put_request.onerror = e => {
1149+
console.warn(`get failed: ${put_request.error}`);
1150+
};
1151+
put_request.onsuccess = {
1152+
console.log(`put succeeded`);
1153+
// No more requests are made, so the transaction will autocommit.
1154+
};
1155+
};
1156+
1157+
transaction.onabort = e => {
1158+
console.warn(`transaction aborted: ${transaction.error}`);
1159+
};
1160+
1161+
transaction.oncomplete = e => {
1162+
console.log(`transaction committed`);
1163+
};
1164+
```
1165+
</aside>
1166+
1167+
<aside class=example id=example-transaction-manualcommit>
1168+
1169+
The following example uses requests within a transaction to atomically
1170+
update a record's value using an asynchronous network fetch. A manually
1171+
committing transaction is necessary.
1172+
1173+
```js
1174+
const transaction = connection.transaction(
1175+
'my_records, 'readwrite', {manualCommit: true});
1176+
1177+
const store = transaction.objectStore('my_records);
1178+
store.get('key').onsuccess = async e => {
1179+
try {
1180+
const record = e.target.result;
1181+
1182+
// Make an asynchronous network request. If the transaction
1183+
// was not set to manual commit, it would autocommit here
1184+
// because there were no outstanding requests.
1185+
const response = await fetch(record.url);
1186+
1187+
// Update the record.
1188+
record.status = response.status;
1189+
store.put(record, 'key');
1190+
1191+
// Commit the transaction, once the request has completed.
1192+
// If the request fails, the transaction will abort instead.
1193+
transaction.commit();
1194+
} catch (ex) {
1195+
// If the fetch() fails, abort the transaction.
1196+
transaction.abort();
1197+
}
1198+
});
1199+
```
1200+
</aside>
1201+
1202+
11271203
<!-- ============================================================ -->
11281204
### Transaction scheduling ### {#transaction-scheduling}
11291205
<!-- ============================================================ -->
@@ -2435,6 +2511,7 @@ interface IDBDatabase : EventTarget {
24352511
enum IDBTransactionDurability { "default", "strict", "relaxed" };
24362512

24372513
dictionary IDBTransactionOptions {
2514+
boolean manualCommit = false;
24382515
IDBTransactionDurability durability = "default";
24392516
};
24402517

@@ -2624,9 +2701,13 @@ instance on which it was called.
26242701
Returns a new [=/transaction=] with the given
26252702
|scope| (which can be a single [=/object store=] [=object-store/name=] or an array of [=object-store/names=]),
26262703
|mode| ({{"readonly"}} or {{"readwrite"}}),
2627-
and additional |options| including {{IDBTransactionOptions/durability}} ({{"default"}}, {{"strict"}} or {{"relaxed"}}).
2704+
and additional |options| including
2705+
{{IDBTransactionOptions/manualCommit}} (true or false), and
2706+
{{IDBTransactionOptions/durability}} ({{"default"}}, {{"strict"}} or {{"relaxed"}}).
26282707

2629-
The default |mode| is {{"readonly"}} and the default {{IDBTransactionOptions/durability}} is {{"default"}}.
2708+
The default |mode| is {{"readonly"}}.
2709+
The default {{IDBTransactionOptions/manualCommit}} is false.
2710+
The default {{IDBTransactionOptions/durability}} is {{"default"}}.
26302711

26312712
: |connection| . {{IDBDatabase/close()|close}}()
26322713
::
@@ -2657,7 +2738,11 @@ The <dfn method for=IDBDatabase>transaction(|storeNames|, |mode|, |options|)</df
26572738
1. If |mode| is not {{"readonly"}} or {{"readwrite"}},
26582739
[=throw=] a [=TypeError=].
26592740

2660-
1. Let |transaction| be a newly [=transaction/created=] [=/transaction=] with |connection|, |mode|, |options|' {{IDBTransactionOptions/durability}} member, and the set of [=/object stores=] named in |scope|.
2741+
1. Let |transaction| be a newly [=transaction/created=] [=/transaction=] with |connection|, |mode|, and the set of [=/object stores=] named in |scope|.
2742+
2743+
1. Set |transaction|'s [=transaction/manual commit flag=] to |options|' {{IDBTransactionOptions/manualCommit}} member.
2744+
2745+
1. Set |transaction|'s [=transaction/durability hint=] to |options|' {{IDBTransactionOptions/durability}} member.
26612746

26622747
1. Set |transaction|'s [=transaction/cleanup event loop=] to the
26632748
current [=/event loop=].
@@ -2666,6 +2751,12 @@ The <dfn method for=IDBDatabase>transaction(|storeNames|, |mode|, |options|)</df
26662751

26672752
</div>
26682753

2754+
<aside class=advisement>
2755+
&#x1F6A7;
2756+
The {{IDBTransactionOptions/manualCommit}} option is new in this edition.
2757+
&#x1F6A7;
2758+
</aside>
2759+
26692760
<aside class=advisement>
26702761
&#x1F6A7;
26712762
The {{IDBTransactionOptions/durability}} option is new in this edition.
@@ -4732,6 +4823,7 @@ the contents of the database.
47324823
interface IDBTransaction : EventTarget {
47334824
readonly attribute DOMStringList objectStoreNames;
47344825
readonly attribute IDBTransactionMode mode;
4826+
readonly attribute boolean manualCommit;
47354827
readonly attribute IDBTransactionDurability durability;
47364828
[SameObject] readonly attribute IDBDatabase db;
47374829
readonly attribute DOMException? error;
@@ -4766,6 +4858,10 @@ enum IDBTransactionMode {
47664858
({{"readonly"}} or {{"readwrite"}}), or {{"versionchange"}} for
47674859
an [=/upgrade transaction=].
47684860

4861+
: |transaction| . {{IDBTransaction/manualCommit}}
4862+
::
4863+
Returns true if the transaction was created with {{IDBTransactionOptions/manualCommit}}: `true` and false otherwise.
4864+
47694865
: |transaction| . {{IDBTransaction/durability}}
47704866
::
47714867
Returns the [=transaction/durability hint=] the transaction was created with
@@ -4806,6 +4902,14 @@ The <dfn attribute for=IDBTransaction>objectStoreNames</dfn> getter steps are:
48064902
The <dfn attribute for=IDBTransaction>mode</dfn> getter steps are to
48074903
return [=/this=]'s [=transaction/mode=].
48084904

4905+
The <dfn attribute for=IDBTransaction>manualCommit</dfn> attribute's getter must return [=/this=]'s [=transaction/manual commit flag=].
4906+
4907+
<aside class=advisement>
4908+
&#x1F6A7;
4909+
The {{IDBTransaction/manualCommit}} attribute is new in this edition.
4910+
&#x1F6A7;
4911+
</aside>
4912+
48094913
The <dfn attribute for=IDBTransaction>durability</dfn> getter steps are to return [=/this=]'s [=transaction/durability hint=].
48104914

48114915
<aside class=advisement>
@@ -4815,7 +4919,6 @@ The <dfn attribute for=IDBTransaction>durability</dfn> getter steps are to retur
48154919
&#x1F6A7;
48164920
</aside>
48174921

4818-
48194922
The <dfn attribute for=IDBTransaction>db</dfn> getter steps are to
48204923
return [=/this=]'s [=transaction/connection=]'s associated [=/database=].
48214924

@@ -4853,6 +4956,9 @@ none.
48534956
transaction to quickly finish, without waiting for pending requests to fire
48544957
<a event>`success`</a> events before attempting to commit normally.
48554958

4959+
If the transaction was created with `manualCommit: true` then this method
4960+
<span class=allow-2119>must</span> be called to commit the transaction.
4961+
48564962
The transaction will abort if a pending request fails, for example due to a
48574963
constraint error. The <a event>`success`</a> events for successful requests
48584964
will still fire, but throwing an exception in an event handler will not abort
@@ -4908,7 +5014,8 @@ The <dfn method for=IDBTransaction>abort()</dfn> method steps are:
49085014

49095015
The <dfn method for=IDBTransaction>commit()</dfn> method steps are:
49105016

4911-
1. If [=/this=]'s [=transaction/state=] is not [=transaction/active=],
5017+
1. If [=/this=]'s [=transaction/manual commit flag=] is false,
5018+
and [=/this=]'s [=transaction/state=] is not [=transaction/active=],
49125019
then [=throw=] an "{{InvalidStateError}}" {{DOMException}}.
49135020

49145021
1. Run [=commit a transaction=] with [=/this=].
@@ -5169,7 +5276,7 @@ To <dfn>commit a transaction</dfn> with the |transaction| to commit, run these s
51695276
<aside class=note>
51705277
Even if an exception is thrown from one of the event handlers of
51715278
this event, the transaction is still committed since writing the
5172-
database changes happens before the event takes places. Only
5279+
database changes happens before the event takes place. Only
51735280
after the transaction has been successfully written is the
51745281
<a event>`complete`</a> event fired.
51755282
</aside>
@@ -5499,14 +5606,14 @@ To <dfn>fire a success event</dfn> at a |request|, run these steps:
54995606
1. If |transaction|'s [=transaction/state=] is [=transaction/active=],
55005607
then:
55015608

5502-
1. Set |transaction|'s [=transaction/state=] to [=transaction/inactive=].
5609+
1. If |transaction|'s [=transaction/manual commit flag=] is false, then set |transaction|'s [=transaction/state=] to [=transaction/inactive=].
55035610

55045611
1. If |legacyOutputDidListenersThrowFlag| is true,
55055612
then run [=abort a transaction=] with
55065613
|transaction| and a newly <a for=exception>created</a>
55075614
"{{AbortError}}" {{DOMException}}.
55085615

5509-
1. If |transaction|'s [=transaction/request list=] is empty,
5616+
1. If |transaction|'s [=transaction/manual commit flag=] is false and if |transaction|'s [=transaction/request list=] is empty,
55105617
then run [=commit a transaction=] with |transaction|.
55115618

55125619
</div>
@@ -5538,7 +5645,7 @@ To <dfn>fire an error event</dfn> at a |request|, run these steps:
55385645
1. If |transaction|'s [=transaction/state=] is [=transaction/active=],
55395646
then:
55405647

5541-
1. Set |transaction|'s [=transaction/state=] to [=transaction/inactive=].
5648+
1. If |transaction|'s [=transaction/manual commit flag=] is false, then set |transaction|'s [=transaction/state=] to [=transaction/inactive=].
55425649

55435650
1. If |legacyOutputDidListenersThrowFlag| is true,
55445651
then run [=abort a transaction=] with
@@ -5559,7 +5666,7 @@ To <dfn>fire an error event</dfn> at a |request|, run these steps:
55595666
|transaction| and [=/request=]'s [=request/error=], and
55605667
terminate these steps.
55615668

5562-
1. If |transaction|'s [=transaction/request list=] is empty,
5669+
1. If |transaction|'s [=transaction/manual commit flag=] is false and |transaction|'s [=transaction/request list=] is empty,
55635670
then run [=commit a transaction=] with |transaction|.
55645671

55655672
</div>
@@ -6777,6 +6884,7 @@ For the revision history of the second edition, see [that document's Revision Hi
67776884
* Transactions are now temporarily made inactive during clone operations.
67786885
* Added {{IDBTransactionOptions/durability}} option and {{IDBTransaction/durability}} attribute. ([Issue #50](https://github.com/w3c/IndexedDB/issues/50))
67796886
* Specified [[#transaction-scheduling]] more precisely and disallow starting read/write transactions while read-only transactions with overlapping scope are running. ([Issue #253](https://github.com/w3c/IndexedDB/issues/253))
6887+
* Specified [=transaction/manual commit flag=], {{IDBTransactionOptions/manualCommit}} option and {{IDBTransaction/manualCommit}} attribute. ([Issue #34](https://github.com/w3c/IndexedDB/issues/34))
67806888

67816889
<!-- ============================================================ -->
67826890
# Acknowledgements # {#acknowledgements}

0 commit comments

Comments
 (0)