@@ -69,16 +69,15 @@ impl Actor for FirmwareManagerActor {
69
69
"FirmwareManager"
70
70
}
71
71
72
- // This actor handles 3 kinds of messages from its peer actors:
72
+ // This actor handles 2 kinds of messages from its peer actors:
73
73
//
74
74
// 1. MQTT messages from the MqttActor for firmware update requests from the cloud and firmware update responses from the child devices
75
75
// 2. Operation timeouts from the TimerActor for requests for which the child devices don't respond within the timeout window
76
- // 3. Download results from the DownloaderActor for firmware download requests
77
76
78
77
async fn run ( mut self ) -> Result < ( ) , RuntimeError > {
79
78
self . resend_operations_to_child_device ( ) . await ?;
80
79
// TODO: We need a dedicated actor to publish 500 later.
81
- self . get_pending_operations_from_cloud ( ) . await ?;
80
+ self . worker . get_pending_operations_from_cloud ( ) . await ?;
82
81
83
82
info ! ( "Ready to serve firmware requests." ) ;
84
83
while let Some ( event) = self . input_receiver . recv ( ) . await {
@@ -207,23 +206,29 @@ impl FirmwareManagerActor {
207
206
} ;
208
207
}
209
208
209
+ // Addressing the new firmware operation to further step.
210
210
let op_id = nanoid ! ( ) ;
211
- if let Err ( err) =
212
- // Addressing the new firmware operation to further step.
213
- self
214
- . handle_firmware_download_request_child_device (
215
- smartrest_request. clone ( ) ,
216
- op_id. as_str ( ) ,
217
- )
218
- . await
211
+ if let Err ( err) = self
212
+ . worker
213
+ . handle_firmware_download_request_child_device (
214
+ smartrest_request. clone ( ) ,
215
+ op_id. as_str ( ) ,
216
+ )
217
+ . await
219
218
{
220
219
self . fail_operation_in_cloud ( child_id, Some ( & op_id) , & err. to_string ( ) )
221
220
. await ?;
222
221
}
223
222
223
+ let operation_key = OperationKey :: new ( child_id, & op_id) ;
224
+ self . active_child_ops
225
+ . insert ( operation_key, ActiveOperationState :: Pending ) ;
226
+
224
227
Ok ( ( ) )
225
228
}
229
+ }
226
230
231
+ impl FirmwareManagerWorker {
227
232
// Check if the firmware file is already in cache.
228
233
// If yes, publish a firmware request to child device with that firmware in the cache.
229
234
// Otherwise, send a download request to the DownloaderActor and return immediately without waiting for the download to complete so that other requests/responses can be processed while the download is in progress.
@@ -236,7 +241,6 @@ impl FirmwareManagerActor {
236
241
let firmware_url = smartrest_request. url . as_str ( ) ;
237
242
let file_cache_key = digest ( firmware_url) ;
238
243
let cache_file_path = self
239
- . worker
240
244
. config
241
245
. validate_and_get_cache_dir_path ( ) ?
242
246
. join ( & file_cache_key) ;
@@ -261,13 +265,12 @@ impl FirmwareManagerActor {
261
265
262
266
// Send a request to the Downloader to download the file asynchronously.
263
267
let download_request = if self
264
- . worker
265
268
. config
266
269
. c8y_end_point
267
270
. maybe_tenant_url ( firmware_url)
268
271
. is_some ( )
269
272
{
270
- if let Ok ( token) = self . worker . jwt_retriever . await_response ( ( ) ) . await ? {
273
+ if let Ok ( token) = self . jwt_retriever . await_response ( ( ) ) . await ? {
271
274
DownloadRequest :: new ( firmware_url, cache_file_path. as_std_path ( ) )
272
275
. with_auth ( Auth :: new_bearer ( & token) )
273
276
} else {
@@ -278,7 +281,6 @@ impl FirmwareManagerActor {
278
281
} ;
279
282
280
283
let ( _, download_result) = self
281
- . worker
282
284
. download_sender
283
285
. await_response ( ( operation_id. to_string ( ) , download_request) )
284
286
. await ?;
@@ -297,28 +299,21 @@ impl FirmwareManagerActor {
297
299
smartrest_request : SmartRestFirmwareRequest ,
298
300
download_result : DownloadResult ,
299
301
) -> Result < ( ) , FirmwareManagementError > {
300
- let child_id = smartrest_request. device . clone ( ) ;
301
302
match download_result {
302
303
Ok ( response) => {
303
- if let Err ( err) =
304
- // Publish a firmware update request to child device.
305
- self
306
- . handle_firmware_update_request_with_downloaded_file (
307
- smartrest_request,
308
- operation_id,
309
- & response. file_path ,
310
- )
311
- . await
312
- {
313
- self . fail_operation_in_cloud ( & child_id, Some ( operation_id) , & err. to_string ( ) )
314
- . await ?;
315
- }
304
+ // Publish a firmware update request to child device.
305
+ self . handle_firmware_update_request_with_downloaded_file (
306
+ smartrest_request,
307
+ operation_id,
308
+ & response. file_path ,
309
+ )
310
+ . await ?
316
311
}
317
312
Err ( err) => {
318
- let firmware_url = smartrest_request . url ;
319
- let failure_reason = format ! ( "Download from { firmware_url} failed with {err}" ) ;
320
- self . fail_operation_in_cloud ( & child_id , Some ( operation_id ) , & failure_reason )
321
- . await ? ;
313
+ return Err ( FirmwareManagementError :: FromDownloadError {
314
+ firmware_url : smartrest_request . url ,
315
+ err ,
316
+ } ) ;
322
317
}
323
318
}
324
319
Ok ( ( ) )
@@ -335,7 +330,7 @@ impl FirmwareManagerActor {
335
330
let child_id = smartrest_request. device . as_str ( ) ;
336
331
let firmware_url = smartrest_request. url . as_str ( ) ;
337
332
let file_cache_key = digest ( firmware_url) ;
338
- let cache_dir_path = self . worker . config . validate_and_get_cache_dir_path ( ) ?;
333
+ let cache_dir_path = self . config . validate_and_get_cache_dir_path ( ) ?;
339
334
let cache_file_path = cache_dir_path. join ( & file_cache_key) ;
340
335
341
336
// If the downloaded firmware is not already in the cache, move it there
@@ -353,7 +348,7 @@ impl FirmwareManagerActor {
353
348
self . create_file_transfer_symlink ( child_id, & file_cache_key, & cache_file_path) ?;
354
349
let file_transfer_url = format ! (
355
350
"http://{}/tedge/file-transfer/{child_id}/firmware_update/{file_cache_key}" ,
356
- & self . worker . config. local_http_host
351
+ & self . config. local_http_host
357
352
) ;
358
353
let file_sha256 = try_digest ( symlink_path. as_path ( ) ) ?;
359
354
@@ -368,27 +363,23 @@ impl FirmwareManagerActor {
368
363
attempt : 1 ,
369
364
} ;
370
365
371
- operation_entry. create_status_file ( self . worker . config . data_dir . firmware_dir ( ) ) ?;
366
+ operation_entry. create_status_file ( self . config . data_dir . firmware_dir ( ) ) ?;
372
367
373
368
self . publish_firmware_update_request ( operation_entry)
374
369
. await ?;
375
370
376
371
let operation_key = OperationKey :: new ( child_id, operation_id) ;
377
- self . active_child_ops
378
- . insert ( operation_key. clone ( ) , ActiveOperationState :: Pending ) ;
379
372
380
373
// Start timer
381
- self . worker
382
- . timer_sender
383
- . send ( SetTimeout :: new (
384
- self . worker . config . timeout_sec ,
385
- operation_key,
386
- ) )
374
+ self . timer_sender
375
+ . send ( SetTimeout :: new ( self . config . timeout_sec , operation_key) )
387
376
. await ?;
388
377
389
378
Ok ( ( ) )
390
379
}
380
+ }
391
381
382
+ impl FirmwareManagerActor {
392
383
// This is the start point function when receiving a firmware response from child device.
393
384
async fn handle_child_device_firmware_operation_response (
394
385
& mut self ,
@@ -441,7 +432,7 @@ impl FirmwareManagerActor {
441
432
match current_operation_state {
442
433
Some ( & ActiveOperationState :: Executing ) => { }
443
434
Some ( & ActiveOperationState :: Pending ) => {
444
- self . publish_c8y_executing_message ( & child_id) . await ?;
435
+ self . worker . publish_c8y_executing_message ( & child_id) . await ?;
445
436
self . active_child_ops
446
437
. insert ( operation_key. clone ( ) , ActiveOperationState :: Executing ) ;
447
438
}
@@ -462,20 +453,24 @@ impl FirmwareManagerActor {
462
453
let operation_entry =
463
454
FirmwareOperationEntry :: read_from_file ( status_file_path. as_path ( ) ) ?;
464
455
465
- self . publish_c8y_installed_firmware_message ( & operation_entry)
456
+ self . worker
457
+ . publish_c8y_installed_firmware_message ( & operation_entry)
458
+ . await ?;
459
+ self . worker
460
+ . publish_c8y_successful_message ( & child_id)
466
461
. await ?;
467
- self . publish_c8y_successful_message ( & child_id) . await ?;
468
462
469
- self . remove_status_file ( operation_id) ?;
463
+ self . worker . remove_status_file ( operation_id) ?;
470
464
self . remove_entry_from_active_operations ( & operation_key) ;
471
465
}
472
466
OperationStatus :: Failed => {
473
- self . publish_c8y_failed_message (
474
- & child_id,
475
- "No failure reason provided by child device." ,
476
- )
477
- . await ?;
478
- self . remove_status_file ( operation_id) ?;
467
+ self . worker
468
+ . publish_c8y_failed_message (
469
+ & child_id,
470
+ "No failure reason provided by child device." ,
471
+ )
472
+ . await ?;
473
+ self . worker . remove_status_file ( operation_id) ?;
479
474
self . remove_entry_from_active_operations ( & operation_key) ;
480
475
}
481
476
OperationStatus :: Executing => {
@@ -542,7 +537,8 @@ impl FirmwareManagerActor {
542
537
) ;
543
538
544
539
new_operation_entry. overwrite_file ( & firmware_dir_path) ?;
545
- self . publish_firmware_update_request ( new_operation_entry)
540
+ self . worker
541
+ . publish_firmware_update_request ( new_operation_entry)
546
542
. await ?;
547
543
// Add operation to hashmap
548
544
self . active_child_ops
@@ -585,16 +581,17 @@ impl FirmwareManagerActor {
585
581
) -> Result < ( ) , FirmwareManagementError > {
586
582
error ! ( "{}" , failure_reason) ;
587
583
let op_state = if let Some ( operation_id) = op_id {
588
- self . remove_status_file ( operation_id) ?;
584
+ self . worker . remove_status_file ( operation_id) ?;
589
585
self . remove_entry_from_active_operations ( & OperationKey :: new ( child_id, operation_id) )
590
586
} else {
591
587
ActiveOperationState :: Pending
592
588
} ;
593
589
594
590
if op_state == ActiveOperationState :: Pending {
595
- self . publish_c8y_executing_message ( child_id) . await ?;
591
+ self . worker . publish_c8y_executing_message ( child_id) . await ?;
596
592
}
597
- self . publish_c8y_failed_message ( child_id, failure_reason)
593
+ self . worker
594
+ . publish_c8y_failed_message ( child_id, failure_reason)
598
595
. await ?;
599
596
600
597
Ok ( ( ) )
@@ -616,7 +613,8 @@ impl FirmwareManagerActor {
616
613
OperationKey :: new ( & operation_entry. child_id , & operation_entry. operation_id ) ;
617
614
618
615
operation_entry. overwrite_file ( & firmware_dir_path) ?;
619
- self . publish_firmware_update_request ( operation_entry)
616
+ self . worker
617
+ . publish_firmware_update_request ( operation_entry)
620
618
. await ?;
621
619
// Add operation to hashmap
622
620
self . active_child_ops
@@ -633,10 +631,11 @@ impl FirmwareManagerActor {
633
631
}
634
632
Ok ( ( ) )
635
633
}
634
+ }
636
635
636
+ impl FirmwareManagerWorker {
637
637
fn remove_status_file ( & mut self , operation_id : & str ) -> Result < ( ) , FirmwareManagementError > {
638
638
let status_file_path = self
639
- . worker
640
639
. config
641
640
. validate_and_get_firmware_dir_path ( ) ?
642
641
. join ( operation_id) ;
@@ -652,7 +651,7 @@ impl FirmwareManagerActor {
652
651
) -> Result < ( ) , FirmwareManagementError > {
653
652
let mqtt_message: MqttMessage =
654
653
FirmwareOperationRequest :: from ( operation_entry. clone ( ) ) . try_into ( ) ?;
655
- self . worker . mqtt_publisher . send ( mqtt_message) . await ?;
654
+ self . mqtt_publisher . send ( mqtt_message) . await ?;
656
655
info ! (
657
656
"Firmware update request is sent. operation_id={}, child={}" ,
658
657
operation_entry. operation_id, operation_entry. child_id
@@ -671,7 +670,7 @@ impl FirmwareManagerActor {
671
670
& c8y_child_topic,
672
671
DownloadFirmwareStatusMessage :: status_executing ( ) ,
673
672
) ;
674
- self . worker . mqtt_publisher . send ( executing_msg) . await ?;
673
+ self . mqtt_publisher . send ( executing_msg) . await ?;
675
674
Ok ( ( ) )
676
675
}
677
676
@@ -686,7 +685,7 @@ impl FirmwareManagerActor {
686
685
& c8y_child_topic,
687
686
DownloadFirmwareStatusMessage :: status_successful ( None ) ,
688
687
) ;
689
- self . worker . mqtt_publisher . send ( successful_msg) . await ?;
688
+ self . mqtt_publisher . send ( successful_msg) . await ?;
690
689
Ok ( ( ) )
691
690
}
692
691
@@ -702,7 +701,7 @@ impl FirmwareManagerActor {
702
701
& c8y_child_topic,
703
702
DownloadFirmwareStatusMessage :: status_failed ( failure_reason) ,
704
703
) ;
705
- self . worker . mqtt_publisher . send ( failed_msg) . await ?;
704
+ self . mqtt_publisher . send ( failed_msg) . await ?;
706
705
Ok ( ( ) )
707
706
}
708
707
@@ -719,13 +718,12 @@ impl FirmwareManagerActor {
719
718
) ;
720
719
let installed_firmware_message =
721
720
MqttMessage :: new ( & c8y_child_topic, installed_firmware_payload) ;
722
- self . worker
723
- . mqtt_publisher
724
- . send ( installed_firmware_message)
725
- . await ?;
721
+ self . mqtt_publisher . send ( installed_firmware_message) . await ?;
726
722
Ok ( ( ) )
727
723
}
724
+ }
728
725
726
+ impl FirmwareManagerActor {
729
727
fn remove_entry_from_active_operations (
730
728
& mut self ,
731
729
operation_key : & OperationKey ,
@@ -736,18 +734,17 @@ impl FirmwareManagerActor {
736
734
ActiveOperationState :: Pending
737
735
}
738
736
}
737
+ }
739
738
739
+ impl FirmwareManagerWorker {
740
740
// The symlink path should be <tedge-data-dir>/file-transfer/<child-id>/firmware_update/<file_cache_key>
741
741
fn create_file_transfer_symlink (
742
742
& self ,
743
743
child_id : & str ,
744
744
file_cache_key : & str ,
745
745
original_file_path : impl AsRef < Path > ,
746
746
) -> Result < Utf8PathBuf , FirmwareManagementError > {
747
- let file_transfer_dir_path = self
748
- . worker
749
- . config
750
- . validate_and_get_file_transfer_dir_path ( ) ?;
747
+ let file_transfer_dir_path = self . config . validate_and_get_file_transfer_dir_path ( ) ?;
751
748
752
749
let symlink_dir_path = file_transfer_dir_path
753
750
. join ( child_id)
@@ -764,7 +761,7 @@ impl FirmwareManagerActor {
764
761
// Candidate to be removed since another actor should be in charge of this.
765
762
async fn get_pending_operations_from_cloud ( & mut self ) -> Result < ( ) , FirmwareManagementError > {
766
763
let message = MqttMessage :: new ( & C8yTopic :: SmartRestResponse . to_topic ( ) ?, "500" ) ;
767
- self . worker . mqtt_publisher . send ( message) . await ?;
764
+ self . mqtt_publisher . send ( message) . await ?;
768
765
Ok ( ( ) )
769
766
}
770
767
}
0 commit comments