void dispatch_t::on_message(const io::message_t& message) { COCAINE_LOG_DEBUG(service_manager()->get_system_logger(), "worker %s received type %d message", m_id, message.id()); switch(message.id()) { case io::event_traits<io::rpc::heartbeat>::id: { m_disown_timer.stop(); break; } case io::event_traits<io::rpc::invoke>::id: { std::string event; message.as<io::rpc::invoke>(event); COCAINE_LOG_DEBUG(service_manager()->get_system_logger(), "worker %s invoking session %d with event '%s'", m_id, message.band(), event); std::shared_ptr<detail::dispatch_upstream_t> upstream( std::make_shared<detail::dispatch_upstream_t>(message.band(), this) ); try { io_pair_t session = {upstream, invoke(event, upstream)}; m_sessions.insert(std::make_pair(message.band(), session)); } catch(const std::exception& e) { upstream->error(invocation_error, e.what()); } catch(...) { upstream->error(invocation_error, "unexpected exception"); } break; } case io::event_traits<io::rpc::chunk>::id: { std::string chunk; message.as<io::rpc::chunk>(chunk); stream_map_t::iterator it = m_sessions.find(message.band()); // NOTE: This may be a chunk for a failed invocation, in which case there // will be no active stream, so drop the message. if(it != m_sessions.end()) { try { it->second.handler->on_chunk(chunk.data(), chunk.size()); } catch(const std::exception& e) { it->second.upstream->error(invocation_error, e.what()); m_sessions.erase(it); } catch(...) { it->second.upstream->error(invocation_error, "unexpected exception"); m_sessions.erase(it); } } break; } case io::event_traits<io::rpc::choke>::id: { stream_map_t::iterator it = m_sessions.find(message.band()); // NOTE: This may be a choke for a failed invocation, in which case there // will be no active stream, so drop the message. if(it != m_sessions.end()) { try { it->second.handler->on_close(); } catch(const std::exception& e) { it->second.upstream->error(invocation_error, e.what()); } catch(...) { it->second.upstream->error(invocation_error, "unexpected exception"); } m_sessions.erase(it); } break; } case io::event_traits<io::rpc::error>::id: { int ec; std::string error_message; message.as<io::rpc::error>(ec, error_message); stream_map_t::iterator it = m_sessions.find(message.band()); // NOTE: This may be a chunk for a failed invocation, in which case there // will be no active stream, so drop the message. if(it != m_sessions.end()) { try { it->second.handler->on_error(ec, error_message); } catch(const std::exception& e) { it->second.upstream->error(invocation_error, e.what()); m_sessions.erase(it); } catch(...) { it->second.upstream->error(invocation_error, "unexpected exception"); m_sessions.erase(it); } } break; } case io::event_traits<io::rpc::terminate>::id: { terminate(io::rpc::terminate::normal, "per request"); break; } default: { COCAINE_LOG_WARNING(service_manager()->get_system_logger(), "worker %s dropping unknown type %d message", m_id, message.id()); } } }
void worker_t::on_message(const io::message_t& message) { COCAINE_LOG_DEBUG( m_log, "worker %s received type %d message", m_id, message.id() ); switch(message.id()) { case event_traits<rpc::heartbeat>::id: m_disown_timer.stop(); m_disown_timer.start(m_profile->heartbeat_timeout); break; case event_traits<rpc::invoke>::id: { uint64_t session_id; std::string event; message.as<rpc::invoke>(session_id, event); COCAINE_LOG_DEBUG(m_log, "worker %s invoking session %s with event '%s'", m_id, session_id, event); std::shared_ptr<api::stream_t> upstream( std::make_shared<upstream_t>(session_id, this) ); try { io_pair_t io = { upstream, m_sandbox->invoke(event, upstream) }; m_streams.insert(std::make_pair(session_id, io)); } catch(const std::exception& e) { upstream->error(invocation_error, e.what()); } catch(...) { upstream->error(invocation_error, "unexpected exception"); } break; } case event_traits<rpc::chunk>::id: { uint64_t session_id; std::string chunk; message.as<rpc::chunk>(session_id, chunk); stream_map_t::iterator it(m_streams.find(session_id)); // NOTE: This may be a chunk for a failed invocation, in which case there // will be no active stream, so drop the message. if(it != m_streams.end()) { try { it->second.downstream->push(chunk.data(), chunk.size()); } catch(const std::exception& e) { it->second.upstream->error(invocation_error, e.what()); m_streams.erase(it); } catch(...) { it->second.upstream->error(invocation_error, "unexpected exception"); m_streams.erase(it); } } break; } case event_traits<rpc::choke>::id: { uint64_t session_id; message.as<rpc::choke>(session_id); stream_map_t::iterator it = m_streams.find(session_id); // NOTE: This may be a choke for a failed invocation, in which case there // will be no active stream, so drop the message. if(it != m_streams.end()) { try { it->second.downstream->close(); } catch(const std::exception& e) { it->second.upstream->error(invocation_error, e.what()); } catch(...) { it->second.upstream->error(invocation_error, "unexpected exception"); } m_streams.erase(it); } break; } case event_traits<rpc::terminate>::id: terminate(rpc::terminate::normal, "per request"); break; default: COCAINE_LOG_WARNING( m_log, "worker %s dropping unknown type %d message", m_id, message.id() ); } }