Class CaldavServerOwnerStorage
Why a cache, and why here. The listing costs a REST login, a GET
and a logout of the user's own BlueMind session. Read only when a pass
meets an eXo-shaped collection nobody here recognises, that is still
every sweep — every five minutes, on every node — for every account that
holds one such calendar, again each time the user opens their agenda,
and once more when the hidden-calendars drawer describes a bound
eXo-shaped calendar (CaldavReadService#describeCollections),
where the listing is what tells a calendar adopted before EXO-90347 —
a colleague's, and kept — from the user's own. Owners almost never
change, so the answer is kept for
meeds.cache.caldav.server.owners.ttl seconds (one hour by
default, caldav.properties) and at most
meeds.cache.caldav.server.owners.max accounts, through the
platform's Spring cache adapter over the Kernel's ExoCache — the
storage-like layer caching belongs to, tunable per deployment, and a
single-flight load under Cacheable.sync(): concurrent misses on
one account open one session, not two.
The key is the account and nothing less. A listing says which
calendars one person's mailbox can see; served to another person it is
a leak. So the key carries the two discriminators the answer depends on
— the declared server and the eXo user whose stored credentials opened
the session — as explicit, equals-compared fields (CaldavServerOwnerStorage.Key),
never a folded hash: two users on one server, and one user on two
servers, hold separate entries by construction. The principal uid the
pass discovered is not part of the key, because it is derived from the
same credentials; the listing carries the uid the session was
authenticated as, and a reader that finds it differing from the pass's
principal — credentials re-pointed at another mailbox — asks for a
refresh rather than believing the entry.
What is not cached. A fetch that throws caches nothing: Spring
writes no entry for a loader that failed, so an unreachable or refusing
server costs one attempt per pass, as it did before the cache, and the
next pass tries again. A listing that does not name a collection is
cached as it came; the reader's one forced refresh(org.exoplatform.caldav.storage.CaldavServerOwnerStorage.Key, org.exoplatform.caldav.client.CalDavEndpoint) per pass is
what keeps a share made after the entry was written from waiting out the
TTL.
Node-local. Each node of a cluster holds its own entries and
expires them on its own clock; an owner change made outside eXo — a
share granted in BlueMind's webmail — is seen by a node within the TTL at
the latest, and sooner on the node whose pass meets the new collection,
since that is a miss it refreshes on. A change eXo itself makes is
evicted at once on the node that made it (evict(org.exoplatform.caldav.storage.CaldavServerOwnerStorage.Key)), and reaches
the others within the TTL.
-
Nested Class Summary
Nested ClassesModifier and TypeClassDescriptionstatic final recordThe account a listing belongs to: the declared server and the eXo user whose stored credentials open the session. -
Field Summary
FieldsModifier and TypeFieldDescriptionstatic final StringThe cache, and themeeds.cache.<name>.*tuning prefix. -
Constructor Summary
Constructors -
Method Summary
Modifier and TypeMethodDescriptionvoidDrops the account's entry: eXo itself changed what the account can see — a share it granted or revoked, a subscription it followed — or the account itself changed hands, on connect, disconnect or new credentials.listing(CaldavServerOwnerStorage.Key key, CalDavEndpoint endpoint) The account's listing, from the cache when it holds one, else read from the server and kept.refresh(CaldavServerOwnerStorage.Key key, CalDavEndpoint endpoint) The account's listing read from the server now, replacing whatever the cache held: a pass that meets a collection the cached listing does not name asks this once, so a share made after the entry was written is classified in the pass that first sees it rather than after the TTL.
-
Field Details
-
CACHE_NAME
The cache, and themeeds.cache.<name>.*tuning prefix.- See Also:
-
-
Constructor Details
-
CaldavServerOwnerStorage
public CaldavServerOwnerStorage()
-
-
Method Details
-
listing
@Cacheable(cacheNames="caldav.server.owners", key="#p0", sync=true) public BlueMindCalendarOwners listing(CaldavServerOwnerStorage.Key key, CalDavEndpoint endpoint) The account's listing, from the cache when it holds one, else read from the server and kept.- Parameters:
key- the accountendpoint- the account's DAV endpoint, minted from the registry for the user's eXo login — the session is opened with its credentials; not part of the key, which the two identifiers already determine- Returns:
- the listing
- Throws:
UnsupportedOperationException- when the account's configured credentials are not a login and password; nothing is cachedCalDavException- when the server refuses, cannot be reached, or answers the wrong shape; nothing is cached
-
refresh
@CachePut(cacheNames="caldav.server.owners", key="#p0") public BlueMindCalendarOwners refresh(CaldavServerOwnerStorage.Key key, CalDavEndpoint endpoint) The account's listing read from the server now, replacing whatever the cache held: a pass that meets a collection the cached listing does not name asks this once, so a share made after the entry was written is classified in the pass that first sees it rather than after the TTL.- Parameters:
key- the accountendpoint- the account's DAV endpoint- Returns:
- the fresh listing, now cached
- Throws:
UnsupportedOperationException- aslisting(org.exoplatform.caldav.storage.CaldavServerOwnerStorage.Key, org.exoplatform.caldav.client.CalDavEndpoint); the stale entry is left as it wasCalDavException- aslisting(org.exoplatform.caldav.storage.CaldavServerOwnerStorage.Key, org.exoplatform.caldav.client.CalDavEndpoint); the stale entry is left as it was
-
evict
@CacheEvict(cacheNames="caldav.server.owners", key="#p0") public void evict(CaldavServerOwnerStorage.Key key) Drops the account's entry: eXo itself changed what the account can see — a share it granted or revoked, a subscription it followed — or the account itself changed hands, on connect, disconnect or new credentials. A no-op when there is no entry.- Parameters:
key- the account
-