Categories
developer documentation v0.0.27
mimik Developer Documentation
  • Tutorials
  • Working with edge microservices in an iOS project

Working with edge microservices in an iOS project

Objective

The objective of this article is to demonstrate how to use the mimik Client Library interfaces when working with edge microservices in an iOS project.

Intended Readers

The intended readers of this document are iOS software developers, who want to familiarize themselves with the basics of mimik Client Library interfaces, specifically methods for interfacing with edge microservices.

What You'll Be Doing

In this tutorial you are going to learn about topics relevant to working with the mimik Client Library edge microservice interfaces. These topics are:

  • Deploying an edge Microservice
  • Referencing an edge Microservice
  • Calling an edge Microservice
  • Updating an edge Microservice
  • Undeploying an edge Microservice

Technical Prerequisites

In order to get full benefit from this article, the reader should have a working knowledge of the following concepts and techniques:

  • Running an iOS device with the latest version of the operating system.
  • An understanding of how to Integrate and initialize mimik Client Library components.
  • An understanding of how to start the edgeEngine Runtime in an iOS application.
  • An understanding of how to generate an edgeEngine Access Token.
NOTE:

Working with the iOS Simulator and the mimik Client Libraries entails some special consideration. For more more information about iOS Simulator support see this tutorial.

Deploying an edge Microservice

Once the mimik Client Library components have been integrated and initialized into your project as well as having the edgeEngine Runtime started and Access Token generated, we can get into the specifics of working with edge microservices.

You can think of deploying (installing) edge microservices as spinning up individual mini backends within your application. The code example shown below in Listing 1 shows how to do this. A detailed explanation follows.


1: // A valid edgeEngine Access Token is required to call this method. The async return is either a success with an object reference to the deployed edge microservice, or a failure with an error.
2: func deployMicroservice(edgeEngineAccessToken: String) async -> Result<MIMIKMicroservice, NSError> {
3:
4: // Establishing application bundle reference to the randomnumber_v1.tar file
5: guard let imageTarPath = Bundle.main.path(forResource: "randomnumber_v1", ofType: "tar") else {
6: // Tar file not found, failing with error
7: return .failure(NSError.init(domain: "Error", code: 404))
8: }
9:
10: // edge microservice deployment configuration object with example values
11: let config = MIMIKMicroserviceConfig.init(imageName: "randomnumber-v1", containerName: "randomnumber-v1", baseApiPath: "/randomnumber/v1", envVariables: [:])
12:
13: // Calling mimik Client Library method to deploy the edge microservice
14: switch await self.edgeClient.deployMicroservice(edgeEngineAccessToken: edgeEngineAccessToken, config: config, imageTarPath: imageTarPath) {
15: case .success(let microservice):
16: print("Success")
17: // Deployment was successful, returning edge microservice object reference
18: return .success(microservice)
19: case .failure(let error):
20: print("Error", error.localizedDescription)
21: // Deployment was unsuccessful, returning error
22: return .failure(error)
23: }
24: }

Listing 1: Deploying an edge microservice


First, we establish a file path to where the edge microservice is stored within the application bundle at Lines 5-8. In this example, the edge microservice is represented by a randomnumber_v1.tar file according to the Bundle.main.path(forResource: "randomnumber_v1", ofType: "tar") statement at Line 5.

Next, we create a configuration object using the function MIMIKMicroserviceConfig.init() at Line 11. MIMIKMicroserviceConfig.init() describes the edge microservice deployment parameters. The example code in Listing 1 is configured with some hard-coded values as shown on Line 11. In a production setting, you'd want to put these values somewhere in a configuration file.

Then, we call the deployMicroservice() method of the mimik Client Library at Line 14 which requires the following parameters:

  • edgeEngineAccessToken
  • config
  • imageTarPath

WHERE

edgeEngineAccessToken is the edgeEngine Access Token we generated earlier

config is a configuration object describing the edge microservice deployment parameters Line 11

imageTarPath is a file path to where the edge microservice is stored within the application bundle Lines 5-8

After the call, we validate the result at Lines 15-23.

