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);