Cache Pattern for Offline Web Applications

Similar documents
Beyond Cookies: Persistent Storage for Web Applications. Brad Neuberg Google

Copyright is owned by the Author of the thesis. Permission is given for a copy to be downloaded by an individual for the purpose of research and

IT Best Practices Audit TCS offers a wide range of IT Best Practices Audit content covering 15 subjects and over 2200 topics, including:

Using HTML5 Offline Storage. Brady Eidson Safari and WebKit Engineer

Creating a Client-Side Search Engine with Gears. Brad Neuberg, Gears

Asynchronous JavaScript + XML (Ajax)

Introduction to Gears. Brad Neuberg Google

Performance Case Study

Creating a Client-Side Search Engine with Gears and Dojo. Brad Neuberg, Google

AJAX for Mobile Devices

Web Application with AJAX. Kateb, Faris; Ahmed, Mohammed; Alzahrani, Omar. University of Colorado, Colorado Springs

MongoDB Web Architecture

Tableau Server - 101

Web application Architecture

Web Programming Step by Step

<Insert Picture Here> RDBMS-based Coverage Collection and Analysis

Active Endpoints. ActiveVOS Platform Architecture Active Endpoints

Designing dashboards for performance. Reference deck

Comet and WebSocket Web Applications How to Scale Server-Side Event-Driven Scenarios

Building Offline Mobile Apps with Oracle JET and MCS

Controller/server communication

A Library and Proxy for SPDY

Project Zygote. Rapid prototyping for the Internet of Things

Module 6 Node.js and Socket.IO

0.9: Faster, Leaner and Dijit? July 25, 2007 Dylan Schiemann. presented by

! The final is at 10:30 am, Sat 6/4, in this room. ! Open book, open notes. ! No electronic devices. ! No food. ! Assignment 7 due 10pm tomorrow

NODE.JS MOCK TEST NODE.JS MOCK TEST I

Sample Kentico Website Audit

Distributed Systems. Lec 10: Distributed File Systems GFS. Slide acks: Sanjay Ghemawat, Howard Gobioff, and Shun-Tak Leung

Build Native-like Experiences in HTML5

Ajax- XMLHttpResponse. Returns a value such as ArrayBuffer, Blob, Document, JavaScript object, or a DOMString, based on the value of

Determining the Best Approach

MySQL & NoSQL: The Best of Both Worlds

GFS Overview. Design goals/priorities Design for big-data workloads Huge files, mostly appends, concurrency, huge bandwidth Design for failures

Asynchronous Method Calls White Paper VERSION Copyright 2014 Jade Software Corporation Limited. All rights reserved.

HTML 5: Fact and Fiction Nathaniel T. Schutta

Using GWT and Eclipse to Build Great Mobile Web Apps

Cross-compiling C++ to JavaScript. Challenges in porting the join.me common library to HTML5

Web Application Development Using Spring, Hibernate and JPA

Investigating Source Code Reusability for Android and Blackberry Applications

Controller/server communication

Questions answered in this lecture: CS 537 Lecture 19 Threads and Cooperation. What s in a process? Organizing a Process

Kaazing Gateway: An Open Source

10/18/2017. Announcements. NoSQL Motivation. NoSQL. Serverless Architecture. What is the Problem? Database Systems CSE 414

Cloud Programming on Java EE Platforms. mgr inż. Piotr Nowak

Building mobile app using Cordova and AngularJS, common practices. Goran Kopevski

Java vs JavaScript. For Enterprise Web Applications. Chris Bailey IBM Runtime Technologies IBM Corporation

Jquery.ajax Call Returns Status Code Of 200 But Fires Jquery Error

A demo Wakanda solution (containing a project) is provided with each chapter. To run a demo:

CS 498RK FALL RESTFUL APIs

JS Event Loop, Promises, Async Await etc. Slava Kim

Real-Time SignalR. Overview

Copyright 2012, Oracle and/or its affiliates. All rights reserved.

JKO Content Development Kit

Time Series Live 2017

Replication features of 2011

Lab 3: Using Worklight Server and Environment Optimization Lab Exercise

Manjunath Subburathinam Sterling L2 Apps Support 11 Feb Lessons Learned. Peak Season IBM Corporation

