Skip to content

Commit 0e35973

Browse files
committed
handle exceptions in all Actor calls
1 parent 4b3b3ad commit 0e35973

File tree

2 files changed

+84
-57
lines changed

2 files changed

+84
-57
lines changed

Framework/include/QualityControl/Actor.h

Lines changed: 69 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include <memory>
1111
#include <type_traits>
1212
#include <format>
13+
#include <functional>
1314

1415
#include "QualityControl/ActorTraits.h"
1516
#include "QualityControl/runnerUtils.h"
@@ -60,11 +61,11 @@ std::shared_ptr<repository::DatabaseInterface> initRepository(const std::unorder
6061
void initCCDB(const std::string& url);
6162
ccdb::CCDBManagerInstance& getCCDB();
6263

64+
void handleExceptions(std::string_view when, const std::function<void()>&);
65+
6366
}
6467

6568

66-
// todo catch and handle exceptions
67-
// todo check if onProcess() and onInit() are implemented by ConcreteActor
6869
// todo consider having a check to avoid overriding Actor methods
6970
// Actor is supposed to contain any common logic for QC actors (starting services, handling exceptions) and bridging with DPL (specs, registering callbacks).
7071
template<typename ConcreteActor>
@@ -130,13 +131,15 @@ class Actor
130131

131132
void init(framework::InitContext& ictx)
132133
{
133-
// we set the fallback activity. fields might get overwritten once runtime values become available
134-
mActivity = mServicesConfig.activity;
134+
impl::handleExceptions("process", [&] {
135+
// we set the fallback activity. fields might get overwritten once runtime values become available
136+
mActivity = mServicesConfig.activity;
135137

136-
initServices(ictx);
137-
initDplCallbacks(ictx);
138+
initServices(ictx);
139+
initDplCallbacks(ictx);
138140

139-
concreteActor().onInit(ictx);
141+
concreteActor().onInit(ictx);
142+
});
140143
}
141144

142145
void initServices(framework::InitContext& ictx)
@@ -203,79 +206,88 @@ class Actor
203206

204207
void process(framework::ProcessingContext& ctx)
205208
{
206-
concreteActor().onProcess(ctx);
209+
impl::handleExceptions("process", [&] {
210+
concreteActor().onProcess(ctx);
211+
});
207212
}
208213

