Android Management - How to send bulk request? - android-management-api

We have been using Android Management APIs to enroll devices in an enterprise and provide restricted environment to our users. We have a requirement where we need to bulk update all the devices by making a patch request using this API: https://developers.google.com/android/management/reference/rest/v1/enterprises.devices/patch
What I am looking for is that instead of sending requests one by one in an arbitrary fashion, is there any way I can send bulk requests and receive a response when all the devices are updated?
Note: I am already aware of how to do it one by one.
Help appreciated, thanks.

Use the AndroidManagement.batch() API to queue several requests for execution and reduce the connections your client makes. The now deprecated Google EMM API documentation has more information about this.
Here's a pseudo example on how to create a batch request, queue a device patch call and execute the request thereafter.
AndroidManagement amapi;
var batchRequest = amapi.batch();
amapi.enterprises().devices().patch(deviceName, content).queue(batchRequest, new JsonBatchCallback<>() {
#Override
public void onFailure(GoogleJsonError e, HttpHeaders responseHeaders) throws IOException {
}
#Override
public void onSuccess(com.google.api.services.androidmanagement.v1.model.Device device, HttpHeaders responseHeaders) throws IOException {
updateDevice(device);
}
});
// queue another device patch request...
// execute all queued requests
batchRequest.execute();
Please note that if you want to do a bulk update in order to save on the API usage limit, this will not help you. All requests in your batch will be counted separately when it comes to limits. There is no way around this.

Can you give more context about what you are trying to achieve? Perhaps what you want to do can be achieved with a policy. For example, to install an app on multiple devices, you could apply the same policy to those devices, and then add these lines to the policy:
"applications": [
{
"packageName": "com.google.samples.apps.iosched",
"installType": "FORCE_INSTALLED"
}
]
Regarding batch requests, here’s a sample code on how you can do batch requests in Android Management API.
def list_devices(request_id, response, exception):
"""Do something with the devices list response."""
if exception is not None:
# Do something with the exception.
pass
else:
# Do something with the response.
pass
get_device1 = androidmanagement.enterprises().devices().get(name=deviceName)
get_device2 = androidmanagement.enterprises().devices().get(name=deviceName)
batch = androidmanagement.new_batch_http_request();
batch.add(get_device1, list_devices)
batch.add(get_device2, list_devices)
batch.execute()
You may also check this link for more details about new_batch_http_request.

"You can use the batch() call on AndroidEnterprise and execute bulk requests by calling BatchRequest.execute().
Please note, you are limited to 1000 calls in a single batch request, so if you need to make more calls than that, use multiple batch requests.
Here's the format you can refer to: EMM API batch format.
Along with an example: EMM API batch example."

Related

HTTP Status to return if resources are partially created in Spring boot - rest api?