5 System architecture

Web Application Development Using Spring, Hibernate and JPA

Building Native Mapping Apps with PhoneGap: Advanced Techniques Andy

Why Discuss JavaScript? CS312: Programming Languages. Lecture 21: JavaScript. JavaScript Target. What s a Scripting Language?

NODE.JS SERVER SIDE JAVASCRIPT. Introduc)on Node.js

FREQUENTLY ASKED QUESTIONS ABOUT CLASS LOGISTICS AND TELECONFERENCE TECHNOLOGY

SALESFORCE DMP SUPERTAG USER GUIDE 00. SuperTag User Guide VER. 2, UPDATED 1/16. Rights Reserved, Proprietary &

OFFLINE MODE OF ANDROID

Web Application Development Using Spring, Hibernate and JPA

Contents Getting Started... 3 About Scribe Online and Connectors... 3 Scribe Online Services... 3 CDK Components... 3 Audience... 4 Prerequisites...

CS312: Programming Languages. Lecture 21: JavaScript

Scaling Without Sharding. Baron Schwartz Percona Inc Surge 2010

,

Simple AngularJS thanks to Best Practices

Architecting C++ apps

CHAPTER 3 - PROCESS CONCEPT

2015 NALIT Professional Development Seminar September 30, Tools for Mobile App Development

Raima Database Manager Version 14.1 In-memory Database Engine

Protocol Buffers, grpc

(Partition Map) Exchange - under the hood

STARCOUNTER. Technical Overview

MarkLogic Server. Database Replication Guide. MarkLogic 6 September, Copyright 2012 MarkLogic Corporation. All rights reserved.

Programming for Digital Media. Lecture 7 JavaScript By: A. Mousavi and P. Broomhead SERG, School of Engineering Design, Brunel University, UK

Putting together the platform: Riak, Redis, Solr and Spark. Bryan Hunt

System Workers. 1 of 11

SystemWorker.exec( )

Implementing Oath s CMP JS

MillWheel:Fault Tolerant Stream Processing at Internet Scale. By FAN Junbo

CS371m - Mobile Computing. Persistence - Web Based Storage CHECK OUT g/sync-adapters/index.

Custom Embedded Tabs, on page 1 Configure Cisco Jabber for Android on Chromebook, on page 8 Cisco Jabber Mobile App Promotion, on page 9

CSE506: Operating Systems CSE 506: Operating Systems

DESIGN TRANSFORMATIONAL IPAD APPS

Guide to Business Continuity Preparedness

Use Page Speed to Optimize Your Web Site for Mobile

SOASTA (mpulse )

Support Offline Mobile Web Apps with HTML5 API's

Distributed File Systems II

RESTful APIs ECS 189 WEB PROGRAMMING. Browser s view. Browser s view. Browser s view. Browser s view. Which will It be for photobooth?

Using Web Workers to Improve the Performance of Metro HTML5- JavaScript* Apps

Manual Trigger Sql Server 2008 Examples Insert Update

This tutorial is intended to make you comfortable in getting started with the Firebase backend platform and its various functions.

Your Speakers. Iwan e1 Rahabok Linkedin.com/in/e1ang

Transcription:

Cache Pattern for Offline Web Applications Robert Kroeger June 27, 2009 Post your questions for this talk on Google Moderator: code.google.com/events/io/questions

Why Mobile Web Applications? Pro: server-side features that cannot be accommodated in a mobile device Mobile devices have limited storage Mobile devices have limited CPU Pro: ease of distribution No app store approval process Launch on your schedule Update frequently But: use of wireless connections can make this much too slow 3

The Connection Problem EDGE/3G Internet Server High latency Flaky Connection 4

Caching Keeps Mobile Web Apps Responsive No Synchronous Connection From Web UI to Server Mobile Device Web application UI Internet Server Update UI Mobile Device Update Cache Web application UI Devicelocal Cache Internet Server 5 Modify Cache Push To Server

Implementing Cache Pattern Storing the data Cached Content to UI Cache Changes from server Changes from UI Browser platform DB Updates bound for Server 6

Cache Storage: Structured Storage Structured storage capability in HTML5 and Gears A SQL database Local to the client Can access in absence of network connection Keep the cached contents here Persistent across browser restarts ACID properties maintain consistent database state 7