If the deployment was successful, we get a reference object to the deployed edge microservice at Line 15. You can either keep a reference to this object or get it again as needed, as described in the section titled Referencing the microservice below . In the last of Listing 1, we return microservice as an object at Line 18.

If there was an issue, we return an error at Line 22.

At this point we are done, the edge microservice has been successfully deployed and it is now functional.

Take a moment to review the statements in the code above using these comments as your guide.

NOTE:
Once an edge microservice is deployed to the edgeEngine Runtime, its lifecycle gets tied to the edgeEngine Runtime, starting up and shutting down along with it.
NOTE:
Each edge microservice provides a set of interfaces, allowing edge microservice developers to develop and deploy cross-platform solutions. This is because the same edge microservice can be deployed to other platforms as well.

Referencing the microservice

After edge microservice deployment, we will want to start calling its endpoints to do the work. Since the endpoint uses http communication protocols, we will need to establish a URL to reach it. There are several ways to accomplish this, but for the learning purposes of this tutorial, we will establish this URL using an edge microservice object reference. The code example below in Listing 2 shows how to do this. A detailed explanation follows the code listing.


1: // A valid edgeEngine Access Token is required to call this method.
2: // The async return is either a success with an array of deployed edge
3: // microservice object references, or a failure with an error
4: func deployedMicroservices(edgeEngineAccessToken: String) async -> Result<[MIMIKMicroservice], NSError> {
5:
6: // Calling mimik Client Library method to get the deployed edge microservice references
7: switch await self.edgeClient.deployedMicroservices(edgeEngineAccessToken: edgeEngineAccessToken) {
8: case .success(let microservices):
9:
10: // Guarding against the array being empty.
11: guard !microservices.isEmpty else {
12: print("Success, but no deployed edge microservices found")
13: // Call was successful, but there were no deployed edge microservices found. Returning the empty array
14: return .success(microservices)
15: }
16:
17: for microservice in microservices {
18: // Attempting to establish a url to the deployed edge microservice /randomNumber endpoint
19: guard let url = microservice.urlComponents(withEndpoint: "/randomNumber")?.url else {
20: print("Error")
21: // Unable to establish the url to the deployed edge microservice endpoint
22: continue
23: }
24:
25: // Printing the url to the deployed edge microservice endpoint
26: print("microservice url:", url)
27: }
28:
29: print("Success")
30: // Call was successful, returning the array of deployed edge microservice object references
31: return .success(microservices)
32:
33: case .failure(let error):
34: print("Error", error.localizedDescription)
35: // Call was unsuccessful, returning error
36: return .failure(error)
37: }
38: }

Listing 2: Referencing an edge microservice


First, we call the deployedMicroservices() method of the mimik Client Library at Line 7, which requires the parameter edgeEngineAccessToken

WHERE

edgeEngineAccessToken is the edgeEngine Access Token.

After the call, we do result-validation checks at Lines 8 and 33.

If the call was successful, but no edge microservices were found, we return an empty array at Line 14. If there was an issue, we return an error at Line 34.

If all is good, we start iterating over the array of deployed edge microservice object references at Lines 17-27.

For learning purposes of this article, while iterating, we attempt to establish a URL to an edge microservice endpoint called /randomNumber at Line 19. For now, we just print the value to the console log at Line 26. In the next section titled Calling the microservices, we will be actively capturing and using this value to make our http call.

Take a moment to review the statements in the code above using these comments as your guide.

Calling the microservice

Once we have established the URL to the deployed edge microservice endpoint, we can start making http calls to it. The code example below in Listing 3 shows how to do this. A detailed explanation follows the code listing.


