1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 // This file simulates a typical background process of an offline-capable
6 // authoring application. When in an "online" state it receives chunks of
7 // data updates from a simulated server and stores them in a temporary IDB
8 // data store. On a different timer, the chunks are drained from the
9 // temporary store and combined into larger records in a permanent store.
10 // When in an "offline" state, nothing else happens.
12 function unexpectedErrorCallback(e
) {
13 self
.postMessage({type
: 'ERROR', error
: {
14 name
: e
.target
.error
.name
,
15 message
: e
.target
.error
.message
19 function unexpectedAbortCallback(e
) {
20 self
.postMessage({type
: 'ABORT', error
: {
21 name
: e
.target
.error
.name
,
22 message
: e
.target
.error
.message
26 function log(message
) {
27 self
.postMessage({type
: 'LOG', message
: message
});
30 function error(message
) {
31 self
.postMessage({type
: 'ERROR', message
: message
});
34 var DBNAME
= 'endurance-db';
38 var MAX_CHUNK_ID
= 10;
39 var MAX_CHUNK_SIZE
= 5 * 1024;
40 var SYNC_TIMEOUT
= 100;
41 var COMBINE_TIMEOUT
= 234; // relatively prime with SYNC_TIMEOUT
43 function randomString(len
)
47 s
+= Math
.floor((Math
.random() * 36)).toString(36);
57 var doc_id
= nextDocID
;
58 var chunk_id
= nextChunkID
;
61 if (nextDocID
>= MAX_DOC_ID
) {
64 if (nextChunkID
>= MAX_CHUNK_ID
)
71 timestamp
: new Date(),
72 data
: randomString(MAX_CHUNK_SIZE
)
79 self
.onmessage = function (event
) {
80 switch (event
.data
.type
) {
88 throw new Error("Unexpected message: " + event
.data
.type
);
94 var syncTimeoutId
= 0;
95 var combineTimeoutId
= 0;
97 function goOffline() {
102 clearTimeout(syncTimeoutId
);
104 clearTimeout(combineTimeoutId
);
105 combineTimeoutId
= 0;
108 function goOnline() {
113 syncTimeoutId
= setTimeout(sync
, SYNC_TIMEOUT
);
114 combineTimeoutId
= setTimeout(combine
, COMBINE_TIMEOUT
);
115 // NOTE: Not using setInterval as we need to be sure they complete.
123 var sync_id
= ++sync_count
;
124 log('sync ' + sync_id
+ ' started');
126 var chunk
= getNextChunk();
127 log('sync ' + sync_id
+
128 ' adding chunk: ' + chunk
.chunkid
+
129 ' to doc: ' + chunk
.docid
);
131 var request
= indexedDB
.open(DBNAME
);
132 request
.onerror
= unexpectedErrorCallback
;
133 request
.onsuccess = function () {
134 var db
= request
.result
;
135 if (db
.version
!== DBVERSION
) {
136 error('DB version incorrect');
140 var transaction
= db
.transaction('sync-chunks', 'readwrite');
141 var store
= transaction
.objectStore('sync-chunks');
142 request
= store
.put(chunk
);
143 transaction
.onabort
= unexpectedAbortCallback
;
144 transaction
.oncomplete = function () {
145 log('sync ' + sync_id
+ ' finished');
147 syncTimeoutId
= setTimeout(sync
, SYNC_TIMEOUT
);
152 var combine_count
= 0;
157 var combine_id
= ++combine_count
;
158 log('combine ' + combine_id
+ ' started');
160 var combine_chunk_count
= 0;
162 var request
= indexedDB
.open(DBNAME
);
163 request
.onerror
= unexpectedErrorCallback
;
164 request
.onsuccess = function () {
165 var db
= request
.result
;
166 if (db
.version
!== DBVERSION
) {
167 error('DB version incorrect');
171 var transaction
= db
.transaction(['sync-chunks', 'docs'], 'readwrite');
172 var syncStore
= transaction
.objectStore('sync-chunks');
173 var docStore
= transaction
.objectStore('docs');
175 var cursorRequest
= syncStore
.openCursor();
176 cursorRequest
.onerror
= unexpectedErrorCallback
;
177 cursorRequest
.onsuccess = function () {
178 var cursor
= cursorRequest
.result
;
180 combine_chunk_count
+= 1;
181 log('combine ' + combine_id
+
182 ' processing chunk # ' + combine_chunk_count
);
184 var key
= cursor
.key
;
185 var chunk
= cursor
.value
;
186 var docRequest
= docStore
.get(chunk
.docid
);
187 docRequest
.onerror
= unexpectedErrorCallback
;
188 docRequest
.onsuccess = function () {
189 var doc
= docRequest
.result
;
195 log('combine # ' + combine_id
+
196 ' created doc: ' + doc
.docid
);
199 log('combine # ' + combine_id
+
200 ' updating doc: ' + doc
.docid
+
201 ' chunk: ' + chunk
.chunkid
);
203 doc
.chunks
[chunk
.chunkid
] = chunk
;
204 doc
.timestamp
= new Date();
205 request
= docStore
.put(doc
);
206 request
.onerror
= unexpectedErrorCallback
;
211 // let transaction complete
212 log('combine ' + combine_id
+
213 ' done, processed ' + combine_chunk_count
+ ' chunks');
216 transaction
.onabort
= unexpectedAbortCallback
;
217 transaction
.oncomplete = function () {
218 log('combine ' + combine_id
+
219 ' finished, processed ' + combine_chunk_count
+ ' chunks');
221 combineTimeoutId
= setTimeout(combine
, COMBINE_TIMEOUT
);