@@ -77,7 +77,7 @@ namespace examples::jobs_engine {
77
77
78
78
.m_types = {{JobsType::kJobsType1 , {.m_group = JobsGroupType::kJobsGroup12 }},
79
79
{JobsType::kJobsType2 , {.m_group = JobsGroupType::kJobsGroup12 }},
80
- {JobsType::kJobsType3 , {.m_group = JobsGroupType::kJobsGroup3 , .m_timeout = std::chrono::milliseconds (500 )}},
80
+ {JobsType::kJobsType3 , {.m_group = JobsGroupType::kJobsGroup3 , .m_timeout = std::chrono::milliseconds (700 )}},
81
81
{JobsType::kJobsDatabase , {.m_group = JobsGroupType::kJobsGroupDatabase }},
82
82
{JobsType::kJobsCache , {.m_group = JobsGroupType::kJobsGroupCache }}}};
83
83
@@ -88,53 +88,52 @@ namespace examples::jobs_engine {
88
88
89
89
// create a cache server (with workers to simulate access to it)
90
90
// (as an external engine outside the jobs engine for demo purposes)
91
- small::worker_thread<JobsEng::JobsID> cache_server ({.threads_count = 1 }, [&](auto &w /* this*/ , const auto &items) {
92
- for (auto &i : items) {
93
- std::cout << " thread " << std::this_thread::get_id ()
94
- << " CACHE processing"
95
- << " {" << i << " }" << " \n " ;
91
+ small::worker_thread<std::pair<JobsEng::JobsID, Request>> cache_server ({.threads_count = 1 }, [&](auto &w /* this*/ , const auto &items) {
92
+ for (auto &[job_id, req] : items) {
93
+ std::cout << " worker thread " << std::this_thread::get_id ()
94
+ << " CACHE processing"
95
+ << " {" << req.first << " , " << req.second << " , jobid=" << job_id << " }"
96
+ << " time " << small::toISOString (small::timeNow ())
97
+ << " \n " ;
96
98
97
99
// mark the jobs id associated as succeeded (for demo purposes to avoid creating other structures)
98
- jobs.jobs_finished (i , (Response)i );
100
+ jobs.jobs_finished (job_id , (Response)job_id );
99
101
}
100
102
// sleep long enough
101
103
// no coalesce for demo purposes (sleep 500) so 3rd parent items is finished due to database and not cache server
102
104
small::sleep (500 );
103
105
});
104
106
107
+ auto fn_print_item = [](auto item, std::string fn_type) {
108
+ std::cout << " thread " << std::this_thread::get_id ()
109
+ << std::setw (10 ) << fn_type
110
+ << " processing "
111
+ << " {"
112
+ << " jobid=" << std::setw (2 ) << item->m_id
113
+ << " type=" << std::setw (1 ) << (int )item->m_type
114
+ << " req.int=" << std::setw (2 ) << item->m_request .first << " ,"
115
+ << " req.str=\" " << item->m_request .second << " \" "
116
+ << " }"
117
+ << " time " << small::toISOString (small::timeNow ())
118
+ << " \n " ;
119
+ };
120
+
105
121
// default processing used for job type 3 with custom delay in between requests
106
122
// one request will succeed and one request will timeout for demo purposes
107
- jobs.config_default_function_processing ([](auto &j /* this jobs engine*/ , const auto &jobs_items, auto &jobs_config) {
123
+ jobs.config_default_function_processing ([& ](auto &j /* this jobs engine*/ , const auto &jobs_items, auto &jobs_config) {
108
124
for (auto &item : jobs_items) {
109
- std::cout << " thread " << std::this_thread::get_id ()
110
- << " DEFAULT processing "
111
- << " {"
112
- << " type=" << (int )item->m_type
113
- << " req.int=" << item->m_request .first << " ,"
114
- << " req.str=\" " << item->m_request .second << " \" "
115
- << " }"
116
- << " ref count " << item.use_count ()
117
- << " time " << small::toISOString (small::timeNow ())
118
- << " \n " ;
125
+ fn_print_item (item, " DEFAULT" );
119
126
}
120
127
121
128
// set a custom delay (timeout for job3 is 500 ms)
122
- jobs_config.m_delay_next_request = std::chrono::milliseconds (1000 );
129
+ jobs_config.m_delay_next_request = std::chrono::milliseconds (500 );
130
+ small::sleep (500 ); // TODO remove this after delay works
123
131
});
124
132
125
133
// add specific function for job1 (calling the function from jobs intead of config allows to pass the engine and extra param)
126
134
jobs.config_jobs_function_processing (JobsType::kJobsType1 , [&](auto &j /* this jobs engine*/ , const auto &jobs_items, auto & /* config */ , auto b /* extra param b*/ ) {
127
135
for (auto &item : jobs_items) {
128
- std::cout << " thread " << std::this_thread::get_id ()
129
- << " JOB1 processing "
130
- << " {"
131
- << " type=" << (int )item->m_type
132
- << " req.int=" << item->m_request .first << " ,"
133
- << " req.str=\" " << item->m_request .second << " \" "
134
- << " }"
135
- << " ref count " << item.use_count ()
136
- << " time " << small::toISOString (small::timeNow ())
137
- << " \n " ;
136
+ fn_print_item (item, " JOB1" );
138
137
139
138
// add 2 more children jobs for current one for database and server cache
140
139
JobsEng::JobsID jobs_child_db_id{};
@@ -152,7 +151,7 @@ namespace examples::jobs_engine {
152
151
153
152
j.jobs_start (small::EnumPriorities::kNormal , jobs_child_db_id);
154
153
// jobs_child_cache_id has no threads to execute, it has external executors
155
- cache_server.push_back (jobs_child_cache_id);
154
+ cache_server.push_back ({ jobs_child_cache_id, item-> m_request } );
156
155
}
157
156
small::sleep (30 ); }, 5 /* param b*/ );
158
157
@@ -165,25 +164,16 @@ namespace examples::jobs_engine {
165
164
// TODO set state merge daca e doar o dependinta, daca sunt mai multe atunci ar tb o functie custom - childProcessing (desi are sau nu are children - sau cum fac un dummy children - poate cu thread_count 0?)
166
165
167
166
// add specific function for job2
168
- jobs.config_jobs_function_processing (JobsType::kJobsType2 , [](auto &j /* this jobs engine*/ , const auto &jobs_items, auto & /* config */ ) {
169
- bool first_job = true ;
167
+ jobs.config_jobs_function_processing (JobsType::kJobsType2 , [& ](auto &j /* this jobs engine*/ , const auto &jobs_items, auto &jobs_config ) {
168
+ static bool first_job = true ;
170
169
for (auto &item : jobs_items) {
171
- std::cout << " thread " << std::this_thread::get_id ()
172
- << " JOB2 processing "
173
- << " {"
174
- << " type=" << (int )item->m_type
175
- << " req.int=" << item->m_request .first << " ,"
176
- << " req.str=\" " << item->m_request .second << " \" "
177
- << " }"
178
- << " ref count " << item.use_count ()
179
- << " time " << small::toISOString (small::timeNow ())
180
- << " \n " ;
170
+ fn_print_item (item, " JOB2" );
181
171
182
172
if (first_job) {
183
173
// for type 2 only database children (for demo purposes no result will be used from database)
184
174
auto ret = j.queue ().push_back_and_start_child (item->m_id /* parent*/ ,
185
- small::EnumPriorities::kNormal ,
186
- JobsType::kJobsDatabase ,
175
+ small::EnumPriorities::kNormal ,
176
+ JobsType::kJobsDatabase ,
187
177
item->m_request );
188
178
if (!ret) {
189
179
j.jobs_failed (item->m_id );
@@ -195,7 +185,21 @@ namespace examples::jobs_engine {
195
185
first_job = false ;
196
186
}
197
187
// TODO config to wait after request (even if it is not specified in the global config - so custom throttle)
198
- small::sleep (30 ); });
188
+ small::sleep (30 );
189
+ jobs_config.m_delay_next_request = std::chrono::milliseconds (30 );
190
+ });
191
+
192
+ // add specific function for job2
193
+ jobs.config_jobs_function_processing (JobsType::kJobsDatabase , [&](auto &j /* this jobs engine*/ , const auto &jobs_items, auto & /* config */ ) {
194
+ for (auto &item : jobs_items) {
195
+ // simulate long db call
196
+ small::sleep (200 );
197
+
198
+ fn_print_item (item, " DATABASE" );
199
+
200
+ // this job will be auto-finished
201
+ }
202
+ });
199
203
200
204
// TODO add function for database where demonstrate coalesce of 3 items (sleep 1000)
201
205
// TODO add function for cache server - no coalesce for demo purposes (sleep 500) so 3rd parent items is finished due to database and not cache server
@@ -207,8 +211,8 @@ namespace examples::jobs_engine {
207
211
std::vector<JobsEng::JobsID> jobs_ids;
208
212
209
213
// type3 one request will succeed and one request will timeout for demo purposes
210
- jobs.queue ().push_back_and_start ( small::EnumPriorities::kNormal , JobsType::kJobsType3 , {3 , " normal3" }, &jobs_id);
211
- jobs.queue ().push_back_and_start ( small::EnumPriorities::kHigh , JobsType::kJobsType3 , {3 , " high3" }, &jobs_id);
214
+ jobs.queue ().push_back_and_start_delay_for ( std::chrono::milliseconds ( 100 ), small::EnumPriorities::kNormal , JobsType::kJobsType3 , {3 , " normal3" }, &jobs_id);
215
+ jobs.queue ().push_back_and_start_delay_for ( std::chrono::milliseconds ( 100 ), small::EnumPriorities::kHigh , JobsType::kJobsType3 , {3 , " high3" }, &jobs_id);
212
216
213
217
// type2 only the first request succeeds and waits for child the other fails from the start
214
218
jobs.queue ().push_back_and_start (small::EnumPriorities::kNormal , JobsType::kJobsType2 , {2 , " normal2" }, &jobs_id);
@@ -242,6 +246,8 @@ namespace examples::jobs_engine {
242
246
auto ret = jobs.wait_for (std::chrono::milliseconds (100 )); // wait to finished
243
247
std::cout << " wait for with timeout, ret = " << static_cast <int >(ret) << " as timeout\n " ;
244
248
jobs.wait (); // wait here for jobs to finish due to exit flag
249
+ cache_server.signal_exit_force ();
250
+ cache_server.wait ();
245
251
246
252
std::cout << " size = " << jobs.size () << " \n " ;
247
253
0 commit comments