Child pages
  • Orchestrate
Skip to end of metadata
Go to start of metadata

Create complex workflows

Apstrata allows you to create your back-end logic using JavaScript scripts running on Apstrata's servers and having native access to all Apstrata's APIs. In addition, you can call any third party API from your Apstrata scripts, which allows you to create sophisticated orchestrations to implement your business processes.

Save your scripts using the Apstrata workbench or by invoking the SaveScript API and execute them using RunScript. In your script, you can call any Apstrata API by invoking the callAPI() method of the native apsdb object and call remote API using apsdb.callHttp().

Back to the map       Next station: Schedule jobs

Example 1: send a gathering request to nearby players with a list of foursquare venues

Let us imagine that you need to add a "gathering" feature to your mobile game app, such as when a player of your game presses the "send gathering request", the app back-end sends a gathering request by email to all nearby players, with a list of nearby cafes. This feature involves the unfolding of an orchestration in three steps: list all nearby players, list all nearby cafes and send email to all nearby players, which we implement using an Apstrata server-side script: 

 

// ... 
 
 // Retrieve the player's location from the request, as sent by the mobile app
 var playerLocation = request.parameters["location"];
 
 // orchestration step 1: Invoke Apstrata's Query API to retrieve the last stored location of other players
 // within 500m of the player's location
 var playersList = getNearbyPlayersList(playerLocation);
 
 // orchestration step 2: Invoke FourSquare's venue API to find a cafe within 500m around the player's location
 var cafesList = getNearbyCafesList(playerLocation);
 
 // orchestration step 3: Invoke Apstrata's sendEmail API to send the list by email
 // to all the nearby players
 return notifyAllPlayers(playersList, cafesList);

function getNearbyPlayersList(pLocation) {
    // ...
}
						
function getNearbyCafesList(pLocation) {
    //...
}

function notifyAllPlayers(pList, cList) {
	// ...			    
}
 Click to see the full code
<script>
	<scriptACL>
		<execute>nobody</execute>
		<read>nobody</read>
		<write>nobody</write>
	</scriptACL>
	<code>
		<![CDATA[
			
			// Retrieve the player's location from the request, as sent by the mobile app
			var playerLocation = request.parameters["location"];
			
			// orchestration step 1: Invoke Apstrata's Query API to retrieve the last stored location of other players
			// within 500m of the player's location
			var playersList = getNearbyPlayersList(playerLocation);
            
            // orchestration step 2: Invoke FourSquare's venue API to find a cafe within 500m around the player's location
            var cafesList = getNearbyCafesList(playerLocation);
            
            // orchestration step 3: Invoke Apstrata's sendEmail API to send the list by email
            // to all the nearby players
            return notifyAllPlayers(playersList, cafesList);
            
            /*
             * This function uses Apatrata's Query API to retrieve the list of nearby players
             * according to their latest saved location
             */ 
			function getNearbyPlayersList(pLocation) {
			    
			    var params = {
                 
                    "apsdb.store": "DefaultStore",
                    "apsdb.query": "location<geospatial> within(" +  pLocation + ",500)", 
                    "apsdb.sort": "distance(location," + pLocation + ")<ASC>", // sort by distance from this location, in ascending order
                    "apsdb.queryFields": "player, email" // ask for saved player name and email
                }
               
                var response = apsdb.callApi("Query", params, null);
                return response.result.documents;
			};
			
			/*
			 * This function uses the callHttp() method of the native apsdb object to invoke 
			 * the Foursquare's venue API
			 */
			function getNearbyCafesList(pLocation) {
			    
			    var callParams = {
                
                    uri: "https://api.foursquare.com/v2/venues/search",
                    method: "get",
                    params: {
                        "ll": pLocation,
                        "radius": 500,
                        "llAcc": 100000.0,
                        "query": "cafe",
                        "oauth_token": "EL1NWXJROOZKSQBFXHLRTTIOWKC4JCX5GRMTILDA4WJQ32HJ", // Replace with your own auth token
                        "v": new Date().toISOString().replace(/-/g, '').substring(0,8)
                    }
                };
            
                // Use the callHttp() method of the native apsdb object to invoke any REST API
                var searchResponse = apsdb.callHttp(callParams.uri, callParams.method, callParams.params, null, null, null, false, null, false, false);
               
                // Extract Foursquare's response from the "body" field and get the name of the first 10 venues
                var foursquareResponse = JSON.parse(searchResponse.body);
                var max = foursquareResponse.response.venues.length < 10 ? foursquareResponse.response.venues.length : 10;
                var venuesNames = [];
                for (var i = 0;  i < max ; i++) {
                    venuesNames.push(foursquareResponse.response.venues[i].name);
                }
        
                return venuesNames;
			}
			
			/*
			 * This function uses Apstrata's SendEmail API to send an email to all nearby players
			 */
			function notifyAllPlayers(pList, cList) {
			    
			    var cListStr = JSON.stringify(cList);
			    var emails = [];
			    for (var i = 0; i < pList.length; i++) {
			        emails.push(pList[i].email);
			    }
			    
			    var email = {
			        
                    "apsma.bcc": emails,
                    "apsma.subject": "Gathering",
                    "apsma.body": "Hey, let's meet at one of these venues: " + cListStr + ". Awaiting your reply."
			    }
			    
			    return apsdb.callApi("SendEmail", email, null);
			}
		]]>
	</code>