209214
void start(framework::ServiceRegistryRef services) {
210-
ILOG(Debug, Trace) << traits::sActorTypeKebabCase << " start" << ENDM;
211-
// todo catch and handle exceptions
215+
impl::handleExceptions("start", [&] {
216+
ILOG(Debug, Trace) << traits::sActorTypeKebabCase << " start" << ENDM;
212217

213-
mActivity = computeActivity(services, mActivity);
218+
mActivity = computeActivity(services, mActivity);
214219

215-
if constexpr (requiresService<Service::InfoLogger>()) {
216-
QcInfoLogger::setRun(mActivity.mId);
217-
QcInfoLogger::setPartition(mActivity.mPartitionName);
218-
}
219-
if constexpr (requiresService<Service::Monitoring>()) {
220-
impl::startMonitoring(*mMonitoring, mActivity.mId);
221-
}
222-
if constexpr (requiresService<Service::Bookkeeping>()) {
223-
std::string actorName;
224-
if constexpr (runsUserCode<traits>()) {
225-
actorName = concreteActor().getUserCodeName();
226-
} else {
227-
actorName = traits::sActorTypeKebabCase;
220+
if constexpr (requiresService<Service::InfoLogger>()) {
221+
QcInfoLogger::setRun(mActivity.mId);
222+
QcInfoLogger::setPartition(mActivity.mPartitionName);
228223
}
229-
230-
std::string detectorName;
231-
if constexpr (traits::sDetectorSpecific) {
232-
detectorName = concreteActor().getDetectorName();
224+
if constexpr (requiresService<Service::Monitoring>()) {
225+
impl::startMonitoring(*mMonitoring, mActivity.mId);
226+
}
227+
if constexpr (requiresService<Service::Bookkeeping>()) {
228+
std::string actorName;
229+
if constexpr (runsUserCode<traits>()) {
230+
actorName = concreteActor().getUserCodeName();
231+
} else {
232+
actorName = traits::sActorTypeKebabCase;
233+
}
234+
235+
std::string detectorName;
236+
if constexpr (traits::sDetectorSpecific) {
237+
detectorName = concreteActor().getDetectorName();
238+
}
239+
240+
// todo: get args
241+
impl::startBookkeeping(mActivity.mId, actorName, detectorName, traits::sDplProcessType, "");
233242
}
234243

235-
// todo: get args
236-
impl::startBookkeeping(mActivity.mId, actorName, detectorName, traits::sDplProcessType, "");
237-
}
238-
239-
// fixme: should we just have empty methods in the base class for the sake of readability?
240-
if constexpr (requires {ConcreteActor::onStart;}) {
241-
concreteActor().onStart(services, mActivity);
242-
}
244+
// fixme: should we just have empty methods in the base class for the sake of readability?
245+
if constexpr (requires {ConcreteActor::onStart;}) {
246+
concreteActor().onStart(services, mActivity);
247+
}
248+
});
243249
}
244250

245251
void stop(framework::ServiceRegistryRef services) {
246-
ILOG(Debug, Trace) << traits::sActorTypeKebabCase << " stop" << ENDM;
252+
impl::handleExceptions("stop", [&] {
253+
ILOG(Debug, Trace) << traits::sActorTypeKebabCase << " stop" << ENDM;
247254

248-
mActivity = computeActivity(services, mActivity);
255+
mActivity = computeActivity(services, mActivity);
249256

250-
if constexpr (requires {ConcreteActor::onStop;}) {
251-
concreteActor().onStop(services, mActivity);
252-
}
257+
if constexpr (requires {ConcreteActor::onStop;}) {
258+
concreteActor().onStop(services, mActivity);
259+
}
260+
});
253261
}
254262

255263
void reset(framework::ServiceRegistryRef services) {
256-
ILOG(Debug, Trace) << traits::sActorTypeKebabCase << " reset" << ENDM;
264+
impl::handleExceptions("reset", [&] {
265+
ILOG(Debug, Trace) << traits::sActorTypeKebabCase << " reset" << ENDM;
257266

258-
mActivity = mServicesConfig.activity;
267+
mActivity = mServicesConfig.activity;
259268

260-
if constexpr (requires {ConcreteActor::onReset;}) {
261-
concreteActor().onReset(services, mActivity);
262-
}
269+
if constexpr (requires {ConcreteActor::onReset;}) {
270+
concreteActor().onReset(services, mActivity);
271+
}
272+
});
263273
}
264274

265275
void endOfStream(framework::EndOfStreamContext& eosContext) {
266-
ILOG(Debug, Trace) << traits::sActorTypeKebabCase << " endOfStream" << ENDM;
267-
// todo catch and handle exceptions
268-
if constexpr (requires {ConcreteActor::onEndOfStream;}) {
269-
concreteActor().onEndOfStream(eosContext);
270-
}
276+
impl::handleExceptions("endOfStream", [&] {
277+
ILOG(Debug, Trace) << traits::sActorTypeKebabCase << " endOfStream" << ENDM;
278+
if constexpr (requires {ConcreteActor::onEndOfStream;}) {
279+
concreteActor().onEndOfStream(eosContext);
280+
}
281+
});
271282
}
272283
void finaliseCCDB(framework::ConcreteDataMatcher& matcher, void* obj)
273284
{
274-
ILOG(Debug, Trace) << traits::sActorTypeKebabCase << " finaliseCCDB" << ENDM;
275-
// todo catch and handle exceptions
276-
if constexpr (requires {ConcreteActor::onFinaliseCCDB;}) {
277-
concreteActor().onFinaliseCCDB(matcher, obj);
278-
}
285+
impl::handleExceptions("finaliseCCDB", [&] {
286+
ILOG(Debug, Trace) << traits::sActorTypeKebabCase << " finaliseCCDB" << ENDM;
287+
if constexpr (requires {ConcreteActor::onFinaliseCCDB;}) {
288+
concreteActor().onFinaliseCCDB(matcher, obj);
289+
}
290+
});
279291
}
280292

281293
protected:
@@ -302,7 +314,7 @@ class Actor
302314

303315
const Activity& getActivity() const { return mActivity; }
304316

305-
private:
317+
private:
306318
Activity mActivity;
307319
const ServicesConfig mServicesConfig;
308320

Framework/src/Actor.cxx

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
#include <Monitoring/Monitoring.h>
1111
#include <Monitoring/MonitoringFactory.h>
1212
#include <CCDB/BasicCCDBManager.h>
13+
#include <boost/exception/diagnostic_information.hpp>
14+
#include <Framework/RuntimeError.h>
1315

1416
namespace o2::quality_control::core
1517
{
@@ -69,6 +71,19 @@ ccdb::CCDBManagerInstance& getCCDB()
6971
return o2::ccdb::BasicCCDBManager::instance();
7072
}
7173

74+
void handleExceptions(std::string_view when, const std::function<void()>& f)
75+
{
76+
try {
77+
f();
78+
} catch (o2::framework::RuntimeErrorRef& ref) {
79+
ILOG(Error) << "Error occurred during " << when << ": " << o2::framework::error_from_ref(ref).what << ENDM;
80+
throw;
81+
} catch (...) {
82+
ILOG(Error) << "Error occurred during " << when << " :"
83+
<< boost::current_exception_diagnostic_information(true) << ENDM;
84+
throw;
85+
}
86+
}
7287

7388
}
7489

0 commit comments

Comments
 (0)