88import { IGraph } from '@microsoft/mgt-element' ;
99import { Presence } from '@microsoft/microsoft-graph-types-beta' ;
1010import { BetaGraph } from '../BetaGraph' ;
11+ import { CacheItem , CacheSchema , CacheService , CacheStore } from '../utils/Cache' ;
1112import { prepScopes } from '../utils/GraphHelpers' ;
1213import { IDynamicPerson } from './types' ;
1314
15+ /**
16+ * Definition of cache structure
17+ */
18+ const cacheSchema : CacheSchema = {
19+ name : 'presence' ,
20+ stores : {
21+ presence : { }
22+ } ,
23+ version : 1
24+ } ;
25+
26+ /**
27+ * Object to be stored in cache representing individual people
28+ */
29+ interface CachePresence extends CacheItem {
30+ /**
31+ * json representing a person stored as string
32+ */
33+ presence ?: string ;
34+ }
35+
36+ /**
37+ * Defines the expiration time
38+ */
39+ const getPresenceInvalidationTime = ( ) : number =>
40+ CacheService . config . presence . invalidationPeriod || CacheService . config . defaultInvalidationPeriod ;
41+
42+ /**
43+ * Whether the groups store is enabled
44+ */
45+ const presenceCacheEnabled = ( ) : boolean => CacheService . config . presence . isEnabled && CacheService . config . isEnabled ;
46+
1447/**
1548 * async promise, allows developer to get my presense
1649 *
@@ -20,11 +53,25 @@ import { IDynamicPerson } from './types';
2053export async function getMyPresence ( graph : IGraph ) : Promise < Presence > {
2154 const betaGraph = BetaGraph . fromGraph ( graph ) ;
2255 const scopes = 'presence.read' ;
56+ let cache : CacheStore < CachePresence > ;
57+
58+ if ( presenceCacheEnabled ( ) ) {
59+ cache = CacheService . getCache ( cacheSchema , 'presence' ) ;
60+ const presence = await cache . getValue ( 'me' ) ;
61+ if ( presence && getPresenceInvalidationTime ( ) > Date . now ( ) - presence . timeCached ) {
62+ return JSON . parse ( presence . presence ) ;
63+ }
64+ }
65+
2366 const result = await betaGraph
2467 . api ( '/me/presence' )
2568 . middlewareOptions ( prepScopes ( scopes ) )
2669 . get ( ) ;
2770
71+ if ( presenceCacheEnabled ( ) ) {
72+ cache . putValue ( 'me' , { presence : result } ) ;
73+ }
74+
2875 return result ;
2976}
3077
@@ -37,10 +84,23 @@ export async function getMyPresence(graph: IGraph): Promise<Presence> {
3784export async function getUserPresence ( graph : IGraph , userId : string ) : Promise < Presence > {
3885 const betaGraph = BetaGraph . fromGraph ( graph ) ;
3986 const scopes = [ 'presence.read' , 'presence.read.all' ] ;
87+ let cache : CacheStore < CachePresence > ;
88+
89+ if ( presenceCacheEnabled ( ) ) {
90+ cache = CacheService . getCache ( cacheSchema , 'presence' ) ;
91+ const presence = await cache . getValue ( userId ) ;
92+ if ( presence && getPresenceInvalidationTime ( ) > Date . now ( ) - presence . timeCached ) {
93+ return JSON . parse ( presence . presence ) ;
94+ }
95+ }
96+
4097 const result = await betaGraph
4198 . api ( `/users/${ userId } /presence` )
4299 . middlewareOptions ( prepScopes ( ...scopes ) )
43100 . get ( ) ;
101+ if ( presenceCacheEnabled ( ) ) {
102+ cache . putValue ( userId , { presence : JSON . stringify ( result ) } ) ;
103+ }
44104
45105 return result ;
46106}
@@ -55,30 +115,65 @@ export async function getUsersPresenceByPeople(graph: IGraph, people?: IDynamicP
55115 if ( ! people || people . length === 0 ) {
56116 return { } ;
57117 }
118+
58119 const betaGraph = BetaGraph . fromGraph ( graph ) ;
59120 const batch = betaGraph . createBatch ( ) ;
121+ const peoplePresence = { } ;
122+ let cache : CacheStore < CachePresence > ;
123+
124+ if ( presenceCacheEnabled ( ) ) {
125+ cache = CacheService . getCache ( cacheSchema , 'presence' ) ;
126+ }
60127
61128 for ( const person of people ) {
62129 if ( person !== '' && person . id ) {
63130 const id = person . id ;
64- batch . get ( id , `/users/${ id } /presence` , [ 'presence.read' , 'presence.read.all' ] ) ;
131+ peoplePresence [ id ] = null ;
132+ let presence : CachePresence ;
133+ if ( presenceCacheEnabled ( ) ) {
134+ presence = await cache . getValue ( id ) ;
135+ }
136+ if (
137+ presenceCacheEnabled ( ) &&
138+ presence &&
139+ getPresenceInvalidationTime ( ) > Date . now ( ) - ( await presence ) . timeCached
140+ ) {
141+ peoplePresence [ id ] = JSON . parse ( presence . presence ) ;
142+ } else {
143+ batch . get ( id , `/users/${ id } /presence` , [ 'presence.read' , 'presence.read.all' ] ) ;
144+ }
65145 }
66146 }
67147
68148 try {
69- const peoplePresence = { } ;
70149 const response = await batch . executeAll ( ) ;
71150
72151 for ( const r of response . values ( ) ) {
73152 peoplePresence [ r . id ] = r . content ;
153+ if ( presenceCacheEnabled ( ) ) {
154+ cache . putValue ( r . id , { presence : JSON . stringify ( r . content ) } ) ;
155+ }
74156 }
75157
76158 return peoplePresence ;
77159 } catch ( _ ) {
78160 try {
79- const peoplePresence = { } ;
161+ /**
162+ * individual calls to getUserPresence as fallback
163+ * must filter out the contacts, which will either 404 or have PresenceUnknown response
164+ * caching will be handled by getUserPresence
165+ */
80166 const response = await Promise . all (
81- people . filter ( person => person && person . id ) . map ( person => getUserPresence ( betaGraph , person . id ) )
167+ people
168+ . filter (
169+ person =>
170+ person &&
171+ person . id &&
172+ ! peoplePresence [ person . id ] &&
173+ 'personType' in person &&
174+ ( person as any ) . personType . subclass === 'OrganizationUser'
175+ )
176+ . map ( person => getUserPresence ( betaGraph , person . id ) )
82177 ) ;
83178
84179 for ( const r of response ) {
0 commit comments