SlideShare ist ein Scribd-Unternehmen logo
1 von 84
Downloaden Sie, um offline zu lesen
A few words about us
●
●
2
A starting point
3
What is Shrimp? From 30000 feets
4
Why Shrimp was created?
●
●
●
5
But there is another reason
6
We need to go deeper...
7
What is Shrimp? Actually
●
●
8
Shrimp in a simple example
9
Shrimp in a simple example
10
$ curl -o test.webp 
"https://shrimp-demo.stiffstream.com/DSCF6555.jpg?op=resize&width=300&target-format=webp"
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 41162 100 41162 0 0 41162 0 0:00:01 --:--:-- 0:00:01 151k
$ ls -l *.webp
-rw-rw-r-- 1 eao197 eao197 41162 сен 4 08:28 test.webp
Shrimp in a simple example
11
$ curl -o test.webp 
"https://shrimp-demo.stiffstream.com/DSCF6555.jpg?op=resize&width=300&target-format=webp"
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 41162 100 41162 0 0 41162 0 0:00:01 --:--:-- 0:00:01 151k
$ ls -l *.webp
-rw-rw-r-- 1 eao197 eao197 41162 сен 4 08:28 test.webp
More formal description
/<file-name>[?params]
●
●
●
12
Examples
/DSCF6555.jpg
/DSCF6555.jpg?target-format=heic
/DSCF6555.jpg?op=resize&max=1024
/DSCF6555.jpg?op=resize&max=1024&target-format=heic
13
Live demo
14
Project's sources
15
Disclaimer
16
No benchmarks
Dockerfile
17
Technical details start here...
18
Shrimp's internals in a few words
●
●
●
19
A picture is worth a thousand words
20
What is used inside Shrimp?
21
Let's speak about
22
RESTinio in Shrimp
●
●
●
●
23
External Asio context
●
●
24
External Asio context
io_context
io_context
run()
25
External Asio context
// ASIO io_context must outlive sobjectizer.
asio::io_context asio_io_ctx;
// Launch SObjectizer and wait while balancer will be started.
...
so_5::wrapped_env_t sobj{
[&]( so_5::environment_t & env ) {...},
[&]( so_5::environment_params_t & params ) {...} };
// Now we can launch HTTP-server.
restinio::run(
asio_io_ctx,
shrimp::make_http_server_settings(...) );
26
External Asio context
// ASIO io_context must outlive sobjectizer.
asio::io_context asio_io_ctx;
// Launch SObjectizer and wait while balancer will be started.
...
so_5::wrapped_env_t sobj{
[&]( so_5::environment_t & env ) {...},
[&]( so_5::environment_params_t & params ) {...} };
// Now we can launch HTTP-server.
restinio::run(
asio_io_ctx,
shrimp::make_http_server_settings(...) );
27
Asio's io_context object is created.
External Asio context
// ASIO io_context must outlive sobjectizer.
asio::io_context asio_io_ctx;
// Launch SObjectizer and wait while balancer will be started.
...
so_5::wrapped_env_t sobj{
[&]( so_5::environment_t & env ) {...},
[&]( so_5::environment_params_t & params ) {...} };
// Now we can launch HTTP-server.
restinio::run(
asio_io_ctx,
shrimp::make_http_server_settings(...) );
28
SObjectizer is started here.
SObjectizer will be stopped and destroyed before
destruction of io_context.
External Asio context
// ASIO io_context must outlive sobjectizer.
asio::io_context asio_io_ctx;
// Launch SObjectizer and wait while balancer will be started.
...
so_5::wrapped_env_t sobj{
[&]( so_5::environment_t & env ) {...},
[&]( so_5::environment_params_t & params ) {...} };
// Now we can launch HTTP-server.
restinio::run(
asio_io_ctx,
shrimp::make_http_server_settings(...) );
29
RESTinio is started here.
restinio::run() returns only after
shutdown of HTTP-server.
Logging via spdlog
30
Wrapper around spdlog's logger
class http_server_logger_t
{
public:
http_server_logger_t( std::shared_ptr<spdlog::logger> logger ) : m_logger{std::move(logger)} {}
template<typename Builder> void trace( Builder && msg_builder ) {
log_if_enabled( spdlog::level::trace, std::forward<Builder>(msg_builder) );
}
template<typename Builder> void info( Builder && msg_builder ) {
log_if_enabled( spdlog::level::info, std::forward<Builder>(msg_builder) );
}
...
private:
template<typename Builder> void log_if_enabled(
spdlog::level::level_enum lv, Builder && msg_builder ) {
if( m_logger->should_log(lv) ) { m_logger->log( lv, msg_builder() ); }
}
std::shared_ptr<spdlog::logger> m_logger;
};
31
Tie our wrapper type with RESTinio's traits
struct http_server_traits_t
: public restinio::default_traits_t
{
using logger_t = http_server_logger_t;
using request_handler_t = http_req_router_t;
};
32
Tie our wrapper type with RESTinio's traits
struct http_server_traits_t
: public restinio::default_traits_t
{
using logger_t = http_server_logger_t;
using request_handler_t = http_req_router_t;
};
33
Now RESTinio server with this traits will use
instance of http_server_logger_t for logging.
Instantiation of our wrapper
[[nodiscard]] inline auto
make_http_server_settings(
unsigned int thread_pool_size,
const app_params_t & params,
std::shared_ptr<spdlog::logger> logger,
so_5::mbox_t req_handler_mbox )
{
...
return restinio::on_thread_pool< http_server_traits_t >( thread_pool_size )
.port( http_srv_params.m_port )
.protocol( ip_protocol(http_srv_params.m_ip_version) )
.address( http_srv_params.m_address )
.handle_request_timeout( std::chrono::seconds(60) )
.write_http_response_timelimit( std::chrono::seconds(60) )
.logger( std::move(logger) )
.request_handler( make_router( params, req_handler_mbox ) );
}
34
Instantiation of our wrapper
[[nodiscard]] inline auto
make_http_server_settings(
unsigned int thread_pool_size,
const app_params_t & params,
std::shared_ptr<spdlog::logger> logger,
so_5::mbox_t req_handler_mbox )
{
...
return restinio::on_thread_pool< http_server_traits_t >( thread_pool_size )
.port( http_srv_params.m_port )
.protocol( ip_protocol(http_srv_params.m_ip_version) )
.address( http_srv_params.m_address )
.handle_request_timeout( std::chrono::seconds(60) )
.write_http_response_timelimit( std::chrono::seconds(60) )
.logger( std::move(logger) )
.request_handler( make_router( params, req_handler_mbox ) );
}
35
Instantiation of our wrapper
[[nodiscard]] inline auto
make_http_server_settings(
unsigned int thread_pool_size,
const app_params_t & params,
std::shared_ptr<spdlog::logger> logger,
so_5::mbox_t req_handler_mbox )
{
...
return restinio::on_thread_pool< http_server_traits_t >( thread_pool_size )
.port( http_srv_params.m_port )
.protocol( ip_protocol(http_srv_params.m_ip_version) )
.address( http_srv_params.m_address )
.handle_request_timeout( std::chrono::seconds(60) )
.write_http_response_timelimit( std::chrono::seconds(60) )
.logger( std::move(logger) )
.request_handler( make_router( params, req_handler_mbox ) );
}
36
Object of type http_server_traits_t::logger_t
(aka http_server_logger_t) will be created here.
Spdlog's logger will be passed to the
constructor of that object.
Log example (with --restinio-tracing -l trace)
37
ExpressJS-like routing
38
ExpressJS-like routing
using http_req_router_t =
restinio::router::express_router_t<
restinio::router::pcre_regex_engine_t<
restinio::router::pcre_traits_t<
// Max capture groups for regex.
5 > > >;
39
ExpressJS-like routing
using http_req_router_t =
restinio::router::express_router_t<
restinio::router::pcre_regex_engine_t<
restinio::router::pcre_traits_t<
// Max capture groups for regex.
5 > > >;
40
Express router can use different engines.
There are engines based on std::regex, Boost.Regex
and PCRE/PCRE2.
A PCRE-based engine is used here.
ExpressJS-like routing
struct http_server_traits_t
: public restinio::default_traits_t
{
using logger_t = http_server_logger_t;
using request_handler_t = http_req_router_t;
};
41
ExpressJS-like routing
void add_transform_op_handler(
const app_params_t & app_params,
http_req_router_t & router,
so_5::mbox_t req_handler_mbox )
{
router.http_get(
R"(/:path(.*).:ext(.{3,4}))",
restinio::path2regex::options_t{}.strict( true ),
[req_handler_mbox, &app_params]( auto req, auto params ) {...} );
}
42
ExpressJS-like routing
void add_transform_op_handler(
const app_params_t & app_params,
http_req_router_t & router,
so_5::mbox_t req_handler_mbox )
{
router.http_get(
R"(/:path(.*).:ext(.{3,4}))",
restinio::path2regex::options_t{}.strict( true ),
[req_handler_mbox, &app_params]( auto req, auto params ) {...} );
}
43
A route with two arguments ('path' and 'ext') is defined here.
sendfile for serving original files
sendfile() TransmitFile()
44
sendfile for serving original files
[[nodiscard]] restinio::request_handling_status_t
serve_as_regular_file(const std::string & root_dir, restinio::request_handle_t req, image_format_t image_format)
{
const auto full_path = make_full_path( root_dir, req->header().path() );
try {
auto sf = restinio::sendfile( full_path );
const auto last_modified = sf.meta().last_modified_at();
auto resp = req->create_response();
return set_common_header_fields_for_image_resp( last_modified, resp )
.append_header( restinio::http_field::content_type, image_content_type_from_img_format(image_format) )
.append_header( restinio::http_header_field_t{
http_header::shrimp_image_src_hf(),
image_src_to_str( http_header::image_src_t::sendfile ) } )
.set_body( std::move(sf) )
.done();
}
catch(...) { }
return do_404_response( std::move( req ) );
}
45
sendfile for serving original files
[[nodiscard]] restinio::request_handling_status_t
serve_as_regular_file(const std::string & root_dir, restinio::request_handle_t req, image_format_t image_format)
{
const auto full_path = make_full_path( root_dir, req->header().path() );
try {
auto sf = restinio::sendfile( full_path );
const auto last_modified = sf.meta().last_modified_at();
auto resp = req->create_response();
return set_common_header_fields_for_image_resp( last_modified, resp )
.append_header( restinio::http_field::content_type, image_content_type_from_img_format(image_format) )
.append_header( restinio::http_header_field_t{
http_header::shrimp_image_src_hf(),
image_src_to_str( http_header::image_src_t::sendfile ) } )
.set_body( std::move(sf) )
.done();
}
catch(...) { }
return do_404_response( std::move( req ) );
}
46
sendfile operation is defined here.
sendfile for serving original files
[[nodiscard]] restinio::request_handling_status_t
serve_as_regular_file(const std::string & root_dir, restinio::request_handle_t req, image_format_t image_format)
{
const auto full_path = make_full_path( root_dir, req->header().path() );
try {
auto sf = restinio::sendfile( full_path );
const auto last_modified = sf.meta().last_modified_at();
auto resp = req->create_response();
return set_common_header_fields_for_image_resp( last_modified, resp )
.append_header( restinio::http_field::content_type, image_content_type_from_img_format(image_format) )
.append_header( restinio::http_header_field_t{
http_header::shrimp_image_src_hf(),
image_src_to_str( http_header::image_src_t::sendfile ) } )
.set_body( std::move(sf) )
.done();
}
catch(...) { }
return do_404_response( std::move( req ) );
}
47
sendfile operation is used here for sending file's content as
response's body.
The next big topic
48
Actors in Shrimp
●
●
49
Actors in Shrimp
50
Actors in Shrimp
51
transformer agent
class a_transformer_t final : public so_5::agent_t
{
public:
struct resize_request_t final : public so_5::message_t {...};
a_transformer_t(context_t ctx, std::shared_ptr<spdlog::logger> logger, storage_params_t cfg);
void so_define_agent() override {
so_subscribe_self().event( &a_transformer_t::on_resize_request );
}
private:
...
on_resize_request(mutable_mhood_t<resize_request_t> cmd);
...
};
52
transformer agent
class a_transformer_t final : public so_5::agent_t
{
public:
struct resize_request_t final : public so_5::message_t {...};
a_transformer_t(context_t ctx, std::shared_ptr<spdlog::logger> logger, storage_params_t cfg);
void so_define_agent() override {
so_subscribe_self().event( &a_transformer_t::on_resize_request );
}
private:
...
on_resize_request(mutable_mhood_t<resize_request_t> cmd);
...
};
53
Message to be handled.
transformer agent
class a_transformer_t final : public so_5::agent_t
{
public:
struct resize_request_t final : public so_5::message_t {...};
a_transformer_t(context_t ctx, std::shared_ptr<spdlog::logger> logger, storage_params_t cfg);
void so_define_agent() override {
so_subscribe_self().event( &a_transformer_t::on_resize_request );
}
private:
...
on_resize_request(mutable_mhood_t<resize_request_t> cmd);
...
};
54
Subscription to the message.
When message resize_request_t arrives the
on_resize_request() method will be called.
Type of message to be subscribed is deduced from
handler's prototype.
transform_manager agent
55
transform_manager agent (1)
class a_transform_manager_t final : public so_5::agent_t
{
public:
struct resize_request_t final : public so_5::message_t {...};
struct resize_result_t final : public so_5::message_t {...};
struct delete_cache_request_t final : public so_5::message_t {...};
a_transform_manager_t(context_t ctx, std::shared_ptr<spdlog::logger> logger);
void so_define_agent() override;
void so_evt_start() override;
...
56
transform_manager agent (1)
class a_transform_manager_t final : public so_5::agent_t
{
public:
struct resize_request_t final : public so_5::message_t {...};
struct resize_result_t final : public so_5::message_t {...};
struct delete_cache_request_t final : public so_5::message_t {...};
a_transform_manager_t(context_t ctx, std::shared_ptr<spdlog::logger> logger);
void so_define_agent() override;
void so_evt_start() override;
...
57
Those are "public" messages. They are sent to transform_manager by external
entities:
● resize_request_t and delete_cache_request_t are sent by HTTP-server;
● resize_result_t is sent by transformer agent.
transform_manager agent (2)
private :
struct negative_delete_cache_response_t : public so_5::message_t {...};
struct clear_cache_t final : public so_5::signal_t {};
struct check_pending_requests_t final : public so_5::signal_t {};
...
void on_resize_request(mutable_mhood_t<resize_request_t> cmd);
void on_resize_result(mutable_mhood_t<resize_result_t> cmd);
void on_delete_cache_request(mutable_mhood_t<delete_cache_request_t> cmd);
void on_negative_delete_cache_response(
mutable_mhood_t<negative_delete_cache_response_t> cmd);
void on_clear_cache(mhood_t<clear_cache_t>);
void on_check_pending_requests(mhood_t<check_pending_requests_t>);
...
};
58
transform_manager agent (2)
private :
struct negative_delete_cache_response_t : public so_5::message_t {...};
struct clear_cache_t final : public so_5::signal_t {};
struct check_pending_requests_t final : public so_5::signal_t {};
...
void on_resize_request(mutable_mhood_t<resize_request_t> cmd);
void on_resize_result(mutable_mhood_t<resize_result_t> cmd);
void on_delete_cache_request(mutable_mhood_t<delete_cache_request_t> cmd);
void on_negative_delete_cache_response(
mutable_mhood_t<negative_delete_cache_response_t> cmd);
void on_clear_cache(mhood_t<clear_cache_t>);
void on_check_pending_requests(mhood_t<check_pending_requests_t>);
...
};
59
Those are "private" message and signals. transform_manager sends them to itself.
transform_manager agent (3)
void a_transform_manager_t::so_define_agent()
{
so_subscribe_self()
.event( &a_transform_manager_t::on_resize_request )
.event( &a_transform_manager_t::on_resize_result )
.event( &a_transform_manager_t::on_delete_cache_request )
.event( &a_transform_manager_t::on_negative_delete_cache_response )
.event( &a_transform_manager_t::on_clear_cache )
.event( &a_transform_manager_t::on_check_pending_requests );
}
60
Basic working scheme
a_transform_manager_t::resize_request_t
61
Basic working scheme
a_transform_manager_t::resize_request_t
62
void handle_resize_op_request(
const so_5::mbox_t & req_handler_mbox,
image_format_t image_format,
const restinio::query_string_params_t & qp,
restinio::request_handle_t req )
{
try_to_handle_request( [&]{
auto op_params = transform::resize_params_t::make(
restinio::opt_value< std::uint32_t >( qp, "width" ),
restinio::opt_value< std::uint32_t >( qp, "height" ),
restinio::opt_value< std::uint32_t >( qp, "max" ) );
transform::resize_params_constraints_t{}.check( op_params );
std::string image_path{ req->header().path() };
so_5::send< so_5::mutable_msg<a_transform_manager_t::resize_request_t> >(
req_handler_mbox,
std::move(req), std::move(image_path), image_format, op_params );
},
req );
}
Basic working scheme
a_transformer_t::resize_request_t
63
Basic working scheme
a_transformer_t::resize_request_t
64
void a_transform_manager_t::try_initiate_pending_requests_processing()
{
while( !m_free_workers.empty() && !m_pending_requests.empty() ) {
auto atoken = m_pending_requests.oldest().value();
const auto key = atoken.key();
m_pending_requests.extract_values_for_key( std::move(atoken),
[&]( auto && value ) {
m_inprogress_requests.insert( transform::resize_request_key_t{key}, std::move(value) );
} );
auto worker = std::move(m_free_workers.top());
m_free_workers.pop();
m_logger->trace("initiate processing of a request; request_key={}, worker_mbox={}",
key, worker->id());
so_5::send< so_5::mutable_msg<a_transformer_t::resize_request_t> >(worker, key, so_direct_mbox());
}
}
Basic working scheme
a_transform_manager_t::resize_result_t
65
Basic working scheme
a_transform_manager_t::resize_result_t
66
void a_transformer_t::on_resize_request(
mutable_mhood_t<resize_request_t> cmd)
{
auto result = handle_resize_request( cmd->m_key );
so_5::send< so_5::mutable_msg<a_transform_manager_t::resize_result_t> >(
cmd->m_reply_to,
so_direct_mbox(),
std::move(cmd->m_key),
std::move(result) );
}
Basic working scheme
67
Basic working scheme
68
void a_transform_manager_t::on_resize_result(
mutable_mhood_t<resize_result_t> cmd )
{
m_logger->trace( "resize_result received; request_key={}, worker_mbox={}",
cmd->m_key,
cmd->m_worker->id() );
m_free_workers.push( std::move(cmd->m_worker) );
try_initiate_pending_requests_processing();
auto key = std::move(cmd->m_key);
auto requests = extract_inprogress_requests(
std::move(m_inprogress_requests.find_first_for_key( key ).value()) );
std::visit( variant_visitor{
[&]( successful_resize_t & result ) {
on_successful_resize( std::move(key), result, std::move(requests) );
},
[&]( failed_resize_t & result ) {
on_failed_resize( std::move(key), result, std::move(requests) );
} },
cmd->m_result );
}
Basic working scheme
69
void a_transform_manager_t::on_resize_result(
mutable_mhood_t<resize_result_t> cmd )
{
m_logger->trace( "resize_result received; request_key={}, worker_mbox={}",
cmd->m_key,
cmd->m_worker->id() );
m_free_workers.push( std::move(cmd->m_worker) );
try_initiate_pending_requests_processing();
auto key = std::move(cmd->m_key);
auto requests = extract_inprogress_requests(
std::move(m_inprogress_requests.find_first_for_key( key ).value()) );
std::visit( variant_visitor{
[&]( successful_resize_t & result ) {
on_successful_resize( std::move(key), result, std::move(requests) );
},
[&]( failed_resize_t & result ) {
on_failed_resize( std::move(key), result, std::move(requests) );
} },
cmd->m_result );
}
void a_transform_manager_t::on_failed_resize(
transform::resize_request_key_t key,
failed_resize_t & result,
original_request_container_t requests )
{
m_logger->warn( "failed resize; request_key={}, reason={}", key, result.m_reason );
for( auto & rq : requests )
{
m_logger->trace( "sending negative response back; request_key={}, connection_id={}",
key, rq->m_http_req->connection_id() );
do_404_response( std::move(rq->m_http_req) );
}
}
Providing work threads to agents
70
Providing work threads to agents (1)
[[nodiscard]] so_5::mbox_t
create_agents(
spdlog::sink_ptr logger_sink,
const shrimp::app_params_t & app_params,
so_5::environment_t & env,
unsigned int worker_threads_count )
{
using namespace shrimp;
using namespace so_5::disp::one_thread; // For create_private_disp.
so_5::mbox_t manager_mbox;
env.introduce_coop([&]( so_5::coop_t & coop ) {
auto manager = coop.make_agent_with_binder< a_transform_manager_t >(
create_private_disp( env, "manager" )->binder(),
make_logger( "manager", logger_sink ) );
manager_mbox = manager->so_direct_mbox();
71
Providing work threads to agents (1)
[[nodiscard]] so_5::mbox_t
create_agents(
spdlog::sink_ptr logger_sink,
const shrimp::app_params_t & app_params,
so_5::environment_t & env,
unsigned int worker_threads_count )
{
using namespace shrimp;
using namespace so_5::disp::one_thread; // For create_private_disp.
so_5::mbox_t manager_mbox;
env.introduce_coop([&]( so_5::coop_t & coop ) {
auto manager = coop.make_agent_with_binder< a_transform_manager_t >(
create_private_disp( env, "manager" )->binder(),
make_logger( "manager", logger_sink ) );
manager_mbox = manager->so_direct_mbox();
72
transform_manager agent is created and is bound to separate
one_thread dispatcher. It means that transform_manager will
have its own work thread.
Providing work threads to agents (2)
// Every worker will work on its own private dispatcher.
for( unsigned int worker{}; worker < worker_threads_count; ++worker )
{
const auto worker_name = fmt::format( "worker_{}", worker );
auto transformer = coop.make_agent_with_binder< a_transformer_t >(
create_private_disp( env, worker_name )->binder(),
make_logger( worker_name, logger_sink ),
app_params.m_storage );
manager->add_worker( transformer->so_direct_mbox() );
}
} );
return manager_mbox;
}
73
Providing work threads to agents (2)
// Every worker will work on its own private dispatcher.
for( unsigned int worker{}; worker < worker_threads_count; ++worker )
{
const auto worker_name = fmt::format( "worker_{}", worker );
auto transformer = coop.make_agent_with_binder< a_transformer_t >(
create_private_disp( env, worker_name )->binder(),
make_logger( worker_name, logger_sink ),
app_params.m_storage );
manager->add_worker( transformer->so_direct_mbox() );
}
} );
return manager_mbox;
}
74
The same is for every transformer agent.
And now the end is near...
75
The results of the experiment
76
It's not a 10-lines HelloWorld
77
It's not a 10-lines HelloWorld
#include <restinio/all.hpp>
int main()
{
restinio::run(
restinio::on_this_thread<>()
.port(8080)
.address("localhost")
.request_handler([](auto req) {
return req->create_response().set_body("Hello, World!").done();
}));
return 0;
}
78
It's not a 10-lines HelloWorld
#include <restinio/all.hpp>
int main()
{
restinio::run(
restinio::on_this_thread<>()
.port(8080)
.address("localhost")
.request_handler([](auto req) {
return req->create_response().set_body("Hello, World!").done();
}));
return 0;
}
79
It's not a 10-lines HelloWorld
#include <restinio/all.hpp>
int main()
{
restinio::run(
restinio::on_this_thread<>()
.port(8080)
.address("localhost")
.request_handler([](auto req) {
return req->create_response().set_body("Hello, World!").done();
}));
return 0;
}
80
New ideas for implementation
81
We are open for new ideas...
82
References at one place
83
That's all
84

