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
6061void initCCDB (const std::string& url);
6162ccdb::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).
7071template <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
0 commit comments