The Asynchronous Programming Model Structured Storage: Gears!= HTML5 Gears JavaScript Thread Function call database action Return HTML5 JavaScript Thread SQL Execution Thread database action Function call Other JavaScript Function call (back) 8

Portability? Gears vs HTML5 Structured Storage SQL database Synchronous Programming model Asynchronous programming model Android Platform iphone HTML5 Structured Storage Google Gears Database 9

Web Storage Portability Layer (WSPL) One API For Gears and HTML5 Statement HTML5 Structured Storage Common API Results Transactions Google Gears Asynchronous worker Code to one common API Asynchronous programming model Gears worker implements the asynchronous programming model above synchronous database Available at code.google.com/ webstorageportabilitylayer 10

Build Portable Cache above WSPL Cached Content to UI Cache Changes from server Changes from UI Browser platform WSPL API DB Updates bound for Server Asynchronous interface 11

Asynchronous Cache Architecture Request Cached Content: getvalues Cached Content to UI: valuecallback Acknowledge UI Change: ackcallback Changes from UI Action: applyuichange Get Apply Changes Cache Server Merge Ack Changes execute callback Server response: ackchange Server response: insertupdate Updates bound for Server: sendxhrpost Queries bound for Server: sendxhrpost WSPL API 12

SimpleNotes A Concrete Example of the Cache Pattern Toy application keep notes server side left as audience exercise Demonstrates use of the WSPL library Included with WSPL Three different pages in the application List Notes Page Time Time Subject... Subject New Click Back View Note Subject Note content Save Edit Edit Note Subject Note content 13

Key Cache Design Aspects Hit Determination: what data is cached? A contiguous range of notes Refresh: when to update the cached data with server changes? Every request for a list of notes Eviction: what to discard to make room for new data Coherency: how to merge server changes into cache Always send updates ahead of queries Reapply actions for unacknowledged updates 14

Simple Notes Tables google.wspl.simplenotes.cache.create_cached_notes_ = new google.wspl.statement( 'CREATE TABLE IF NOT EXISTS cached_notes (' + 'notekey INTEGER UNIQUE PRIMARY KEY,' + 'subject TEXT,' + 'body TEXT' + ');' ); Separate write buffer: actions vs state google.wspl.simplenotes.cache.create_write_buffer_ = new google.wspl.statement( 'CREATE TABLE IF NOT EXISTS write_buffer (' + 'sequence INTEGER UNIQUE PRIMARY KEY AUTOINCREMENT,' + 'notekey INTEGER,' + 'status INTEGER,' + 'subject TEXT,' + 'body TEXT' + ');' ); google.wspl.simplenotes.cache.determine_min_key_ = new google.wspl.statement( 'SELECT MIN(noteKey) as minnotekey FROM cached_notes;'); google.wspl.simplenotes.cache.determine_max_key_ = new google.wspl.statement( 'SELECT MAX(noteKey) as maxnotekey FROM cached_notes;'); 15