Weitere ähnliche Inhalte

Was ist angesagt?

Serverless, The Middy Way - Workshop
Serverless, The Middy Way - WorkshopServerless, The Middy Way - Workshop
Serverless, The Middy Way - WorkshopLuciano Mammino
 
Jdk 7 4-forkjoin
Jdk 7 4-forkjoinJdk 7 4-forkjoin
Jdk 7 4-forkjoinknight1128
 
Java9 Beyond Modularity - Java 9 más allá de la modularidad
Java9 Beyond Modularity - Java 9 más allá de la modularidadJava9 Beyond Modularity - Java 9 más allá de la modularidad
Java9 Beyond Modularity - Java 9 más allá de la modularidadDavid Gómez García
 
Avoiding Callback Hell with Async.js
Avoiding Callback Hell with Async.jsAvoiding Callback Hell with Async.js
Avoiding Callback Hell with Async.jscacois
 
Behind modern concurrency primitives
Behind modern concurrency primitivesBehind modern concurrency primitives
Behind modern concurrency primitivesBartosz Sypytkowski
 
Akka.NET streams and reactive streams
Akka.NET streams and reactive streamsAkka.NET streams and reactive streams
Akka.NET streams and reactive streamsBartosz Sypytkowski
 
Callbacks and control flow in Node js
Callbacks and control flow in Node jsCallbacks and control flow in Node js
Callbacks and control flow in Node jsThomas Roch
 
ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency I...
ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency I...ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency I...
ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency I...ZFConf Conference
 
