@@ -49,6 +49,7 @@ def __init__(self, configuration: Configuration, client: ApifyClientAsync) -> No
49
49
self ._not_ppe_warning_printed = False
50
50
51
51
async def init (self ) -> None :
52
+ """Initialize the charging manager - this is called by the `Actor` class and shouldn't be invoked manually."""
52
53
self ._charging_state = {}
53
54
54
55
if self ._is_at_home :
@@ -86,15 +87,21 @@ async def init(self) -> None:
86
87
self ._charging_log_dataset = await Dataset .open (name = self .LOCAL_CHARGING_LOG_DATASET_NAME )
87
88
88
89
async def charge (self , event_name : str , count : int = 1 ) -> ChargeResult :
90
+ """Charge for a specified number of events - sub-operations of the Actor.
91
+
92
+ This is relevant only for the pay-per-event pricing model.
93
+ """
89
94
if self ._charging_state is None :
90
95
raise RuntimeError ('Charging manager is not initialized' )
91
96
92
97
def calculate_chargeable () -> dict [str , int | None ]:
98
+ """Calculate the maximum number of events of each type that can be charged within the current budget."""
93
99
return {
94
100
event_name : self .calculate_max_event_charge_count_within_limit (event_name )
95
101
for event_name in self ._pricing_info
96
102
}
97
103
104
+ # For runs that do not use the pay-per-event pricing model, just print a warning and return
98
105
if self ._pricing_model != 'PAY_PER_EVENT' :
99
106
if not self ._not_ppe_warning_printed :
100
107
logger .warning (
@@ -109,6 +116,8 @@ def calculate_chargeable() -> dict[str, int | None]:
109
116
)
110
117
111
118
# START OF CRITICAL SECTION - no awaits here
119
+
120
+ # Determine the maximum amount of events that can be charged within the budget
112
121
charged_count = min (count , self .calculate_max_event_charge_count_within_limit (event_name ) or count )
113
122
114
123
if charged_count == 0 :
@@ -130,11 +139,14 @@ def calculate_chargeable() -> dict[str, int | None]:
130
139
),
131
140
)
132
141
142
+ # Update the charging state
133
143
self ._charging_state .setdefault (event_name , ChargingStateItem (0 , Decimal ()))
134
144
self ._charging_state [event_name ].charge_count += charged_count
135
145
self ._charging_state [event_name ].total_charged_amount += charged_count * pricing_info .price
136
146
137
147
# END OF CRITICAL SECTION
148
+
149
+ # If running on the platform, call the charge endpoint
138
150
if self ._is_at_home :
139
151
if self ._actor_run_id is None :
140
152
raise RuntimeError ('Actor run ID not configured' )
@@ -144,6 +156,7 @@ def calculate_chargeable() -> dict[str, int | None]:
144
156
else :
145
157
logger .warning (f"Attempting to charge for an unknown event '{ event_name } '" )
146
158
159
+ # Log the charged operation (if enabled)
147
160
if self ._charging_log_dataset :
148
161
await self ._charging_log_dataset .push_data (
149
162
{
@@ -155,6 +168,7 @@ def calculate_chargeable() -> dict[str, int | None]:
155
168
}
156
169
)
157
170
171
+ # If it is not possible to charge the full amount, log that fact
158
172
if charged_count < count :
159
173
subject = 'instance' if count == 1 else 'instances'
160
174
logger .info (
@@ -171,6 +185,7 @@ def calculate_chargeable() -> dict[str, int | None]:
171
185
)
172
186
173
187
def calculate_total_charged_amount (self ) -> Decimal :
188
+ """Calculate the total amount of money charged for pay-per-event events."""
174
189
if self ._charging_state is None :
175
190
raise RuntimeError ('Charging manager is not initialized' )
176
191
@@ -180,6 +195,7 @@ def calculate_total_charged_amount(self) -> Decimal:
180
195
)
181
196
182
197
def calculate_max_event_charge_count_within_limit (self , event_name : str ) -> int | None :
198
+ """Calculate how many instances of an event can be charged before we reach the configured limit."""
183
199
if self ._charging_state is None :
184
200
raise RuntimeError ('Charging manager is not initialized' )
185
201
@@ -199,6 +215,7 @@ def calculate_max_event_charge_count_within_limit(self, event_name: str) -> int
199
215
return math .floor (result ) if result .is_finite () else None
200
216
201
217
def get_pricing_info (self ) -> ActorPricingInfo :
218
+ """Retrieve detailed infor about the effective pricing of the current Actor run."""
202
219
if self ._charging_state is None :
203
220
raise RuntimeError ('Charging manager is not initialized' )
204
221
0 commit comments