From 775e67a7d12811abd1900d816b01c364b0b862e8 Mon Sep 17 00:00:00 2001 From: Mouad BANI Date: Tue, 14 Oct 2025 19:47:03 +0100 Subject: [PATCH 1/2] fix: deperecate multiprocessing and performance improvements --- services/apps/git_integration/pyproject.toml | 1 + .../services/commit/commit_service.py | 278 ++++++++---------- .../git_integration/src/crowdgit/settings.py | 2 +- .../src/crowdgit/worker/repository_worker.py | 1 - services/apps/git_integration/uv.lock | 79 +++++ 5 files changed, 206 insertions(+), 155 deletions(-) diff --git a/services/apps/git_integration/pyproject.toml b/services/apps/git_integration/pyproject.toml index 15eae31e31..d6c5969c31 100644 --- a/services/apps/git_integration/pyproject.toml +++ b/services/apps/git_integration/pyproject.toml @@ -34,6 +34,7 @@ dependencies = [ "aiofiles>=24.1.0", "aioboto3>=15.1.0", "slugify>=0.0.1", + "orjson>=3.11.3", ] diff --git a/services/apps/git_integration/src/crowdgit/services/commit/commit_service.py b/services/apps/git_integration/src/crowdgit/services/commit/commit_service.py index 3f914a8d57..488da4e889 100644 --- a/services/apps/git_integration/src/crowdgit/services/commit/commit_service.py +++ b/services/apps/git_integration/src/crowdgit/services/commit/commit_service.py @@ -1,15 +1,14 @@ import asyncio import datetime +import gc import hashlib -import json import re import time import uuid -from concurrent.futures import ProcessPoolExecutor -from concurrent.futures.process import BrokenProcessPool from decimal import Decimal from typing import Any +import orjson from loguru import logger from pydantic import validate_email from tenacity import retry, stop_after_attempt, wait_fixed @@ -29,7 +28,7 @@ from crowdgit.services.commit.activitymap import ActivityMap from crowdgit.services.queue.queue_service import QueueService from crowdgit.services.utils import get_default_branch, run_shell_command -from crowdgit.settings import DEFAULT_TENANT_ID, MAX_WORKER_PROCESSES +from crowdgit.settings import DEFAULT_TENANT_ID class CommitService(BaseService): @@ -54,32 +53,16 @@ class CommitService(BaseService): def __init__(self, queue_service: QueueService): super().__init__() - self.process_pool = None self.queue_service = queue_service # Metrics tracking for current repository self._metrics_context = None - def _get_or_create_pool(self) -> ProcessPoolExecutor: - """Get or create process pool with proper lifecycle management""" - max_workers = max(1, MAX_WORKER_PROCESSES - 1) - if self.process_pool is None: - self.process_pool = ProcessPoolExecutor(max_workers=max_workers) - return self.process_pool - - def cleanup_process_pool(self): - """Cleanup process pool to prevent resource leaks""" - if self.process_pool: - self.logger.info("Cleaning up process pool") - self.process_pool.shutdown(wait=False) - self.process_pool = None - @property def git_log_format(self) -> str: """Git log format string with commit splitter""" return f"{self.COMMIT_START_SPLITTER}%n%H%n%aI%n%an%n%ae%n%cI%n%cn%n%ce%n%P%n%d%n%B%n{self.NUMSTAT_SPLITTER}" - @staticmethod - def is_valid_commit_hash(commit_hash: str) -> bool: + def is_valid_commit_hash(self, commit_hash: str) -> bool: """Check if the given commit hash is valid. :param commit_hash: The commit hash. @@ -90,10 +73,9 @@ def is_valid_commit_hash(commit_hash: str) -> bool: >>> is_valid_commit_hash('not so') False """ - return CommitService._COMMIT_HASH_PATTERN.match(commit_hash) is not None + return self._COMMIT_HASH_PATTERN.match(commit_hash) is not None - @staticmethod - def is_valid_datetime(commit_datetime: str) -> bool: + def is_valid_datetime(self, commit_datetime: str) -> bool: """Check if the given datetime string is valid. :param commit_datetime: The datetime string. @@ -105,7 +87,7 @@ def is_valid_datetime(commit_datetime: str) -> bool: False """ try: - time.strptime(commit_datetime, CommitService.DATETIME_FORMAT) + time.strptime(commit_datetime, self.DATETIME_FORMAT) return True except ValueError: return False @@ -229,8 +211,7 @@ def _build_git_log_command(self, repo_path: str, commit_range: str) -> list[str] f"--pretty=format:{self.git_log_format}", ] - @staticmethod - def _parse_numstats(raw_numstats: str) -> tuple[int, int]: + def _parse_numstats(self, raw_numstats: str) -> tuple[int, int]: """ Parse raw numstats into -> (insertions, deletions). @@ -299,21 +280,19 @@ async def _execute_git_log( self.logger.info(f"Executing git log for range: {commit_range}") return await run_shell_command(raw_commits_cmd) - @staticmethod - def should_skip_commit(raw_commit: str | None, edge_commit: str | None) -> bool: + def should_skip_commit(self, raw_commit: str | None, edge_commit: str | None) -> bool: """Check if commit should be skipped based on edge commit comparison.""" # Only skip the boundary commit of the current shallow clone. return not raw_commit or (edge_commit and raw_commit.startswith(edge_commit)) - @staticmethod - def clean_up_username(name: str): + def clean_up_username(self, name: str): name = re.sub(r"(?i)Reviewed[- ]by:", "", name) name = re.sub(r"(?i)from:", "", name) name = re.sub(r"(?i)cc:.*", "", name).strip() return name.strip() - @staticmethod def create_activity( + self, remote: str, commit: dict, activity_type: str, @@ -354,14 +333,14 @@ def create_activity( display_name = member.get("displayName") or primary_email.split("@")[0] # Clean up names once - processed_member["displayName"] = CommitService.clean_up_username(display_name) + processed_member["displayName"] = self.clean_up_username(display_name) # Build identities list more efficiently identities = [ { - "platform": CommitService._GIT_PLATFORM, + "platform": self._GIT_PLATFORM, "value": primary_email, - "type": CommitService._USERNAME_TYPE, + "type": self._USERNAME_TYPE, "verified": True, } ] @@ -370,9 +349,9 @@ def create_activity( for email in emails: identities.append( { - "platform": CommitService._GIT_PLATFORM, + "platform": self._GIT_PLATFORM, "value": email, - "type": CommitService._EMAIL_TYPE, + "type": self._EMAIL_TYPE, "verified": False, } ) @@ -387,7 +366,7 @@ def create_activity( "timestamp": timestamp, "sourceId": source_id, "sourceParentId": source_parent_id, - "platform": CommitService._GIT_PLATFORM, + "platform": self._GIT_PLATFORM, "channel": remote, "body": "\n".join(commit["message"]), "isContribution": True, @@ -404,8 +383,7 @@ def create_activity( "segmentId": segment_id, } - @staticmethod - def extract_activities(commit_message: list[str]) -> list[dict[str, dict[str, str]]]: + def extract_activities(self, commit_message: list[str]) -> list[dict[str, dict[str, str]]]: """ Extract activities from the commit message and return a list of activities. Each activity in the list includes the activity and the person who made it, @@ -424,7 +402,7 @@ def extract_activities(commit_message: list[str]) -> list[dict[str, dict[str, st activities = [] for line in commit_message: - match = CommitService._ACTIVITY_PATTERN.match(line) + match = self._ACTIVITY_PATTERN.match(line) if match: activity_name, name, email = match.groups() activity_name = activity_name.strip().lower() @@ -435,9 +413,8 @@ def extract_activities(commit_message: list[str]) -> list[dict[str, dict[str, st activities.append({activity: {"name": name, "email": email}}) return activities - @staticmethod def prepare_activity_for_db_and_queue( - activity: dict, segment_id: str, integration_id: str + self, activity: dict, segment_id: str, integration_id: str ) -> tuple[tuple, dict]: activity["segmentId"] = segment_id result_id = str(uuid.uuid1()) @@ -449,14 +426,14 @@ def prepare_activity_for_db_and_queue( activity_db = ( result_id, IntegrationResultState.PENDING, - json.dumps(data_dict), + orjson.dumps(data_dict).decode(), DEFAULT_TENANT_ID, integration_id, ) operation = "upsert_activities_with_members" activity_kafka = { - "message_id": f"{DEFAULT_TENANT_ID}-{operation}-{CommitService._GIT_PLATFORM}-{result_id}", - "payload": json.dumps( + "message_id": f"{DEFAULT_TENANT_ID}-{operation}-{self._GIT_PLATFORM}-{result_id}", + "payload": orjson.dumps( { "type": DataSinkWorkerQueueMessageType.PROCESS_INTEGRATION_RESULT, "tenantId": DEFAULT_TENANT_ID, @@ -464,13 +441,12 @@ def prepare_activity_for_db_and_queue( "integrationId": integration_id, "resultId": result_id, } - ), + ).decode(), } return activity_db, activity_kafka - @staticmethod def create_activities_from_commit( - remote: str, commit: dict[str, Any], segment_id: str, integration_id: str + self, remote: str, commit: dict[str, Any], segment_id: str, integration_id: str ) -> tuple[list[tuple], list[dict[str, Any]]]: """ Create activities from a commit with improved efficiency. @@ -500,7 +476,7 @@ def create_activities_from_commit( "displayName": author_name, "emails": [author_email], } - activity = CommitService.create_activity( + activity = self.create_activity( remote=remote, commit=commit, activity_type="authored-commit", @@ -508,7 +484,7 @@ def create_activities_from_commit( source_id=commit_hash, segment_id=segment_id, ) - activity_db, activity_kafka = CommitService.prepare_activity_for_db_and_queue( + activity_db, activity_kafka = self.prepare_activity_for_db_and_queue( activity, segment_id, integration_id ) activities_db.append(activity_db) @@ -527,7 +503,7 @@ def create_activities_from_commit( "displayName": committer_name, "emails": [committer_email], } - activity = CommitService.create_activity( + activity = self.create_activity( remote=remote, commit=commit, activity_type="committed-commit", @@ -536,14 +512,14 @@ def create_activities_from_commit( source_parent_id=commit_hash, segment_id=segment_id, ) - activity_db, activity_kafka = CommitService.prepare_activity_for_db_and_queue( + activity_db, activity_kafka = self.prepare_activity_for_db_and_queue( activity, segment_id, integration_id ) activities_db.append(activity_db) activities_queue.append(activity_kafka) # Process extracted activities from commit message - extracted_activities = CommitService.extract_activities(commit["message"]) + extracted_activities = self.extract_activities(commit["message"]) for extracted_activity in extracted_activities: activity_type, member_data = list(extracted_activity.items())[0] @@ -561,7 +537,7 @@ def create_activities_from_commit( source_id = hashlib.sha1( (commit_hash + activity_type + member_data["email"]).encode("utf-8") ).hexdigest() - activity = CommitService.create_activity( + activity = self.create_activity( remote=remote, commit=commit, activity_type=activity_type, @@ -570,7 +546,7 @@ def create_activities_from_commit( source_parent_id=commit_hash, segment_id=segment_id, ) - activity_db, activity_kafka = CommitService.prepare_activity_for_db_and_queue( + activity_db, activity_kafka = self.prepare_activity_for_db_and_queue( activity, segment_id, integration_id ) activities_db.append(activity_db) @@ -578,21 +554,17 @@ def create_activities_from_commit( return activities_db, activities_queue - @staticmethod - def process_commits_chunk( + async def process_commits_chunk( + self, commit_texts_chunk: list[str | None], repo_path: str, edge_commit_hash: str | None, remote: str, segment_id: str, integration_id: str, - ) -> tuple[list[tuple], list[dict]]: + ) -> None: """ - Process a chunk of raw commit texts into activities. - - This is a low-level method used for parallel processing of commit data. - It takes pre-split commit text chunks, converts them to activity objects, - and returns them for batch processing in the main async context. + Process a chunk of raw commit texts into activities and write them to DB and Kafka. Args: commit_texts_chunk: List of commit text strings to process @@ -601,9 +573,6 @@ def process_commits_chunk( remote: Remote repository URL segment_id: Segment identifier integration_id: Integration identifier - - Returns: - Tuple of (activities_db, activities_queue) for database and queue """ activities_db = [] activities_queue = [] @@ -612,14 +581,14 @@ def process_commits_chunk( commit = None for full_commit_text in commit_texts_chunk: - if CommitService.should_skip_commit(full_commit_text, edge_commit_hash): + if self.should_skip_commit(full_commit_text, edge_commit_hash): continue - commit_text, numstats_text = full_commit_text.split(CommitService.NUMSTAT_SPLITTER) + commit_text, numstats_text = full_commit_text.split(self.NUMSTAT_SPLITTER) commit_lines = commit_text.strip().splitlines() del full_commit_text del commit_text - if not CommitService._validate_commit_structure(commit_lines): - logger.warning( + if not self._validate_commit_structure(commit_lines): + self.logger.warning( f"Invalid commit structure in {repo_path}: {len(commit_lines)} fields" ) bad_commits += 1 @@ -628,12 +597,10 @@ def process_commits_chunk( continue try: - commit = CommitService._construct_commit_dict(commit_lines, numstats_text) - if CommitService._validate_commit_data(commit): - activity_db_records, activity_kafka = ( - CommitService.create_activities_from_commit( - remote, commit, segment_id, integration_id - ) + commit = self._construct_commit_dict(commit_lines, numstats_text) + if self._validate_commit_data(commit): + activity_db_records, activity_kafka = self.create_activities_from_commit( + remote, commit, segment_id, integration_id ) activities_db.extend(activity_db_records) activities_queue.extend(activity_kafka) @@ -644,7 +611,7 @@ def process_commits_chunk( bad_commits += 1 except Exception as e: - logger.warning(f"Failed to parse commit in {repo_path}: {e}") + self.logger.warning(f"Failed to parse commit in {repo_path}: {e}") bad_commits += 1 continue finally: @@ -652,11 +619,18 @@ def process_commits_chunk( del commit_lines del numstats_text - logger.info( + self.logger.info( f"Processed {processed_commits} commits, skipped {bad_commits} invalid commits in {repo_path}" ) - return activities_db, activities_queue + # Write activities to database and queue + if activities_db: + await asyncio.gather( + batch_insert_activities(activities_db), + self.queue_service.send_batch_activities(activities_queue), + ) + + del activities_db, activities_queue async def _process_activities_from_commits( self, @@ -674,69 +648,74 @@ async def _process_activities_from_commits( c.strip() for c in raw_commits.split(self.COMMIT_START_SPLITTER) if c.strip() ] del raw_commits + gc.collect() + logger.info(f"Actual number of commits to be processed: {len(commit_texts)}") if len(commit_texts) == 0: self.logger.info("No commits to be processed") return - chunk_size = min(max(20, len(commit_texts) // MAX_WORKER_PROCESSES), self.MAX_CHUNK_SIZE) + chunk_size = self.MAX_CHUNK_SIZE + total_chunks = (len(commit_texts) + chunk_size - 1) // chunk_size + self.logger.info( + f"Total commits {len(commit_texts)} - Total chunks: {total_chunks} - Chunk size: {chunk_size}" + ) + + max_concurrent = 2 + semaphore = asyncio.Semaphore(max_concurrent) + self.logger.info(f"Processing with max_concurrent={max_concurrent}") - self.logger.info(f"Spliting commits into chunks of {chunk_size}") - chunks = [ - commit_texts[i : i + chunk_size] for i in range(0, len(commit_texts), chunk_size) + completed_chunks = 0 + + async def process_single_chunk(chunk_start_idx: int, chunk_end_idx: int): + nonlocal completed_chunks, total_chunks + + async with semaphore: + chunk = commit_texts[chunk_start_idx:chunk_end_idx] # noqa: F821 + try: + # Process chunk and write to DB/Kafka + await self.process_commits_chunk( + chunk, + repo_path, + edge_commit_hash, + remote, + segment_id, + integration_id, + ) + completed_chunks += 1 + self.logger.info(f"Progress: {completed_chunks}/{total_chunks} chunks") + del chunk + except Exception as e: + self.logger.error(f"Error processing chunk: {repr(e)}") + raise + + tasks = [ + process_single_chunk(i, min(i + chunk_size, len(commit_texts))) + for i in range(0, len(commit_texts), chunk_size) ] - self.logger.info(f"Total commits {len(commit_texts)} chunks {len(chunks)}") - del commit_texts # to release memory - loop = asyncio.get_event_loop() - executor = self._get_or_create_pool() + self.logger.info( + f"Created {len(tasks)} tasks. Processing with max {max_concurrent} concurrent tasks" + ) try: - futures = [ - loop.run_in_executor( - executor, - CommitService.process_commits_chunk, - chunk, - repo_path, - edge_commit_hash, - remote, - segment_id, - integration_id, - ) - for chunk in chunks - ] - self.logger.info(f"Submitted {len(futures)} tasks to process pool") + await asyncio.gather(*tasks) + + self.logger.info(f"All {total_chunks} chunks processed successfully.") + except Exception as e: - if isinstance(e, BrokenProcessPool): - self.logger.warning("BrokenProcessPool during task submission, cleaning up") - self.cleanup_process_pool() + self.logger.error( + f"Error during chunk processing at chunk {completed_chunks}/{total_chunks}: {e}" + ) raise - # Save each chunk's activities as they complete - completed_chunks = 0 - for future in asyncio.as_completed(futures): - try: - chunk_activities_db, chunk_activities_queue = await future - completed_chunks += 1 - self.logger.info(f"Chunk {completed_chunks}/{len(futures)} completed") - if chunk_activities_db and chunk_activities_queue: - await asyncio.gather( - batch_insert_activities(chunk_activities_db), - self.queue_service.send_batch_activities(chunk_activities_queue), - ) - del chunk_activities_db - del chunk_activities_queue - except Exception as e: - if isinstance(e, BrokenProcessPool): - self.logger.warning( - f"BrokenProcessPool after {completed_chunks}/{len(futures)} chunks, cleaning up" - ) - self.cleanup_process_pool() - raise + finally: + del commit_texts + gc.collect() + self.logger.info("Memory cleanup completed") - @staticmethod def _construct_commit_dict( - commit_metadata_lines: list[str], numstats_text: str + self, commit_metadata_lines: list[str], numstats_text: str ) -> dict[str, Any]: """Create commit dictionary from parsed lines.""" commit_hash = commit_metadata_lines[0] @@ -751,14 +730,13 @@ def _construct_commit_dict( # Use name as email if email is empty and name is a valid email author_email = ( author_name - if (not author_email or not author_email.strip()) - and CommitService._is_valid_email(author_name) + if (not author_email or not author_email.strip()) and self._is_valid_email(author_name) else author_email ) committer_email = ( committer_name if (not committer_email or not committer_email.strip()) - and CommitService._is_valid_email(committer_name) + and self._is_valid_email(committer_name) else committer_email ) @@ -766,12 +744,12 @@ def _construct_commit_dict( commit_message = commit_metadata_lines[9:] if len(commit_metadata_lines) > 9 else [] # Validate and adjust commit datetime if it's in the future - adjusted_commit_datetime = CommitService._validate_and_adjust_datetime( + adjusted_commit_datetime = self._validate_and_adjust_datetime( commit_datetime, author_datetime ) # Parse numstats to get insertions/deletions - insertions, deletions = CommitService._parse_numstats(numstats_text) + insertions, deletions = self._parse_numstats(numstats_text) # release memory del numstats_text del commit_metadata_lines @@ -791,35 +769,32 @@ def _construct_commit_dict( "deletions": deletions, } - @staticmethod - def _validate_commit_structure(commit_lines: list[str]) -> bool: + def _validate_commit_structure(self, commit_lines: list[str]) -> bool: """Validate that commit has minimum required fields.""" - return len(commit_lines) >= CommitService.MIN_COMMIT_FIELDS + return len(commit_lines) >= self.MIN_COMMIT_FIELDS - @staticmethod - def _validate_commit_data(commit_dict: dict[str, Any]) -> bool: + def _validate_commit_data(self, commit_dict: dict[str, Any]) -> bool: """Validate commit data content.""" # Check required fields if not commit_dict.get("author_email", "").strip(): - logger.info(f"Commit without author_email: {commit_dict.get('hash', 'unknown')}") + self.logger.info(f"Commit without author_email: {commit_dict.get('hash', 'unknown')}") return False # Validate commit hash format - if not CommitService.is_valid_commit_hash(commit_dict.get("hash", "")): - logger.error(f"Invalid commit hash: {commit_dict.get('hash', 'unknown')}") + if not self.is_valid_commit_hash(commit_dict.get("hash", "")): + self.logger.error(f"Invalid commit hash: {commit_dict.get('hash', 'unknown')}") return False # Validate datetime format - if not CommitService.is_valid_datetime(commit_dict.get("committer_datetime", "")): - logger.error( + if not self.is_valid_datetime(commit_dict.get("committer_datetime", "")): + self.logger.error( f"Invalid commit datetime: {commit_dict.get('committer_datetime', 'unknown')}" ) return False return True - @staticmethod - def _is_valid_email(email: str) -> bool: + def _is_valid_email(self, email: str) -> bool: """Check if a string is a valid email format using Pydantic validation.""" try: validate_email(email.strip()) @@ -827,19 +802,16 @@ def _is_valid_email(email: str) -> bool: except Exception: return False - @staticmethod - def _validate_and_adjust_datetime(commit_datetime: str, author_datetime: str) -> str: + def _validate_and_adjust_datetime(self, commit_datetime: str, author_datetime: str) -> str: """Validate commit datetime and adjust if it's in the future.""" try: - commit_datetime_obj = datetime.datetime.strptime( - commit_datetime, CommitService.DATETIME_FORMAT - ) + commit_datetime_obj = datetime.datetime.strptime(commit_datetime, self.DATETIME_FORMAT) future_threshold = datetime.datetime.now(datetime.timezone.utc) + datetime.timedelta( - days=CommitService.FUTURE_DATE_THRESHOLD_DAYS + days=self.FUTURE_DATE_THRESHOLD_DAYS ) if commit_datetime_obj > future_threshold: - logger.warning( + self.logger.warning( f"Commit datetime in future, using author datetime instead: {commit_datetime}" ) return author_datetime @@ -847,7 +819,7 @@ def _validate_and_adjust_datetime(commit_datetime: str, author_datetime: str) -> return commit_datetime except ValueError: - logger.warning( + self.logger.warning( f"Invalid commit datetime format: {commit_datetime}, using author datetime" ) return author_datetime diff --git a/services/apps/git_integration/src/crowdgit/settings.py b/services/apps/git_integration/src/crowdgit/settings.py index ebf20508a4..445f05d1a6 100644 --- a/services/apps/git_integration/src/crowdgit/settings.py +++ b/services/apps/git_integration/src/crowdgit/settings.py @@ -18,7 +18,7 @@ def load_env_var(key: str, required=True, default=None): REPOSITORY_UPDATE_INTERVAL_HOURS = int( load_env_var("REPOSITORY_UPDATE_INTERVAL_HOURS", default=24) ) -MAX_WORKER_PROCESSES = int(load_env_var("MAX_WORKER_PROCESSES", default=min(3, os.cpu_count()))) +MAX_WORKER_PROCESSES = int(load_env_var("MAX_WORKER_PROCESSES", default=min(2, os.cpu_count()))) DEFAULT_TENANT_ID = load_env_var( "CROWD_SSO_LF_TENANT_ID", default="875c38bd-2b1b-4e91-ad07-0cfbabb4c49f" ) diff --git a/services/apps/git_integration/src/crowdgit/worker/repository_worker.py b/services/apps/git_integration/src/crowdgit/worker/repository_worker.py index 7988ca9ee3..06dda43969 100644 --- a/services/apps/git_integration/src/crowdgit/worker/repository_worker.py +++ b/services/apps/git_integration/src/crowdgit/worker/repository_worker.py @@ -169,7 +169,6 @@ async def _process_single_repository(self, repository: Repository): processing_state = RepositoryState.FAILED logger.error(f"Processing failed with error: {repr(e)}") finally: - self.commit_service.cleanup_process_pool() # Reset logger context for all services self._reset_all_contexts() diff --git a/services/apps/git_integration/uv.lock b/services/apps/git_integration/uv.lock index 23629b65c9..c358c72001 100644 --- a/services/apps/git_integration/uv.lock +++ b/services/apps/git_integration/uv.lock @@ -456,6 +456,7 @@ dependencies = [ { name = "gitpython" }, { name = "loguru" }, { name = "openai" }, + { name = "orjson" }, { name = "prettytable" }, { name = "python-dotenv" }, { name = "python-json-logger" }, @@ -491,6 +492,7 @@ requires-dist = [ { name = "gitpython" }, { name = "loguru", specifier = ">=0.7.3" }, { name = "openai", specifier = ">=1.45.0" }, + { name = "orjson", specifier = ">=3.11.3" }, { name = "prettytable", specifier = ">=3.11.0" }, { name = "python-dotenv", specifier = ">=1.0.1" }, { name = "python-json-logger" }, @@ -1245,6 +1247,83 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/64/46/a10d9df4673df56f71201d129ba1cb19eaff3366d08c8664d61a7df52e65/openai-1.93.0-py3-none-any.whl", hash = "sha256:3d746fe5498f0dd72e0d9ab706f26c91c0f646bf7459e5629af8ba7c9dbdf090", size = 755038, upload-time = "2025-06-27T21:21:37.532Z" }, ] +[[package]] +name = "orjson" +version = "3.11.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/be/4d/8df5f83256a809c22c4d6792ce8d43bb503be0fb7a8e4da9025754b09658/orjson-3.11.3.tar.gz", hash = "sha256:1c0603b1d2ffcd43a411d64797a19556ef76958aef1c182f22dc30860152a98a", size = 5482394, upload-time = "2025-08-26T17:46:43.171Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/9b/64/4a3cef001c6cd9c64256348d4c13a7b09b857e3e1cbb5185917df67d8ced/orjson-3.11.3-cp310-cp310-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:29cb1f1b008d936803e2da3d7cba726fc47232c45df531b29edf0b232dd737e7", size = 238600, upload-time = "2025-08-26T17:44:36.875Z" }, + { url = "https://files.pythonhosted.org/packages/10/ce/0c8c87f54f79d051485903dc46226c4d3220b691a151769156054df4562b/orjson-3.11.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:97dceed87ed9139884a55db8722428e27bd8452817fbf1869c58b49fecab1120", size = 123526, upload-time = "2025-08-26T17:44:39.574Z" }, + { url = "https://files.pythonhosted.org/packages/ef/d0/249497e861f2d438f45b3ab7b7b361484237414945169aa285608f9f7019/orjson-3.11.3-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:58533f9e8266cb0ac298e259ed7b4d42ed3fa0b78ce76860626164de49e0d467", size = 128075, upload-time = "2025-08-26T17:44:40.672Z" }, + { url = "https://files.pythonhosted.org/packages/e5/64/00485702f640a0fd56144042a1ea196469f4a3ae93681871564bf74fa996/orjson-3.11.3-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0c212cfdd90512fe722fa9bd620de4d46cda691415be86b2e02243242ae81873", size = 130483, upload-time = "2025-08-26T17:44:41.788Z" }, + { url = "https://files.pythonhosted.org/packages/64/81/110d68dba3909171bf3f05619ad0cf187b430e64045ae4e0aa7ccfe25b15/orjson-3.11.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5ff835b5d3e67d9207343effb03760c00335f8b5285bfceefd4dc967b0e48f6a", size = 132539, upload-time = "2025-08-26T17:44:43.12Z" }, + { url = "https://files.pythonhosted.org/packages/79/92/dba25c22b0ddfafa1e6516a780a00abac28d49f49e7202eb433a53c3e94e/orjson-3.11.3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f5aa4682912a450c2db89cbd92d356fef47e115dffba07992555542f344d301b", size = 135390, upload-time = "2025-08-26T17:44:44.199Z" }, + { url = "https://files.pythonhosted.org/packages/44/1d/ca2230fd55edbd87b58a43a19032d63a4b180389a97520cc62c535b726f9/orjson-3.11.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d7d18dd34ea2e860553a579df02041845dee0af8985dff7f8661306f95504ddf", size = 132966, upload-time = "2025-08-26T17:44:45.719Z" }, + { url = "https://files.pythonhosted.org/packages/6e/b9/96bbc8ed3e47e52b487d504bd6861798977445fbc410da6e87e302dc632d/orjson-3.11.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:d8b11701bc43be92ea42bd454910437b355dfb63696c06fe953ffb40b5f763b4", size = 131349, upload-time = "2025-08-26T17:44:46.862Z" }, + { url = "https://files.pythonhosted.org/packages/c4/3c/418fbd93d94b0df71cddf96b7fe5894d64a5d890b453ac365120daec30f7/orjson-3.11.3-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:90368277087d4af32d38bd55f9da2ff466d25325bf6167c8f382d8ee40cb2bbc", size = 404087, upload-time = "2025-08-26T17:44:48.079Z" }, + { url = "https://files.pythonhosted.org/packages/5b/a9/2bfd58817d736c2f63608dec0c34857339d423eeed30099b126562822191/orjson-3.11.3-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:fd7ff459fb393358d3a155d25b275c60b07a2c83dcd7ea962b1923f5a1134569", size = 146067, upload-time = "2025-08-26T17:44:49.302Z" }, + { url = "https://files.pythonhosted.org/packages/33/ba/29023771f334096f564e48d82ed855a0ed3320389d6748a9c949e25be734/orjson-3.11.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:f8d902867b699bcd09c176a280b1acdab57f924489033e53d0afe79817da37e6", size = 135506, upload-time = "2025-08-26T17:44:50.558Z" }, + { url = "https://files.pythonhosted.org/packages/39/62/b5a1eca83f54cb3aa11a9645b8a22f08d97dbd13f27f83aae7c6666a0a05/orjson-3.11.3-cp310-cp310-win32.whl", hash = "sha256:bb93562146120bb51e6b154962d3dadc678ed0fce96513fa6bc06599bb6f6edc", size = 136352, upload-time = "2025-08-26T17:44:51.698Z" }, + { url = "https://files.pythonhosted.org/packages/e3/c0/7ebfaa327d9a9ed982adc0d9420dbce9a3fec45b60ab32c6308f731333fa/orjson-3.11.3-cp310-cp310-win_amd64.whl", hash = "sha256:976c6f1975032cc327161c65d4194c549f2589d88b105a5e3499429a54479770", size = 131539, upload-time = "2025-08-26T17:44:52.974Z" }, + { url = "https://files.pythonhosted.org/packages/cd/8b/360674cd817faef32e49276187922a946468579fcaf37afdfb6c07046e92/orjson-3.11.3-cp311-cp311-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:9d2ae0cc6aeb669633e0124531f342a17d8e97ea999e42f12a5ad4adaa304c5f", size = 238238, upload-time = "2025-08-26T17:44:54.214Z" }, + { url = "https://files.pythonhosted.org/packages/05/3d/5fa9ea4b34c1a13be7d9046ba98d06e6feb1d8853718992954ab59d16625/orjson-3.11.3-cp311-cp311-macosx_15_0_arm64.whl", hash = "sha256:ba21dbb2493e9c653eaffdc38819b004b7b1b246fb77bfc93dc016fe664eac91", size = 127713, upload-time = "2025-08-26T17:44:55.596Z" }, + { url = "https://files.pythonhosted.org/packages/e5/5f/e18367823925e00b1feec867ff5f040055892fc474bf5f7875649ecfa586/orjson-3.11.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:00f1a271e56d511d1569937c0447d7dce5a99a33ea0dec76673706360a051904", size = 123241, upload-time = "2025-08-26T17:44:57.185Z" }, + { url = "https://files.pythonhosted.org/packages/0f/bd/3c66b91c4564759cf9f473251ac1650e446c7ba92a7c0f9f56ed54f9f0e6/orjson-3.11.3-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b67e71e47caa6680d1b6f075a396d04fa6ca8ca09aafb428731da9b3ea32a5a6", size = 127895, upload-time = "2025-08-26T17:44:58.349Z" }, + { url = "https://files.pythonhosted.org/packages/82/b5/dc8dcd609db4766e2967a85f63296c59d4722b39503e5b0bf7fd340d387f/orjson-3.11.3-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d7d012ebddffcce8c85734a6d9e5f08180cd3857c5f5a3ac70185b43775d043d", size = 130303, upload-time = "2025-08-26T17:44:59.491Z" }, + { url = "https://files.pythonhosted.org/packages/48/c2/d58ec5fd1270b2aa44c862171891adc2e1241bd7dab26c8f46eb97c6c6f1/orjson-3.11.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:dd759f75d6b8d1b62012b7f5ef9461d03c804f94d539a5515b454ba3a6588038", size = 132366, upload-time = "2025-08-26T17:45:00.654Z" }, + { url = "https://files.pythonhosted.org/packages/73/87/0ef7e22eb8dd1ef940bfe3b9e441db519e692d62ed1aae365406a16d23d0/orjson-3.11.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6890ace0809627b0dff19cfad92d69d0fa3f089d3e359a2a532507bb6ba34efb", size = 135180, upload-time = "2025-08-26T17:45:02.424Z" }, + { url = "https://files.pythonhosted.org/packages/bb/6a/e5bf7b70883f374710ad74faf99bacfc4b5b5a7797c1d5e130350e0e28a3/orjson-3.11.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f9d4a5e041ae435b815e568537755773d05dac031fee6a57b4ba70897a44d9d2", size = 132741, upload-time = "2025-08-26T17:45:03.663Z" }, + { url = "https://files.pythonhosted.org/packages/bd/0c/4577fd860b6386ffaa56440e792af01c7882b56d2766f55384b5b0e9d39b/orjson-3.11.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:2d68bf97a771836687107abfca089743885fb664b90138d8761cce61d5625d55", size = 131104, upload-time = "2025-08-26T17:45:04.939Z" }, + { url = "https://files.pythonhosted.org/packages/66/4b/83e92b2d67e86d1c33f2ea9411742a714a26de63641b082bdbf3d8e481af/orjson-3.11.3-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:bfc27516ec46f4520b18ef645864cee168d2a027dbf32c5537cb1f3e3c22dac1", size = 403887, upload-time = "2025-08-26T17:45:06.228Z" }, + { url = "https://files.pythonhosted.org/packages/6d/e5/9eea6a14e9b5ceb4a271a1fd2e1dec5f2f686755c0fab6673dc6ff3433f4/orjson-3.11.3-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:f66b001332a017d7945e177e282a40b6997056394e3ed7ddb41fb1813b83e824", size = 145855, upload-time = "2025-08-26T17:45:08.338Z" }, + { url = "https://files.pythonhosted.org/packages/45/78/8d4f5ad0c80ba9bf8ac4d0fc71f93a7d0dc0844989e645e2074af376c307/orjson-3.11.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:212e67806525d2561efbfe9e799633b17eb668b8964abed6b5319b2f1cfbae1f", size = 135361, upload-time = "2025-08-26T17:45:09.625Z" }, + { url = "https://files.pythonhosted.org/packages/0b/5f/16386970370178d7a9b438517ea3d704efcf163d286422bae3b37b88dbb5/orjson-3.11.3-cp311-cp311-win32.whl", hash = "sha256:6e8e0c3b85575a32f2ffa59de455f85ce002b8bdc0662d6b9c2ed6d80ab5d204", size = 136190, upload-time = "2025-08-26T17:45:10.962Z" }, + { url = "https://files.pythonhosted.org/packages/09/60/db16c6f7a41dd8ac9fb651f66701ff2aeb499ad9ebc15853a26c7c152448/orjson-3.11.3-cp311-cp311-win_amd64.whl", hash = "sha256:6be2f1b5d3dc99a5ce5ce162fc741c22ba9f3443d3dd586e6a1211b7bc87bc7b", size = 131389, upload-time = "2025-08-26T17:45:12.285Z" }, + { url = "https://files.pythonhosted.org/packages/3e/2a/bb811ad336667041dea9b8565c7c9faf2f59b47eb5ab680315eea612ef2e/orjson-3.11.3-cp311-cp311-win_arm64.whl", hash = "sha256:fafb1a99d740523d964b15c8db4eabbfc86ff29f84898262bf6e3e4c9e97e43e", size = 126120, upload-time = "2025-08-26T17:45:13.515Z" }, + { url = "https://files.pythonhosted.org/packages/3d/b0/a7edab2a00cdcb2688e1c943401cb3236323e7bfd2839815c6131a3742f4/orjson-3.11.3-cp312-cp312-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:8c752089db84333e36d754c4baf19c0e1437012242048439c7e80eb0e6426e3b", size = 238259, upload-time = "2025-08-26T17:45:15.093Z" }, + { url = "https://files.pythonhosted.org/packages/e1/c6/ff4865a9cc398a07a83342713b5932e4dc3cb4bf4bc04e8f83dedfc0d736/orjson-3.11.3-cp312-cp312-macosx_15_0_arm64.whl", hash = "sha256:9b8761b6cf04a856eb544acdd82fc594b978f12ac3602d6374a7edb9d86fd2c2", size = 127633, upload-time = "2025-08-26T17:45:16.417Z" }, + { url = "https://files.pythonhosted.org/packages/6e/e6/e00bea2d9472f44fe8794f523e548ce0ad51eb9693cf538a753a27b8bda4/orjson-3.11.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8b13974dc8ac6ba22feaa867fc19135a3e01a134b4f7c9c28162fed4d615008a", size = 123061, upload-time = "2025-08-26T17:45:17.673Z" }, + { url = "https://files.pythonhosted.org/packages/54/31/9fbb78b8e1eb3ac605467cb846e1c08d0588506028b37f4ee21f978a51d4/orjson-3.11.3-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f83abab5bacb76d9c821fd5c07728ff224ed0e52d7a71b7b3de822f3df04e15c", size = 127956, upload-time = "2025-08-26T17:45:19.172Z" }, + { url = "https://files.pythonhosted.org/packages/36/88/b0604c22af1eed9f98d709a96302006915cfd724a7ebd27d6dd11c22d80b/orjson-3.11.3-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e6fbaf48a744b94091a56c62897b27c31ee2da93d826aa5b207131a1e13d4064", size = 130790, upload-time = "2025-08-26T17:45:20.586Z" }, + { url = "https://files.pythonhosted.org/packages/0e/9d/1c1238ae9fffbfed51ba1e507731b3faaf6b846126a47e9649222b0fd06f/orjson-3.11.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bc779b4f4bba2847d0d2940081a7b6f7b5877e05408ffbb74fa1faf4a136c424", size = 132385, upload-time = "2025-08-26T17:45:22.036Z" }, + { url = "https://files.pythonhosted.org/packages/a3/b5/c06f1b090a1c875f337e21dd71943bc9d84087f7cdf8c6e9086902c34e42/orjson-3.11.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:bd4b909ce4c50faa2192da6bb684d9848d4510b736b0611b6ab4020ea6fd2d23", size = 135305, upload-time = "2025-08-26T17:45:23.4Z" }, + { url = "https://files.pythonhosted.org/packages/a0/26/5f028c7d81ad2ebbf84414ba6d6c9cac03f22f5cd0d01eb40fb2d6a06b07/orjson-3.11.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:524b765ad888dc5518bbce12c77c2e83dee1ed6b0992c1790cc5fb49bb4b6667", size = 132875, upload-time = "2025-08-26T17:45:25.182Z" }, + { url = "https://files.pythonhosted.org/packages/fe/d4/b8df70d9cfb56e385bf39b4e915298f9ae6c61454c8154a0f5fd7efcd42e/orjson-3.11.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:84fd82870b97ae3cdcea9d8746e592b6d40e1e4d4527835fc520c588d2ded04f", size = 130940, upload-time = "2025-08-26T17:45:27.209Z" }, + { url = "https://files.pythonhosted.org/packages/da/5e/afe6a052ebc1a4741c792dd96e9f65bf3939d2094e8b356503b68d48f9f5/orjson-3.11.3-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:fbecb9709111be913ae6879b07bafd4b0785b44c1eb5cac8ac76da048b3885a1", size = 403852, upload-time = "2025-08-26T17:45:28.478Z" }, + { url = "https://files.pythonhosted.org/packages/f8/90/7bbabafeb2ce65915e9247f14a56b29c9334003536009ef5b122783fe67e/orjson-3.11.3-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:9dba358d55aee552bd868de348f4736ca5a4086d9a62e2bfbbeeb5629fe8b0cc", size = 146293, upload-time = "2025-08-26T17:45:29.86Z" }, + { url = "https://files.pythonhosted.org/packages/27/b3/2d703946447da8b093350570644a663df69448c9d9330e5f1d9cce997f20/orjson-3.11.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:eabcf2e84f1d7105f84580e03012270c7e97ecb1fb1618bda395061b2a84a049", size = 135470, upload-time = "2025-08-26T17:45:31.243Z" }, + { url = "https://files.pythonhosted.org/packages/38/70/b14dcfae7aff0e379b0119c8a812f8396678919c431efccc8e8a0263e4d9/orjson-3.11.3-cp312-cp312-win32.whl", hash = "sha256:3782d2c60b8116772aea8d9b7905221437fdf53e7277282e8d8b07c220f96cca", size = 136248, upload-time = "2025-08-26T17:45:32.567Z" }, + { url = "https://files.pythonhosted.org/packages/35/b8/9e3127d65de7fff243f7f3e53f59a531bf6bb295ebe5db024c2503cc0726/orjson-3.11.3-cp312-cp312-win_amd64.whl", hash = "sha256:79b44319268af2eaa3e315b92298de9a0067ade6e6003ddaef72f8e0bedb94f1", size = 131437, upload-time = "2025-08-26T17:45:34.949Z" }, + { url = "https://files.pythonhosted.org/packages/51/92/a946e737d4d8a7fd84a606aba96220043dcc7d6988b9e7551f7f6d5ba5ad/orjson-3.11.3-cp312-cp312-win_arm64.whl", hash = "sha256:0e92a4e83341ef79d835ca21b8bd13e27c859e4e9e4d7b63defc6e58462a3710", size = 125978, upload-time = "2025-08-26T17:45:36.422Z" }, + { url = "https://files.pythonhosted.org/packages/fc/79/8932b27293ad35919571f77cb3693b5906cf14f206ef17546052a241fdf6/orjson-3.11.3-cp313-cp313-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:af40c6612fd2a4b00de648aa26d18186cd1322330bd3a3cc52f87c699e995810", size = 238127, upload-time = "2025-08-26T17:45:38.146Z" }, + { url = "https://files.pythonhosted.org/packages/1c/82/cb93cd8cf132cd7643b30b6c5a56a26c4e780c7a145db6f83de977b540ce/orjson-3.11.3-cp313-cp313-macosx_15_0_arm64.whl", hash = "sha256:9f1587f26c235894c09e8b5b7636a38091a9e6e7fe4531937534749c04face43", size = 127494, upload-time = "2025-08-26T17:45:39.57Z" }, + { url = "https://files.pythonhosted.org/packages/a4/b8/2d9eb181a9b6bb71463a78882bcac1027fd29cf62c38a40cc02fc11d3495/orjson-3.11.3-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:61dcdad16da5bb486d7227a37a2e789c429397793a6955227cedbd7252eb5a27", size = 123017, upload-time = "2025-08-26T17:45:40.876Z" }, + { url = "https://files.pythonhosted.org/packages/b4/14/a0e971e72d03b509190232356d54c0f34507a05050bd026b8db2bf2c192c/orjson-3.11.3-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:11c6d71478e2cbea0a709e8a06365fa63da81da6498a53e4c4f065881d21ae8f", size = 127898, upload-time = "2025-08-26T17:45:42.188Z" }, + { url = "https://files.pythonhosted.org/packages/8e/af/dc74536722b03d65e17042cc30ae586161093e5b1f29bccda24765a6ae47/orjson-3.11.3-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ff94112e0098470b665cb0ed06efb187154b63649403b8d5e9aedeb482b4548c", size = 130742, upload-time = "2025-08-26T17:45:43.511Z" }, + { url = "https://files.pythonhosted.org/packages/62/e6/7a3b63b6677bce089fe939353cda24a7679825c43a24e49f757805fc0d8a/orjson-3.11.3-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ae8b756575aaa2a855a75192f356bbda11a89169830e1439cfb1a3e1a6dde7be", size = 132377, upload-time = "2025-08-26T17:45:45.525Z" }, + { url = "https://files.pythonhosted.org/packages/fc/cd/ce2ab93e2e7eaf518f0fd15e3068b8c43216c8a44ed82ac2b79ce5cef72d/orjson-3.11.3-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c9416cc19a349c167ef76135b2fe40d03cea93680428efee8771f3e9fb66079d", size = 135313, upload-time = "2025-08-26T17:45:46.821Z" }, + { url = "https://files.pythonhosted.org/packages/d0/b4/f98355eff0bd1a38454209bbc73372ce351ba29933cb3e2eba16c04b9448/orjson-3.11.3-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b822caf5b9752bc6f246eb08124c3d12bf2175b66ab74bac2ef3bbf9221ce1b2", size = 132908, upload-time = "2025-08-26T17:45:48.126Z" }, + { url = "https://files.pythonhosted.org/packages/eb/92/8f5182d7bc2a1bed46ed960b61a39af8389f0ad476120cd99e67182bfb6d/orjson-3.11.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:414f71e3bdd5573893bf5ecdf35c32b213ed20aa15536fe2f588f946c318824f", size = 130905, upload-time = "2025-08-26T17:45:49.414Z" }, + { url = "https://files.pythonhosted.org/packages/1a/60/c41ca753ce9ffe3d0f67b9b4c093bdd6e5fdb1bc53064f992f66bb99954d/orjson-3.11.3-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:828e3149ad8815dc14468f36ab2a4b819237c155ee1370341b91ea4c8672d2ee", size = 403812, upload-time = "2025-08-26T17:45:51.085Z" }, + { url = "https://files.pythonhosted.org/packages/dd/13/e4a4f16d71ce1868860db59092e78782c67082a8f1dc06a3788aef2b41bc/orjson-3.11.3-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:ac9e05f25627ffc714c21f8dfe3a579445a5c392a9c8ae7ba1d0e9fb5333f56e", size = 146277, upload-time = "2025-08-26T17:45:52.851Z" }, + { url = "https://files.pythonhosted.org/packages/8d/8b/bafb7f0afef9344754a3a0597a12442f1b85a048b82108ef2c956f53babd/orjson-3.11.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:e44fbe4000bd321d9f3b648ae46e0196d21577cf66ae684a96ff90b1f7c93633", size = 135418, upload-time = "2025-08-26T17:45:54.806Z" }, + { url = "https://files.pythonhosted.org/packages/60/d4/bae8e4f26afb2c23bea69d2f6d566132584d1c3a5fe89ee8c17b718cab67/orjson-3.11.3-cp313-cp313-win32.whl", hash = "sha256:2039b7847ba3eec1f5886e75e6763a16e18c68a63efc4b029ddf994821e2e66b", size = 136216, upload-time = "2025-08-26T17:45:57.182Z" }, + { url = "https://files.pythonhosted.org/packages/88/76/224985d9f127e121c8cad882cea55f0ebe39f97925de040b75ccd4b33999/orjson-3.11.3-cp313-cp313-win_amd64.whl", hash = "sha256:29be5ac4164aa8bdcba5fa0700a3c9c316b411d8ed9d39ef8a882541bd452fae", size = 131362, upload-time = "2025-08-26T17:45:58.56Z" }, + { url = "https://files.pythonhosted.org/packages/e2/cf/0dce7a0be94bd36d1346be5067ed65ded6adb795fdbe3abd234c8d576d01/orjson-3.11.3-cp313-cp313-win_arm64.whl", hash = "sha256:18bd1435cb1f2857ceb59cfb7de6f92593ef7b831ccd1b9bfb28ca530e539dce", size = 125989, upload-time = "2025-08-26T17:45:59.95Z" }, + { url = "https://files.pythonhosted.org/packages/ef/77/d3b1fef1fc6aaeed4cbf3be2b480114035f4df8fa1a99d2dac1d40d6e924/orjson-3.11.3-cp314-cp314-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:cf4b81227ec86935568c7edd78352a92e97af8da7bd70bdfdaa0d2e0011a1ab4", size = 238115, upload-time = "2025-08-26T17:46:01.669Z" }, + { url = "https://files.pythonhosted.org/packages/e4/6d/468d21d49bb12f900052edcfbf52c292022d0a323d7828dc6376e6319703/orjson-3.11.3-cp314-cp314-macosx_15_0_arm64.whl", hash = "sha256:bc8bc85b81b6ac9fc4dae393a8c159b817f4c2c9dee5d12b773bddb3b95fc07e", size = 127493, upload-time = "2025-08-26T17:46:03.466Z" }, + { url = "https://files.pythonhosted.org/packages/67/46/1e2588700d354aacdf9e12cc2d98131fb8ac6f31ca65997bef3863edb8ff/orjson-3.11.3-cp314-cp314-manylinux_2_34_aarch64.whl", hash = "sha256:88dcfc514cfd1b0de038443c7b3e6a9797ffb1b3674ef1fd14f701a13397f82d", size = 122998, upload-time = "2025-08-26T17:46:04.803Z" }, + { url = "https://files.pythonhosted.org/packages/3b/94/11137c9b6adb3779f1b34fd98be51608a14b430dbc02c6d41134fbba484c/orjson-3.11.3-cp314-cp314-manylinux_2_34_x86_64.whl", hash = "sha256:d61cd543d69715d5fc0a690c7c6f8dcc307bc23abef9738957981885f5f38229", size = 132915, upload-time = "2025-08-26T17:46:06.237Z" }, + { url = "https://files.pythonhosted.org/packages/10/61/dccedcf9e9bcaac09fdabe9eaee0311ca92115699500efbd31950d878833/orjson-3.11.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:2b7b153ed90ababadbef5c3eb39549f9476890d339cf47af563aea7e07db2451", size = 130907, upload-time = "2025-08-26T17:46:07.581Z" }, + { url = "https://files.pythonhosted.org/packages/0e/fd/0e935539aa7b08b3ca0f817d73034f7eb506792aae5ecc3b7c6e679cdf5f/orjson-3.11.3-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:7909ae2460f5f494fecbcd10613beafe40381fd0316e35d6acb5f3a05bfda167", size = 403852, upload-time = "2025-08-26T17:46:08.982Z" }, + { url = "https://files.pythonhosted.org/packages/4a/2b/50ae1a5505cd1043379132fdb2adb8a05f37b3e1ebffe94a5073321966fd/orjson-3.11.3-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:2030c01cbf77bc67bee7eef1e7e31ecf28649353987775e3583062c752da0077", size = 146309, upload-time = "2025-08-26T17:46:10.576Z" }, + { url = "https://files.pythonhosted.org/packages/cd/1d/a473c158e380ef6f32753b5f39a69028b25ec5be331c2049a2201bde2e19/orjson-3.11.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:a0169ebd1cbd94b26c7a7ad282cf5c2744fce054133f959e02eb5265deae1872", size = 135424, upload-time = "2025-08-26T17:46:12.386Z" }, + { url = "https://files.pythonhosted.org/packages/da/09/17d9d2b60592890ff7382e591aa1d9afb202a266b180c3d4049b1ec70e4a/orjson-3.11.3-cp314-cp314-win32.whl", hash = "sha256:0c6d7328c200c349e3a4c6d8c83e0a5ad029bdc2d417f234152bf34842d0fc8d", size = 136266, upload-time = "2025-08-26T17:46:13.853Z" }, + { url = "https://files.pythonhosted.org/packages/15/58/358f6846410a6b4958b74734727e582ed971e13d335d6c7ce3e47730493e/orjson-3.11.3-cp314-cp314-win_amd64.whl", hash = "sha256:317bbe2c069bbc757b1a2e4105b64aacd3bc78279b66a6b9e51e846e4809f804", size = 131351, upload-time = "2025-08-26T17:46:15.27Z" }, + { url = "https://files.pythonhosted.org/packages/28/01/d6b274a0635be0468d4dbd9cafe80c47105937a0d42434e805e67cd2ed8b/orjson-3.11.3-cp314-cp314-win_arm64.whl", hash = "sha256:e8f6a7a27d7b7bec81bd5924163e9af03d49bbb63013f107b48eb5d16db711bc", size = 125985, upload-time = "2025-08-26T17:46:16.67Z" }, +] + [[package]] name = "packaging" version = "25.0" From c25041c525787ca58aa66d33fbe24d7fc0df9929 Mon Sep 17 00:00:00 2001 From: Mouad BANI Date: Wed, 15 Oct 2025 12:53:26 +0100 Subject: [PATCH 2/2] chore: remove unsed env var --- services/apps/git_integration/src/crowdgit/settings.py | 1 - 1 file changed, 1 deletion(-) diff --git a/services/apps/git_integration/src/crowdgit/settings.py b/services/apps/git_integration/src/crowdgit/settings.py index 445f05d1a6..51a3bfe541 100644 --- a/services/apps/git_integration/src/crowdgit/settings.py +++ b/services/apps/git_integration/src/crowdgit/settings.py @@ -18,7 +18,6 @@ def load_env_var(key: str, required=True, default=None): REPOSITORY_UPDATE_INTERVAL_HOURS = int( load_env_var("REPOSITORY_UPDATE_INTERVAL_HOURS", default=24) ) -MAX_WORKER_PROCESSES = int(load_env_var("MAX_WORKER_PROCESSES", default=min(2, os.cpu_count()))) DEFAULT_TENANT_ID = load_env_var( "CROWD_SSO_LF_TENANT_ID", default="875c38bd-2b1b-4e91-ad07-0cfbabb4c49f" )