Beyond Profilers: Tracing Node.js Transactions
Beyond Profilers: Tracing Node.js TransactionsBeyond Profilers: Tracing Node.js Transactions
Beyond Profilers: Tracing Node.js TransactionsTerral R Jordan
 
Creating a Java EE 7 Websocket Chat Application
Creating a Java EE 7 Websocket Chat ApplicationCreating a Java EE 7 Websocket Chat Application
Creating a Java EE 7 Websocket Chat ApplicationMicha Kops
 
DRYing to Monad in Java8
DRYing to Monad in Java8DRYing to Monad in Java8
DRYing to Monad in Java8Dhaval Dalal
 
Unit Testing Express and Koa Middleware in ES2015
Unit Testing Express and Koa Middleware in ES2015Unit Testing Express and Koa Middleware in ES2015
Unit Testing Express and Koa Middleware in ES2015Morris Singer
 
服务框架: Thrift & PasteScript
服务框架: Thrift & PasteScript服务框架: Thrift & PasteScript
服务框架: Thrift & PasteScriptQiangning Hong
 
Client server part 12
Client server part 12Client server part 12
Client server part 12fadlihulopi
 
Asynchronous programming done right - Node.js
Asynchronous programming done right - Node.jsAsynchronous programming done right - Node.js
Asynchronous programming done right - Node.jsPiotr Pelczar
 
JVM Mechanics: When Does the JVM JIT & Deoptimize?
JVM Mechanics: When Does the JVM JIT & Deoptimize?JVM Mechanics: When Does the JVM JIT & Deoptimize?
JVM Mechanics: When Does the JVM JIT & Deoptimize?Doug Hawkins
 

Was ist angesagt? (20)

Serverless, The Middy Way - Workshop
Serverless, The Middy Way - WorkshopServerless, The Middy Way - Workshop
Serverless, The Middy Way - Workshop
 
Jdk 7 4-forkjoin
Jdk 7 4-forkjoinJdk 7 4-forkjoin
Jdk 7 4-forkjoin
 
Java9 Beyond Modularity - Java 9 más allá de la modularidad
Java9 Beyond Modularity - Java 9 más allá de la modularidadJava9 Beyond Modularity - Java 9 más allá de la modularidad
Java9 Beyond Modularity - Java 9 más allá de la modularidad
 
Forgive me for i have allocated
Forgive me for i have allocatedForgive me for i have allocated
Forgive me for i have allocated
 
Avoiding Callback Hell with Async.js
Avoiding Callback Hell with Async.jsAvoiding Callback Hell with Async.js
Avoiding Callback Hell with Async.js
 
Behind modern concurrency primitives
Behind modern concurrency primitivesBehind modern concurrency primitives
Behind modern concurrency primitives
 
Akka.NET streams and reactive streams
Akka.NET streams and reactive streamsAkka.NET streams and reactive streams
Akka.NET streams and reactive streams
 
Callbacks and control flow in Node js
Callbacks and control flow in Node jsCallbacks and control flow in Node js
Callbacks and control flow in Node js
 
ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency I...
ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency I...ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency I...
ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency I...
 
Beyond Profilers: Tracing Node.js Transactions
Beyond Profilers: Tracing Node.js TransactionsBeyond Profilers: Tracing Node.js Transactions
Beyond Profilers: Tracing Node.js Transactions
 
Creating a Java EE 7 Websocket Chat Application
Creating a Java EE 7 Websocket Chat ApplicationCreating a Java EE 7 Websocket Chat Application
Creating a Java EE 7 Websocket Chat Application
 
DRYing to Monad in Java8
DRYing to Monad in Java8DRYing to Monad in Java8
DRYing to Monad in Java8
 
Finatra v2
Finatra v2Finatra v2
Finatra v2
 
Unit Testing Express and Koa Middleware in ES2015
Unit Testing Express and Koa Middleware in ES2015Unit Testing Express and Koa Middleware in ES2015
Unit Testing Express and Koa Middleware in ES2015
 
Full Stack Unit Testing
Full Stack Unit TestingFull Stack Unit Testing
Full Stack Unit Testing
 