1: import Alamofire
2:
3: // A valid edgeEngine Access Token is required to call this method. The async return is either a success with the response value from the edge microservice endpoint, or a failure with an error
4: func callMicroservice(edgeEngineAccessToken: String) async -> Result<Any, NSError> {
5:
6: // First getting an object reference to the url of the deployed edge microservice endpoint
7: guard case let .success(microservices) = await self.edgeClient.deployedMicroservices(edgeEngineAccessToken: accessToken),
8: let url = microservices.first?.urlComponents(withEndpoint: "/randomNumber")?.url else {
9: print("Error")
10: // Getting url was unsuccessful, returning error
11: return .failure(NSError.init(domain: "Error", code: 404))
12: }
13:
14: // Access Token can be used, when the edge microservice endpoint requires authentication
15: let httpHeaders = HTTPHeaders.init(["Authorization" : "Bearer \(edgeEngineAccessToken)"])
16:
17: // Alamofire request call to the endpoint's url, with serialization of a Decodable value
18: let dataTask = AF.request(url, headers: httpHeaders).serializingDecodable(Int.self)
19: guard let value = try? await dataTask.value else {
20: print("Error")
21: // Response value serializing was unsuccessful, returning error
22: return .failure(NSError.init(domain: "Error", code: 500))
23: }
24:
25: // Response value serializing was successful, returning the value
26: print("Success. value:", value)
27: return .success(value)
28: }

Listing 3: Calling an edge microservice


To simplify the code, we will use an established Swift networking library called Alamofire to make the call. Since the Alamofire library is already a dependency of the mimik Client Library, it is made available to our iOS project as part of the CocoaPods dependency manager automatically.

First, we make the Alamofire library available to our class, by importing it on Line 1.

Next, we get a reference to the URL of the deployed edge microservice at Lines 7-12. We are simplifying the example code, by simply getting a reference to the first edge microservice we receive in the array. In a production application, you'd want to do additional checks, to make sure that the correct edge microservice has been selected especially if there are multiple edge microservices deployed.

Then, we setup the http headers on Line 15 to pass the edgeEngine Access Token as the Bearer Authorization http headers parameter.

At this point, we are ready to use the request() method of the Alamofire Library to make the http call to the edge microservice endpoint.

We set the following parameters of the request() method:

  • url
  • headers

WHERE

url is the url to the endpoint of the deployed edge microservice. See here

headers are optional HTTP headers values that we might want to include in the http call. In our example, we include the Bearer Authorization header to demonstrate how to pass authorizations to an endpoint

NOTE:
There are other components that you might want to include in your http calls. Please see the Alamofire library documentation for more information.

Once the http call is made on Line 18, we do a validation check to make sure that we get the expected response on Lines 19-23. In our example, we are expecting an Int value in the response.

If there is an issue, we return an error on Line 22.

When all is good, and an Integer value is received, we return a success with the said value on Line 27.

Take a moment to review the statements in the code above using these comments as your guide.

Updating an edge microservice

As an iOS developer, you might be asked to update an already deployed edge microservice. For example, when the edge microservice developer releases a new version that might include bug fixes or new features.

There are two ways to update an already deployed edge microservice.

You can simply re-deploy the same edge microservice from a new, updated .tar file. You have to be careful, though, to use exactly the same configuration that was used during the initial deployment. This is so that you don't end up with two instances of the same edge microservice. (However, environment variables can change.)

Instead, you can safely use the updateMicroservice() method of the mimik Client Library. Using this method guarantees that only the specifically selected edge microservice is updated.

The code example below in Listing 4 shows you the recommended, safer way of updating an already deployed edge microservice. A detailed explanation follows the code example.


1: // A valid edgeEngine Access Token is required to call this method. The async return is either a success with an object reference to the updated edge microservice, or a failure with an error.
2: func updateMicroservice(edgeEngineAccessToken: String) async -> Result<MIMIKMicroservice, NSError> {
3:
4: // First getting an object reference to the deployed edge microservice endpoint
5: guard case let .success(microservices) = await self.edgeClient.deployedMicroservices(edgeEngineAccessToken: accessToken),
6: let microservice = microservices.first else {
7: print("Error")
8: // Getting object reference was unsuccessful, returning error
9: return .failure(NSError.init(domain: "Error", code: 500))
10: }
11:
12: // Establishing application bundle reference to the new, updated randomnumber_v2.tar file
13: guard let imageTarPath = Bundle.main.path(forResource: "randomnumber_v2", ofType: "tar") else {
14: print("Error")
15: // Tar file not found, returning error
16: return .failure(NSError.init(domain: "Error", code: 500))
17: }
18:
19: // Calling mimik Client Library method to update the selected edge microservice
20: switch await self.edgeClient.updateMicroservice(edgeEngineAccessToken: accessToken, microservice: microservice, imageTarPath: imageTarPath, envVariables: ["MyKey3" : "MyValue3"]) {
21: case .success(let microservice):
22: print("Success")
23: // Update was successful, returning edge microservice object reference
24: return .success(microservice)
25: case .failure(let error):
26: print("Error updating microservice", error.localizedDescription)
27: // Update was unsuccessful, returning error
28: return .failure(NSError.init(domain: "Error", code: 500))
29: }
30: }

