Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
d9604a4
:art: Improve acapy error logging
ff137 Jul 24, 2025
d5cff3b
:arrow_up: Update acapy reference
ff137 Jul 24, 2025
ef02baf
:sparkles: Script to monitor logs and kill agent
ff137 Jul 28, 2025
3b2965f
:test_tube: Testing revocation registry recovery
ff137 Jul 28, 2025
3692ffc
:arrow_up: Updated acapy commit hash
ff137 Jul 28, 2025
bef3be2
:test_tube:
ff137 Jul 28, 2025
02be29b
:truck: Move util methods for better organization
ff137 Jul 29, 2025
748062f
:wrench:
ff137 Jul 29, 2025
6ef9b6a
:arrow_up: Update acapy commit hash
ff137 Jul 29, 2025
a288ed8
:sparkles: Support monitoring custom log patterns
ff137 Jul 29, 2025
b2a2ccf
:truck: Move experimental tests to own module
ff137 Jul 29, 2025
56ea0ab
:bug: Fix assertion
ff137 Jul 29, 2025
01d4f4c
:test_tube: Fix monitor script
ff137 Jul 29, 2025
97f1e55
:test_tube:
ff137 Jul 30, 2025
15aec74
:arrow_up:
ff137 Jul 31, 2025
71c4178
:arrow_up: Update acapy / plugin commit hash
ff137 Aug 1, 2025
9f2c6b3
:test_tube: Refactored test to run multiple scenarios
ff137 Aug 1, 2025
24c0038
:test_tube: More scenarios
ff137 Aug 1, 2025
469c3f1
:art:
ff137 Aug 1, 2025
1105360
:rewind: Revert accidental gitmodules change
ff137 Aug 4, 2025
285f066
:arrow_up: acapy: add recovery delay; cheqd: recover rev_list if it a…
ff137 Aug 4, 2025
6228c3f
:test_tube: Ignore test by default
ff137 Aug 5, 2025
8ebbd0c
:arrow_up: acapy/plugins: improved traceability
ff137 Aug 7, 2025
0e45870
:sparkles: Emit event if manual intervention is required
ff137 Aug 7, 2025
1c97d21
:wrench: Make retry count and sleep time configurable
ff137 Aug 12, 2025
6a4a714
:arrow_up: Bump acapy with latest changes:
ff137 Aug 13, 2025
0637240
Merge branch 'master' into feat/rev-reg-events
ff137 Aug 14, 2025
c967dba
:art:
ff137 Aug 14, 2025
d2c50b1
:arrow_up: Update acapy - fix missing log args, and persist request-i…
ff137 Aug 14, 2025
0c0b2b5
:arrow_up: Update acapy
ff137 Aug 14, 2025
d41056e
🎨 Add options to RevListFinishedEvent
ff137 Aug 14, 2025
d305cb8
:bug: Fix import
ff137 Aug 14, 2025
7f9e284
:arrow_up: Update acapy
ff137 Aug 14, 2025
4700533
:loud_sound: Cheqd: Elevate log level for resource recovery
ff137 Aug 15, 2025
fd7bdeb
:loud_sound: Cheqd: Make resource recovery a warning log
ff137 Aug 15, 2025
c669b03
:arrow_up: Upgrade with latest retry handling logic
ff137 Aug 15, 2025
794e1bc
:construction: Debug
ff137 Aug 15, 2025
ef4924c
🐛 Fix updating event for retry
ff137 Aug 15, 2025
a5a65a5
:arrow_up: Sync acapy + plugins to latest
ff137 Aug 26, 2025
10ed8b7
Merge branch 'master' into feat/rev-reg-events
ff137 Aug 26, 2025
b432cc1
:art: Replace assertion with warning log
ff137 Aug 26, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions app/exceptions/handle_acapy_call.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from collections.abc import Callable, Coroutine
from typing import Any