服务框架: Thrift & PasteScript
服务框架: Thrift & PasteScript服务框架: Thrift & PasteScript
服务框架: Thrift & PasteScript
 
Client server part 12
Client server part 12Client server part 12
Client server part 12
 
Fidl analysis
Fidl analysisFidl analysis
Fidl analysis
 
Asynchronous programming done right - Node.js
Asynchronous programming done right - Node.jsAsynchronous programming done right - Node.js
Asynchronous programming done right - Node.js
 
JVM Mechanics: When Does the JVM JIT & Deoptimize?
JVM Mechanics: When Does the JVM JIT & Deoptimize?JVM Mechanics: When Does the JVM JIT & Deoptimize?
JVM Mechanics: When Does the JVM JIT & Deoptimize?
 

Ähnlich wie Shrimp: A Rather Practical Example Of Application Development With RESTinio and SObjectizer

marko_go_in_badoo
marko_go_in_badoomarko_go_in_badoo
marko_go_in_badooMarko Kevac
 
CONFidence 2015: DTrace + OSX = Fun - Andrzej Dyjak
CONFidence 2015: DTrace + OSX = Fun - Andrzej Dyjak   CONFidence 2015: DTrace + OSX = Fun - Andrzej Dyjak
CONFidence 2015: DTrace + OSX = Fun - Andrzej Dyjak PROIDEA
 
Debugging Ruby Systems
Debugging Ruby SystemsDebugging Ruby Systems
Debugging Ruby SystemsEngine Yard
 
Доклад Антона Поварова "Go in Badoo" с Golang Meetup
Доклад Антона Поварова "Go in Badoo" с Golang MeetupДоклад Антона Поварова "Go in Badoo" с Golang Meetup
Доклад Антона Поварова "Go in Badoo" с Golang MeetupBadoo Development
 
Performance tweaks and tools for Linux (Joe Damato)
Performance tweaks and tools for Linux (Joe Damato)Performance tweaks and tools for Linux (Joe Damato)
Performance tweaks and tools for Linux (Joe Damato)Ontico
 
Nodejs性能分析优化和分布式设计探讨
Nodejs性能分析优化和分布式设计探讨Nodejs性能分析优化和分布式设计探讨
Nodejs性能分析优化和分布式设计探讨flyinweb
 
Presto anatomy
Presto anatomyPresto anatomy
Presto anatomyDongmin Yu
 
Debugging Ruby
Debugging RubyDebugging Ruby
Debugging RubyAman Gupta
 
Reverse engineering Swisscom's Centro Grande Modem
Reverse engineering Swisscom's Centro Grande ModemReverse engineering Swisscom's Centro Grande Modem
Reverse engineering Swisscom's Centro Grande ModemCyber Security Alliance
 
Replacing Squid with ATS
Replacing Squid with ATSReplacing Squid with ATS
Replacing Squid with ATSKit Chan
 
Why you should be using structured logs
Why you should be using structured logsWhy you should be using structured logs
Why you should be using structured logsStefan Krawczyk
 
Anton Moldovan "Load testing which you always wanted"
Anton Moldovan "Load testing which you always wanted"Anton Moldovan "Load testing which you always wanted"
Anton Moldovan "Load testing which you always wanted"Fwdays
 
Complex Made Simple: Sleep Better with TorqueBox
Complex Made Simple: Sleep Better with TorqueBoxComplex Made Simple: Sleep Better with TorqueBox
Complex Made Simple: Sleep Better with TorqueBoxbobmcwhirter
 
Rhebok, High Performance Rack Handler / Rubykaigi 2015
Rhebok, High Performance Rack Handler / Rubykaigi 2015Rhebok, High Performance Rack Handler / Rubykaigi 2015
Rhebok, High Performance Rack Handler / Rubykaigi 2015Masahiro Nagano
 
Joker 2015 - Валеев Тагир - Что же мы измеряем?
Joker 2015 - Валеев Тагир - Что же мы измеряем?Joker 2015 - Валеев Тагир - Что же мы измеряем?
Joker 2015 - Валеев Тагир - Что же мы измеряем?tvaleev
 
Docker tips-for-java-developers
Docker tips-for-java-developersDocker tips-for-java-developers
Docker tips-for-java-developersAparna Chaudhary
 
[245] presto 내부구조 파헤치기
[245] presto 내부구조 파헤치기[245] presto 내부구조 파헤치기
[245] presto 내부구조 파헤치기NAVER D2
 

Ähnlich wie Shrimp: A Rather Practical Example Of Application Development With RESTinio and SObjectizer (20)

marko_go_in_badoo
marko_go_in_badoomarko_go_in_badoo
marko_go_in_badoo
 
CONFidence 2015: DTrace + OSX = Fun - Andrzej Dyjak
CONFidence 2015: DTrace + OSX = Fun - Andrzej Dyjak   CONFidence 2015: DTrace + OSX = Fun - Andrzej Dyjak
CONFidence 2015: DTrace + OSX = Fun - Andrzej Dyjak
 
Debugging Ruby Systems
Debugging Ruby SystemsDebugging Ruby Systems
Debugging Ruby Systems
 
Solr @ Etsy - Apache Lucene Eurocon
Solr @ Etsy - Apache Lucene EuroconSolr @ Etsy - Apache Lucene Eurocon
Solr @ Etsy - Apache Lucene Eurocon
 
Osol Pgsql
Osol PgsqlOsol Pgsql
Osol Pgsql
 
Доклад Антона Поварова "Go in Badoo" с Golang Meetup
Доклад Антона Поварова "Go in Badoo" с Golang MeetupДоклад Антона Поварова "Go in Badoo" с Golang Meetup
Доклад Антона Поварова "Go in Badoo" с Golang Meetup
 
Performance tweaks and tools for Linux (Joe Damato)
Performance tweaks and tools for Linux (Joe Damato)Performance tweaks and tools for Linux (Joe Damato)
Performance tweaks and tools for Linux (Joe Damato)
 
Nodejs性能分析优化和分布式设计探讨
Nodejs性能分析优化和分布式设计探讨Nodejs性能分析优化和分布式设计探讨
Nodejs性能分析优化和分布式设计探讨
 
Presto anatomy
Presto anatomyPresto anatomy
Presto anatomy
 
Debugging Ruby
Debugging RubyDebugging Ruby
Debugging Ruby
 
Reverse engineering Swisscom's Centro Grande Modem
Reverse engineering Swisscom's Centro Grande ModemReverse engineering Swisscom's Centro Grande Modem
Reverse engineering Swisscom's Centro Grande Modem
 
ReplacingSquidWithATS
ReplacingSquidWithATSReplacingSquidWithATS
ReplacingSquidWithATS
 
Replacing Squid with ATS
Replacing Squid with ATSReplacing Squid with ATS
Replacing Squid with ATS
 
Why you should be using structured logs
Why you should be using structured logsWhy you should be using structured logs
Why you should be using structured logs
 
Anton Moldovan "Load testing which you always wanted"
Anton Moldovan "Load testing which you always wanted"Anton Moldovan "Load testing which you always wanted"
Anton Moldovan "Load testing which you always wanted"
 
Complex Made Simple: Sleep Better with TorqueBox
Complex Made Simple: Sleep Better with TorqueBoxComplex Made Simple: Sleep Better with TorqueBox
Complex Made Simple: Sleep Better with TorqueBox
 
Rhebok, High Performance Rack Handler / Rubykaigi 2015
Rhebok, High Performance Rack Handler / Rubykaigi 2015Rhebok, High Performance Rack Handler / Rubykaigi 2015
Rhebok, High Performance Rack Handler / Rubykaigi 2015
 
Joker 2015 - Валеев Тагир - Что же мы измеряем?
Joker 2015 - Валеев Тагир - Что же мы измеряем?Joker 2015 - Валеев Тагир - Что же мы измеряем?
Joker 2015 - Валеев Тагир - Что же мы измеряем?
 
Docker tips-for-java-developers
Docker tips-for-java-developersDocker tips-for-java-developers
Docker tips-for-java-developers
 
[245] presto 내부구조 파헤치기
[245] presto 내부구조 파헤치기[245] presto 내부구조 파헤치기
[245] presto 내부구조 파헤치기
 

Mehr von Yauheni Akhotnikau

Actor Model and C++: what, why and how? (March 2020 Edition)
Actor Model and C++: what, why and how? (March 2020 Edition)Actor Model and C++: what, why and how? (March 2020 Edition)
Actor Model and C++: what, why and how? (March 2020 Edition)Yauheni Akhotnikau
 
What is SObjectizer 5.7 (at v.5.7.0)
What is SObjectizer 5.7 (at v.5.7.0)What is SObjectizer 5.7 (at v.5.7.0)
What is SObjectizer 5.7 (at v.5.7.0)Yauheni Akhotnikau
 
What is SObjectizer 5.6 (at v.5.6.0)
What is SObjectizer 5.6 (at v.5.6.0)What is SObjectizer 5.6 (at v.5.6.0)
What is SObjectizer 5.6 (at v.5.6.0)Yauheni Akhotnikau
 
[C++ CoreHard Autumn 2018] Actors vs CSP vs Task...
[C++ CoreHard Autumn 2018] Actors vs CSP vs Task...[C++ CoreHard Autumn 2018] Actors vs CSP vs Task...
[C++ CoreHard Autumn 2018] Actors vs CSP vs Task...Yauheni Akhotnikau
 