I've a scenario where a post request from first microservice creates new user and creates a wallet for newly created user from different microservice.
I'm returning HTTP status 201 when both user and wallet created. I'm bit confused what status should I return if user is created but wallet isn't.
I came across some articles and found two relevant to my confusion but are contradictory on returning HTTP status 207 due to its limitation related to WebDAV.
Is Http response 207 MULTI-STATUS appropriate for multi task operations?
REST API response in partial success
refer my code -
#PostMapping("/register")
public ResponseEntity<User> saveUser(#RequestBody User user) {
user.setUserId(sequenceGeneratorService.generateSequence(User.SEQUENCE_NAME));
user.getRoles().forEach(role -> role.setRoleId(sequenceGeneratorService.generateSequence(Role.SEQUENCE_NAME)));
User savedUser = userService.saveUser(user);
ResponseEntity<Wallet> createdWallet = createUserWallet(savedUser);
if (createdWallet.getStatusCode().is2xxSuccessful()) {
savedUser.setWallet(createdWallet.getBody());
return new ResponseEntity<User>(savedUser, HttpStatus.CREATED);
} else {// here is the confusion
return new ResponseEntity<User>(savedUser, HttpStatus.MULTI_STATUS);
}
}
private ResponseEntity<Wallet> createUserWallet(User savedUser) {
Wallet userWallet = Wallet.builder()
.walletId(sequenceGeneratorService.generateSequence(Wallet.SEQUENCE_NAME))
.userId(savedUser.getUserId())
.balance(BigDecimal.ZERO).build();
return walletServiceProxy.createWallet(userWallet);
}
May I know which status should I return here?
I'm returning HTTP status 201 when both user and wallet created. I'm bit confused what status should I return if user is created but wallet isn't.
HTTP status codes are metadata of the transfer-of-documents-over-a-network domain (see Webber 2011); they are there so that general purpose HTTP components can correctly interpret the response, and do intelligent things (like invalidating previously cached responses, when appropriate).
Your HTTP API is a facade: a costume that your implementation wears that makes it look like an HTTP aware document store. (The fact that your implementation doesn't have "documents" is an implementation detail, hidden behind this facade.)
The responses you send should be understood in this same way - you are telling the HTTP client (and also any intermediary components who can read the response metadata) how your (imaginary) web page reacted to the request that was sent.
Was the message processed successfully? Did it create a new (imaginary) web page with its own identifier, that clients can send messages to? Then you should normally be sending back a 201 Created, even if the implementation didn't achieve that outcome via the "happy path".
On the other hand, if you want general purpose components to understand that request processing failed, you send a 4XX Client Error or a 5XX Server Error, as appropriate.
(You probably shouldn't be using 207 MultiStatus unless you are deliberately doing WebDav things and are expecting requests from WebDav aware components; it doesn't achieve anything useful unless the client implementation knows how to handle multistatus XML documents).
Reminder: the part of an HTTP response where you describe in detail what happened and how the end consumer can respond to it is the body of the HTTP response.
201 Created
Location: /users/12345
Content-Type: text/plain
Hey, we created the new user you asked us to. Isn't that great?
You can review the details of the user at: /users/12345
But, we weren't able to create a wallet for the user. If that's
kind of important to you, could you fill in this form and send it
to us: /lost-wallets#form ?
Thanks, and have a great day

Background processing on C# web api controller

I'm new on .NET technology and come into some problem. Currenlty i'm trying to build a REST API that handle long processing before sending the result to client.
What i'm trying to achieve is, i would like to do a background processing after receiving request from client. But, i would also like to send a response to client.
In short, it would be something like this.
Client Request -> Handled by controller ( doing some processing ) -> send response directly, ignoring the background that still running.
On Java, i can do this using Runnable Thread. How can i achieve this on C# Web API ?
Thank you.
In short, don't do this.
The job of an API is not to perform heavy duty, long running tasks.
You could simply let the API receive the request to perform something, then delegate that to another service. The API can then send a 200 response to show it received the request and maybe a URL to another resource which allows a user to track the progress.
The API needs to be available and responsive at all times. It needs to serve a number of users and if a number of them all request something that uses a lot of resources and takes a lot of time, chances are the API will simply go down and not serve anyone.
This is why you do not do such things in an API. Let other services do the heavy lifting.
Your api can call another async method and return 200/OK response without waiting for the request to complete.
You can learn more about async programing in c#.
static async Task Main(string[] args)
{
Console.WriteLine("coffee is ready");
var toastTask = MakeToastWithButterAndJamAsync(2);
async Task<Toast> MakeToastWithButterAndJamAsync(int number)
{
//Do something here.
}
}
This can be achieve this using loosed coupled architecture, by introducing service bus or blob storage, once you receive request in web api you can save it to blob/service bus and return acknowlegement response from web api. From service bus/blob storage use webjob/function/ durable function app to process the message using event.

How to make a OkHttp call within a Android.WorkManager?

I have several OkHttp requests that I need to send and even if there is no internet for some time, in the end they have to be delivered. It seems that WorkManager is a good API that can handle this.
But how to integrate OkHttp requests and WorkManager?
And (second) be able to get notifications?
I have recently used same as you want:
You can do that like:
#NonNull
#Override
public Result doWork() {
// DO OKHTTP REQUEST HERE........
return Result.success();
}
Note : Do not use any UI thread here like progress bar.

How to design a spring boot application that can process 1k requests a second

I have a rest controller which accepts post requests and returns the statuses of whether the operations are successfull or not. It works fine for 100 requests per second as I have multiple operations underlying it which at the end send the response.
There could be hundreds of users trying to send the requests to the controller, thereby its all done using a completable future and http Async invoker. The problem happens when there are a 1000 requests per second and then the controller threads are exhausted as there are already multiple thread processing multiple requests and all are waiting for there future to be complete and then sending the response.
How can I make my rest controller be able to handle 1000 requests per Second without breaking.
there are already multiple thread processing multiple requests and all are waiting for there future to be complete and then sending the response.
You can actually make you controllers asynchronous by making them return a CompletableFuture. Just chain the calls on the CompletableFuture returned by your service to convert them into a an appropriate response instead of using get() or join():
#RequestMapping
public CompletableFuture<ResponseEntity<…>> processRequest() {
return myService.getStatusFuture()
.thenApply(status -> convertToResponseEntity(status));
}
Of course for this to work properly you should have a truly asynchronous service. If you are using #Async or submitting tasks with CompletableFuture.supplyAsync(), this will just move the problem from the HTTP threadpool to another threadpool.
It depends on the servlet server you are using. In the application.properties file, you can use the server.* properties to set the parameters you need.
In this link you can find these properties under the EMBEDDED SERVER CONFIGURATION section. If you are using the default tomcat embedded server, check out the server.tomcat.* properties. Especially the server.tomcat.accept-count, server.tomcat.max-connections and server.tomcat.max-threads properties.

Prevent client repeatedly sending requests

I have a spring controller and request mapped method.
#RequestMapping(value = { "/doSomething.do" })
public ModelAndView emailToNonBelievers(){
.....
// do something which takes lot of time
// send response..
return modelAndView;
}
This method takes very long time, about an hour.(It is for Admin, not users. And Admin doesn't need to wait an hour. Just fire and forget, that's ok. And this is not a batch job)
But I found that client send requests repeatedly with 3 minutes interval(observed 6 times and I stopeed Spring service).
I guess because client didn't get any response from server.
If my guess is right, server should response sort of "Your request is accepted, just shut up and wait!!" .
But how to send response(200 ok) before jobs finished in Spring?
Or am I missing something?
In this situation it would be recommended to use asynchronous task processing. Spring comes with out-of-box support for it via #Async annotation.Consult my answer for detailed setup for similar query and here for docs.

Resources