Simple Notes Creation google.wspl.simplenotes.cache.prototype.startcache = function(callback) { var statc = 0; var self = this; var perstatcallback = function(tx, result) { google.logger('perstatcallback'); if (statc == 4) { self.start_ = (result.isvalidrow())? result.getrow().minnotekey : -1; self.serverstart_ = self.start_; // Temporary. Remove when server exists. } else if (statc == 5) { self.end_ = (result.isvalidrow())? result.getrow().maxnotekey : -1; self.serverend_ = self.end_; // Temporary. Remove when server exists. } statc++; }; this.dbms_.executeall([ google.wspl.simplenotes.cache.create_cached_notes_, google.wspl.simplenotes.cache.create_write_buffer_, google.wspl.simplenotes.cache.create_update_trigger_, google.wspl.simplenotes.cache.create_replay_trigger_, google.wspl.simplenotes.cache.determine_min_key_, google.wspl.simplenotes.cache.determine_max_key_], {onsuccess: perstatcallback, onfailure: this.logerror_}, {onsuccess: callback, onfailure: this.logerror_}); google.logger('finished startcache'); }; Asynchronous here too 16

getvalues Hit Call Flow Request Cached Content: getvalues Cached Content to UI: valuecallback Acknowledge UI Change: ackcallback Changes from UI Action: applyuichange createtransaction Get Apply Changes Cache Server Merge Ack Changes execute intransactiongetnotes execute callback accumulateresults Server response: ackchange Server response: insertupdate Updates bound for Server: sendxhrpost Queries bound for Server: sendxhrpost WSPL API 17

getvalues Example Code (1) google.wspl.simplenotes.cache.prototype.getvalues = function(type, query, valuescallback) { // Reduce any query to what would be available from the server query[0] = Math.max(this.serverStart_, query[0]); query[1] = Math.min(this.serverEnd_, query[1]); if (type == 'list') { this.getnotelist_(query[0], query[1], valuescallback); } else if (type == 'fullnote') { this.getonenote_(query[0], valuescallback); } }; Same idea as getnotelist_ 18

getvalues Example Code (2) google.wspl.simplenotes.cache.prototype.getnotelist_ = function(start, end, valuescallback) { var notes = []; var accumulateresults = function(tx, result) { for(; result.isvalidrow(); result.next()) { notes.push(result.getrow()); } }; var intransactiongetnotes = function(tx) { tx.execute(google.wspl.simplenotes.cache.list_cached_notes_. createstatement([start, end]), { onsuccess: accumulateresults, onfailure: this.logerror_}); }; Need a cache membership scheme var hit = this.iscachehit_(start, end); this.dbms_.createtransaction(intransactiongetnotes, {onsuccess: function() { valuescallback(notes, hit); }, onfailure: this.logerror_}); if (hit) { this.fetchfromserver(this.start_, this.end_); // Refresh } else { this.fetchfromserver(math.min(this.start_, start), Math.max(this.end_, end)); this.lastmiss_ = {callback: valuescallback, start: start, end: end}; } }; In transaction getnotelist intransactiongetnotes accumulateresults valuescallback 19

Hitting and Missing iscachehit Application Specific Simple approach here: cache contains a contiguous range of notes. google.wspl.simplenotes.cache.prototype.iscachehit_ = function(start, end) { return start >= this.start_ && end <= this.end_; }; Cache maintains the start and end values in JavaScript Cache grows its range by making a server request for the missing values. Avoid database accesses 20

applyuichange Call Flow Request Cached Content: getvalues Cached Content to UI: valuecallback Acknowledge UI Change: ackcallback Changes from UI Action: applyuichange executeall Get Apply Changes Cache ackcallback Server Merge Ack Changes execute callback Server response: ackchange Server response: insertupdate Updates bound for Server: sendxhrpost Queries bound for Server: sendxhrpost Update via a trigger WSPL API updatetrigger 21

applyuichange Code google.wspl.simplenotes.cache.insert_ui_update_ = new google.wpsl.statement( 'INSERT INTO write_buffer (' + 'notekey, status, subject, body )' + 'VALUES(?,?,?,?);'); google.wspl.simplenotes.cache.prototype.applyuichange = function(notekey, subject, body, ackcallback) { var self = this; var update = [notekey, 2 8, subject, body]; var stat = google.wspl.simplenotes.cache.insert_ui_update_.createstatement( update); this.dbms_.execute(stat, null, {onsuccess: function() { ackcallback(notekey); }, onfailure: function (error) { self.logerror_(error); ackcallback(-1); }}); }; 22

Why Triggers: Avoid Ping-Ponging Long Transactions Are Bad JavaScript Thread SQL Execution Thread onclick txget In transaction select txmodify update end of tx Read-modifiy-write operations are inefficient A trigger runs entirely inside SQL thread JavaScript Thread SQL Execution Thread onclick In transaction txmodify trigger update end of tx 23

applyuichange Trigger Code google.wspl.simplenotes.cache.create_update_trigger_ = new google.wspl.statement( 'CREATE TRIGGER IF NOT EXISTS updatetrigger ' + 'AFTER INSERT ON write_buffer ' + 'BEGIN ' + ' REPLACE INTO cached_notes ' + ' SELECT notekey, subject, body ' + ' FROM write_buffer WHERE status & 8 = 8; ' + ' UPDATE write_buffer SET status = status & ~ 8; ' + 'END;' ); status: a bit-field of states 1 The update is inflight to the server 2 The update needs to be (re)sent to the server 8 The update needs to replayed against the cache Update cache from write_buffer Trigger is only way to execute several statements 24

insertupdate Call Flow Request Cached Content: getvalues Cached Content to UI: valuecallback Acknowledge UI Change: ackcallback Changes from UI Action: applyuichange Callback if servicing a cache miss Get Apply Changes createtransaction Cache callback execute Server Merge Ack Changes intrans executeall afterinsert Server response: ackchange Server response: insertupdate Updates bound for Server: sendxhrpost Queries bound for Server: sendxhrpost Coherency: replay actions WSPL API replaytrigger 25

insertupdate Code google.wspl.simplenotes.cache.prototype.insertupdate = function(notes) { var self = this; var stats = []; var start = notes[0].notekey; var end = notes[0].notekey; for (var i = 0; i < notes.length; i++) { stats.push(google.wspl.simplenotes.cache.insert_note_. createstatement([notes[i].notekey, notes[i].subject, notes[i].body])); start = Math.min(start, notes[0].notekey); end = Math.max(end, notes[0].notekey); } stats.push(google.wspl.simplenotes.cache.evict_.createstatement([start, end])); stats.push(google.wspl.simplenotes.cache.force_replay_); var intrans = function(tx) { self.start_ = start; self.end_ = end; tx.executeall(stats); }; Must update here to align JS change with transaction boundary var afterinsert = function(tx) { if (this.lastmiss_ && this.iscachehit_(this.lastmiss_.start, this.lastmiss_.end)) { this.lastmiss_.callback(notes); this.lastmiss_ = undefined; } }; this.dbms_.createtransaction(intrans, {onsuccess: afterinsert, onerror: this.logerror_}); }; Callback if this update from the server satisfies a pending request 26

fetchfromserver Call Flow Handling Cache Misses and Refresh Request Cache-miss Content: getvalues Cached Content to UI: valuecallback Acknowledge UI Change: ackcallback Changes from UI Action: applyuichange executeall Get Apply Changes Cache accumulateupdates Server Merge Ack Changes ackandpost execute callback Server response: ackchange Server response: insertupdate Updates bound for Server: sendxhrpost Queries bound for Server: sendxhrpost WSPL API 27

fetchfromserver Code google.wspl.simplenotes.cache.prototype.fetchfromserver = function(start, end) { var now = this.dbms_.getcurrenttime(); if (start >= this.start_ && end <= this.end_ && now - this.lastrefresh_ < google.wspl.simplenotes.cache.time_between_refresh_) { return; } var updates = []; var self = this; var flag = 1; var sql = []; sql.push(google.wspl.simplenotes.cache.get_updates_to_resend_); sql.push(google.wspl.simplenotes.cache.mark_as_inflight_); var accumulateupdates = function(tx, rs) { if (flag == 1) { for(; rs.isvalidrow(); rs.next()) { updates.push(['u', rs.getrow()]); } flag++; } }; var ackandpost = function() { updates.push(['q', {start: start, end: end}]); self.sendxhrpost(updates); }; this.dbms_.executeall(sql, {onsuccess: accumulateupdates, onfailure: this.logerror_}, {onsuccess: ackandpost, onfailure: this.logerror_}); }; 28

Maintaining Server Consistency Resend failures before queries, then reapply actions Time! 1 Q In Flight 1 2 Q ackchange Write Buffer sendxhrpost ackchange 1 1 1 2 2 3 3 1 1 2 fetchfromserver applyuichange fetchfromserver applyuichange insertupdate 29

Miscellaneous Tidbits Messages to server JSON-encoded via XHR POST See the WSPL open source distribution for the remaining missing bits Asynchronous model decouples the execution order from the display order Triggers crucial to rapid development SimpleNotes glosses over some hard problems: Database too slow to serve as application model Too much data traffic 30

Summary Cache pattern workable in real products: Mobile Gmail for iphone and Android. WSDL library same Workable local storage solution across iphone and Android 31

Q & A Post your questions for this talk on Google Moderator: code.google.com/events/io/questions