Listing 4: Updating an edge microservice


First, we get an object reference to the already deployed edge microservice on Lines 5-10. We are simplifying the example code, by simply getting a reference to the first edge microservice we receive in the array. In a production application, you'd want to do additional checks, to make sure that the correct edge microservice has been selected. Especially, if there are multiple edge microservices deployed.

Next, we establish a file path to where the new, updated edge microservice is stored within the application bundle at Lines 13-17. This example edge microservice is represented by a new, updated randomnumber_v2.tar file.

Then, we call the updateMicroservice() method of the mimik Client Library, which requires the following parameters:

  • edgeEngineAccessToken
  • microservice
  • imageTarPath
  • envVariables

WHERE

edgeEngineAccessToken is the edgeEngine Access Token.

microservice is the object reference to the deployed edge microservice Lines 5-10in Listing 4 above.

imageTarPath is a file path to where the new, updated edge microservice is stored within the application bundle Lines 12-17

envVariables are any environment variables configuration values for the edge microservice. All need to be explicitly set, every time.

After the call, we validate the result at Lines 21-28.

If the edge microservice update is successful, we get a reference object to the updated edge microservice at Line 21. You can either keep a reference to this object or get it again as needed. We return this object at Line 24.

If there is an issue, we return an error at Line 28.

At this point we are done, the edge microservice has been successfully updated.

Take a moment to review the statements in the code above using these comments as your guide.

Undeploying an edge microservice

Sometimes there is a need to undeploy (uninstall) an edge microservice from the edgeEngine Runtime. The code example below in Listing 5 shows how to accomplish this. A detailed discussion follows the code example.


1: // A valid edgeEngine Access Token is required to call this method. The async return is either a success or an error.
2: func undeployMicroservice(edgeEngineAccessToken: String) async -> Result<Bool, NSError> {
3:
4: // First getting an object reference to deployed edge microservice
5: guard case let .success(microservices) = await self.edgeClient.deployedMicroservices(edgeEngineAccessToken: edgeEngineAccessToken), let microservice = microservices.first else {
6: print("Error")
7: // Getting object reference was unsuccessful, returning error
8: return .failure(NSError.init(domain: "Error", code: 500))
9: }
10:
11: // Calling mimik Client Library method to undeploy the selected edge microservice
12: switch await self.edgeClient.undeployMicroservice(edgeEngineAccessToken: accessToken, microservice: microservice) {
13: case .success:
14: print("Success")
15: // Undeploy was successful, returning success
16: return .success(true)
17: case .failure(let error):
18: print("Error", error.localizedDescription)
19: // Undeploy was unsuccessful, returning error
20: return .failure(NSError.init(domain: "Error", code: 500))
21: }
22: }

Listing 5: Undeploying an edge microservice


First, we get an object reference to the deployed edge microservice on Lines 5-9. We are simplifying the example code, by simply getting a reference to the first edge microservice we receive in the array. In a production application, you'd want to do additional checks to make sure that the correct edge microservice has been selected especially if there are multiple edge microservices deployed.

Then, we call the undeployMicroservice() method of the mimik Client Library, which requires the following parameters:

  • edgeEngineAccessToken
  • microservice

WHERE

edgeEngineAccessToken is the edgeEngine Access Token. microservice is the object reference to the deployed edge microservice Lines 5-9

After the call, we validate the result at Lines 13-20

If the edge microservice undeployment is successful, we return a success at Line 16. If there is an issue, we return an error at Line 20.

At this point we are done, the edge microservice has been successfully undeployed and is no longer functional.

Take a moment to review the statements in the code above using these comments as your guide.

Was this article helpful?

© mimik technology, Inc. all rights reserved