from aiohttp import ClientConnectionResetError
import aiohttp
from aries_cloudcontroller.exceptions import (
ApiException,
BadRequestException,
Expand Down Expand Up @@ -73,11 +73,14 @@ async def handle_acapy_call[T](
# Handle other / 500 errors:
logger.warning("Error during {}: {}", method_identifier, error_msg)
raise CloudApiException(status_code=status, detail=error_msg) from e
except ClientConnectionResetError as e: # pragma: no cover
logger.error("Client connection reset error")
except aiohttp.ClientConnectionResetError as e: # pragma: no cover
logger.error("Client connection reset error: {}", e)
raise CloudApiException(
status_code=500, detail="Client connection reset error"
) from e
except aiohttp.ClientConnectionError as e: # pragma: no cover
logger.error("Client connection error: {}", e)
raise CloudApiException(status_code=503, detail="Service unavailable") from e
except Exception as e:
# General exceptions:
logger.exception("Unexpected exception from ACA-Py call")
Expand Down
2 changes: 1 addition & 1 deletion app/services/revocation_registry.py
Original file line number Diff line number Diff line change
Expand Up @@ -389,7 +389,7 @@ async def get_created_active_registries(
except CloudApiException as e:
detail = (
"Error while creating credential definition: "
+ f"Could not retrieve active revocation registries `{e.detail}`."
f"Could not retrieve active revocation registries `{e.detail}`."
)
raise CloudApiException(detail=detail, status_code=e.status_code) from e

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
"""Utility functions for resilience testing

This module provides helper functions for:
- Pod monitoring and kubectl operations
- Agent status checking and health monitoring
- Enhanced error handling and logging
"""

import subprocess

from shared.log_config import get_logger

LOGGER = get_logger(__name__)


class LogPatternMonitor:
"""Monitor for specific log patterns that should trigger pod kills"""

def __init__(self, monitor_script_path: str = "./monitor_and_kill_pod.sh") -> None:
"""Initialize the log pattern monitor"""
self.monitor_script_path = monitor_script_path
self.monitor_process = None

def start_monitoring(self, log_pattern: str | None = None) -> subprocess.Popen:
"""Start log pattern monitoring

Args:
log_pattern: Custom log pattern to monitor for. If None, uses script default.

Example patterns:
"Registering revocation registry definition"
"Uploading tails file"
"Emitting store revocation registry definition event"

"""
LOGGER.info("Starting log pattern monitoring...")

# Build command with optional log pattern
cmd = [self.monitor_script_path]
if log_pattern:
cmd.append(log_pattern)
LOGGER.info(f"Using custom log pattern: '{log_pattern}'")
else:
LOGGER.info("Using default log pattern from script")

self.monitor_process = subprocess.Popen(
cmd,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
text=True,
bufsize=1,
universal_newlines=True,
)

LOGGER.info(f"Log monitor started (PID: {self.monitor_process.pid})")
return self.monitor_process

def is_monitoring_active(self) -> bool:
"""Check if monitoring process is still active"""
return self.monitor_process and self.monitor_process.poll() is None

def stop_monitoring(self):
"""Stop the monitoring process"""
if self.monitor_process and self.monitor_process.poll() is None:
LOGGER.info("Stopping log monitor...")
self.monitor_process.terminate()
try:
self.monitor_process.wait(timeout=5)
except subprocess.TimeoutExpired:
self.monitor_process.kill()
self.monitor_process.wait()
LOGGER.info("Log monitor stopped")

def get_monitor_output(self) -> tuple[str, str]:
"""Get the output from the monitoring process"""
if not self.monitor_process:
return "", ""

try:
stdout, stderr = self.monitor_process.communicate(timeout=1)
return stdout, stderr
except subprocess.TimeoutExpired:
return "", ""
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
#!/bin/bash

set -e

# Default log pattern if none provided
DEFAULT_PATTERN="Publishing revocation registry definition resource"
LOG_PATTERN="${1:-$DEFAULT_PATTERN}"

echo "🔍 Looking for multitenant-agent pod..."
echo "🎯 Monitoring for pattern: '$LOG_PATTERN'"

# Get the multitenant-agent pod name
POD_NAME=$(kubectl get pods --no-headers | grep "^multitenant-agent-" | awk '{print $1}' | head -1)

if [ -z "$POD_NAME" ]; then
echo "❌ No multitenant-agent pod found!"
exit 1
fi

echo "✅ Found pod: $POD_NAME"
echo "👀 Following logs and waiting for pattern match..."

# Follow logs from now onwards and look for the specific pattern
kubectl logs -f --tail=0 "$POD_NAME" | while IFS= read -r line; do
# Check if the line matches our pattern
if echo "$line" | grep -q "$LOG_PATTERN"; then
echo ""
echo "🎯 Found pattern match! Deleting pod..."

# Kill the pod immediately
kubectl delete pod "$POD_NAME" --force --grace-period=0

echo "💀 Pod $POD_NAME has been deleted!"
break
fi
done

echo "✨ Script completed!"
Loading
Loading