Transcript
Page 1: Zach Pinter - Caching and Synchronization with Flex

Caching and Synchronization in Flex

1

Zachary PinterSenior DeveloperEffectiveUI360Flex

Page 2: Zach Pinter - Caching and Synchronization with Flex

The ProblemCommon application data shown in multiple views, being manipulated by multiple users at roughly the same time.

2

Page 3: Zach Pinter - Caching and Synchronization with Flex

GoalsFetch entities only once and only as needed.

One definitive instance of a server-side entity.

Update all relevant views when the server sends notice that an entity has changed.

Server-side agnostic.

3

Page 4: Zach Pinter - Caching and Synchronization with Flex

What’s the strategy?Store all fetched entities in a single cache (Dictionary).

Bind the views to the cache.

4

Page 5: Zach Pinter - Caching and Synchronization with Flex

What about memory use?

5

public class WeakReference{ private var dic:Dictionary; public function WeakReference(obj:*) { dic = new Dictionary(true); dic[obj] = 1; } public function getValue():* { for (var item:* in dic) { return item; } return null; }

}

Text

Allows cache values to be garbage-collected if they’re not being referenced anywhere else.

Page 6: Zach Pinter - Caching and Synchronization with Flex

The CacheHow do we add an entity to the cache?

6

public class EntityCache{ public function updateEntity(entity:BaseVO, ...):BaseVO { //... }}

Page 7: Zach Pinter - Caching and Synchronization with Flex

Recurse through properties

UserVO id: 1 firstname: “Zachary” lastname: “Pinter” address: AddressVO id: 2 line1: “4444 W 44th Ave” city: “Denver” state: “CO”

7

EntityCache 1: UserVO 2: AddressVO

Adding a user to the cache also adds its address.

Page 8: Zach Pinter - Caching and Synchronization with Flex

Recurse through properties

UserVO id: 1 firstname: “Zachary” lastname: “Pinter” addresses: [ AddressVO id: 2 label: “home” line1: “4444 W 44th Ave” city: “Denver” state: “CO” AddressVO id: 3 label: “work” line1: “5555 W 55th Ave” city: “Denver” state: “CO”]

8

EntityCache 1: UserVO 2: AddressVO 3: AddressVO

Arrays behave the same way

Page 9: Zach Pinter - Caching and Synchronization with Flex

Finding an object’s propertiesSpring Actionscript (formally Prana)

http://www.pranaframework.org/

9

var type:Type = Type.forName(classname); for each (var accessor:Accessor in type.accessors) { if (accessor.isStatic == false && accessor.access.name == "readwrite") { result.push(accessor.name); }}return result;

Page 10: Zach Pinter - Caching and Synchronization with Flex

Finding an object’s propertiesSource generator

10

public class UserVO extends BaseVO { public var username : String; public var firstname : String; public var lastname : String; public var address : AddressVO;

override public function getProperties():Array { return super.getProperties().concat("username","firstname","lastname","address"); }}

Page 11: Zach Pinter - Caching and Synchronization with Flex

Updating the cacheWhat if the entity is already in the cache?

11

EntityCache 1: UserVO(instance A) id: 1 firstname: “Robert” lastname: “Smith”

EntityCache.updateEntity( UserVO(instance B) id: 1 firstname: “Bob” lastname: “Smith” )

EntityCache 1: UserVO(instance A) id: 1 firstname: “Bob” lastname: “Smith”

Copy the properties from instance B into instance A

Leave instance A in the cache

Discard instance B

Page 12: Zach Pinter - Caching and Synchronization with Flex

Updating the cacheWhat about arrays?

12

EntityCache UserVO id: 1 firstname: “Zachary” lastname: “Pinter” addresses: [ AddressVO(instance A) id: 2 label: “home” line1: “4444 W 44th Ave” city: “Denver” state: “CO” AddressVO id: 3 label: “work” line1: “5555 W 55th Ave” city: “Denver” state: “CO”]

EntityCache.updateEntity( AddressVO(instance B) id: 2 label: “home” line1: “3333 W 33rd Ave” city: “Denver” state: “CO” )

Page 13: Zach Pinter - Caching and Synchronization with Flex

Updating the cacheWhat about arrays?

13

UserVO id: 1 firstname: “Zachary” lastname: “Pinter” addresses: [ AddressVO(instance A) id: 2 label: “home” line1: “3333 W 33rd Ave” city: “Denver” state: “CO” AddressVO id: 3 label: “work” line1: “5555 W 55th Ave” city: “Denver” state: “CO”]

Since we update the existing instance, all references to it will see the update.

Page 14: Zach Pinter - Caching and Synchronization with Flex

Updating the CacheThe flip side

14

UserVO id: 5 firstname: “Zachary” lastname: “Pinter” addresses: [ AddressVO(instance B) id: 2 label: “home” line1: “6666 W 66th Ave” city: “Denver” state: “CO” AddressVO id: 3 label: “work” line1: “5555 W 55th Ave” city: “Denver” state: “CO”]

EntityCache AddressVO(instance A) id: 2 label: “home” line1: “5555 W 55th Ave” city: “Denver” state: “CO”

Your cache already has an AddressVO with id 2 in it, and you add a new UserVO to the cache that references an updated instance of the AddressVO

Page 15: Zach Pinter - Caching and Synchronization with Flex

Updating the Cache

15

UserVO id: 5 firstname: “Zachary” lastname: “Pinter” addresses: [ AddressVO(instance A) id: 2 label: “home” line1: “6666 W 66th Ave” city: “Denver” state: “CO” AddressVO id: 3 label: “work” line1: “5555 W 55th Ave” city: “Denver” state: “CO”]

EntityCache AddressVO(instance A) id: 2 label: “home” line1: “6666 W 66th Ave” city: “Denver” state: “CO”

The AddressVO in the cache is updated and the AddressVO in UserVO.addresses is replaced with the instance from the cache.

Page 16: Zach Pinter - Caching and Synchronization with Flex

Updating the Cache

16

if (obj is Array) { var arr:Array = obj as Array; for (var i:int=0;i<arr.length;i++) { if (arr[i] is BaseVO) { var res:BaseVO = updateEntity(arr[i] as BaseVO,...); if (res != null) arr[i] = res; } }}

Code looks something like this...

Page 17: Zach Pinter - Caching and Synchronization with Flex

Updating the Cache

17

if (obj is ArrayCollection) { var ac:ArrayCollection = obj as ArrayCollection; ac.disableAutoUpdate(); for (i=0;i<ac.length;i++) { if (ac.getItemAt(i) is BaseVO) { var res:BaseVO = updateEntity(ac.getItemAt(i) as BaseVO,...); if (res != null) { ac.setItemAt(res,i); } } } ac.enableAutoUpdate();}

ArrayCollection’s are slightly trickier

Page 18: Zach Pinter - Caching and Synchronization with Flex

18

Now that we’ve added an entity to the cache...

Page 19: Zach Pinter - Caching and Synchronization with Flex

The CacheHow do we get an entity?

What happens if we ask for an entity that isn’t in the cache?

19

public class EntityCache{

public function getEntity(id:String):EntityWrapper { //... } }

Page 20: Zach Pinter - Caching and Synchronization with Flex

EntityWrapperWhen requesting an entity, a wrapper object is returned.

If that object is in the cache, EntityWrapper.entity will have a value.

If the object is not in the cache, EntityWrapper.entity will be null and a call to fetch the entity will be queued.

20

[Bindable]public class EntityWrapper{ public var entityId:String; public var entity:BaseVO; public function EntityWrapper(id:String) { entityId = id; } }

Page 21: Zach Pinter - Caching and Synchronization with Flex

Using the Cache

21

<mx:Label text="Username: {userWrapper.entity.username}"/>

userWrapper = cache.getEntity(userid.text);

Page 22: Zach Pinter - Caching and Synchronization with Flex

Using the Cache - List RenderersBenefits‣ Faster initial query since you’re only grabbing the id’s‣ Rows are lazy-fetched as you scroll

Drawbacks‣ Sorting has to be handled by the server

22

Page 23: Zach Pinter - Caching and Synchronization with Flex

Using the Cache - List RenderersWhat’s the code for the item renderer look like?

23

override public function set data(val:Object):void { if(val != data){ if (!val) { wrapper = null; } else { wrapper = cache.getEntity(val); } super.data = val; }}

Page 24: Zach Pinter - Caching and Synchronization with Flex

Serverside ConsiderationsWhat does this require of your backend infrastructure?‣ Globally unique keys (or a way to fake it)‣ Ability to get an entity by its key‣ Ability to query for entities and only return their keys (used by lazy lists)

Perks:‣ Versioned entities‣ Get multiple entities in a single call by passing multiple keys

24

Page 25: Zach Pinter - Caching and Synchronization with Flex

Dictionary KeysOnly one cache, need to prevent collisions

Some Options:‣ Globally unique sequence across all tables (UserVO with id 1, AddressVO with id 2)‣ UUID’s (great for generating new id’s flex-side)‣ Combine type with id (“UserVO-1”, “AddressVO-1”)

25

Page 26: Zach Pinter - Caching and Synchronization with Flex

26

Demo

Page 27: Zach Pinter - Caching and Synchronization with Flex

27

Questions?

Page 28: Zach Pinter - Caching and Synchronization with Flex

Thanks!Zachary Pinter

http://github.com/zpinter/cache-synchttp://slideshare.net/zpinterhttp://zacharypinter.comhttp://effectiveui.com

Twitter: zpinter

28


Top Related