rucio 32.8.6__py3-none-any.whl → 35.8.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of rucio might be problematic. Click here for more details.

Files changed (502) hide show
  1. rucio/__init__.py +0 -1
  2. rucio/alembicrevision.py +1 -2
  3. rucio/client/__init__.py +0 -1
  4. rucio/client/accountclient.py +45 -25
  5. rucio/client/accountlimitclient.py +37 -9
  6. rucio/client/baseclient.py +199 -154
  7. rucio/client/client.py +2 -3
  8. rucio/client/configclient.py +19 -6
  9. rucio/client/credentialclient.py +9 -4
  10. rucio/client/didclient.py +238 -63
  11. rucio/client/diracclient.py +13 -5
  12. rucio/client/downloadclient.py +162 -51
  13. rucio/client/exportclient.py +4 -4
  14. rucio/client/fileclient.py +3 -4
  15. rucio/client/importclient.py +4 -4
  16. rucio/client/lifetimeclient.py +21 -5
  17. rucio/client/lockclient.py +18 -8
  18. rucio/client/{metaclient.py → metaconventionsclient.py} +18 -15
  19. rucio/client/pingclient.py +0 -1
  20. rucio/client/replicaclient.py +15 -5
  21. rucio/client/requestclient.py +35 -19
  22. rucio/client/rseclient.py +133 -51
  23. rucio/client/ruleclient.py +29 -22
  24. rucio/client/scopeclient.py +8 -6
  25. rucio/client/subscriptionclient.py +47 -35
  26. rucio/client/touchclient.py +8 -4
  27. rucio/client/uploadclient.py +166 -82
  28. rucio/common/__init__.py +0 -1
  29. rucio/common/cache.py +4 -4
  30. rucio/common/config.py +52 -47
  31. rucio/common/constants.py +69 -2
  32. rucio/common/constraints.py +0 -1
  33. rucio/common/didtype.py +24 -22
  34. rucio/common/dumper/__init__.py +70 -41
  35. rucio/common/dumper/consistency.py +26 -22
  36. rucio/common/dumper/data_models.py +16 -23
  37. rucio/common/dumper/path_parsing.py +0 -1
  38. rucio/common/exception.py +281 -222
  39. rucio/common/extra.py +0 -1
  40. rucio/common/logging.py +54 -38
  41. rucio/common/pcache.py +122 -101
  42. rucio/common/plugins.py +153 -0
  43. rucio/common/policy.py +4 -4
  44. rucio/common/schema/__init__.py +17 -10
  45. rucio/common/schema/atlas.py +7 -5
  46. rucio/common/schema/belleii.py +7 -5
  47. rucio/common/schema/domatpc.py +7 -5
  48. rucio/common/schema/escape.py +7 -5
  49. rucio/common/schema/generic.py +8 -6
  50. rucio/common/schema/generic_multi_vo.py +7 -5
  51. rucio/common/schema/icecube.py +7 -5
  52. rucio/common/stomp_utils.py +0 -1
  53. rucio/common/stopwatch.py +0 -1
  54. rucio/common/test_rucio_server.py +2 -2
  55. rucio/common/types.py +262 -17
  56. rucio/common/utils.py +743 -451
  57. rucio/core/__init__.py +0 -1
  58. rucio/core/account.py +99 -29
  59. rucio/core/account_counter.py +89 -24
  60. rucio/core/account_limit.py +90 -24
  61. rucio/core/authentication.py +86 -29
  62. rucio/core/config.py +108 -38
  63. rucio/core/credential.py +14 -7
  64. rucio/core/did.py +680 -782
  65. rucio/core/did_meta_plugins/__init__.py +8 -6
  66. rucio/core/did_meta_plugins/did_column_meta.py +17 -12
  67. rucio/core/did_meta_plugins/did_meta_plugin_interface.py +60 -11
  68. rucio/core/did_meta_plugins/filter_engine.py +90 -50
  69. rucio/core/did_meta_plugins/json_meta.py +41 -16
  70. rucio/core/did_meta_plugins/mongo_meta.py +25 -8
  71. rucio/core/did_meta_plugins/postgres_meta.py +3 -4
  72. rucio/core/dirac.py +46 -17
  73. rucio/core/distance.py +66 -43
  74. rucio/core/exporter.py +5 -5
  75. rucio/core/heartbeat.py +181 -81
  76. rucio/core/identity.py +22 -12
  77. rucio/core/importer.py +23 -12
  78. rucio/core/lifetime_exception.py +32 -32
  79. rucio/core/lock.py +244 -142
  80. rucio/core/message.py +79 -38
  81. rucio/core/{meta.py → meta_conventions.py} +57 -44
  82. rucio/core/monitor.py +19 -13
  83. rucio/core/naming_convention.py +68 -27
  84. rucio/core/nongrid_trace.py +17 -5
  85. rucio/core/oidc.py +151 -29
  86. rucio/core/permission/__init__.py +18 -6
  87. rucio/core/permission/atlas.py +50 -35
  88. rucio/core/permission/belleii.py +6 -5
  89. rucio/core/permission/escape.py +8 -6
  90. rucio/core/permission/generic.py +82 -80
  91. rucio/core/permission/generic_multi_vo.py +9 -7
  92. rucio/core/quarantined_replica.py +91 -58
  93. rucio/core/replica.py +1303 -772
  94. rucio/core/replica_sorter.py +10 -12
  95. rucio/core/request.py +1133 -285
  96. rucio/core/rse.py +142 -102
  97. rucio/core/rse_counter.py +49 -18
  98. rucio/core/rse_expression_parser.py +6 -7
  99. rucio/core/rse_selector.py +41 -16
  100. rucio/core/rule.py +1538 -474
  101. rucio/core/rule_grouping.py +213 -68
  102. rucio/core/scope.py +50 -22
  103. rucio/core/subscription.py +92 -44
  104. rucio/core/topology.py +66 -24
  105. rucio/core/trace.py +42 -28
  106. rucio/core/transfer.py +543 -259
  107. rucio/core/vo.py +36 -18
  108. rucio/core/volatile_replica.py +59 -32
  109. rucio/daemons/__init__.py +0 -1
  110. rucio/daemons/abacus/__init__.py +0 -1
  111. rucio/daemons/abacus/account.py +29 -19
  112. rucio/daemons/abacus/collection_replica.py +21 -10
  113. rucio/daemons/abacus/rse.py +22 -12
  114. rucio/daemons/atropos/__init__.py +0 -1
  115. rucio/daemons/atropos/atropos.py +1 -2
  116. rucio/daemons/auditor/__init__.py +56 -28
  117. rucio/daemons/auditor/hdfs.py +17 -6
  118. rucio/daemons/auditor/srmdumps.py +116 -45
  119. rucio/daemons/automatix/__init__.py +0 -1
  120. rucio/daemons/automatix/automatix.py +30 -18
  121. rucio/daemons/badreplicas/__init__.py +0 -1
  122. rucio/daemons/badreplicas/minos.py +29 -18
  123. rucio/daemons/badreplicas/minos_temporary_expiration.py +5 -7
  124. rucio/daemons/badreplicas/necromancer.py +9 -13
  125. rucio/daemons/bb8/__init__.py +0 -1
  126. rucio/daemons/bb8/bb8.py +10 -13
  127. rucio/daemons/bb8/common.py +151 -154
  128. rucio/daemons/bb8/nuclei_background_rebalance.py +15 -9
  129. rucio/daemons/bb8/t2_background_rebalance.py +15 -8
  130. rucio/daemons/c3po/__init__.py +0 -1
  131. rucio/daemons/c3po/algorithms/__init__.py +0 -1
  132. rucio/daemons/c3po/algorithms/simple.py +8 -5
  133. rucio/daemons/c3po/algorithms/t2_free_space.py +10 -7
  134. rucio/daemons/c3po/algorithms/t2_free_space_only_pop.py +10 -7
  135. rucio/daemons/c3po/algorithms/t2_free_space_only_pop_with_network.py +30 -15
  136. rucio/daemons/c3po/c3po.py +81 -52
  137. rucio/daemons/c3po/collectors/__init__.py +0 -1
  138. rucio/daemons/c3po/collectors/agis.py +17 -17
  139. rucio/daemons/c3po/collectors/free_space.py +32 -13
  140. rucio/daemons/c3po/collectors/jedi_did.py +14 -5
  141. rucio/daemons/c3po/collectors/mock_did.py +11 -6
  142. rucio/daemons/c3po/collectors/network_metrics.py +12 -4
  143. rucio/daemons/c3po/collectors/workload.py +21 -19
  144. rucio/daemons/c3po/utils/__init__.py +0 -1
  145. rucio/daemons/c3po/utils/dataset_cache.py +15 -5
  146. rucio/daemons/c3po/utils/expiring_dataset_cache.py +16 -5
  147. rucio/daemons/c3po/utils/expiring_list.py +6 -7
  148. rucio/daemons/c3po/utils/popularity.py +5 -2
  149. rucio/daemons/c3po/utils/timeseries.py +25 -12
  150. rucio/daemons/cache/__init__.py +0 -1
  151. rucio/daemons/cache/consumer.py +21 -15
  152. rucio/daemons/common.py +42 -18
  153. rucio/daemons/conveyor/__init__.py +0 -1
  154. rucio/daemons/conveyor/common.py +69 -37
  155. rucio/daemons/conveyor/finisher.py +83 -46
  156. rucio/daemons/conveyor/poller.py +101 -69
  157. rucio/daemons/conveyor/preparer.py +35 -28
  158. rucio/daemons/conveyor/receiver.py +64 -21
  159. rucio/daemons/conveyor/stager.py +33 -28
  160. rucio/daemons/conveyor/submitter.py +71 -47
  161. rucio/daemons/conveyor/throttler.py +99 -35
  162. rucio/daemons/follower/__init__.py +0 -1
  163. rucio/daemons/follower/follower.py +12 -8
  164. rucio/daemons/hermes/__init__.py +0 -1
  165. rucio/daemons/hermes/hermes.py +57 -21
  166. rucio/daemons/judge/__init__.py +0 -1
  167. rucio/daemons/judge/cleaner.py +27 -17
  168. rucio/daemons/judge/evaluator.py +31 -18
  169. rucio/daemons/judge/injector.py +31 -23
  170. rucio/daemons/judge/repairer.py +28 -18
  171. rucio/daemons/oauthmanager/__init__.py +0 -1
  172. rucio/daemons/oauthmanager/oauthmanager.py +7 -8
  173. rucio/daemons/reaper/__init__.py +0 -1
  174. rucio/daemons/reaper/dark_reaper.py +15 -9
  175. rucio/daemons/reaper/reaper.py +109 -67
  176. rucio/daemons/replicarecoverer/__init__.py +0 -1
  177. rucio/daemons/replicarecoverer/suspicious_replica_recoverer.py +255 -116
  178. rucio/{api → daemons/rsedecommissioner}/__init__.py +0 -1
  179. rucio/daemons/rsedecommissioner/config.py +81 -0
  180. rucio/daemons/rsedecommissioner/profiles/__init__.py +24 -0
  181. rucio/daemons/rsedecommissioner/profiles/atlas.py +60 -0
  182. rucio/daemons/rsedecommissioner/profiles/generic.py +451 -0
  183. rucio/daemons/rsedecommissioner/profiles/types.py +92 -0
  184. rucio/daemons/rsedecommissioner/rse_decommissioner.py +280 -0
  185. rucio/daemons/storage/__init__.py +0 -1
  186. rucio/daemons/storage/consistency/__init__.py +0 -1
  187. rucio/daemons/storage/consistency/actions.py +152 -59
  188. rucio/daemons/tracer/__init__.py +0 -1
  189. rucio/daemons/tracer/kronos.py +47 -24
  190. rucio/daemons/transmogrifier/__init__.py +0 -1
  191. rucio/daemons/transmogrifier/transmogrifier.py +35 -26
  192. rucio/daemons/undertaker/__init__.py +0 -1
  193. rucio/daemons/undertaker/undertaker.py +10 -10
  194. rucio/db/__init__.py +0 -1
  195. rucio/db/sqla/__init__.py +16 -2
  196. rucio/db/sqla/constants.py +10 -1
  197. rucio/db/sqla/migrate_repo/__init__.py +0 -1
  198. rucio/db/sqla/migrate_repo/env.py +0 -1
  199. rucio/db/sqla/migrate_repo/versions/01eaf73ab656_add_new_rule_notification_state_progress.py +0 -1
  200. rucio/db/sqla/migrate_repo/versions/0437a40dbfd1_add_eol_at_in_rules.py +0 -3
  201. rucio/db/sqla/migrate_repo/versions/0f1adb7a599a_create_transfer_hops_table.py +1 -3
  202. rucio/db/sqla/migrate_repo/versions/102efcf145f4_added_stuck_at_column_to_rules.py +0 -3
  203. rucio/db/sqla/migrate_repo/versions/13d4f70c66a9_introduce_transfer_limits.py +1 -3
  204. rucio/db/sqla/migrate_repo/versions/140fef722e91_cleanup_distances_table.py +1 -3
  205. rucio/db/sqla/migrate_repo/versions/14ec5aeb64cf_add_request_external_host.py +0 -3
  206. rucio/db/sqla/migrate_repo/versions/156fb5b5a14_add_request_type_to_requests_idx.py +1 -4
  207. rucio/db/sqla/migrate_repo/versions/1677d4d803c8_split_rse_availability_into_multiple.py +0 -1
  208. rucio/db/sqla/migrate_repo/versions/16a0aca82e12_create_index_on_table_replicas_path.py +0 -2
  209. rucio/db/sqla/migrate_repo/versions/1803333ac20f_adding_provenance_and_phys_group.py +0 -1
  210. rucio/db/sqla/migrate_repo/versions/1a29d6a9504c_add_didtype_chck_to_requests.py +0 -1
  211. rucio/db/sqla/migrate_repo/versions/1a80adff031a_create_index_on_rules_hist_recent.py +0 -2
  212. rucio/db/sqla/migrate_repo/versions/1c45d9730ca6_increase_identity_length.py +0 -1
  213. rucio/db/sqla/migrate_repo/versions/1d1215494e95_add_quarantined_replicas_table.py +1 -3
  214. rucio/db/sqla/migrate_repo/versions/1d96f484df21_asynchronous_rules_and_rule_approval.py +0 -1
  215. rucio/db/sqla/migrate_repo/versions/1f46c5f240ac_add_bytes_column_to_bad_replicas.py +0 -3
  216. rucio/db/sqla/migrate_repo/versions/1fc15ab60d43_add_message_history_table.py +0 -1
  217. rucio/db/sqla/migrate_repo/versions/2190e703eb6e_move_rse_settings_to_rse_attributes.py +1 -2
  218. rucio/db/sqla/migrate_repo/versions/21d6b9dc9961_add_mismatch_scheme_state_to_requests.py +0 -1
  219. rucio/db/sqla/migrate_repo/versions/22cf51430c78_add_availability_column_to_table_rses.py +0 -3
  220. rucio/db/sqla/migrate_repo/versions/22d887e4ec0a_create_sources_table.py +1 -3
  221. rucio/db/sqla/migrate_repo/versions/25821a8a45a3_remove_unique_constraint_on_requests.py +1 -4
  222. rucio/db/sqla/migrate_repo/versions/25fc855625cf_added_unique_constraint_to_rules.py +0 -2
  223. rucio/db/sqla/migrate_repo/versions/269fee20dee9_add_repair_cnt_to_locks.py +0 -3
  224. rucio/db/sqla/migrate_repo/versions/271a46ea6244_add_ignore_availability_column_to_rules.py +0 -3
  225. rucio/db/sqla/migrate_repo/versions/277b5fbb41d3_switch_heartbeats_executable.py +1 -2
  226. rucio/db/sqla/migrate_repo/versions/27e3a68927fb_remove_replicas_tombstone_and_replicas_.py +0 -1
  227. rucio/db/sqla/migrate_repo/versions/2854cd9e168_added_rule_id_column.py +0 -1
  228. rucio/db/sqla/migrate_repo/versions/295289b5a800_processed_by_and__at_in_requests.py +0 -2
  229. rucio/db/sqla/migrate_repo/versions/2962ece31cf4_add_nbaccesses_column_in_the_did_table.py +0 -3
  230. rucio/db/sqla/migrate_repo/versions/2af3291ec4c_added_replicas_history_table.py +1 -3
  231. rucio/db/sqla/migrate_repo/versions/2b69addda658_add_columns_for_third_party_copy_read_.py +0 -2
  232. rucio/db/sqla/migrate_repo/versions/2b8e7bcb4783_add_config_table.py +1 -4
  233. rucio/db/sqla/migrate_repo/versions/2ba5229cb54c_add_submitted_at_to_requests_table.py +0 -3
  234. rucio/db/sqla/migrate_repo/versions/2cbee484dcf9_added_column_volume_to_rse_transfer_.py +1 -4
  235. rucio/db/sqla/migrate_repo/versions/2edee4a83846_add_source_to_requests_and_requests_.py +0 -1
  236. rucio/db/sqla/migrate_repo/versions/2eef46be23d4_change_tokens_pk.py +1 -3
  237. rucio/db/sqla/migrate_repo/versions/2f648fc909f3_index_in_rule_history_on_scope_name.py +0 -2
  238. rucio/db/sqla/migrate_repo/versions/3082b8cef557_add_naming_convention_table_and_closed_.py +1 -3
  239. rucio/db/sqla/migrate_repo/versions/30fa38b6434e_add_index_on_service_column_in_the_message_table.py +1 -3
  240. rucio/db/sqla/migrate_repo/versions/3152492b110b_added_staging_area_column.py +1 -2
  241. rucio/db/sqla/migrate_repo/versions/32c7d2783f7e_create_bad_replicas_table.py +1 -3
  242. rucio/db/sqla/migrate_repo/versions/3345511706b8_replicas_table_pk_definition_is_in_.py +1 -3
  243. rucio/db/sqla/migrate_repo/versions/35ef10d1e11b_change_index_on_table_requests.py +0 -2
  244. rucio/db/sqla/migrate_repo/versions/379a19b5332d_create_rse_limits_table.py +1 -3
  245. rucio/db/sqla/migrate_repo/versions/384b96aa0f60_created_rule_history_tables.py +2 -3
  246. rucio/db/sqla/migrate_repo/versions/3ac1660a1a72_extend_distance_table.py +0 -3
  247. rucio/db/sqla/migrate_repo/versions/3ad36e2268b0_create_collection_replicas_updates_table.py +1 -4
  248. rucio/db/sqla/migrate_repo/versions/3c9df354071b_extend_waiting_request_state.py +0 -1
  249. rucio/db/sqla/migrate_repo/versions/3d9813fab443_add_a_new_state_lost_in_badfilesstatus.py +0 -1
  250. rucio/db/sqla/migrate_repo/versions/40ad39ce3160_add_transferred_at_to_requests_table.py +0 -3
  251. rucio/db/sqla/migrate_repo/versions/4207be2fd914_add_notification_column_to_rules.py +0 -1
  252. rucio/db/sqla/migrate_repo/versions/42db2617c364_create_index_on_requests_external_id.py +0 -2
  253. rucio/db/sqla/migrate_repo/versions/436827b13f82_added_column_activity_to_table_requests.py +0 -3
  254. rucio/db/sqla/migrate_repo/versions/44278720f774_update_requests_typ_sta_upd_idx_index.py +0 -2
  255. rucio/db/sqla/migrate_repo/versions/45378a1e76a8_create_collection_replica_table.py +2 -4
  256. rucio/db/sqla/migrate_repo/versions/469d262be19_removing_created_at_index.py +0 -2
  257. rucio/db/sqla/migrate_repo/versions/4783c1f49cb4_create_distance_table.py +1 -3
  258. rucio/db/sqla/migrate_repo/versions/49a21b4d4357_create_index_on_table_tokens.py +1 -4
  259. rucio/db/sqla/migrate_repo/versions/4a2cbedda8b9_add_source_replica_expression_column_to_.py +0 -3
  260. rucio/db/sqla/migrate_repo/versions/4a7182d9578b_added_bytes_length_accessed_at_columns.py +0 -3
  261. rucio/db/sqla/migrate_repo/versions/4bab9edd01fc_create_index_on_requests_rule_id.py +0 -2
  262. rucio/db/sqla/migrate_repo/versions/4c3a4acfe006_new_attr_account_table.py +1 -3
  263. rucio/db/sqla/migrate_repo/versions/4cf0a2e127d4_adding_transient_metadata.py +0 -3
  264. rucio/db/sqla/migrate_repo/versions/4df2c5ddabc0_remove_temporary_dids.py +55 -0
  265. rucio/db/sqla/migrate_repo/versions/50280c53117c_add_qos_class_to_rse.py +0 -2
  266. rucio/db/sqla/migrate_repo/versions/52153819589c_add_rse_id_to_replicas_table.py +0 -2
  267. rucio/db/sqla/migrate_repo/versions/52fd9f4916fa_added_activity_to_rules.py +0 -3
  268. rucio/db/sqla/migrate_repo/versions/53b479c3cb0f_fix_did_meta_table_missing_updated_at_.py +0 -3
  269. rucio/db/sqla/migrate_repo/versions/5673b4b6e843_add_wfms_metadata_to_rule_tables.py +0 -3
  270. rucio/db/sqla/migrate_repo/versions/575767d9f89_added_source_history_table.py +1 -2
  271. rucio/db/sqla/migrate_repo/versions/58bff7008037_add_started_at_to_requests.py +0 -3
  272. rucio/db/sqla/migrate_repo/versions/58c8b78301ab_rename_callback_to_message.py +1 -3
  273. rucio/db/sqla/migrate_repo/versions/5f139f77382a_added_child_rule_id_column.py +1 -3
  274. rucio/db/sqla/migrate_repo/versions/688ef1840840_adding_did_meta_table.py +1 -2
  275. rucio/db/sqla/migrate_repo/versions/6e572a9bfbf3_add_new_split_container_column_to_rules.py +0 -3
  276. rucio/db/sqla/migrate_repo/versions/70587619328_add_comment_column_for_subscriptions.py +0 -3
  277. rucio/db/sqla/migrate_repo/versions/739064d31565_remove_history_table_pks.py +1 -2
  278. rucio/db/sqla/migrate_repo/versions/7541902bf173_add_didsfollowed_and_followevents_table.py +2 -4
  279. rucio/db/sqla/migrate_repo/versions/7ec22226cdbf_new_replica_state_for_temporary_.py +0 -1
  280. rucio/db/sqla/migrate_repo/versions/810a41685bc1_added_columns_rse_transfer_limits.py +1 -4
  281. rucio/db/sqla/migrate_repo/versions/83f991c63a93_correct_rse_expression_length.py +0 -2
  282. rucio/db/sqla/migrate_repo/versions/8523998e2e76_increase_size_of_extended_attributes_.py +0 -3
  283. rucio/db/sqla/migrate_repo/versions/8ea9122275b1_adding_missing_function_based_indices.py +1 -2
  284. rucio/db/sqla/migrate_repo/versions/90f47792bb76_add_clob_payload_to_messages.py +0 -3
  285. rucio/db/sqla/migrate_repo/versions/914b8f02df38_new_table_for_lifetime_model_exceptions.py +1 -3
  286. rucio/db/sqla/migrate_repo/versions/94a5961ddbf2_add_estimator_columns.py +0 -3
  287. rucio/db/sqla/migrate_repo/versions/9a1b149a2044_add_saml_identity_type.py +0 -1
  288. rucio/db/sqla/migrate_repo/versions/9a45bc4ea66d_add_vp_table.py +1 -2
  289. rucio/db/sqla/migrate_repo/versions/9eb936a81eb1_true_is_true.py +0 -2
  290. rucio/db/sqla/migrate_repo/versions/a08fa8de1545_transfer_stats_table.py +55 -0
  291. rucio/db/sqla/migrate_repo/versions/a118956323f8_added_vo_table_and_vo_col_to_rse.py +1 -3
  292. rucio/db/sqla/migrate_repo/versions/a193a275255c_add_status_column_in_messages.py +0 -2
  293. rucio/db/sqla/migrate_repo/versions/a5f6f6e928a7_1_7_0.py +1 -4
  294. rucio/db/sqla/migrate_repo/versions/a616581ee47_added_columns_to_table_requests.py +0 -1
  295. rucio/db/sqla/migrate_repo/versions/a6eb23955c28_state_idx_non_functional.py +0 -1
  296. rucio/db/sqla/migrate_repo/versions/a74275a1ad30_added_global_quota_table.py +1 -3
  297. rucio/db/sqla/migrate_repo/versions/a93e4e47bda_heartbeats.py +1 -4
  298. rucio/db/sqla/migrate_repo/versions/ae2a56fcc89_added_comment_column_to_rules.py +0 -1
  299. rucio/db/sqla/migrate_repo/versions/b0070f3695c8_add_deletedidmeta_table.py +57 -0
  300. rucio/db/sqla/migrate_repo/versions/b4293a99f344_added_column_identity_to_table_tokens.py +0 -3
  301. rucio/db/sqla/migrate_repo/versions/b5493606bbf5_fix_primary_key_for_subscription_history.py +41 -0
  302. rucio/db/sqla/migrate_repo/versions/b7d287de34fd_removal_of_replicastate_source.py +1 -2
  303. rucio/db/sqla/migrate_repo/versions/b818052fa670_add_index_to_quarantined_replicas.py +1 -3
  304. rucio/db/sqla/migrate_repo/versions/b8caac94d7f0_add_comments_column_for_subscriptions_.py +0 -3
  305. rucio/db/sqla/migrate_repo/versions/b96a1c7e1cc4_new_bad_pfns_table_and_bad_replicas_.py +1 -5
  306. rucio/db/sqla/migrate_repo/versions/bb695f45c04_extend_request_state.py +1 -3
  307. rucio/db/sqla/migrate_repo/versions/bc68e9946deb_add_staging_timestamps_to_request.py +0 -3
  308. rucio/db/sqla/migrate_repo/versions/bf3baa1c1474_correct_pk_and_idx_for_history_tables.py +1 -3
  309. rucio/db/sqla/migrate_repo/versions/c0937668555f_add_qos_policy_map_table.py +1 -2
  310. rucio/db/sqla/migrate_repo/versions/c129ccdb2d5_add_lumiblocknr_to_dids.py +0 -3
  311. rucio/db/sqla/migrate_repo/versions/ccdbcd48206e_add_did_type_column_index_on_did_meta_.py +1 -4
  312. rucio/db/sqla/migrate_repo/versions/cebad904c4dd_new_payload_column_for_heartbeats.py +1 -2
  313. rucio/db/sqla/migrate_repo/versions/d1189a09c6e0_oauth2_0_and_jwt_feature_support_adding_.py +1 -4
  314. rucio/db/sqla/migrate_repo/versions/d23453595260_extend_request_state_for_preparer.py +1 -3
  315. rucio/db/sqla/migrate_repo/versions/d6dceb1de2d_added_purge_column_to_rules.py +1 -4
  316. rucio/db/sqla/migrate_repo/versions/d6e2c3b2cf26_remove_third_party_copy_column_from_rse.py +0 -2
  317. rucio/db/sqla/migrate_repo/versions/d91002c5841_new_account_limits_table.py +1 -3
  318. rucio/db/sqla/migrate_repo/versions/e138c364ebd0_extending_columns_for_filter_and_.py +0 -3
  319. rucio/db/sqla/migrate_repo/versions/e59300c8b179_support_for_archive.py +1 -3
  320. rucio/db/sqla/migrate_repo/versions/f1b14a8c2ac1_postgres_use_check_constraints.py +0 -1
  321. rucio/db/sqla/migrate_repo/versions/f41ffe206f37_oracle_global_temporary_tables.py +1 -2
  322. rucio/db/sqla/migrate_repo/versions/f85a2962b021_adding_transfertool_column_to_requests_.py +1 -3
  323. rucio/db/sqla/migrate_repo/versions/fa7a7d78b602_increase_refresh_token_size.py +0 -2
  324. rucio/db/sqla/migrate_repo/versions/fb28a95fe288_add_replicas_rse_id_tombstone_idx.py +0 -1
  325. rucio/db/sqla/migrate_repo/versions/fe1a65b176c9_set_third_party_copy_read_and_write_.py +1 -2
  326. rucio/db/sqla/migrate_repo/versions/fe8ea2fa9788_added_third_party_copy_column_to_rse_.py +0 -3
  327. rucio/db/sqla/models.py +122 -216
  328. rucio/db/sqla/sautils.py +12 -5
  329. rucio/db/sqla/session.py +71 -43
  330. rucio/db/sqla/types.py +3 -4
  331. rucio/db/sqla/util.py +91 -69
  332. rucio/gateway/__init__.py +13 -0
  333. rucio/{api → gateway}/account.py +119 -46
  334. rucio/{api → gateway}/account_limit.py +12 -13
  335. rucio/{api → gateway}/authentication.py +106 -33
  336. rucio/{api → gateway}/config.py +12 -13
  337. rucio/{api → gateway}/credential.py +15 -4
  338. rucio/{api → gateway}/did.py +384 -140
  339. rucio/{api → gateway}/dirac.py +16 -6
  340. rucio/{api → gateway}/exporter.py +3 -4
  341. rucio/{api → gateway}/heartbeat.py +17 -5
  342. rucio/{api → gateway}/identity.py +63 -19
  343. rucio/{api → gateway}/importer.py +3 -4
  344. rucio/{api → gateway}/lifetime_exception.py +35 -10
  345. rucio/{api → gateway}/lock.py +34 -12
  346. rucio/{api/meta.py → gateway/meta_conventions.py} +18 -16
  347. rucio/{api → gateway}/permission.py +4 -5
  348. rucio/{api → gateway}/quarantined_replica.py +13 -4
  349. rucio/{api → gateway}/replica.py +12 -11
  350. rucio/{api → gateway}/request.py +129 -28
  351. rucio/{api → gateway}/rse.py +11 -12
  352. rucio/{api → gateway}/rule.py +117 -35
  353. rucio/{api → gateway}/scope.py +24 -14
  354. rucio/{api → gateway}/subscription.py +65 -43
  355. rucio/{api → gateway}/vo.py +17 -7
  356. rucio/rse/__init__.py +3 -4
  357. rucio/rse/protocols/__init__.py +0 -1
  358. rucio/rse/protocols/bittorrent.py +184 -0
  359. rucio/rse/protocols/cache.py +1 -2
  360. rucio/rse/protocols/dummy.py +1 -2
  361. rucio/rse/protocols/gfal.py +12 -10
  362. rucio/rse/protocols/globus.py +7 -7
  363. rucio/rse/protocols/gsiftp.py +2 -3
  364. rucio/rse/protocols/http_cache.py +1 -2
  365. rucio/rse/protocols/mock.py +1 -2
  366. rucio/rse/protocols/ngarc.py +1 -2
  367. rucio/rse/protocols/posix.py +12 -13
  368. rucio/rse/protocols/protocol.py +116 -52
  369. rucio/rse/protocols/rclone.py +6 -7
  370. rucio/rse/protocols/rfio.py +4 -5
  371. rucio/rse/protocols/srm.py +9 -10
  372. rucio/rse/protocols/ssh.py +8 -9
  373. rucio/rse/protocols/storm.py +2 -3
  374. rucio/rse/protocols/webdav.py +17 -14
  375. rucio/rse/protocols/xrootd.py +23 -17
  376. rucio/rse/rsemanager.py +19 -7
  377. rucio/tests/__init__.py +0 -1
  378. rucio/tests/common.py +43 -17
  379. rucio/tests/common_server.py +3 -3
  380. rucio/transfertool/__init__.py +0 -1
  381. rucio/transfertool/bittorrent.py +199 -0
  382. rucio/transfertool/bittorrent_driver.py +52 -0
  383. rucio/transfertool/bittorrent_driver_qbittorrent.py +133 -0
  384. rucio/transfertool/fts3.py +250 -138
  385. rucio/transfertool/fts3_plugins.py +152 -0
  386. rucio/transfertool/globus.py +9 -8
  387. rucio/transfertool/globus_library.py +1 -2
  388. rucio/transfertool/mock.py +21 -12
  389. rucio/transfertool/transfertool.py +33 -24
  390. rucio/vcsversion.py +4 -4
  391. rucio/version.py +5 -13
  392. rucio/web/__init__.py +0 -1
  393. rucio/web/rest/__init__.py +0 -1
  394. rucio/web/rest/flaskapi/__init__.py +0 -1
  395. rucio/web/rest/flaskapi/authenticated_bp.py +0 -1
  396. rucio/web/rest/flaskapi/v1/__init__.py +0 -1
  397. rucio/web/rest/flaskapi/v1/accountlimits.py +15 -13
  398. rucio/web/rest/flaskapi/v1/accounts.py +49 -48
  399. rucio/web/rest/flaskapi/v1/archives.py +12 -10
  400. rucio/web/rest/flaskapi/v1/auth.py +146 -144
  401. rucio/web/rest/flaskapi/v1/common.py +82 -41
  402. rucio/web/rest/flaskapi/v1/config.py +5 -6
  403. rucio/web/rest/flaskapi/v1/credentials.py +7 -8
  404. rucio/web/rest/flaskapi/v1/dids.py +158 -28
  405. rucio/web/rest/flaskapi/v1/dirac.py +8 -8
  406. rucio/web/rest/flaskapi/v1/export.py +3 -5
  407. rucio/web/rest/flaskapi/v1/heartbeats.py +3 -5
  408. rucio/web/rest/flaskapi/v1/identities.py +3 -5
  409. rucio/web/rest/flaskapi/v1/import.py +3 -4
  410. rucio/web/rest/flaskapi/v1/lifetime_exceptions.py +6 -9
  411. rucio/web/rest/flaskapi/v1/locks.py +2 -4
  412. rucio/web/rest/flaskapi/v1/main.py +10 -2
  413. rucio/web/rest/flaskapi/v1/{meta.py → meta_conventions.py} +26 -11
  414. rucio/web/rest/flaskapi/v1/metrics.py +1 -2
  415. rucio/web/rest/flaskapi/v1/nongrid_traces.py +4 -4
  416. rucio/web/rest/flaskapi/v1/ping.py +6 -7
  417. rucio/web/rest/flaskapi/v1/redirect.py +8 -9
  418. rucio/web/rest/flaskapi/v1/replicas.py +43 -19
  419. rucio/web/rest/flaskapi/v1/requests.py +178 -21
  420. rucio/web/rest/flaskapi/v1/rses.py +61 -26
  421. rucio/web/rest/flaskapi/v1/rules.py +48 -18
  422. rucio/web/rest/flaskapi/v1/scopes.py +3 -5
  423. rucio/web/rest/flaskapi/v1/subscriptions.py +22 -18
  424. rucio/web/rest/flaskapi/v1/traces.py +4 -4
  425. rucio/web/rest/flaskapi/v1/types.py +20 -0
  426. rucio/web/rest/flaskapi/v1/vos.py +3 -5
  427. rucio/web/rest/main.py +0 -1
  428. rucio/web/rest/metrics.py +0 -1
  429. rucio/web/rest/ping.py +27 -0
  430. {rucio-32.8.6.data → rucio-35.8.0.data}/data/rucio/etc/ldap.cfg.template +1 -1
  431. rucio-35.8.0.data/data/rucio/requirements.server.txt +268 -0
  432. {rucio-32.8.6.data → rucio-35.8.0.data}/data/rucio/tools/bootstrap.py +3 -3
  433. {rucio-32.8.6.data → rucio-35.8.0.data}/data/rucio/tools/merge_rucio_configs.py +2 -5
  434. {rucio-32.8.6.data → rucio-35.8.0.data}/data/rucio/tools/reset_database.py +3 -3
  435. {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio +87 -85
  436. {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-abacus-account +0 -1
  437. {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-abacus-collection-replica +0 -1
  438. {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-abacus-rse +0 -1
  439. {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-admin +45 -32
  440. {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-atropos +0 -1
  441. {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-auditor +13 -7
  442. {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-automatix +1 -2
  443. {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-bb8 +0 -1
  444. {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-c3po +0 -1
  445. {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-cache-client +2 -3
  446. {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-cache-consumer +0 -1
  447. {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-conveyor-finisher +1 -2
  448. {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-conveyor-poller +0 -1
  449. {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-conveyor-preparer +0 -1
  450. {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-conveyor-receiver +0 -1
  451. {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-conveyor-stager +0 -1
  452. {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-conveyor-submitter +2 -3
  453. {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-conveyor-throttler +0 -1
  454. {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-dark-reaper +0 -1
  455. {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-dumper +11 -10
  456. {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-follower +0 -1
  457. {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-hermes +0 -1
  458. {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-judge-cleaner +0 -1
  459. {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-judge-evaluator +2 -3
  460. {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-judge-injector +0 -1
  461. {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-judge-repairer +0 -1
  462. {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-kronos +1 -3
  463. {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-minos +0 -1
  464. {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-minos-temporary-expiration +0 -1
  465. {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-necromancer +1 -2
  466. {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-oauth-manager +2 -3
  467. {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-reaper +0 -1
  468. {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-replica-recoverer +6 -7
  469. rucio-35.8.0.data/scripts/rucio-rse-decommissioner +66 -0
  470. {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-storage-consistency-actions +0 -1
  471. {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-transmogrifier +0 -1
  472. {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-undertaker +1 -2
  473. rucio-35.8.0.dist-info/METADATA +72 -0
  474. rucio-35.8.0.dist-info/RECORD +493 -0
  475. {rucio-32.8.6.dist-info → rucio-35.8.0.dist-info}/WHEEL +1 -1
  476. {rucio-32.8.6.dist-info → rucio-35.8.0.dist-info}/licenses/AUTHORS.rst +3 -0
  477. rucio/api/temporary_did.py +0 -49
  478. rucio/common/schema/cms.py +0 -478
  479. rucio/common/schema/lsst.py +0 -423
  480. rucio/core/permission/cms.py +0 -1166
  481. rucio/core/temporary_did.py +0 -188
  482. rucio/daemons/reaper/light_reaper.py +0 -255
  483. rucio/web/rest/flaskapi/v1/tmp_dids.py +0 -115
  484. rucio-32.8.6.data/data/rucio/requirements.txt +0 -55
  485. rucio-32.8.6.data/scripts/rucio-light-reaper +0 -53
  486. rucio-32.8.6.dist-info/METADATA +0 -83
  487. rucio-32.8.6.dist-info/RECORD +0 -481
  488. {rucio-32.8.6.data → rucio-35.8.0.data}/data/rucio/etc/alembic.ini.template +0 -0
  489. {rucio-32.8.6.data → rucio-35.8.0.data}/data/rucio/etc/alembic_offline.ini.template +0 -0
  490. {rucio-32.8.6.data → rucio-35.8.0.data}/data/rucio/etc/globus-config.yml.template +0 -0
  491. {rucio-32.8.6.data → rucio-35.8.0.data}/data/rucio/etc/mail_templates/rule_approval_request.tmpl +0 -0
  492. {rucio-32.8.6.data → rucio-35.8.0.data}/data/rucio/etc/mail_templates/rule_approved_admin.tmpl +0 -0
  493. {rucio-32.8.6.data → rucio-35.8.0.data}/data/rucio/etc/mail_templates/rule_approved_user.tmpl +0 -0
  494. {rucio-32.8.6.data → rucio-35.8.0.data}/data/rucio/etc/mail_templates/rule_denied_admin.tmpl +0 -0
  495. {rucio-32.8.6.data → rucio-35.8.0.data}/data/rucio/etc/mail_templates/rule_denied_user.tmpl +0 -0
  496. {rucio-32.8.6.data → rucio-35.8.0.data}/data/rucio/etc/mail_templates/rule_ok_notification.tmpl +0 -0
  497. {rucio-32.8.6.data → rucio-35.8.0.data}/data/rucio/etc/rse-accounts.cfg.template +0 -0
  498. {rucio-32.8.6.data → rucio-35.8.0.data}/data/rucio/etc/rucio.cfg.atlas.client.template +0 -0
  499. {rucio-32.8.6.data → rucio-35.8.0.data}/data/rucio/etc/rucio.cfg.template +0 -0
  500. {rucio-32.8.6.data → rucio-35.8.0.data}/data/rucio/etc/rucio_multi_vo.cfg.template +0 -0
  501. {rucio-32.8.6.dist-info → rucio-35.8.0.dist-info}/licenses/LICENSE +0 -0
  502. {rucio-32.8.6.dist-info → rucio-35.8.0.dist-info}/top_level.txt +0 -0
rucio/daemons/common.py CHANGED
@@ -1,4 +1,3 @@
1
- # -*- coding: utf-8 -*-
2
1
  # Copyright European Organization for Nuclear Research (CERN) since 2012
3
2
  #
4
3
  # Licensed under the Apache License, Version 2.0 (the "License");
@@ -22,13 +21,16 @@ import socket
22
21
  import threading
23
22
  import time
24
23
  from collections.abc import Callable, Generator, Iterator, Sequence
25
- from typing import Any, Generic, Optional, TypeVar, Union
24
+ from typing import TYPE_CHECKING, Any, Generic, Optional, TypeVar, Union
26
25
 
27
26
  from rucio.common.logging import formatted_logger
28
27
  from rucio.common.utils import PriorityQueue
29
28
  from rucio.core import heartbeat as heartbeat_core
30
29
  from rucio.core.monitor import MetricManager
31
30
 
31
+ if TYPE_CHECKING:
32
+ from rucio.common.types import LoggerFunction
33
+
32
34
  T = TypeVar('T')
33
35
  METRICS = MetricManager(module=__name__)
34
36
 
@@ -42,7 +44,7 @@ class HeartbeatHandler:
42
44
  """
43
45
  :param executable: the executable name which will be set in heartbeats
44
46
  :param renewal_interval: the interval at which the heartbeat will be renewed in the database.
45
- Calls to live() in-between intervals will re-use the locally cached heartbeat.
47
+ Calls to live() in-between intervals will reuse the locally cached heartbeat.
46
48
  """
47
49
  self.executable = executable
48
50
  self._hash_executable = None
@@ -58,28 +60,32 @@ class HeartbeatHandler:
58
60
  self.last_time = None
59
61
  self.last_payload = None
60
62
 
61
- def __enter__(self):
63
+ def __enter__(self) -> 'HeartbeatHandler':
62
64
  heartbeat_core.sanity_check(executable=self.executable, hostname=self.hostname)
63
65
  self.live()
64
66
  return self
65
67
 
66
- def __exit__(self, exc_type, exc_val, exc_tb):
68
+ def __exit__(self, exc_type, exc_val, exc_tb) -> None:
67
69
  if self.last_heart_beat:
68
70
  heartbeat_core.die(self.executable, self.hostname, self.pid, self.hb_thread)
69
71
  if self.logger:
70
72
  self.logger(logging.INFO, 'Heartbeat cleaned up')
71
73
 
72
74
  @property
73
- def hash_executable(self):
75
+ def hash_executable(self) -> str:
74
76
  if not self._hash_executable:
75
77
  self._hash_executable = heartbeat_core.calc_hash(self.executable)
76
78
  return self._hash_executable
77
79
 
78
80
  @property
79
- def short_executable(self):
81
+ def short_executable(self) -> str:
80
82
  return min(self.executable, self.hash_executable, key=len)
81
83
 
82
- def live(self, force_renew: bool = False, payload: Optional[str] = None):
84
+ def live(
85
+ self,
86
+ force_renew: bool = False,
87
+ payload: Optional[str] = None
88
+ ) -> tuple[int, int, Callable]:
83
89
  """
84
90
  :return: a tuple: <the number of the current worker>, <total number of workers>, <decorated logger>
85
91
  """
@@ -171,7 +177,18 @@ def db_workqueue(
171
177
  partition_wait_time: int,
172
178
  sleep_time: int,
173
179
  activities: Optional[Sequence[str]] = None,
174
- ):
180
+ ) -> Callable[
181
+ [
182
+ Callable[
183
+ ...,
184
+ Union[bool, tuple[bool, T], None]
185
+ ]
186
+ ],
187
+ Callable[
188
+ [],
189
+ Iterator[Union[T, None]]
190
+ ]
191
+ ]:
175
192
  """
176
193
  Used to wrap a function for interacting with the database as a work queue: i.e. to select
177
194
  a set of rows and perform some work on those rows while ensuring that two instances running in parallel don't
@@ -180,7 +197,7 @@ def db_workqueue(
180
197
 
181
198
  :param once: Whether to stop after one iteration
182
199
  :param graceful_stop: the threading.Event() object used for graceful stop of the daemon
183
- :param executable: the name of the executable used for hearbeats
200
+ :param executable: the name of the executable used for heartbeats
184
201
  :param partition_wait_time: time to wait for database partition rebalancing before starting the actual daemon loop
185
202
  :param sleep_time: time to sleep between the iterations of the daemon
186
203
  :param activities: optional list of activities on which to work. The run_once_fnc will be called on activities one by one.
@@ -189,7 +206,7 @@ def db_workqueue(
189
206
  def _decorate(run_once_fnc: Callable[..., Optional[Union[bool, tuple[bool, T]]]]) -> Callable[[], Iterator[Optional[T]]]:
190
207
 
191
208
  @functools.wraps(run_once_fnc)
192
- def _generator():
209
+ def _generator() -> Iterator[T]:
193
210
 
194
211
  with HeartbeatHandler(executable=executable, renewal_interval=sleep_time - 1) as heartbeat_handler:
195
212
  logger = heartbeat_handler.logger
@@ -254,7 +271,8 @@ def run_daemon(
254
271
  partition_wait_time: int,
255
272
  sleep_time: int,
256
273
  run_once_fnc: Callable[..., Optional[Union[bool, tuple[bool, Any]]]],
257
- activities: Optional[list[str]] = None):
274
+ activities: Optional[list[str]] = None
275
+ ) -> None:
258
276
  """
259
277
  Run the daemon loop and call the function run_once_fnc at each iteration
260
278
  """
@@ -277,7 +295,13 @@ class ProducerConsumerDaemon(Generic[T]):
277
295
  Daemon which connects N producers with M consumers via a queue.
278
296
  """
279
297
 
280
- def __init__(self, producers, consumers, graceful_stop, logger=logging.log):
298
+ def __init__(
299
+ self,
300
+ producers: Sequence[Callable[[], Iterator[T]]],
301
+ consumers: Sequence[Callable[..., None]],
302
+ graceful_stop: threading.Event,
303
+ logger: "LoggerFunction" = logging.log
304
+ ):
281
305
  self.producers = producers
282
306
  self.consumers = consumers
283
307
 
@@ -292,7 +316,7 @@ class ProducerConsumerDaemon(Generic[T]):
292
316
  self,
293
317
  it: Callable[[], Iterator[T]],
294
318
  wait_for_consumers: bool = False
295
- ):
319
+ ) -> None:
296
320
  """
297
321
  Iterate over the generator function and put the extracted elements into the queue.
298
322
 
@@ -328,7 +352,7 @@ class ProducerConsumerDaemon(Generic[T]):
328
352
  def _consume(
329
353
  self,
330
354
  fnc: Callable[[T], Any]
331
- ):
355
+ ) -> None:
332
356
  """
333
357
  Wait for elements to arrive via the queue and call the given function on each element.
334
358
 
@@ -349,9 +373,9 @@ class ProducerConsumerDaemon(Generic[T]):
349
373
  finally:
350
374
  self.queue.task_done()
351
375
 
352
- def run(self):
376
+ def run(self) -> None:
353
377
 
354
- producer_threads = []
378
+ producer_threads: list[threading.Thread] = []
355
379
  for i, producer in enumerate(self.producers):
356
380
  thread = threading.Thread(
357
381
  target=self._produce,
@@ -364,7 +388,7 @@ class ProducerConsumerDaemon(Generic[T]):
364
388
  thread.start()
365
389
  producer_threads.append(thread)
366
390
 
367
- consumer_threads = []
391
+ consumer_threads: list[threading.Thread] = []
368
392
  for i, consumer in enumerate(self.consumers):
369
393
  thread = threading.Thread(
370
394
  target=self._consume,
@@ -1,4 +1,3 @@
1
- # -*- coding: utf-8 -*-
2
1
  # Copyright European Organization for Nuclear Research (CERN) since 2012
3
2
  #
4
3
  # Licensed under the Apache License, Version 2.0 (the "License");
@@ -1,4 +1,3 @@
1
- # -*- coding: utf-8 -*-
2
1
  # Copyright European Organization for Nuclear Research (CERN) since 2012
3
2
  #
4
3
  # Licensed under the Apache License, Version 2.0 (the "License");
@@ -22,37 +21,52 @@ import functools
22
21
  import itertools
23
22
  import logging
24
23
  import re
25
- from typing import TYPE_CHECKING
24
+ from typing import TYPE_CHECKING, Any, Optional
26
25
 
27
26
  from rucio.common.config import config_get_bool
28
- from rucio.common.exception import (InvalidRSEExpression, TransferToolTimeout, TransferToolWrongAnswer, RequestNotFound,
29
- DuplicateFileTransferSubmission, VONotFound, DatabaseException)
27
+ from rucio.common.constants import RseAttr
28
+ from rucio.common.exception import DatabaseException, DuplicateFileTransferSubmission, InvalidRSEExpression, RequestNotFound, TransferToolTimeout, TransferToolWrongAnswer, VONotFound
30
29
  from rucio.common.stopwatch import Stopwatch
31
- from rucio.core import request as request_core, transfer as transfer_core
30
+ from rucio.core import request as request_core
31
+ from rucio.core import transfer as transfer_core
32
32
  from rucio.core.monitor import MetricManager
33
33
  from rucio.core.replica import add_replicas, tombstone_from_delay, update_replica_state
34
- from rucio.core.request import set_request_state, queue_requests
34
+ from rucio.core.request import queue_requests, transition_request_state
35
35
  from rucio.core.rse import list_rses
36
36
  from rucio.core.rse_expression_parser import parse_expression
37
37
  from rucio.core.transfer import build_transfer_paths
38
38
  from rucio.core.vo import list_vos
39
39
  from rucio.db.sqla import models
40
- from rucio.db.sqla.constants import RequestState, ReplicaState
40
+ from rucio.db.sqla.constants import ReplicaState, RequestState
41
41
  from rucio.db.sqla.session import transactional_session
42
42
  from rucio.rse import rsemanager as rsemgr
43
43
 
44
44
  if TYPE_CHECKING:
45
- from collections.abc import Callable, Sequence
46
- from typing import Optional
47
- from rucio.core.transfer import DirectTransferDefinition
48
- from rucio.transfertool.transfertool import TransferToolBuilder
45
+ from collections.abc import Iterable, Mapping, Sequence
46
+
49
47
  from sqlalchemy.orm import Session
50
48
 
49
+ from rucio.common.types import InternalAccount, LoggerFunction, RSESettingsDict
50
+ from rucio.core.request import DirectTransfer, RequestWithSources
51
+ from rucio.core.topology import Topology
52
+ from rucio.core.transfer import ProtocolFactory
53
+ from rucio.transfertool.transfertool import Transfertool, TransferToolBuilder
54
+
51
55
  METRICS = MetricManager(module=__name__)
52
56
 
53
57
 
54
- def pick_and_prepare_submission_path(requests_with_sources, topology, protocol_factory, default_tombstone_delay=transfer_core.DEFAULT_MULTIHOP_TOMBSTONE_DELAY,
55
- admin_accounts=None, schemes=None, failover_schemes=None, max_sources=4, transfertools=None, logger=logging.log):
58
+ def pick_and_prepare_submission_path(
59
+ requests_with_sources: "Mapping[str, RequestWithSources]",
60
+ topology: "Topology",
61
+ protocol_factory: "ProtocolFactory",
62
+ default_tombstone_delay: int = transfer_core.DEFAULT_MULTIHOP_TOMBSTONE_DELAY,
63
+ admin_accounts: Optional[set["InternalAccount"]] = None,
64
+ schemes: Optional["Sequence[str]"] = None,
65
+ failover_schemes: Optional["Sequence[str]"] = None,
66
+ max_sources: int = 4,
67
+ transfertools: Optional["Sequence[str]"] = None,
68
+ logger: "LoggerFunction" = logging.log
69
+ ) -> dict["TransferToolBuilder", list[list["DirectTransfer"]]]:
56
70
  """
57
71
  For each transfer, pick a (sub)path; and a transfertool to be used to submit that (sub)path
58
72
  """
@@ -119,22 +133,22 @@ def pick_and_prepare_submission_path(requests_with_sources, topology, protocol_f
119
133
  reqs_no_source.update(reqs_no_host)
120
134
  if reqs_no_source:
121
135
  logger(logging.INFO, "Marking requests as no-sources: %s", reqs_no_source)
122
- request_core.set_requests_state_if_possible(reqs_no_source, RequestState.NO_SOURCES, logger=logger)
136
+ request_core.transition_requests_state_if_possible(reqs_no_source, RequestState.NO_SOURCES, logger=logger)
123
137
  if reqs_only_tape_source:
124
138
  logger(logging.INFO, "Marking requests as only-tape-sources: %s", reqs_only_tape_source)
125
- request_core.set_requests_state_if_possible(reqs_only_tape_source, RequestState.ONLY_TAPE_SOURCES, logger=logger)
139
+ request_core.transition_requests_state_if_possible(reqs_only_tape_source, RequestState.ONLY_TAPE_SOURCES, logger=logger)
126
140
  if reqs_scheme_mismatch:
127
141
  logger(logging.INFO, "Marking requests as scheme-mismatch: %s", reqs_scheme_mismatch)
128
- request_core.set_requests_state_if_possible(reqs_scheme_mismatch, RequestState.MISMATCH_SCHEME, logger=logger)
142
+ request_core.transition_requests_state_if_possible(reqs_scheme_mismatch, RequestState.MISMATCH_SCHEME, logger=logger)
129
143
 
130
144
  return paths_by_transfertool_builder
131
145
 
132
146
 
133
147
  def __assign_to_transfertool(
134
- transfer_path: "list[DirectTransferDefinition]",
135
- transfertools: "Optional[list[str]]",
136
- logger: "Callable",
137
- ) -> "list[tuple[list[DirectTransferDefinition], Optional[TransferToolBuilder]]]":
148
+ transfer_path: list["DirectTransfer"],
149
+ transfertools: Optional["Iterable[str]"],
150
+ logger: "LoggerFunction",
151
+ ) -> list[tuple[list["DirectTransfer"], Optional["TransferToolBuilder"]]]:
138
152
  """
139
153
  Iterate over a multihop path and assign sub-paths to transfertools in chucks from left to right.
140
154
 
@@ -174,11 +188,11 @@ def __assign_to_transfertool(
174
188
 
175
189
 
176
190
  def assign_paths_to_transfertool_and_create_hops(
177
- candidate_paths_by_request_id: "dict[str: list[DirectTransferDefinition]]",
191
+ candidate_paths_by_request_id: "Mapping[str, Sequence[DirectTransfer]]",
178
192
  default_tombstone_delay: int,
179
- transfertools: "Optional[list[str]]" = None,
180
- logger: "Callable" = logging.log,
181
- ) -> "tuple[dict[TransferToolBuilder, list[DirectTransferDefinition]], set[str]]":
193
+ transfertools: Optional["Sequence[str]"] = None,
194
+ logger: "LoggerFunction" = logging.log,
195
+ ) -> "tuple[dict[TransferToolBuilder, list[list[DirectTransfer]]], set[str]]":
182
196
  """
183
197
  for each request, pick the first path which can be submitted by one of the transfertools.
184
198
  If the chosen path is multihop, create all missing intermediate requests and replicas.
@@ -214,13 +228,13 @@ def assign_paths_to_transfertool_and_create_hops(
214
228
  @transactional_session
215
229
  def __assign_paths_to_transfertool_and_create_hops(
216
230
  request_id: str,
217
- candidate_paths: "Sequence[list[DirectTransferDefinition]]",
231
+ candidate_paths: "Sequence[list[DirectTransfer]]",
218
232
  default_tombstone_delay: int,
219
- transfertools: "Optional[list[str]]" = None,
233
+ transfertools: "Optional[Sequence[str]]" = None,
220
234
  *,
221
- logger: "Callable" = logging.log,
235
+ logger: "LoggerFunction" = logging.log,
222
236
  session: "Session",
223
- ) -> "tuple[Optional[list[DirectTransferDefinition]], Optional[TransferToolBuilder]]":
237
+ ) -> "tuple[Optional[list[DirectTransfer]], Optional[TransferToolBuilder]]":
224
238
  """
225
239
  Out of a sequence of candidate paths for the given request, pick the first path which can
226
240
  be submitted by one of the transfertools.
@@ -231,9 +245,9 @@ def __assign_paths_to_transfertool_and_create_hops(
231
245
 
232
246
  # Selects the first path which can be submitted using a chain of supported transfertools
233
247
  # and for which the creation of intermediate hops (if it is a multihop) works correctly
234
- best_path = None
248
+ best_path = []
235
249
  builder_to_use = None
236
- hops_to_submit = None
250
+ hops_to_submit = []
237
251
  must_skip_submission = False
238
252
 
239
253
  tt_assignments = [(transfer_path, __assign_to_transfertool(transfer_path, transfertools, logger=logger))
@@ -290,10 +304,10 @@ def __assign_paths_to_transfertool_and_create_hops(
290
304
 
291
305
  @transactional_session
292
306
  def __create_missing_replicas_and_requests(
293
- transfer_path: "list[DirectTransferDefinition]",
307
+ transfer_path: "list[DirectTransfer]",
294
308
  default_tombstone_delay: int,
295
309
  *,
296
- logger: "Callable",
310
+ logger: "LoggerFunction",
297
311
  session: "Session"
298
312
  ) -> tuple[bool, bool]:
299
313
  """
@@ -310,7 +324,7 @@ def __create_missing_replicas_and_requests(
310
324
  if rws.request_id:
311
325
  continue
312
326
 
313
- tombstone_delay = rws.dest_rse.attributes.get('multihop_tombstone_delay', default_tombstone_delay)
327
+ tombstone_delay = rws.dest_rse.attributes.get(RseAttr.MULTIHOP_TOMBSTONE_DELAY, default_tombstone_delay)
314
328
  try:
315
329
  tombstone = tombstone_from_delay(tombstone_delay)
316
330
  except ValueError:
@@ -376,7 +390,13 @@ def __create_missing_replicas_and_requests(
376
390
  return creation_successful, must_skip_submission
377
391
 
378
392
 
379
- def submit_transfer(transfertool_obj, transfers, job_params, timeout=None, logger=logging.log):
393
+ def submit_transfer(
394
+ transfertool_obj: "Transfertool",
395
+ transfers: "Sequence[DirectTransfer]",
396
+ job_params: dict[str, str],
397
+ timeout: Optional[int] = None,
398
+ logger: "LoggerFunction" = logging.log
399
+ ) -> None:
380
400
  """
381
401
  Submit a transfer or staging request
382
402
 
@@ -396,7 +416,7 @@ def submit_transfer(transfertool_obj, transfers, job_params, timeout=None, logge
396
416
  return
397
417
  except Exception:
398
418
  logger(logging.ERROR, 'Failed to prepare requests %s state to SUBMITTING. Mark it SUBMISSION_FAILED and abort submission.' % [str(t.rws) for t in transfers], exc_info=True)
399
- set_request_state(request_id=transfer.rws.request_id, state=RequestState.SUBMISSION_FAILED)
419
+ transition_request_state(request_id=transfer.rws.request_id, state=RequestState.SUBMISSION_FAILED)
400
420
  return
401
421
 
402
422
  try:
@@ -408,7 +428,13 @@ def submit_transfer(transfertool_obj, transfers, job_params, timeout=None, logge
408
428
  _submit_transfers(transfertool_obj, [transfer], job_params, timeout, logger)
409
429
 
410
430
 
411
- def _submit_transfers(transfertool_obj, transfers, job_params, timeout=None, logger=logging.log):
431
+ def _submit_transfers(
432
+ transfertool_obj: "Transfertool",
433
+ transfers: "Sequence[DirectTransfer]",
434
+ job_params: dict[str, str],
435
+ timeout: Optional[int] = None,
436
+ logger: "LoggerFunction" = logging.log
437
+ ) -> None:
412
438
  """
413
439
  helper function for submit_transfers. Performs the actual submission of one or more transfers.
414
440
 
@@ -470,7 +496,13 @@ def _submit_transfers(transfertool_obj, transfers, job_params, timeout=None, log
470
496
  logger(logging.ERROR, 'Failed to cancel transfers %s on %s with error' % (eid, transfertool_obj), exc_info=True)
471
497
 
472
498
 
473
- def get_conveyor_rses(rses=None, include_rses=None, exclude_rses=None, vos=None, logger=logging.log):
499
+ def get_conveyor_rses(
500
+ rses: Optional["Sequence[Mapping[str, Any]]"] = None,
501
+ include_rses: Optional[str] = None,
502
+ exclude_rses: Optional[str] = None,
503
+ vos: Optional["Sequence[str]"] = None,
504
+ logger: "LoggerFunction" = logging.log
505
+ ) -> list["RSESettingsDict"]:
474
506
  """
475
507
  Get a list of rses for conveyor
476
508
 
@@ -1,4 +1,3 @@
1
- # -*- coding: utf-8 -*-
2
1
  # Copyright European Organization for Nuclear Research (CERN) since 2012
3
2
  #
4
3
  # Licensed under the Apache License, Version 2.0 (the "License");
@@ -23,8 +22,7 @@ import logging
23
22
  import os
24
23
  import re
25
24
  import threading
26
- from types import FrameType
27
- from typing import TYPE_CHECKING, Optional
25
+ from typing import TYPE_CHECKING, Any, Literal, Optional
28
26
  from urllib.parse import urlparse
29
27
 
30
28
  from dogpile.cache.api import NoValue
@@ -32,22 +30,27 @@ from sqlalchemy.exc import DatabaseError
32
30
 
33
31
  import rucio.db.sqla.util
34
32
  from rucio.common.cache import make_region_memcached
35
- from rucio.common.config import config_get_list, config_get_bool
36
- from rucio.common.exception import DatabaseException, UnsupportedOperation, ReplicaNotFound, RequestNotFound, RSEProtocolNotSupported
33
+ from rucio.common.config import config_get_bool, config_get_list
34
+ from rucio.common.exception import DatabaseException, ReplicaNotFound, RequestNotFound, RSEProtocolNotSupported, UnsupportedOperation
37
35
  from rucio.common.logging import setup_logging
38
36
  from rucio.common.stopwatch import Stopwatch
39
- from rucio.common.types import InternalAccount
37
+ from rucio.common.types import InternalAccount, LoggerFunction, RequestDict
40
38
  from rucio.common.utils import chunks
41
- from rucio.core import request as request_core, replica as replica_core
39
+ from rucio.core import replica as replica_core
40
+ from rucio.core import request as request_core
42
41
  from rucio.core.monitor import MetricManager
43
42
  from rucio.core.rse import list_rses
43
+ from rucio.core.topology import ExpiringObjectCache, Topology
44
44
  from rucio.core.transfer import ProtocolFactory
45
- from rucio.core.topology import Topology, ExpiringObjectCache
46
- from rucio.daemons.common import db_workqueue, ProducerConsumerDaemon
47
- from rucio.db.sqla.constants import RequestState, RequestType, ReplicaState, BadFilesStatus
45
+ from rucio.daemons.common import ProducerConsumerDaemon, db_workqueue
46
+ from rucio.db.sqla.constants import MYSQL_LOCK_WAIT_TIMEOUT_EXCEEDED, ORACLE_DEADLOCK_DETECTED_REGEX, ORACLE_RESOURCE_BUSY_REGEX, BadFilesStatus, ReplicaState, RequestState, RequestType
48
47
  from rucio.db.sqla.session import transactional_session
49
48
 
50
49
  if TYPE_CHECKING:
50
+ from types import FrameType
51
+
52
+ from sqlalchemy.orm import Session
53
+
51
54
  from rucio.daemons.common import HeartbeatHandler
52
55
 
53
56
  GRACEFUL_STOP = threading.Event()
@@ -59,12 +62,12 @@ FAILED_DURING_SUBMISSION_DELAY = datetime.timedelta(minutes=120)
59
62
 
60
63
 
61
64
  def _fetch_requests(
62
- db_bulk,
65
+ db_bulk: int,
63
66
  set_last_processed_by: bool,
64
- cached_topology,
65
- heartbeat_handler,
66
- activity,
67
- ):
67
+ cached_topology: Optional[ExpiringObjectCache],
68
+ heartbeat_handler: "HeartbeatHandler",
69
+ activity: str,
70
+ ) -> tuple[bool, tuple[list[dict[str, Any]], Topology]]:
68
71
  worker_number, total_workers, logger = heartbeat_handler.live()
69
72
 
70
73
  logger(logging.DEBUG, 'Working on activity %s', activity)
@@ -109,13 +112,13 @@ def _fetch_requests(
109
112
 
110
113
 
111
114
  def _handle_requests(
112
- batch,
113
- bulk,
114
- suspicious_patterns,
115
- retry_protocol_mismatches,
115
+ batch: tuple[list[RequestDict], Topology],
116
+ bulk: int,
117
+ suspicious_patterns: list[re.Pattern],
118
+ retry_protocol_mismatches: bool,
116
119
  *,
117
- logger=logging.log,
118
- ):
120
+ logger: LoggerFunction = logging.log,
121
+ ) -> None:
119
122
  reqs, topology = batch
120
123
  if not reqs:
121
124
  return
@@ -137,22 +140,22 @@ def _handle_requests(
137
140
  logger(logging.DEBUG, 'Finish to update %s finished requests in %s seconds', len(reqs), total_stopwatch.elapsed)
138
141
 
139
142
  except (DatabaseException, DatabaseError) as error:
140
- if re.match('.*ORA-00054.*', error.args[0]) or re.match('.*ORA-00060.*', error.args[0]) or 'ERROR 1205 (HY000)' in error.args[0]:
143
+ if re.match(ORACLE_RESOURCE_BUSY_REGEX, error.args[0]) or re.match(ORACLE_DEADLOCK_DETECTED_REGEX, error.args[0]) or MYSQL_LOCK_WAIT_TIMEOUT_EXCEEDED in error.args[0]:
141
144
  logger(logging.WARNING, 'Lock detected when handling request - skipping: %s', str(error))
142
145
  else:
143
146
  raise
144
147
 
145
148
 
146
149
  def finisher(
147
- once=False,
148
- sleep_time=60,
149
- activities=None,
150
- bulk=100,
151
- db_bulk=1000,
152
- partition_wait_time=10,
153
- cached_topology=None,
154
- total_threads=1,
155
- ):
150
+ once: bool = False,
151
+ sleep_time: int = 60,
152
+ activities: Optional[list[str]] = None,
153
+ bulk: int = 100,
154
+ db_bulk: int = 1000,
155
+ partition_wait_time: int = 10,
156
+ cached_topology: Optional[ExpiringObjectCache] = None,
157
+ total_threads: int = 1,
158
+ ) -> None:
156
159
  """
157
160
  Main loop to update the replicas and rules based on finished requests.
158
161
  """
@@ -176,7 +179,11 @@ def finisher(
176
179
  sleep_time=sleep_time,
177
180
  activities=activities,
178
181
  )
179
- def _db_producer(*, activity: str, heartbeat_handler: "HeartbeatHandler"):
182
+ def _db_producer(
183
+ *,
184
+ activity: str,
185
+ heartbeat_handler: "HeartbeatHandler"
186
+ ) -> tuple[bool, tuple[list[dict[str, Any]], Topology]]:
180
187
  return _fetch_requests(
181
188
  db_bulk=db_bulk,
182
189
  cached_topology=cached_topology,
@@ -185,7 +192,7 @@ def finisher(
185
192
  heartbeat_handler=heartbeat_handler,
186
193
  )
187
194
 
188
- def _consumer(batch):
195
+ def _consumer(batch: tuple[list[RequestDict], Topology]) -> None:
189
196
  return _handle_requests(
190
197
  batch=batch,
191
198
  bulk=bulk,
@@ -200,7 +207,7 @@ def finisher(
200
207
  ).run()
201
208
 
202
209
 
203
- def stop(signum: Optional[int] = None, frame: Optional[FrameType] = None) -> None:
210
+ def stop(signum: Optional[int] = None, frame: Optional["FrameType"] = None) -> None:
204
211
  """
205
212
  Graceful exit.
206
213
  """
@@ -208,9 +215,16 @@ def stop(signum: Optional[int] = None, frame: Optional[FrameType] = None) -> Non
208
215
  GRACEFUL_STOP.set()
209
216
 
210
217
 
211
- def run(once=False, total_threads=1, sleep_time=60, activities=None, bulk=100, db_bulk=1000):
218
+ def run(
219
+ once: bool = False,
220
+ total_threads: int = 1,
221
+ sleep_time: int = 60,
222
+ activities: Optional[list[str]] = None,
223
+ bulk: int = 100,
224
+ db_bulk: int = 1000
225
+ ) -> None:
212
226
  """
213
- Starts up the conveyer threads.
227
+ Starts up the conveyor threads.
214
228
  """
215
229
  setup_logging(process_name=DAEMON_NAME)
216
230
 
@@ -229,7 +243,13 @@ def run(once=False, total_threads=1, sleep_time=60, activities=None, bulk=100, d
229
243
  )
230
244
 
231
245
 
232
- def _finish_requests(topology: "Topology", reqs, suspicious_patterns, retry_protocol_mismatches, logger=logging.log):
246
+ def _finish_requests(
247
+ topology: Topology,
248
+ reqs: list[RequestDict],
249
+ suspicious_patterns: list[re.Pattern],
250
+ retry_protocol_mismatches: bool,
251
+ logger: LoggerFunction = logging.log
252
+ ) -> None:
233
253
  """
234
254
  Used by finisher to handle terminated requests,
235
255
 
@@ -325,11 +345,11 @@ def _finish_requests(topology: "Topology", reqs, suspicious_patterns, retry_prot
325
345
  __handle_terminated_replicas(replicas, logger=logger)
326
346
 
327
347
 
328
- def __get_undeterministic_rses(logger=logging.log):
348
+ def __get_undeterministic_rses(logger: LoggerFunction = logging.log) -> list[str]:
329
349
  """
330
350
  Get the undeterministic rses from the database
331
351
 
332
- :returns: List of undeterministc rses
352
+ :returns: List of undeterministic rses
333
353
  """
334
354
  key = 'undeterministic_rses'
335
355
  result = REGION.get(key)
@@ -343,7 +363,11 @@ def __get_undeterministic_rses(logger=logging.log):
343
363
  return result
344
364
 
345
365
 
346
- def __check_suspicious_files(req, suspicious_patterns, logger=logging.log):
366
+ def __check_suspicious_files(
367
+ req: RequestDict,
368
+ suspicious_patterns: list[re.Pattern],
369
+ logger: LoggerFunction = logging.log
370
+ ) -> bool:
347
371
  """
348
372
  Check suspicious files when a transfer failed.
349
373
 
@@ -376,7 +400,10 @@ def __check_suspicious_files(req, suspicious_patterns, logger=logging.log):
376
400
  return is_suspicious
377
401
 
378
402
 
379
- def __handle_terminated_replicas(replicas, logger=logging.log):
403
+ def __handle_terminated_replicas(
404
+ replicas: dict[str, dict[str, list[dict[str, Any]]]],
405
+ logger: LoggerFunction = logging.log
406
+ ) -> None:
380
407
  """
381
408
  Used by finisher to handle available and unavailable replicas.
382
409
 
@@ -394,14 +421,14 @@ def __handle_terminated_replicas(replicas, logger=logging.log):
394
421
  try:
395
422
  __update_replica(replica, logger=logger)
396
423
  except (DatabaseException, DatabaseError) as error:
397
- if re.match('.*ORA-00054.*', error.args[0]) or re.match('.*ORA-00060.*', error.args[0]) or 'ERROR 1205 (HY000)' in error.args[0]:
424
+ if re.match(ORACLE_RESOURCE_BUSY_REGEX, error.args[0]) or re.match(ORACLE_DEADLOCK_DETECTED_REGEX, error.args[0]) or MYSQL_LOCK_WAIT_TIMEOUT_EXCEEDED in error.args[0]:
398
425
  logger(logging.WARNING, "Locks detected when handling replica %s:%s at RSE %s", replica['scope'], replica['name'], replica['rse_id'])
399
426
  else:
400
427
  logger(logging.ERROR, "Could not finish handling replicas %s:%s at RSE %s", replica['scope'], replica['name'], replica['rse_id'], exc_info=True)
401
428
  except Exception as error:
402
429
  logger(logging.ERROR, "Something unexpected happened when updating replica state for transfer %s:%s at %s (%s)", replica['scope'], replica['name'], replica['rse_id'], str(error))
403
430
  except (DatabaseException, DatabaseError) as error:
404
- if re.match('.*ORA-00054.*', error.args[0]) or re.match('.*ORA-00060.*', error.args[0]) or 'ERROR 1205 (HY000)' in error.args[0]:
431
+ if re.match(ORACLE_RESOURCE_BUSY_REGEX, error.args[0]) or re.match(ORACLE_DEADLOCK_DETECTED_REGEX, error.args[0]) or MYSQL_LOCK_WAIT_TIMEOUT_EXCEEDED in error.args[0]:
405
432
  logger(logging.WARNING, "Locks detected when handling replicas on %s rule %s, update updated time.", req_type, rule_id)
406
433
  try:
407
434
  request_core.touch_requests_by_rule(rule_id)
@@ -414,9 +441,14 @@ def __handle_terminated_replicas(replicas, logger=logging.log):
414
441
 
415
442
 
416
443
  @transactional_session
417
- def __update_bulk_replicas(replicas, *, session, logger=logging.log):
444
+ def __update_bulk_replicas(
445
+ replicas: list[dict[str, Any]],
446
+ *,
447
+ session: "Session",
448
+ logger: LoggerFunction = logging.log
449
+ ) -> Literal[True]:
418
450
  """
419
- Used by finisher to handle available and unavailable replicas blongs to same rule in bulk way.
451
+ Used by finisher to handle available and unavailable replicas belongs to same rule in bulk way.
420
452
 
421
453
  :param replicas: List of replicas.
422
454
  :param session: The database session to use.
@@ -436,7 +468,12 @@ def __update_bulk_replicas(replicas, *, session, logger=logging.log):
436
468
 
437
469
 
438
470
  @transactional_session
439
- def __update_replica(replica, *, session, logger=logging.log):
471
+ def __update_replica(
472
+ replica: dict[str, Any],
473
+ *,
474
+ session: "Session",
475
+ logger: LoggerFunction = logging.log
476
+ ) -> None:
440
477
  """
441
478
  Used by finisher to update a replica to a finished state.
442
479