Акторы в C++: взгляд старого практикующего актородела (St. Petersburg C++ Use...
Акторы в C++: взгляд старого практикующего актородела (St. Petersburg C++ Use...Акторы в C++: взгляд старого практикующего актородела (St. Petersburg C++ Use...
Акторы в C++: взгляд старого практикующего актородела (St. Petersburg C++ Use...Yauheni Akhotnikau
 
Акторы на C++: стоило ли оно того?
Акторы на C++: стоило ли оно того?Акторы на C++: стоило ли оно того?
Акторы на C++: стоило ли оно того?Yauheni Akhotnikau
 
25 Years of C++ History Flashed in Front of My Eyes
25 Years of C++ History Flashed in Front of My Eyes25 Years of C++ History Flashed in Front of My Eyes
25 Years of C++ History Flashed in Front of My EyesYauheni Akhotnikau
 
GECon 2017: C++ - a Monster that no one likes but that will outlast them all
GECon 2017: C++ - a Monster that no one likes but that will outlast them allGECon 2017: C++ - a Monster that no one likes but that will outlast them all
GECon 2017: C++ - a Monster that no one likes but that will outlast them allYauheni Akhotnikau
 
Dive into SObjectizer 5.5. Tenth part: Mutable Messages
Dive into SObjectizer 5.5. Tenth part: Mutable MessagesDive into SObjectizer 5.5. Tenth part: Mutable Messages
Dive into SObjectizer 5.5. Tenth part: Mutable MessagesYauheni Akhotnikau
 
Actor Model and C++: what, why and how?
Actor Model and C++: what, why and how?Actor Model and C++: what, why and how?
Actor Model and C++: what, why and how?Yauheni Akhotnikau
 
Шишки, набитые за 15 лет использования акторов в C++
Шишки, набитые за 15 лет использования акторов в C++Шишки, набитые за 15 лет использования акторов в C++
Шишки, набитые за 15 лет использования акторов в C++Yauheni Akhotnikau
 
Для чего мы делали свой акторный фреймворк и что из этого вышло?
Для чего мы делали свой акторный фреймворк и что из этого вышло?Для чего мы делали свой акторный фреймворк и что из этого вышло?
Для чего мы делали свой акторный фреймворк и что из этого вышло?Yauheni Akhotnikau
 
Модель акторов и C++ что, зачем и как?
Модель акторов и C++ что, зачем и как?Модель акторов и C++ что, зачем и как?
Модель акторов и C++ что, зачем и как?Yauheni Akhotnikau
 
Dive into SObjectizer 5.5. Ninth Part: Message Chains
Dive into SObjectizer 5.5. Ninth Part: Message ChainsDive into SObjectizer 5.5. Ninth Part: Message Chains
Dive into SObjectizer 5.5. Ninth Part: Message ChainsYauheni Akhotnikau
 
Dive into SObjectizer 5.5. Eighth Part: Dispatchers
Dive into SObjectizer 5.5. Eighth Part: DispatchersDive into SObjectizer 5.5. Eighth Part: Dispatchers
Dive into SObjectizer 5.5. Eighth Part: DispatchersYauheni Akhotnikau
 
What's new in SObjectizer 5.5.9
What's new in SObjectizer 5.5.9What's new in SObjectizer 5.5.9
What's new in SObjectizer 5.5.9Yauheni Akhotnikau
 
Dive into SObjectizer 5.5. Seventh part: Message Limits
Dive into SObjectizer 5.5. Seventh part: Message LimitsDive into SObjectizer 5.5. Seventh part: Message Limits
Dive into SObjectizer 5.5. Seventh part: Message LimitsYauheni Akhotnikau
 
Dive into SObjectizer-5.5. Sixth part: Synchronous Interaction
Dive into SObjectizer-5.5. Sixth part: Synchronous InteractionDive into SObjectizer-5.5. Sixth part: Synchronous Interaction
Dive into SObjectizer-5.5. Sixth part: Synchronous InteractionYauheni Akhotnikau
 
Dive into SObjectizer 5.5. Fifth part: Timers
Dive into SObjectizer 5.5. Fifth part: TimersDive into SObjectizer 5.5. Fifth part: Timers
Dive into SObjectizer 5.5. Fifth part: TimersYauheni Akhotnikau
 
What’s new in SObjectizer 5.5.8
What’s new in SObjectizer 5.5.8What’s new in SObjectizer 5.5.8
What’s new in SObjectizer 5.5.8Yauheni Akhotnikau
 

Mehr von Yauheni Akhotnikau (20)

Actor Model and C++: what, why and how? (March 2020 Edition)
Actor Model and C++: what, why and how? (March 2020 Edition)Actor Model and C++: what, why and how? (March 2020 Edition)
Actor Model and C++: what, why and how? (March 2020 Edition)
 
What is SObjectizer 5.7 (at v.5.7.0)
What is SObjectizer 5.7 (at v.5.7.0)What is SObjectizer 5.7 (at v.5.7.0)
What is SObjectizer 5.7 (at v.5.7.0)
 
What is SObjectizer 5.6 (at v.5.6.0)
What is SObjectizer 5.6 (at v.5.6.0)What is SObjectizer 5.6 (at v.5.6.0)
What is SObjectizer 5.6 (at v.5.6.0)
 
[C++ CoreHard Autumn 2018] Actors vs CSP vs Task...
[C++ CoreHard Autumn 2018] Actors vs CSP vs Task...[C++ CoreHard Autumn 2018] Actors vs CSP vs Task...
[C++ CoreHard Autumn 2018] Actors vs CSP vs Task...
 
Акторы в C++: взгляд старого практикующего актородела (St. Petersburg C++ Use...
Акторы в C++: взгляд старого практикующего актородела (St. Petersburg C++ Use...Акторы в C++: взгляд старого практикующего актородела (St. Petersburg C++ Use...
Акторы в C++: взгляд старого практикующего актородела (St. Petersburg C++ Use...
 
Акторы на C++: стоило ли оно того?
Акторы на C++: стоило ли оно того?Акторы на C++: стоило ли оно того?
Акторы на C++: стоило ли оно того?
 
25 Years of C++ History Flashed in Front of My Eyes
25 Years of C++ History Flashed in Front of My Eyes25 Years of C++ History Flashed in Front of My Eyes
25 Years of C++ History Flashed in Front of My Eyes
 
GECon 2017: C++ - a Monster that no one likes but that will outlast them all
GECon 2017: C++ - a Monster that no one likes but that will outlast them allGECon 2017: C++ - a Monster that no one likes but that will outlast them all
GECon 2017: C++ - a Monster that no one likes but that will outlast them all
 
Dive into SObjectizer 5.5. Tenth part: Mutable Messages
Dive into SObjectizer 5.5. Tenth part: Mutable MessagesDive into SObjectizer 5.5. Tenth part: Mutable Messages
Dive into SObjectizer 5.5. Tenth part: Mutable Messages
 
Actor Model and C++: what, why and how?
Actor Model and C++: what, why and how?Actor Model and C++: what, why and how?
Actor Model and C++: what, why and how?
 
Шишки, набитые за 15 лет использования акторов в C++
Шишки, набитые за 15 лет использования акторов в C++Шишки, набитые за 15 лет использования акторов в C++
Шишки, набитые за 15 лет использования акторов в C++
 
Для чего мы делали свой акторный фреймворк и что из этого вышло?
Для чего мы делали свой акторный фреймворк и что из этого вышло?Для чего мы делали свой акторный фреймворк и что из этого вышло?
Для чего мы делали свой акторный фреймворк и что из этого вышло?
 
Модель акторов и C++ что, зачем и как?
Модель акторов и C++ что, зачем и как?Модель акторов и C++ что, зачем и как?
Модель акторов и C++ что, зачем и как?
 
Dive into SObjectizer 5.5. Ninth Part: Message Chains
Dive into SObjectizer 5.5. Ninth Part: Message ChainsDive into SObjectizer 5.5. Ninth Part: Message Chains
Dive into SObjectizer 5.5. Ninth Part: Message Chains
 
Dive into SObjectizer 5.5. Eighth Part: Dispatchers
Dive into SObjectizer 5.5. Eighth Part: DispatchersDive into SObjectizer 5.5. Eighth Part: Dispatchers
Dive into SObjectizer 5.5. Eighth Part: Dispatchers
 
What's new in SObjectizer 5.5.9
What's new in SObjectizer 5.5.9What's new in SObjectizer 5.5.9
What's new in SObjectizer 5.5.9
 
Dive into SObjectizer 5.5. Seventh part: Message Limits
Dive into SObjectizer 5.5. Seventh part: Message LimitsDive into SObjectizer 5.5. Seventh part: Message Limits
Dive into SObjectizer 5.5. Seventh part: Message Limits
 
Dive into SObjectizer-5.5. Sixth part: Synchronous Interaction
Dive into SObjectizer-5.5. Sixth part: Synchronous InteractionDive into SObjectizer-5.5. Sixth part: Synchronous Interaction
Dive into SObjectizer-5.5. Sixth part: Synchronous Interaction
 
Dive into SObjectizer 5.5. Fifth part: Timers
Dive into SObjectizer 5.5. Fifth part: TimersDive into SObjectizer 5.5. Fifth part: Timers
Dive into SObjectizer 5.5. Fifth part: Timers
 
What’s new in SObjectizer 5.5.8
What’s new in SObjectizer 5.5.8What’s new in SObjectizer 5.5.8
What’s new in SObjectizer 5.5.8
 

Kürzlich hochgeladen

CRM Contender Series: HubSpot vs. Salesforce
CRM Contender Series: HubSpot vs. SalesforceCRM Contender Series: HubSpot vs. Salesforce
CRM Contender Series: HubSpot vs. SalesforceBrainSell Technologies
 
Precise and Complete Requirements? An Elusive Goal
Precise and Complete Requirements? An Elusive GoalPrecise and Complete Requirements? An Elusive Goal
Precise and Complete Requirements? An Elusive GoalLionel Briand
 
Software Coding for software engineering
Software Coding for software engineeringSoftware Coding for software engineering
Software Coding for software engineeringssuserb3a23b
 
Introduction Computer Science - Software Design.pdf
Introduction Computer Science - Software Design.pdfIntroduction Computer Science - Software Design.pdf
Introduction Computer Science - Software Design.pdfFerryKemperman
 
Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...
Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...
Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...Cizo Technology Services
 
Cyber security and its impact on E commerce
Cyber security and its impact on E commerceCyber security and its impact on E commerce
Cyber security and its impact on E commercemanigoyal112
 
英国UN学位证,北安普顿大学毕业证书1:1制作
英国UN学位证,北安普顿大学毕业证书1:1制作英国UN学位证,北安普顿大学毕业证书1:1制作
英国UN学位证,北安普顿大学毕业证书1:1制作qr0udbr0
 
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte Germany
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte GermanySuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte Germany
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte GermanyChristoph Pohl
 
Implementing Zero Trust strategy with Azure
Implementing Zero Trust strategy with AzureImplementing Zero Trust strategy with Azure
Implementing Zero Trust strategy with AzureDinusha Kumarasiri
 
How to submit a standout Adobe Champion Application
How to submit a standout Adobe Champion ApplicationHow to submit a standout Adobe Champion Application
How to submit a standout Adobe Champion ApplicationBradBedford3
 
Unveiling the Future: Sylius 2.0 New Features
Unveiling the Future: Sylius 2.0 New FeaturesUnveiling the Future: Sylius 2.0 New Features
Unveiling the Future: Sylius 2.0 New FeaturesŁukasz Chruściel
 
SensoDat: Simulation-based Sensor Dataset of Self-driving Cars
SensoDat: Simulation-based Sensor Dataset of Self-driving CarsSensoDat: Simulation-based Sensor Dataset of Self-driving Cars
SensoDat: Simulation-based Sensor Dataset of Self-driving CarsChristian Birchler
 
Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...
Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...
Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...Matt Ray
 
Folding Cheat Sheet #4 - fourth in a series
Folding Cheat Sheet #4 - fourth in a seriesFolding Cheat Sheet #4 - fourth in a series
Folding Cheat Sheet #4 - fourth in a seriesPhilip Schwarz
 
SpotFlow: Tracking Method Calls and States at Runtime
SpotFlow: Tracking Method Calls and States at RuntimeSpotFlow: Tracking Method Calls and States at Runtime
SpotFlow: Tracking Method Calls and States at Runtimeandrehoraa
 
Ahmed Motair CV April 2024 (Senior SW Developer)
Ahmed Motair CV April 2024 (Senior SW Developer)Ahmed Motair CV April 2024 (Senior SW Developer)
Ahmed Motair CV April 2024 (Senior SW Developer)Ahmed Mater
 
Exploring Selenium_Appium Frameworks for Seamless Integration with HeadSpin.pdf
Exploring Selenium_Appium Frameworks for Seamless Integration with HeadSpin.pdfExploring Selenium_Appium Frameworks for Seamless Integration with HeadSpin.pdf
Exploring Selenium_Appium Frameworks for Seamless Integration with HeadSpin.pdfkalichargn70th171
 
Powering Real-Time Decisions with Continuous Data Streams
Powering Real-Time Decisions with Continuous Data StreamsPowering Real-Time Decisions with Continuous Data Streams
Powering Real-Time Decisions with Continuous Data StreamsSafe Software
 
Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...
Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...
Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...OnePlan Solutions
 

Kürzlich hochgeladen (20)

CRM Contender Series: HubSpot vs. Salesforce
CRM Contender Series: HubSpot vs. SalesforceCRM Contender Series: HubSpot vs. Salesforce
CRM Contender Series: HubSpot vs. Salesforce
 
Precise and Complete Requirements? An Elusive Goal
Precise and Complete Requirements? An Elusive GoalPrecise and Complete Requirements? An Elusive Goal
Precise and Complete Requirements? An Elusive Goal
 
Software Coding for software engineering
Software Coding for software engineeringSoftware Coding for software engineering
Software Coding for software engineering
 
Introduction Computer Science - Software Design.pdf
Introduction Computer Science - Software Design.pdfIntroduction Computer Science - Software Design.pdf
Introduction Computer Science - Software Design.pdf
 
Advantages of Odoo ERP 17 for Your Business
Advantages of Odoo ERP 17 for Your BusinessAdvantages of Odoo ERP 17 for Your Business
Advantages of Odoo ERP 17 for Your Business
 
Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...
Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...
Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...
 
Cyber security and its impact on E commerce
Cyber security and its impact on E commerceCyber security and its impact on E commerce
Cyber security and its impact on E commerce
 
英国UN学位证,北安普顿大学毕业证书1:1制作
英国UN学位证,北安普顿大学毕业证书1:1制作英国UN学位证,北安普顿大学毕业证书1:1制作
英国UN学位证,北安普顿大学毕业证书1:1制作
 
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte Germany
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte GermanySuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte Germany
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte Germany
 
Implementing Zero Trust strategy with Azure
Implementing Zero Trust strategy with AzureImplementing Zero Trust strategy with Azure
Implementing Zero Trust strategy with Azure
 
How to submit a standout Adobe Champion Application
How to submit a standout Adobe Champion ApplicationHow to submit a standout Adobe Champion Application
How to submit a standout Adobe Champion Application
 
Unveiling the Future: Sylius 2.0 New Features
Unveiling the Future: Sylius 2.0 New FeaturesUnveiling the Future: Sylius 2.0 New Features
Unveiling the Future: Sylius 2.0 New Features
 
SensoDat: Simulation-based Sensor Dataset of Self-driving Cars
SensoDat: Simulation-based Sensor Dataset of Self-driving CarsSensoDat: Simulation-based Sensor Dataset of Self-driving Cars
SensoDat: Simulation-based Sensor Dataset of Self-driving Cars
 
Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...
Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...
Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...
 
Folding Cheat Sheet #4 - fourth in a series
Folding Cheat Sheet #4 - fourth in a seriesFolding Cheat Sheet #4 - fourth in a series
Folding Cheat Sheet #4 - fourth in a series
 
SpotFlow: Tracking Method Calls and States at Runtime
SpotFlow: Tracking Method Calls and States at RuntimeSpotFlow: Tracking Method Calls and States at Runtime
SpotFlow: Tracking Method Calls and States at Runtime
 
Ahmed Motair CV April 2024 (Senior SW Developer)
Ahmed Motair CV April 2024 (Senior SW Developer)Ahmed Motair CV April 2024 (Senior SW Developer)
Ahmed Motair CV April 2024 (Senior SW Developer)
 
Exploring Selenium_Appium Frameworks for Seamless Integration with HeadSpin.pdf
Exploring Selenium_Appium Frameworks for Seamless Integration with HeadSpin.pdfExploring Selenium_Appium Frameworks for Seamless Integration with HeadSpin.pdf
Exploring Selenium_Appium Frameworks for Seamless Integration with HeadSpin.pdf
 
Powering Real-Time Decisions with Continuous Data Streams
Powering Real-Time Decisions with Continuous Data StreamsPowering Real-Time Decisions with Continuous Data Streams
Powering Real-Time Decisions with Continuous Data Streams
 
Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...
Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...
Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...
 

Shrimp: A Rather Practical Example Of Application Development With RESTinio and SObjectizer

  • 1.
  • 2. A few words about us ● ● 2
  • 4. What is Shrimp? From 30000 feets 4
  • 5. Why Shrimp was created? ● ● ● 5
  • 6. But there is another reason 6
  • 7. We need to go deeper... 7
  • 8. What is Shrimp? Actually ● ● 8
  • 9. Shrimp in a simple example 9
  • 10. Shrimp in a simple example 10 $ curl -o test.webp "https://shrimp-demo.stiffstream.com/DSCF6555.jpg?op=resize&width=300&target-format=webp" % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 41162 100 41162 0 0 41162 0 0:00:01 --:--:-- 0:00:01 151k $ ls -l *.webp -rw-rw-r-- 1 eao197 eao197 41162 сен 4 08:28 test.webp
  • 11. Shrimp in a simple example 11 $ curl -o test.webp "https://shrimp-demo.stiffstream.com/DSCF6555.jpg?op=resize&width=300&target-format=webp" % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 41162 100 41162 0 0 41162 0 0:00:01 --:--:-- 0:00:01 151k $ ls -l *.webp -rw-rw-r-- 1 eao197 eao197 41162 сен 4 08:28 test.webp
  • 19. Shrimp's internals in a few words ● ● ● 19
  • 20. A picture is worth a thousand words 20
  • 21. What is used inside Shrimp? 21
  • 26. External Asio context // ASIO io_context must outlive sobjectizer. asio::io_context asio_io_ctx; // Launch SObjectizer and wait while balancer will be started. ... so_5::wrapped_env_t sobj{ [&]( so_5::environment_t & env ) {...}, [&]( so_5::environment_params_t & params ) {...} }; // Now we can launch HTTP-server. restinio::run( asio_io_ctx, shrimp::make_http_server_settings(...) ); 26
  • 27. External Asio context // ASIO io_context must outlive sobjectizer. asio::io_context asio_io_ctx; // Launch SObjectizer and wait while balancer will be started. ... so_5::wrapped_env_t sobj{ [&]( so_5::environment_t & env ) {...}, [&]( so_5::environment_params_t & params ) {...} }; // Now we can launch HTTP-server. restinio::run( asio_io_ctx, shrimp::make_http_server_settings(...) ); 27 Asio's io_context object is created.
  • 28. External Asio context // ASIO io_context must outlive sobjectizer. asio::io_context asio_io_ctx; // Launch SObjectizer and wait while balancer will be started. ... so_5::wrapped_env_t sobj{ [&]( so_5::environment_t & env ) {...}, [&]( so_5::environment_params_t & params ) {...} }; // Now we can launch HTTP-server. restinio::run( asio_io_ctx, shrimp::make_http_server_settings(...) ); 28 SObjectizer is started here. SObjectizer will be stopped and destroyed before destruction of io_context.
  • 29. External Asio context // ASIO io_context must outlive sobjectizer. asio::io_context asio_io_ctx; // Launch SObjectizer and wait while balancer will be started. ... so_5::wrapped_env_t sobj{ [&]( so_5::environment_t & env ) {...}, [&]( so_5::environment_params_t & params ) {...} }; // Now we can launch HTTP-server. restinio::run( asio_io_ctx, shrimp::make_http_server_settings(...) ); 29 RESTinio is started here. restinio::run() returns only after shutdown of HTTP-server.
  • 31. Wrapper around spdlog's logger class http_server_logger_t { public: http_server_logger_t( std::shared_ptr<spdlog::logger> logger ) : m_logger{std::move(logger)} {} template<typename Builder> void trace( Builder && msg_builder ) { log_if_enabled( spdlog::level::trace, std::forward<Builder>(msg_builder) ); } template<typename Builder> void info( Builder && msg_builder ) { log_if_enabled( spdlog::level::info, std::forward<Builder>(msg_builder) ); } ... private: template<typename Builder> void log_if_enabled( spdlog::level::level_enum lv, Builder && msg_builder ) { if( m_logger->should_log(lv) ) { m_logger->log( lv, msg_builder() ); } } std::shared_ptr<spdlog::logger> m_logger; }; 31
  • 32. Tie our wrapper type with RESTinio's traits struct http_server_traits_t : public restinio::default_traits_t { using logger_t = http_server_logger_t; using request_handler_t = http_req_router_t; }; 32
  • 33. Tie our wrapper type with RESTinio's traits struct http_server_traits_t : public restinio::default_traits_t { using logger_t = http_server_logger_t; using request_handler_t = http_req_router_t; }; 33 Now RESTinio server with this traits will use instance of http_server_logger_t for logging.
  • 34. Instantiation of our wrapper [[nodiscard]] inline auto make_http_server_settings( unsigned int thread_pool_size, const app_params_t & params, std::shared_ptr<spdlog::logger> logger, so_5::mbox_t req_handler_mbox ) { ... return restinio::on_thread_pool< http_server_traits_t >( thread_pool_size ) .port( http_srv_params.m_port ) .protocol( ip_protocol(http_srv_params.m_ip_version) ) .address( http_srv_params.m_address ) .handle_request_timeout( std::chrono::seconds(60) ) .write_http_response_timelimit( std::chrono::seconds(60) ) .logger( std::move(logger) ) .request_handler( make_router( params, req_handler_mbox ) ); } 34
  • 35. Instantiation of our wrapper [[nodiscard]] inline auto make_http_server_settings( unsigned int thread_pool_size, const app_params_t & params, std::shared_ptr<spdlog::logger> logger, so_5::mbox_t req_handler_mbox ) { ... return restinio::on_thread_pool< http_server_traits_t >( thread_pool_size ) .port( http_srv_params.m_port ) .protocol( ip_protocol(http_srv_params.m_ip_version) ) .address( http_srv_params.m_address ) .handle_request_timeout( std::chrono::seconds(60) ) .write_http_response_timelimit( std::chrono::seconds(60) ) .logger( std::move(logger) ) .request_handler( make_router( params, req_handler_mbox ) ); } 35
  • 36. Instantiation of our wrapper [[nodiscard]] inline auto make_http_server_settings( unsigned int thread_pool_size, const app_params_t & params, std::shared_ptr<spdlog::logger> logger, so_5::mbox_t req_handler_mbox ) { ... return restinio::on_thread_pool< http_server_traits_t >( thread_pool_size ) .port( http_srv_params.m_port ) .protocol( ip_protocol(http_srv_params.m_ip_version) ) .address( http_srv_params.m_address ) .handle_request_timeout( std::chrono::seconds(60) ) .write_http_response_timelimit( std::chrono::seconds(60) ) .logger( std::move(logger) ) .request_handler( make_router( params, req_handler_mbox ) ); } 36 Object of type http_server_traits_t::logger_t (aka http_server_logger_t) will be created here. Spdlog's logger will be passed to the constructor of that object.
  • 37. Log example (with --restinio-tracing -l trace) 37
  • 39. ExpressJS-like routing using http_req_router_t = restinio::router::express_router_t< restinio::router::pcre_regex_engine_t< restinio::router::pcre_traits_t< // Max capture groups for regex. 5 > > >; 39
  • 40. ExpressJS-like routing using http_req_router_t = restinio::router::express_router_t< restinio::router::pcre_regex_engine_t< restinio::router::pcre_traits_t< // Max capture groups for regex. 5 > > >; 40 Express router can use different engines. There are engines based on std::regex, Boost.Regex and PCRE/PCRE2. A PCRE-based engine is used here.
  • 41. ExpressJS-like routing struct http_server_traits_t : public restinio::default_traits_t { using logger_t = http_server_logger_t; using request_handler_t = http_req_router_t; }; 41
  • 42. ExpressJS-like routing void add_transform_op_handler( const app_params_t & app_params, http_req_router_t & router, so_5::mbox_t req_handler_mbox ) { router.http_get( R"(/:path(.*).:ext(.{3,4}))", restinio::path2regex::options_t{}.strict( true ), [req_handler_mbox, &app_params]( auto req, auto params ) {...} ); } 42
  • 43. ExpressJS-like routing void add_transform_op_handler( const app_params_t & app_params, http_req_router_t & router, so_5::mbox_t req_handler_mbox ) { router.http_get( R"(/:path(.*).:ext(.{3,4}))", restinio::path2regex::options_t{}.strict( true ), [req_handler_mbox, &app_params]( auto req, auto params ) {...} ); } 43 A route with two arguments ('path' and 'ext') is defined here.
  • 44. sendfile for serving original files sendfile() TransmitFile() 44
  • 45. sendfile for serving original files [[nodiscard]] restinio::request_handling_status_t serve_as_regular_file(const std::string & root_dir, restinio::request_handle_t req, image_format_t image_format) { const auto full_path = make_full_path( root_dir, req->header().path() ); try { auto sf = restinio::sendfile( full_path ); const auto last_modified = sf.meta().last_modified_at(); auto resp = req->create_response(); return set_common_header_fields_for_image_resp( last_modified, resp ) .append_header( restinio::http_field::content_type, image_content_type_from_img_format(image_format) ) .append_header( restinio::http_header_field_t{ http_header::shrimp_image_src_hf(), image_src_to_str( http_header::image_src_t::sendfile ) } ) .set_body( std::move(sf) ) .done(); } catch(...) { } return do_404_response( std::move( req ) ); } 45
  • 46. sendfile for serving original files [[nodiscard]] restinio::request_handling_status_t serve_as_regular_file(const std::string & root_dir, restinio::request_handle_t req, image_format_t image_format) { const auto full_path = make_full_path( root_dir, req->header().path() ); try { auto sf = restinio::sendfile( full_path ); const auto last_modified = sf.meta().last_modified_at(); auto resp = req->create_response(); return set_common_header_fields_for_image_resp( last_modified, resp ) .append_header( restinio::http_field::content_type, image_content_type_from_img_format(image_format) ) .append_header( restinio::http_header_field_t{ http_header::shrimp_image_src_hf(), image_src_to_str( http_header::image_src_t::sendfile ) } ) .set_body( std::move(sf) ) .done(); } catch(...) { } return do_404_response( std::move( req ) ); } 46 sendfile operation is defined here.
  • 47. sendfile for serving original files [[nodiscard]] restinio::request_handling_status_t serve_as_regular_file(const std::string & root_dir, restinio::request_handle_t req, image_format_t image_format) { const auto full_path = make_full_path( root_dir, req->header().path() ); try { auto sf = restinio::sendfile( full_path ); const auto last_modified = sf.meta().last_modified_at(); auto resp = req->create_response(); return set_common_header_fields_for_image_resp( last_modified, resp ) .append_header( restinio::http_field::content_type, image_content_type_from_img_format(image_format) ) .append_header( restinio::http_header_field_t{ http_header::shrimp_image_src_hf(), image_src_to_str( http_header::image_src_t::sendfile ) } ) .set_body( std::move(sf) ) .done(); } catch(...) { } return do_404_response( std::move( req ) ); } 47 sendfile operation is used here for sending file's content as response's body.
  • 48. The next big topic 48
  • 52. transformer agent class a_transformer_t final : public so_5::agent_t { public: struct resize_request_t final : public so_5::message_t {...}; a_transformer_t(context_t ctx, std::shared_ptr<spdlog::logger> logger, storage_params_t cfg); void so_define_agent() override { so_subscribe_self().event( &a_transformer_t::on_resize_request ); } private: ... on_resize_request(mutable_mhood_t<resize_request_t> cmd); ... }; 52
  • 53. transformer agent class a_transformer_t final : public so_5::agent_t { public: struct resize_request_t final : public so_5::message_t {...}; a_transformer_t(context_t ctx, std::shared_ptr<spdlog::logger> logger, storage_params_t cfg); void so_define_agent() override { so_subscribe_self().event( &a_transformer_t::on_resize_request ); } private: ... on_resize_request(mutable_mhood_t<resize_request_t> cmd); ... }; 53 Message to be handled.
  • 54. transformer agent class a_transformer_t final : public so_5::agent_t { public: struct resize_request_t final : public so_5::message_t {...}; a_transformer_t(context_t ctx, std::shared_ptr<spdlog::logger> logger, storage_params_t cfg); void so_define_agent() override { so_subscribe_self().event( &a_transformer_t::on_resize_request ); } private: ... on_resize_request(mutable_mhood_t<resize_request_t> cmd); ... }; 54 Subscription to the message. When message resize_request_t arrives the on_resize_request() method will be called. Type of message to be subscribed is deduced from handler's prototype.
  • 56. transform_manager agent (1) class a_transform_manager_t final : public so_5::agent_t { public: struct resize_request_t final : public so_5::message_t {...}; struct resize_result_t final : public so_5::message_t {...}; struct delete_cache_request_t final : public so_5::message_t {...}; a_transform_manager_t(context_t ctx, std::shared_ptr<spdlog::logger> logger); void so_define_agent() override; void so_evt_start() override; ... 56
  • 57. transform_manager agent (1) class a_transform_manager_t final : public so_5::agent_t { public: struct resize_request_t final : public so_5::message_t {...}; struct resize_result_t final : public so_5::message_t {...}; struct delete_cache_request_t final : public so_5::message_t {...}; a_transform_manager_t(context_t ctx, std::shared_ptr<spdlog::logger> logger); void so_define_agent() override; void so_evt_start() override; ... 57 Those are "public" messages. They are sent to transform_manager by external entities: ● resize_request_t and delete_cache_request_t are sent by HTTP-server; ● resize_result_t is sent by transformer agent.
  • 58. transform_manager agent (2) private : struct negative_delete_cache_response_t : public so_5::message_t {...}; struct clear_cache_t final : public so_5::signal_t {}; struct check_pending_requests_t final : public so_5::signal_t {}; ... void on_resize_request(mutable_mhood_t<resize_request_t> cmd); void on_resize_result(mutable_mhood_t<resize_result_t> cmd); void on_delete_cache_request(mutable_mhood_t<delete_cache_request_t> cmd); void on_negative_delete_cache_response( mutable_mhood_t<negative_delete_cache_response_t> cmd); void on_clear_cache(mhood_t<clear_cache_t>); void on_check_pending_requests(mhood_t<check_pending_requests_t>); ... }; 58
  • 59. transform_manager agent (2) private : struct negative_delete_cache_response_t : public so_5::message_t {...}; struct clear_cache_t final : public so_5::signal_t {}; struct check_pending_requests_t final : public so_5::signal_t {}; ... void on_resize_request(mutable_mhood_t<resize_request_t> cmd); void on_resize_result(mutable_mhood_t<resize_result_t> cmd); void on_delete_cache_request(mutable_mhood_t<delete_cache_request_t> cmd); void on_negative_delete_cache_response( mutable_mhood_t<negative_delete_cache_response_t> cmd); void on_clear_cache(mhood_t<clear_cache_t>); void on_check_pending_requests(mhood_t<check_pending_requests_t>); ... }; 59 Those are "private" message and signals. transform_manager sends them to itself.
  • 60. transform_manager agent (3) void a_transform_manager_t::so_define_agent() { so_subscribe_self() .event( &a_transform_manager_t::on_resize_request ) .event( &a_transform_manager_t::on_resize_result ) .event( &a_transform_manager_t::on_delete_cache_request ) .event( &a_transform_manager_t::on_negative_delete_cache_response ) .event( &a_transform_manager_t::on_clear_cache ) .event( &a_transform_manager_t::on_check_pending_requests ); } 60
  • 62. Basic working scheme a_transform_manager_t::resize_request_t 62 void handle_resize_op_request( const so_5::mbox_t & req_handler_mbox, image_format_t image_format, const restinio::query_string_params_t & qp, restinio::request_handle_t req ) { try_to_handle_request( [&]{ auto op_params = transform::resize_params_t::make( restinio::opt_value< std::uint32_t >( qp, "width" ), restinio::opt_value< std::uint32_t >( qp, "height" ), restinio::opt_value< std::uint32_t >( qp, "max" ) ); transform::resize_params_constraints_t{}.check( op_params ); std::string image_path{ req->header().path() }; so_5::send< so_5::mutable_msg<a_transform_manager_t::resize_request_t> >( req_handler_mbox, std::move(req), std::move(image_path), image_format, op_params ); }, req ); }
  • 64. Basic working scheme a_transformer_t::resize_request_t 64 void a_transform_manager_t::try_initiate_pending_requests_processing() { while( !m_free_workers.empty() && !m_pending_requests.empty() ) { auto atoken = m_pending_requests.oldest().value(); const auto key = atoken.key(); m_pending_requests.extract_values_for_key( std::move(atoken), [&]( auto && value ) { m_inprogress_requests.insert( transform::resize_request_key_t{key}, std::move(value) ); } ); auto worker = std::move(m_free_workers.top()); m_free_workers.pop(); m_logger->trace("initiate processing of a request; request_key={}, worker_mbox={}", key, worker->id()); so_5::send< so_5::mutable_msg<a_transformer_t::resize_request_t> >(worker, key, so_direct_mbox()); } }
  • 66. Basic working scheme a_transform_manager_t::resize_result_t 66 void a_transformer_t::on_resize_request( mutable_mhood_t<resize_request_t> cmd) { auto result = handle_resize_request( cmd->m_key ); so_5::send< so_5::mutable_msg<a_transform_manager_t::resize_result_t> >( cmd->m_reply_to, so_direct_mbox(), std::move(cmd->m_key), std::move(result) ); }
  • 68. Basic working scheme 68 void a_transform_manager_t::on_resize_result( mutable_mhood_t<resize_result_t> cmd ) { m_logger->trace( "resize_result received; request_key={}, worker_mbox={}", cmd->m_key, cmd->m_worker->id() ); m_free_workers.push( std::move(cmd->m_worker) ); try_initiate_pending_requests_processing(); auto key = std::move(cmd->m_key); auto requests = extract_inprogress_requests( std::move(m_inprogress_requests.find_first_for_key( key ).value()) ); std::visit( variant_visitor{ [&]( successful_resize_t & result ) { on_successful_resize( std::move(key), result, std::move(requests) ); }, [&]( failed_resize_t & result ) { on_failed_resize( std::move(key), result, std::move(requests) ); } }, cmd->m_result ); }
  • 69. Basic working scheme 69 void a_transform_manager_t::on_resize_result( mutable_mhood_t<resize_result_t> cmd ) { m_logger->trace( "resize_result received; request_key={}, worker_mbox={}", cmd->m_key, cmd->m_worker->id() ); m_free_workers.push( std::move(cmd->m_worker) ); try_initiate_pending_requests_processing(); auto key = std::move(cmd->m_key); auto requests = extract_inprogress_requests( std::move(m_inprogress_requests.find_first_for_key( key ).value()) ); std::visit( variant_visitor{ [&]( successful_resize_t & result ) { on_successful_resize( std::move(key), result, std::move(requests) ); }, [&]( failed_resize_t & result ) { on_failed_resize( std::move(key), result, std::move(requests) ); } }, cmd->m_result ); } void a_transform_manager_t::on_failed_resize( transform::resize_request_key_t key, failed_resize_t & result, original_request_container_t requests ) { m_logger->warn( "failed resize; request_key={}, reason={}", key, result.m_reason ); for( auto & rq : requests ) { m_logger->trace( "sending negative response back; request_key={}, connection_id={}", key, rq->m_http_req->connection_id() ); do_404_response( std::move(rq->m_http_req) ); } }
  • 70. Providing work threads to agents 70
  • 71. Providing work threads to agents (1) [[nodiscard]] so_5::mbox_t create_agents( spdlog::sink_ptr logger_sink, const shrimp::app_params_t & app_params, so_5::environment_t & env, unsigned int worker_threads_count ) { using namespace shrimp; using namespace so_5::disp::one_thread; // For create_private_disp. so_5::mbox_t manager_mbox; env.introduce_coop([&]( so_5::coop_t & coop ) { auto manager = coop.make_agent_with_binder< a_transform_manager_t >( create_private_disp( env, "manager" )->binder(), make_logger( "manager", logger_sink ) ); manager_mbox = manager->so_direct_mbox(); 71
  • 72. Providing work threads to agents (1) [[nodiscard]] so_5::mbox_t create_agents( spdlog::sink_ptr logger_sink, const shrimp::app_params_t & app_params, so_5::environment_t & env, unsigned int worker_threads_count ) { using namespace shrimp; using namespace so_5::disp::one_thread; // For create_private_disp. so_5::mbox_t manager_mbox; env.introduce_coop([&]( so_5::coop_t & coop ) { auto manager = coop.make_agent_with_binder< a_transform_manager_t >( create_private_disp( env, "manager" )->binder(), make_logger( "manager", logger_sink ) ); manager_mbox = manager->so_direct_mbox(); 72 transform_manager agent is created and is bound to separate one_thread dispatcher. It means that transform_manager will have its own work thread.
  • 73. Providing work threads to agents (2) // Every worker will work on its own private dispatcher. for( unsigned int worker{}; worker < worker_threads_count; ++worker ) { const auto worker_name = fmt::format( "worker_{}", worker ); auto transformer = coop.make_agent_with_binder< a_transformer_t >( create_private_disp( env, worker_name )->binder(), make_logger( worker_name, logger_sink ), app_params.m_storage ); manager->add_worker( transformer->so_direct_mbox() ); } } ); return manager_mbox; } 73
  • 74. Providing work threads to agents (2) // Every worker will work on its own private dispatcher. for( unsigned int worker{}; worker < worker_threads_count; ++worker ) { const auto worker_name = fmt::format( "worker_{}", worker ); auto transformer = coop.make_agent_with_binder< a_transformer_t >( create_private_disp( env, worker_name )->binder(), make_logger( worker_name, logger_sink ), app_params.m_storage ); manager->add_worker( transformer->so_direct_mbox() ); } } ); return manager_mbox; } 74 The same is for every transformer agent.
  • 75. And now the end is near... 75
  • 76. The results of the experiment 76
  • 77. It's not a 10-lines HelloWorld 77
  • 78. It's not a 10-lines HelloWorld #include <restinio/all.hpp> int main() { restinio::run( restinio::on_this_thread<>() .port(8080) .address("localhost") .request_handler([](auto req) { return req->create_response().set_body("Hello, World!").done(); })); return 0; } 78
  • 79. It's not a 10-lines HelloWorld #include <restinio/all.hpp> int main() { restinio::run( restinio::on_this_thread<>() .port(8080) .address("localhost") .request_handler([](auto req) { return req->create_response().set_body("Hello, World!").done(); })); return 0; } 79
  • 80. It's not a 10-lines HelloWorld #include <restinio/all.hpp> int main() { restinio::run( restinio::on_this_thread<>() .port(8080) .address("localhost") .request_handler([](auto req) { return req->create_response().set_body("Hello, World!").done(); })); return 0; } 80
  • 81. New ideas for implementation 81
  • 82. We are open for new ideas... 82
  • 83. References at one place 83