()
| 119 | |
| 120 | # Task enqueued in register_recurring_tasks below. |
| 121 | def handle_api_usage_notifications() -> None: |
| 122 | openfeature_client = get_openfeature_client() |
| 123 | |
| 124 | threshold_percentage = min(API_USAGE_ALERT_THRESHOLDS) / 100 |
| 125 | for organisation in Organisation.objects.filter( |
| 126 | # Not having a subscription information cache implies that the organisation has |
| 127 | # no usage so no notification is needed. |
| 128 | subscription_information_cache__isnull=False, |
| 129 | # Skip organisations whose usage in the last 30d is below the threshold of the |
| 130 | # minimum notification level for their allowance. If their usage is below the |
| 131 | # threshold in the last 30d, it must be below it for the current billing period |
| 132 | # (which by definition is <30d). |
| 133 | subscription_information_cache__api_calls_30d__gte=F( |
| 134 | "subscription_information_cache__allowed_30d_api_calls" |
| 135 | ) |
| 136 | * threshold_percentage, |
| 137 | ).select_related("subscription", "subscription_information_cache"): |
| 138 | feature_enabled = openfeature_client.get_boolean_value( |
| 139 | "api_usage_alerting", |
| 140 | default_value=False, |
| 141 | evaluation_context=organisation.openfeature_evaluation_context, |
| 142 | ) |
| 143 | if not feature_enabled: |
| 144 | logger.info( |
| 145 | f"Skipping processing API usage for organisation {organisation.id}" |
| 146 | ) |
| 147 | continue |
| 148 | |
| 149 | try: |
| 150 | handle_api_usage_notification_for_organisation(organisation) |
| 151 | except Exception: |
| 152 | logger.error( |
| 153 | f"Error processing api usage for organisation {organisation.id}", |
| 154 | exc_info=True, |
| 155 | ) |
| 156 | |
| 157 | |
| 158 | # Task enqueued in register_recurring_tasks below. |
searching dependent graphs…