At the end of last year, Amazon released (finally!) The
C ++ SDK for its AWS platform. It is not clear why they took so long to drag on - there are a lot of applications written in C ++, of which we have long wanted to use AWS conveniently. Not a single java, in fact.
It is always interesting to look at something written in C ++ nowadays from scratch, without the burden of backward compatibility and strange architectural solutions inherent in some of the developments of the past. I will not retell the documentation here, but I will focus on the key points that determine the entire behavior of the SDK.
C ++ 11
As Carthage should have been
destroyed in its time, today all libraries and applications that have not yet switched to C ++ 11 should die. They simply have no place in the modern world. With tears in my eyes, I read posts
like this about libraries, which “in order to expand the audience, they try to do without C ++ 11.” As for me, this decision is somewhere around “we will ride horses, because they are accustomed to cars.” Amazon’s new SDK doesn’t pursue retrogrades - all C ++ 11 features are offered out of the box: auto, smart pointers, lambdas, etc. To give the opportunity to specify a lambda in the form of a callback function is vital, without this even Javascript will laugh us. Well, no new \ delete explicitly, of course. Beauty!
Code simplicity
As a result of the previous item, look only at the code that is obtained as a result. 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 complex and redundant” - why is this worse than Java or Python? And the memory will eat less and run faster.
No extra dependencies
The guys from Amazon understand that every extra dependency creates additional complexity when connecting and building a project, and therefore reduces the number of users. Therefore, AWS C ++ SDK does not depend on boost or on other fundamental frameworks. Even small libraries, like logging, are not in it. The only dependency is the HTTP client. Still, stuffing your own implementation of this business into the SDK would be too much. Out of the box, you can choose to bind to system CURL, WinHTTP, WinInet, or the ability to implement your own implementation.
CMake
World C ++ is moving towards standardization of project descriptions in a small way. CMake may still not be completely defeated yet, 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 has not distinguished itself here either - everything is in CMake and compile for yourself on anything. It is very convenient to work in CLion.
Dependency Injection
Dependency injection as the basis for application configuration. We have the ability to use default implementations from Amazon or, instead, our own literally for everything: http-client, logging, authorization, memory allocator, strategies for speed limiting and retry, handler for asychronic events, etc. As a result, each of these components is small, testable and does not cause problems with integration.
Logging
There are no libraries for logging in dependencies. If you want to receive logs - implement a specific interface and transfer it to the config when the client is initialized. You will receive callback calls with the text of logs - and write them where you want. The default implementation writes everything to the logs in the current folder and deletes the old logs every hour.
Synchronous and asynchronous versions of all operations
Amazon understands that the application architecture is different and therefore all operations are presented in both synchronous and asynchronous versions. In the synchronous version, you are waiting for the end of the operation (perhaps you are waiting for a long time, for example, if you are loading a large file), and after that check what 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 callback function will transfer the data of the request, the response plus some context that you can define before the call in order to understand what the call is and how to handle its result.
void putItemFinished(const DynamoDBClient *client, const PutItemRequest& request, const PutItemOutcome& outcome, const std::shared_ptr<AsyncContext>& context) { if (outcome.IsSuccess()) { SEND_QUEUE.erase(context->GetUUID()); } } auto context = Aws::MakeShared<AsyncContext>("Hello!"); context.SetUUID("UniqueRequestKey"); SEND_QUEUE["UniqueRequestKey"] = putItemRequest; client.PutItemAsync(putItemRequest, &putItemFinished, context);
Again, the glory of C ++ 11: as a callback, you can pass not only a function, but also a class method of some object (via std :: bind) or lambda.
Asynchronous executor support
If you like asynchronous operations and you already have some background-thread pool, asynchronous operations execution class, you can use it to run AWS C ++ SDK operations. Thus, all asynchronous operations in your application will be executed according to one scheme and you will save resources on the background threads that the SDK would otherwise run.
Speed ​​Limit
If you need to limit the data transfer rate for some operations - all in your power. Implement the RateLimiter interface, transfer your implementation to the config when initialized - and get full control of the data transfer band.
No exceptions
The question of using or not using exceptions is a long-standing holivar in the C ++ world. But in an increasing number of examples in recent times, exceptions are being avoided. There are no exceptions in AWS C ++ SDK either. Argued by greater flexibility and performance. I need an error code - check the outcome.IsSuccess (), if there is false - the outcome will also contain additional data about the error. I do not know about you, but I like this approach.
Included default retry strategy
Since any Amazon SDK is first and foremost a story about network operations, you need to understand that network operations often end in errors. Somewhere, Wi-Fi let down, somewhere a mobile network, and somewhere it seemed to be a stable terrestrial channel for some reason refused to download a funny three-byte byte file. AWS C ++ SDK by default tries to repeat the operation that ended in error. The details of the algorithm (the number of retry attempts, the time between attempts) can be controlled by your own implementation of the retry strategy.
Ability to determine memory allocators
If it matters to 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 would you write in C ++?) - you can define your own allocator of 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 to fit 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 good.
Good luck with AWS from C ++ apps!