Ignore:
Timestamp:
Jan 31, 2011, 8:16:03 PM (12 years ago)
Author:
robert@…
Message:
  • Implemented a cache for module rest calls, to increase performance (see moduleCommunicationService)
  • Implemented searching in module data.
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/grails-app/services/dbnp/modules/ModuleCommunicationService.groovy

    r1455 r1458  
    2020
    2121class ModuleCommunicationService implements Serializable {
    22     boolean transactional = false
     22        boolean transactional = false
    2323        def authenticationService
    2424        def moduleNotificationService
    25        
    26     /**
    27      * Sends a notification to assay modules that some part of a study has changed.
    28      *
    29      * Only modules that have the notify flag set to true will be notified. They will be notified on the URL
    30      *
    31      * [moduleUrl]/rest/notifyStudyChange?studyToken=abc
    32      *
    33      * Errors that occur when calling this URL are ignored. The module itself is responsible of
    34      * maintaining a synchronized state.
    35      *
    36      * @param study
    37      * @return
    38      */
     25
     26        /**
     27         * Cache containing the contents of different URLs. These urls are
     28         * saved per user, since the data could be different for different users.
     29         */
     30        def cache = [:]
     31
     32        /**
     33         * Number of seconds to save the data in cache
     34         */
     35        def numberOfSecondsInCache = 10 * 60;
     36
     37        /**
     38         * Sends a notification to assay modules that some part of a study has changed.
     39         *
     40         * Only modules that have the notify flag set to true will be notified. They will be notified on the URL
     41         *
     42         * [moduleUrl]/rest/notifyStudyChange?studyToken=abc
     43         *
     44         * Errors that occur when calling this URL are ignored. The module itself is responsible of
     45         * maintaining a synchronized state.
     46         *
     47         * @param study
     48         * @return
     49         */
    3950        def invalidateStudy( Study study ) {
    4051                moduleNotificationService.invalidateStudy( study );
    41     }
    42        
     52        }
     53
    4354        /**
    4455         * Checks whether a specific method on a module is reachable and returns a SC_OK response code.
     
    5566                try {
    5667                        return connection.responseCode == HttpServletResponse.SC_OK
    57                 } catch(e) { 
    58                         return false 
     68                } catch(e) {
     69                        return false
    5970                }
    6071        }
    61        
     72
    6273        /**
    6374         * Calls a rest method on a module
     
    6879         */
    6980        def callModuleRestMethodJSON( consumer, restUrl ) throws Exception {
    70                 // create a random session token that will be used to allow to module to
    71                 // sync with gscf prior to presenting the measurement data
    72                 def sessionToken = UUID.randomUUID().toString()
    73 
    7481                if (!authenticationService.isLoggedIn()) {
    7582                        // should not happen because we can only get here when a user is
     
    7784                        throw new Exception('User is not logged in.')
    7885                }
     86
     87                // Check whether the url is present in cache
     88                def cacheData = retrieveFromCache( restUrl );
     89                if( cacheData && cacheData[ "success" ] )
     90                        return cacheData[ "contents" ];
     91                else if( cacheData && !cacheData[ "success" ] )
     92                        throw new Exception( "Error while fetching data from " + restUrl + " (from cache): " + cacheData[ "error" ] )
     93
     94                // create a random session token that will be used to allow to module to
     95                // sync with gscf prior to presenting the measurement data
     96                def sessionToken = UUID.randomUUID().toString()
    7997
    8098                // put the session token to work
     
    90108                        url += '?sessionToken=' + sessionToken
    91109                }
    92                
     110
    93111                // Perform a call to the url
    94112                def restResponse
    95113                try {
    96114                        def textResponse = url.toURL().getText()
     115                        println "GSCF call to " + consumer + " URL: " + url
     116                        println "GSCF response: " + textResponse
    97117                        restResponse = JSON.parse( textResponse )
    98118                } catch (Exception e) {
     119                        storeErrorInCache( restUrl, e.getMessage() );
    99120                        throw new Exception( "An error occurred while fetching " + url + ".", e )
    100121                } finally {
     
    102123                        authenticationService.logOffRemotely(consumer, sessionToken)
    103124                }
     125
     126                // Store the response in cache
     127                storeInCache( restUrl, restResponse );
    104128               
    105129                return restResponse
    106130        }
     131
     132        /**
     133         * Checks whether a specific url exists in cache
     134         * @param url   URL to call
     135         * @return              true if the url is present in cache
     136         */
     137        def existsInCache( url ) {
     138                return retrieveFromCache( url ) == null;
     139        }
     140
     141        /**
     142         * Retrieves the contents of a specific URL from cache
     143         * @param url   URL to call
     144         * @return              JSON object with the contents of the URL or null if the url doesn't exist in cache
     145         */
     146        def retrieveFromCache( url ) {
     147                def user = authenticationService.getLoggedInUser();
     148                def userId = user ? user.id : -1;
     149
     150                if( cache[ userId ] && cache[ userId ][ url ] && ( System.currentTimeMillis() - cache[ userId ][ url ][ "timestamp" ] ) < numberOfSecondsInCache * 1000 ) {
     151                        return cache[ userId ][ url ];
     152                } else {
     153                        return null;
     154                }
     155        }
     156
     157        /**
     158         * Store the retrieved contents from a url in cache
     159         * @param url           URL that has been called
     160         * @param contents      Contents of the URL
     161         */
     162        def storeInCache( url, contents ) {
     163                def user = authenticationService.getLoggedInUser();
     164                def userId = user ? user.id : -1;
     165
     166                if( !cache[ userId ] )
     167                        cache[ userId ] = [:]
     168
     169                cache[ userId ][ url ] = [
     170                        "timestamp": System.currentTimeMillis(),
     171                        "success": true,
     172                        "contents": contents
     173                ];
     174        }
     175       
     176        /**
     177        * Store the retrieved error from a url in cache
     178        * @param url            URL that has been called
     179        * @param contents       Contents of the URL
     180        */
     181   def storeErrorInCache( url, error ) {
     182           def user = authenticationService.getLoggedInUser();
     183           def userId = user ? user.id : -1;
     184
     185           if( !cache[ userId ] )
     186                   cache[ userId ] = [:]
     187
     188           cache[ userId ][ url ] = [
     189                   "timestamp": System.currentTimeMillis(),
     190                   "success": false,
     191                   "error": error
     192           ];
     193   }
     194
    107195}
Note: See TracChangeset for help on using the changeset viewer.