Working through getting all the properties that the client needs to display the stacker, I ran into a stumbling block with: block.clickedTimestamp block.ignoredTimestamp These actually are UserBlockData properties, and are thus user specific and cannot be cached in the data-model cache. Doing: @DMProperty(cached=false) long getClickedTimestamp() { return view.getUserBlockData().getClickedTimestampAsLong(); } Hits two problems: A) We always load the BlockView() from the system viewpoint, since we want to return user-independent data for caching and let the data model filter that down to what each user can see. B) If everything else is cached, then loading and populating the BlockView just to get the clicked timestamp from the UserBlockData is prohibitively expensive. If we instead we go with @DMProperty(cached=false) long getClickedTimestamp() { if (viewpoint instanceof UserViewpoint) { User user = ((UserViewpoint)viewer); /* Lookup UserBlockData for user and blockId */ return userBlockData.getClickedTimestampAsLong(); } else { return -1; } } We still hit two problems: A) Even though the BlockView wasn't used, it still got loaded by the initialization step run before getClickedTimestamp was called(). B) If we also added getIgnoredTimestamp() it would also look up the UserBlockData, separately. The second issue makes me think that this is related to the group support I added a while ago which allows a bunch of properties to be computed and cached at once. This currently looks like private static final int CONTACTERS_GROUP = 1; private boolean currentTrackFetched; private TrackHistory currentTrack; private void ensureCurrentTrack() { if (!currentTrackFetched) { /* Bunch of work to look up currentTrack */ } } @DMProperty(group=CURRENT_TRACK_GROUP) public TrackDMO getCurrentTrack() { ensureCurrentTrack(); if (currentTrack != null) return session.findUnchecked(TrackDMO.class, currentTrack.getTrack().getId()); else return null; } @DMProperty(group=CURRENT_TRACK_GROUP) public long getCurrentTrackPlayTime() { ensureCurrentTrack(); if (currentTrack != null) return currentTrack.getLastUpdated().getTime(); else return -1; } } But what if we extended it so we could do: private TrackHistory currentTrack; @DMInit(group=CURRENT_TRACK_GROUP) private void initCurrentTrack() { /* Bunch of work to look up currentTrack */ } @DMProperty(group=CURRENT_TRACK_GROUP) public TrackDMO getCurrentTrack() { if (currentTrack != null) return session.findUnchecked(TrackDMO.class, currentTrack.getTrack().getId()); else return null; } @DMProperty(group=CURRENT_TRACK_GROUP) public long getCurrentTrackPlayTime() { if (currentTrack != null) return currentTrack.getLastUpdated().getTime(); else return -1; } } Then, one step more of extension allows: @DMInit(group=USER_BLOCK_DATA_GROUP, initMain=false) long initUserBlockData() { if (viewpoint instanceof UserViewpoint) { User user = ((UserViewpoint)viewer); /* Lookup UserBlockData for user and blockId */ } } @DMProperty(cached=FALSE, group=USER_BLOCK_DATA_GROUP) long getClickedTimestamp() { return userBlockData.getClickedTimestampAsLong(); } @DMProperty(cached=FALSE, group=USER_BLOCK_DATA_GROUP) long getClickedTimestamp() { return userBlockData.getIgnoredTimestampAsLong(); } Which I'm pretty happy with. - Owen
Attachment:
signature.asc
Description: This is a digitally signed message part