C ++ SDK for Amazon Web Services

  • Tutorial

At the end of last year, Amazon released (finally!) The C ++ SDK for its AWS platform. It is not clear why they pulled for so long - there are a lot of applications written in C ++, of which I have long wanted to use AWS conveniently. Not a single Java, indeed.

It is always interesting to look at something written in C ++ these days from scratch, without the burden of backward compatibility and strange architectural solutions inherent in some developments of the past. I will not retell the documentation here, but dwell on the key points that determine the entire behavior of the SDK.

C ++ 11


As Carthage was supposed to be destroyed at the time , today all libraries and applications that still have not switched to C ++ 11 should die. They simply do not belong in the modern world. With tears in my eyes, I read posts like this about libraries that "try to do without C ++ 11 to expand the audience." As for me, this decision is somewhere around "we will ride horses, because they are more familiar than cars." Amazon’s new SDK does not chase retrogrades - out of the box we are offered all the features of C ++ 11: auto, smart pointers, lambdas, etc. To give the opportunity to specify a lambda as a callback function is vital, without it even Javascript would ridicule us. Well, no new \ delete explicitly, of course. Beauty!

Code simplicity


As a result of the previous paragraph, look only at the code that results. We put a key-value pair in DynamoDB:

DynamoDBClient client;
AttributeValue haskKeyAttribute;
hashKeyAttribute.SetS("SampleHashKeyValue")
AttributeValue valueAttribute;
valueAttribute.SetS("SampleValue")
PutItemRequest putItemRequest;
putItemRequest.WithTableName("TestTableName").AddItem("HashKey", hashKeyAttribute).AddItem("Value", valueAttribute);
client.PutItem(putItemRequest);


Well, tell me, lovers of expressions like "C ++ is too complicated and redundant" - what is worse than Java or Python? A memory will eat less and run faster.

No unnecessary dependencies


The guys from Amazon understand that every unnecessary addiction creates additional complexity when connecting and assembling a project, and therefore reduces the number of users. Therefore, the AWS C ++ SDK does not depend on boost, nor on other fundamental frameworks. Even small libraries, like logging, are not in it. The only dependency is the HTTP client. Still, pushing your own implementation of this matter into the SDK would be too much. Out of the box, a choice of binding to system CURL, WinHTTP, WinInet or the ability to implement your implementation is offered.

CMake


The C ++ world is moving a little towards standardizing project descriptions. CMake may not yet have won completely, but for those who need to be given the opportunity to build under the widest possible set of platforms and compilers, this option comes to mind first. Amazon did not differ here either - everything is in CMake and compile yourself on anything. It is very convenient to work in CLion.

Dependency injection


Dependency injection as the basis of application configuration. We have the opportunity to use default implementations from Amazon or instead of them our own literally for everything: http-client, logging, authorization, memory allocator, strategies for limiting speed and retrying, asynchronous event handler, etc. As a result, each of these components turns out to be small, testable and not causing integration problems.

Logging


There are no libraries for logging in dependencies. If you want to receive logs, implement a specific interface and pass it to the config when initializing the client. You will receive callbacks with the text of the logs - and write them wherever you want. The default implementation writes everything to the logs in a row, to the current folder and deletes the old logs every hour.

Synchronous and asynchronous versions of all operations


Amazon understands that the architecture of applications is different and therefore all operations are presented in both synchronous and asynchronous versions. In the synchronous version, you wait for the operation to finish (you may wait a long time if, for example, load a large file), and after that check that the function returned:

CreateTableOutcome createTableOutcome = dynamoDbClient->CreateTable(createTableRequest);
  if (createTableOutcome.IsSuccess())
  {
...
  } else {
...
  }


In the asynchronous version, you specify the callback function that will be called at the end of the operation. The request, response data plus some context that you can define before the call will be transferred to the callback function to understand what the call is and how to process its result.

void putItemFinished(const DynamoDBClient *client, const PutItemRequest& request, 
				const PutItemOutcome& outcome,
				const std::shared_ptr& context)
{
 if (outcome.IsSuccess())
 {
 	SEND_QUEUE.erase(context->GetUUID());
 }
}
auto context = Aws::MakeShared("Hello!");
context.SetUUID("UniqueRequestKey");
SEND_QUEUE["UniqueRequestKey"] = putItemRequest;
client.PutItemAsync(putItemRequest, &putItemFinished, context);


Glory to C ++ 11 again: as a callback, you can pass not only a function, but also a class method of some object (via std :: bind) or a lambda.

Asynchronous executor support


If you like asynchronous operations and you already have some pool of background flows in the program, a class for performing asynchronous operations, you can use it to start AWS C ++ SDK operations. Thus, all asynchronous operations in your application will be performed according to one scheme and you will save resources on the background threads that the SDK would launch otherwise.

Speed ​​Limit


If you need to limit the data transfer rate for certain operations - everything is in your power. Implement the RateLimiter interface, transfer your implementation to the config during initialization - and get full control of the data transfer band.

No exceptions


The issue of using or not using exceptions is a long-standing holivar in the C ++ world. But in an increasing number of examples recently, they try to avoid exceptions. There are no exceptions to the AWS C ++ SDK. They argue with greater flexibility and performance. Need an error code - check outcome.IsSuccess (), if false - there will also be additional error data in the outcome. I don’t know about you, but I like this approach.

The default retry retry strategy


Since any Amazon SDK is primarily a story about network operations, you need to understand that network operations often end in errors. Somewhere Wi-Fi failed, somewhere a mobile network, and somewhere a seemingly stable terrestrial channel for some reason refused to download a funny three-terabyte file. The AWS C ++ SDK, by default, attempts to retry a failed operation. The details of the algorithm (the number of retry attempts, the time between attempts) can be controlled by the own implementation of the retry strategy.

Ability to define memory allocators


If it is important for you how much memory your application uses, when it allocates it and when it deletes, how quickly it happens (and for you all this should be interesting, why else do you write in C ++ at all?) - you can define your own allocator memory. To do this, you need to inherit from MemorySystemInterface and define several methods. You can try to pull a good allocator from somewhere, sharpen it for your data volumes and algorithms and get a good performance boost.

Github


Everything lives on GitHub , Issues, Pull Requests are accepted. Contact with the community is well placed.

Good luck using AWS from C ++ applications!

Also popular now: