CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-pylibmc

Quick and small memcached client for Python

86

1.03x
Overview
Eval results
Files

error-handling.mddocs/

Error Handling

Complete exception hierarchy for robust error handling, covering connection issues, protocol errors, and operational failures. pylibmc provides specific exception types to help applications handle different error conditions appropriately.

Capabilities

Base Exceptions

Foundation exception classes that form the hierarchy for all pylibmc errors.

class Error(Exception):
    """
    Base exception for all pylibmc errors.
    All other pylibmc exceptions inherit from this class.
    """

class MemcachedError(Error):
    """
    Backwards compatible alias for Error.
    Maintained for compatibility with older versions.
    """

class CacheMiss(Error):
    """
    Raised when a requested key is not found in the cache.
    This is a normal condition, not necessarily an error.
    """

Connection Errors

Exceptions related to network connectivity and server communication.

class ConnectionError(Error):
    """
    General connection failure to memcached server.
    Raised when client cannot establish or maintain connection.
    """

class ConnectionBindError(Error):
    """
    Failed to bind connection to specific address.
    Usually indicates network configuration issues.
    """

class HostLookupError(Error):
    """
    DNS resolution failed for memcached server hostname.
    Check hostname spelling and DNS configuration.
    """

class SocketCreateError(Error):
    """
    Failed to create network socket for connection.
    May indicate system resource limits or permissions.
    """

class UnixSocketError(Error):
    """
    Error specific to Unix domain socket connections.
    Check socket file permissions and path.
    """

Protocol Errors

Exceptions related to memcached protocol communication and data format issues.

class ProtocolError(Error):
    """
    Memcached protocol violation or unexpected response.
    Usually indicates server or network issues.
    """

class WriteError(Error):
    """
    Failed to write data to memcached server.
    May indicate network issues or server problems.
    """

class ReadError(Error):
    """
    Failed to read data from memcached server.
    May indicate network timeout or connection issues.
    """

class UnknownReadFailure(Error):
    """
    Unexpected failure during read operation.
    Generic read error when specific cause is unknown.
    """

Server-Side Errors

Exceptions originating from memcached server responses and conditions.

class ServerError(Error):
    """
    Internal server error reported by memcached.
    Usually indicates server-side issues or bugs.
    """

class ClientError(Error):
    """
    Client request error as reported by memcached server.
    Indicates malformed request or invalid operation.
    """

class ServerDead(Error):
    """
    Server is marked as dead due to repeated failures.
    Server will be retried after retry_timeout period.
    """

class ServerDown(Error):
    """
    Server is currently down or unreachable.
    Temporary condition that may resolve automatically.
    """

class NoServers(Error):
    """
    No servers are available for operations.
    All servers may be down or configuration is empty.
    """

Data-Related Errors

Exceptions related to data operations, key validation, and value constraints.

class DataExists(Error):
    """
    Data already exists when using add operation.
    Normal condition when key already present for add().
    """

class DataDoesNotExist(Error):
    """
    Data does not exist for replace or update operation.
    Normal condition when key missing for replace().
    """

class NotFound(Error):
    """
    Requested key was not found in cache.
    Similar to CacheMiss but used in different contexts.
    """

class BadKeyProvided(Error):
    """
    Invalid key format or characters provided.
    Key may contain invalid characters or be too long.
    """

class TooBig(Error):
    """
    Value exceeds maximum size limit for memcached.
    Default limit is 1MB, configurable on server.
    """

Operational Errors

Exceptions related to operation state and resource management.

class Failure(Error):
    """
    General operation failure without specific cause.
    Generic error when operation cannot complete.
    """

class AllocationError(Error):
    """
    Memory allocation failure within pylibmc or libmemcached.
    May indicate system memory pressure.
    """

class SomeErrors(Error):
    """
    Some operations in batch failed while others succeeded.
    Used with multi-key operations for partial failures.
    """

class FetchNotFinished(Error):
    """
    Attempt to access results before fetch operation completed.
    Usually indicates improper async operation handling.
    """

class NotSupportedError(Error):
    """
    Requested operation is not supported by server or configuration.
    Feature may require specific server version or compile options.
    """

class InvalidHostProtocolError(Error):
    """
    Invalid protocol specified in server host specification.
    Check server URL format and protocol specification.
    """

class UnknownStatKey(Error):
    """
    Requested statistics key is not recognized by server.
    Use get_stats() without arguments to see available keys.
    """

Exception Information

Access to complete exception catalog and metadata.

errors: tuple           # Tuple of all exception classes
exceptions: list        # List of (name, exception_class) tuples

Usage Examples

Basic Error Handling

import pylibmc

client = pylibmc.Client(["localhost:11211"])

try:
    value = client.get("nonexistent_key")
    if value is None:
        print("Key not found")
except pylibmc.CacheMiss:
    print("Cache miss - key doesn't exist")
except pylibmc.ConnectionError:
    print("Cannot connect to memcached server")
except pylibmc.Error as e:
    print(f"Memcached error: {e}")

Comprehensive Error Handling

import pylibmc
import logging

logger = logging.getLogger(__name__)

def safe_cache_get(client, key, default=None):
    """Safely get value from cache with comprehensive error handling."""
    try:
        return client.get(key)
    
    except pylibmc.CacheMiss:
        logger.debug(f"Cache miss for key: {key}")
        return default
    
    except pylibmc.ConnectionError as e:
        logger.error(f"Connection failed: {e}")
        return default
    
    except pylibmc.ServerError as e:
        logger.error(f"Server error: {e}")
        return default
    
    except pylibmc.BadKeyProvided as e:
        logger.warning(f"Invalid key format: {key} - {e}")
        return default
    
    except pylibmc.Error as e:
        logger.exception(f"Unexpected cache error: {e}")
        return default

def safe_cache_set(client, key, value, time=0):
    """Safely set value in cache with error handling."""
    try:
        return client.set(key, value, time)
    
    except pylibmc.TooBig as e:
        logger.warning(f"Value too large for key {key}: {e}")
        return False
    
    except pylibmc.BadKeyProvided as e:
        logger.warning(f"Invalid key format: {key} - {e}")
        return False
    
    except pylibmc.ConnectionError as e:
        logger.error(f"Connection failed during set: {e}")
        return False
    
    except pylibmc.ServerError as e:
        logger.error(f"Server error during set: {e}")
        return False
    
    except pylibmc.Error as e:
        logger.exception(f"Unexpected error during set: {e}")
        return False

Batch Operation Error Handling

import pylibmc

client = pylibmc.Client(["localhost:11211"])

def safe_multi_get(client, keys):
    """Get multiple keys with proper error handling."""
    try:
        return client.get_multi(keys)
    
    except pylibmc.SomeErrors as e:
        logger.warning(f"Some keys failed in multi-get: {e}")
        # Partial results may still be available
        return {}
    
    except pylibmc.NoServers as e:
        logger.error(f"No servers available: {e}")
        return {}
    
    except pylibmc.Error as e:
        logger.exception(f"Multi-get failed: {e}")
        return {}

def safe_multi_set(client, key_value_pairs):
    """Set multiple keys with error handling."""
    try:
        failed_keys = client.set_multi(key_value_pairs)
        if failed_keys:
            logger.warning(f"Failed to set keys: {failed_keys}")
        return failed_keys
    
    except pylibmc.SomeErrors as e:
        logger.warning(f"Partial failure in multi-set: {e}")
        return list(key_value_pairs.keys())  # Assume all failed
    
    except pylibmc.Error as e:
        logger.exception(f"Multi-set failed completely: {e}")
        return list(key_value_pairs.keys())

Connection Pool Error Handling

import pylibmc
from queue import Empty

client = pylibmc.Client(["localhost:11211"])
pool = pylibmc.ClientPool()
pool.fill(client, 5)

def safe_pooled_operation(key, value=None):
    """Perform cache operation using pool with error handling."""
    try:
        with pool.reserve(block=False) as pooled_client:
            if value is not None:
                return pooled_client.set(key, value)
            else:
                return pooled_client.get(key)
    
    except Empty:
        logger.warning("Connection pool exhausted")
        return None
    
    except pylibmc.ConnectionError as e:
        logger.error(f"Connection error in pool: {e}")
        return None
    
    except pylibmc.Error as e:
        logger.exception(f"Cache error in pool: {e}")
        return None

Server Failure Recovery

import pylibmc
import time

def create_resilient_client():
    """Create client configured for automatic failure recovery."""
    client = pylibmc.Client([
        "server1:11211",
        "server2:11211", 
        "server3:11211"
    ], binary=True)
    
    # Configure for automatic failover
    client.behaviors = {
        "auto_eject": True,      # Remove failed servers
        "failure_limit": 2,      # Failures before ejection
        "retry_timeout": 30,     # Retry failed servers after 30s
        "connect_timeout": 2000, # Quick connection timeout
    }
    
    return client

def resilient_operation(client, operation_func, max_retries=3):
    """Perform operation with retry logic for server failures."""
    for attempt in range(max_retries):
        try:
            return operation_func()
        
        except (pylibmc.ServerDead, pylibmc.ServerDown, pylibmc.NoServers) as e:
            if attempt == max_retries - 1:
                logger.error(f"All retry attempts failed: {e}")
                raise
            
            logger.warning(f"Server failure (attempt {attempt + 1}): {e}")
            time.sleep(2 ** attempt)  # Exponential backoff
        
        except pylibmc.ConnectionError as e:
            if attempt == max_retries - 1:
                logger.error(f"Connection failed after retries: {e}")
                raise
            
            logger.warning(f"Connection error (attempt {attempt + 1}): {e}")
            time.sleep(1)

# Usage
client = create_resilient_client()

def get_user_data(user_id):
    return client.get(f"user:{user_id}")

try:
    user_data = resilient_operation(client, lambda: get_user_data(123))
except pylibmc.Error:
    # Fallback to database or default value
    user_data = None

Error Pattern Analysis

import pylibmc
from collections import defaultdict, Counter

class CacheErrorTracker:
    """Track and analyze cache error patterns."""
    
    def __init__(self):
        self.error_counts = Counter()
        self.error_details = defaultdict(list)
    
    def record_error(self, operation, error):
        """Record an error for analysis."""
        error_type = type(error).__name__
        self.error_counts[error_type] += 1
        self.error_details[error_type].append({
            'operation': operation,
            'message': str(error),
            'timestamp': time.time()
        })
    
    def get_stats(self):
        """Get error statistics."""
        return dict(self.error_counts)
    
    def should_fallback(self, error_threshold=10):
        """Determine if error rate suggests fallback needed."""
        connection_errors = (
            self.error_counts.get('ConnectionError', 0) +
            self.error_counts.get('ServerDead', 0) +
            self.error_counts.get('NoServers', 0)
        )
        return connection_errors >= error_threshold

# Usage
tracker = CacheErrorTracker()
client = pylibmc.Client(["localhost:11211"])

def monitored_cache_get(key):
    """Cache get with error monitoring."""
    try:
        return client.get(key)
    except pylibmc.Error as e:
        tracker.record_error('get', e)
        
        if tracker.should_fallback():
            logger.warning("High error rate - consider fallback strategy")
        
        raise

Install with Tessl CLI

npx tessl i tessl/pypi-pylibmc

docs

client-operations.md

configuration.md

connection-pooling.md

error-handling.md

index.md

tile.json