</script>

Example 2 - reuse your code

In example 1 above, we implemented three functions, "getNearbyPlayersList", "getNearbyCafesList" and "notifyAllPlayers". Looking at the code, it sounds pretty obvious that these functions could be reused in many other scripts. So let's split the above example into four new scripts, where the orchestration script of example 1 requires the other scripts that factor out the reusable functions from our initial orchestration script.

 

gatheringOrchestration
<script>
	<scriptACL>
		<execute>nobody</execute>
		<read>nobody</read>
		<write>nobody</write>
	</scriptACL>
	<code>
		<![CDATA[
			
			// Retrieve the player's location from the request, as sent by the mobile app
			var playerLocation = request.parameters["location"];
			
			// orchestration step 1: Retrieve the last stored location of other players within 500m of the player's location
			// this function has been factored out into the "playersLocator" script, so we need to require (import) it
			var playersLocator = apsdb.require("playersLocator");
			// notice that we need to pass the apsdb object to the required script if the latter needs it
			var playersList = playersLocator.getNearbyPlayersList(apsdb, playerLocation);
			
            // orchestration step 2: Invoke FourSquare's venue API to find a cafe within 500m around the player's location
            // this function has been factored out into the "venuesLocator" script, so we need to require (import) it
            var venuesLocator = apsdb.require("venuesLocator");
            // notice that we need to pass the apsdb object to the required script if the latter needs it
            var cafesList = venuesLocator.getNearbyCafesList(apsdb, playerLocation);
            
            // orchestration step 3:Send the list of cafes by email to all the nearby players
            // this function has been factored out into the "notificationManager" script, so we need to require (import) it
            var notificationManager = apsdb.require("notificationManager");
            var msg = "Hey, let's meet at one of these venues: " + 	JSON.stringify(cafesList) + ". Awaiting your reply.";
            // notice that we need to pass the apsdb object to the required script if the latter needs it
            return notificationManager.notifyAllPlayers(apsdb, playersList, msg);
            
		]]>
	</code>
</script>
 Click here to see the playersLocator script
playersLocator
<script>
	<scriptACL>
		<execute>nobody</execute>
		<read>nobody</read>
		<write>nobody</write>
	</scriptACL>
	<code>
		<![CDATA[
			
			/*
             * This function uses Apatrata's Query API to retrieve the list of nearby players
             * according to their latest saved location
             */ 
            function getNearbyPlayersList(apsdb, pLocation) {
            	
            	var params = {
            	 
            		"apsdb.store": "cabstore",
            		"apsdb.query": "location<geospatial> within(" +  pLocation + ",500)", 
            		"apsdb.sort": "distance(location," + pLocation + ")<ASC>", // sort by distance from this location, in ascending order
            		"apsdb.queryFields": "player, email" // ask for saved player name and email
            	}
               
            	var response = apsdb.callApi("Query", params, null);
            	return response.result.documents;
            };
			
		]]>
	</code>
</script>
 Click here to see the venuesLocator script
venuesLocator
<script>
	<scriptACL>
		<execute>nobody</execute>
		<read>nobody</read>
		<write>nobody</write>
	</scriptACL>
	<code>
		<![CDATA[
			
			/*
             * This function uses the callHttp() method of the native apsdb object to invoke 
             * the Foursquare's venue API
             */
            function getNearbyCafesList(apsdb, pLocation) {
            	
            	var callParams = {
            	
            		uri: "https://api.foursquare.com/v2/venues/search",
            		method: "get",
            		params: {
            			"ll": pLocation,
            			"radius": 500,
            			"llAcc": 100000.0,
            			"query": "",
            			"oauth_token": "EL1NWXJROOZKSQBFXHLRTTIOWKC4JCX5GRMTILDA4WJQ32HJ", // Replace with your own auth token
            			"v": new Date().toISOString().replace(/-/g, '').substring(0,8)
            		}
            	};
            
            	// Use the callHttp() method of the native apsdb object to invoke any REST API
            	var searchResponse = apsdb.callHttp(callParams.uri, callParams.method, callParams.params, null, null, null, false, null, false, false);
            	// Extract Foursquare's response from the "body" field and get the name of the first 10 venues
            	var foursquareResponse = JSON.parse(searchResponse.body);
            	var max = foursquareResponse.response.venues.length < 10 ? foursquareResponse.response.venues.length : 10;
            	var venuesNames = [];
            	for (var i = 0;  i < max ; i++) {
            		venuesNames.push(foursquareResponse.response.venues[i].name);
            	}
            
            	return venuesNames;
            }
		]]>
	</code>
</script>
 Click here to see the notificationManager script
notificationManager
<script>
	<scriptACL>
		<execute>nobody</execute>
		<read>nobody</read>
		<write>nobody</write>
	</scriptACL>
	<code>
		<![CDATA[
			
			/*
             * This function uses Apstrata's SendEmail API to send an email to all nearby players
             */
            function notifyAllPlayers(apsdb, pList, message) {
            
            	var emails = [];
            	for (var i = 0; i < pList.length; i++) {
            		emails.push(pList[i].email);
            	}
            	
            	var email = {
            		
            		"apsma.bcc": emails,
            		"apsma.subject": "Gathering",
            		"apsma.body": message
            	}
            	
            	return apsdb.callApi("SendEmail", email, null);
            }
			
		]]>
	</code>
</script>

 

Dig deeper

Related tutorials