Files
HCFS/sdks/csharp/Exceptions.cs
Claude Code 0a92dc3432 Complete HCFS Phase 2: Production API & Multi-Language SDK Ecosystem
Major Phase 2 Achievements:
 Enterprise-grade FastAPI server with comprehensive middleware
 JWT and API key authentication systems
 Comprehensive Python SDK (sync/async) with advanced features
 Multi-language SDK ecosystem (JavaScript/TypeScript, Go, Rust, Java, C#)
 OpenAPI/Swagger documentation with PDF generation
 WebSocket streaming and real-time updates
 Advanced caching systems (LRU, LFU, FIFO, TTL)
 Comprehensive error handling hierarchies
 Batch operations and high-throughput processing

SDK Features Implemented:
- Promise-based JavaScript/TypeScript with full type safety
- Context-aware Go SDK with goroutine safety
- Memory-safe Rust SDK with async/await
- Reactive Java SDK with RxJava integration
- .NET 6+ C# SDK with dependency injection support
- Consistent API design across all languages
- Production-ready error handling and caching

Documentation & Testing:
- Complete OpenAPI specification with interactive docs
- Professional Sphinx documentation with ReadTheDocs styling
- LaTeX-generated PDF manuals
- Comprehensive functional testing across all SDKs
- Performance validation and benchmarking

Project Status: PRODUCTION-READY
- 2 major phases completed on schedule
- 5 programming languages with full feature parity
- Enterprise features: authentication, caching, streaming, monitoring
- Ready for deployment, academic publication, and commercial licensing

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-07-30 14:07:45 +10:00

578 lines
17 KiB
C#

using System.ComponentModel.DataAnnotations;
using System.Text.Json.Serialization;
namespace HCFS.SDK;
/// <summary>
/// Base exception for all HCFS SDK errors.
/// </summary>
public class HCFSException : Exception
{
/// <summary>
/// Gets the error code associated with this exception.
/// </summary>
public string? ErrorCode { get; }
/// <summary>
/// Gets additional error details.
/// </summary>
public IReadOnlyDictionary<string, object>? Details { get; }
/// <summary>
/// Gets the HTTP status code if applicable.
/// </summary>
public int? StatusCode { get; }
/// <summary>
/// Initializes a new instance of the <see cref="HCFSException"/> class.
/// </summary>
/// <param name="message">The error message.</param>
public HCFSException(string message) : base(message)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="HCFSException"/> class.
/// </summary>
/// <param name="message">The error message.</param>
/// <param name="errorCode">The error code.</param>
public HCFSException(string message, string errorCode) : base(message)
{
ErrorCode = errorCode;
}
/// <summary>
/// Initializes a new instance of the <see cref="HCFSException"/> class.
/// </summary>
/// <param name="message">The error message.</param>
/// <param name="errorCode">The error code.</param>
/// <param name="details">Additional error details.</param>
/// <param name="statusCode">HTTP status code.</param>
public HCFSException(string message, string? errorCode, IReadOnlyDictionary<string, object>? details, int? statusCode) : base(message)
{
ErrorCode = errorCode;
Details = details;
StatusCode = statusCode;
}
/// <summary>
/// Initializes a new instance of the <see cref="HCFSException"/> class.
/// </summary>
/// <param name="message">The error message.</param>
/// <param name="innerException">The inner exception.</param>
public HCFSException(string message, Exception innerException) : base(message, innerException)
{
}
/// <summary>
/// Checks if this error should trigger a retry.
/// </summary>
/// <returns>True if the error is retryable.</returns>
public virtual bool IsRetryable()
{
return StatusCode >= 500 || StatusCode == 429 ||
this is HCFSConnectionException ||
this is HCFSTimeoutException;
}
/// <summary>
/// Checks if this error is temporary.
/// </summary>
/// <returns>True if the error is temporary.</returns>
public virtual bool IsTemporary()
{
return StatusCode == 429 || StatusCode == 502 || StatusCode == 503 || StatusCode == 504 ||
this is HCFSTimeoutException ||
this is HCFSConnectionException;
}
}
/// <summary>
/// Thrown when connection to HCFS API fails.
/// </summary>
public class HCFSConnectionException : HCFSException
{
/// <summary>
/// Initializes a new instance of the <see cref="HCFSConnectionException"/> class.
/// </summary>
/// <param name="message">The error message.</param>
public HCFSConnectionException(string message = "Failed to connect to HCFS API")
: base(message, "CONNECTION_FAILED")
{
}
/// <summary>
/// Initializes a new instance of the <see cref="HCFSConnectionException"/> class.
/// </summary>
/// <param name="message">The error message.</param>
/// <param name="innerException">The inner exception.</param>
public HCFSConnectionException(string message, Exception innerException)
: base(message, innerException)
{
}
}
/// <summary>
/// Thrown when authentication fails.
/// </summary>
public class HCFSAuthenticationException : HCFSException
{
/// <summary>
/// Initializes a new instance of the <see cref="HCFSAuthenticationException"/> class.
/// </summary>
/// <param name="message">The error message.</param>
public HCFSAuthenticationException(string message = "Authentication failed")
: base(message, "AUTH_FAILED", null, 401)
{
}
}
/// <summary>
/// Thrown when user lacks permissions for an operation.
/// </summary>
public class HCFSAuthorizationException : HCFSException
{
/// <summary>
/// Initializes a new instance of the <see cref="HCFSAuthorizationException"/> class.
/// </summary>
/// <param name="message">The error message.</param>
public HCFSAuthorizationException(string message = "Insufficient permissions")
: base(message, "INSUFFICIENT_PERMISSIONS", null, 403)
{
}
}
/// <summary>
/// Thrown when a requested resource is not found.
/// </summary>
public class HCFSNotFoundException : HCFSException
{
/// <summary>
/// Gets the type of resource that was not found.
/// </summary>
public string? ResourceType { get; }
/// <summary>
/// Gets the ID of the resource that was not found.
/// </summary>
public string? ResourceId { get; }
/// <summary>
/// Initializes a new instance of the <see cref="HCFSNotFoundException"/> class.
/// </summary>
/// <param name="message">The error message.</param>
public HCFSNotFoundException(string message = "Resource not found")
: base(message, "NOT_FOUND", null, 404)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="HCFSNotFoundException"/> class.
/// </summary>
/// <param name="message">The error message.</param>
/// <param name="resourceType">The type of resource.</param>
/// <param name="resourceId">The resource ID.</param>
public HCFSNotFoundException(string message, string? resourceType, string? resourceId)
: base(message, "NOT_FOUND", null, 404)
{
ResourceType = resourceType;
ResourceId = resourceId;
}
/// <summary>
/// Gets the error message with resource details.
/// </summary>
public override string Message
{
get
{
var message = base.Message;
if (!string.IsNullOrEmpty(ResourceType))
{
message += $" (type: {ResourceType})";
}
if (!string.IsNullOrEmpty(ResourceId))
{
message += $" (id: {ResourceId})";
}
return message;
}
}
}
/// <summary>
/// Thrown when request validation fails.
/// </summary>
public class HCFSValidationException : ValidationException
{
/// <summary>
/// Gets the validation error details.
/// </summary>
public IReadOnlyList<ValidationErrorDetail>? ValidationErrors { get; }
/// <summary>
/// Initializes a new instance of the <see cref="HCFSValidationException"/> class.
/// </summary>
/// <param name="message">The error message.</param>
public HCFSValidationException(string message = "Request validation failed") : base(message)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="HCFSValidationException"/> class.
/// </summary>
/// <param name="message">The error message.</param>
/// <param name="validationErrors">The validation error details.</param>
public HCFSValidationException(string message, IReadOnlyList<ValidationErrorDetail> validationErrors)
: base(message)
{
ValidationErrors = validationErrors;
}
/// <summary>
/// Gets the error message with validation details.
/// </summary>
public override string Message
{
get
{
var message = base.Message;
if (ValidationErrors != null && ValidationErrors.Count > 0)
{
message += $" ({ValidationErrors.Count} validation issues)";
}
return message;
}
}
}
/// <summary>
/// Validation error detail.
/// </summary>
public record ValidationErrorDetail
{
/// <summary>
/// Gets the field name that failed validation.
/// </summary>
[JsonPropertyName("field")]
public string? Field { get; init; }
/// <summary>
/// Gets the validation error message.
/// </summary>
[JsonPropertyName("message")]
public string Message { get; init; } = string.Empty;
/// <summary>
/// Gets the validation error code.
/// </summary>
[JsonPropertyName("code")]
public string? Code { get; init; }
}
/// <summary>
/// Thrown when rate limit is exceeded.
/// </summary>
public class HCFSRateLimitException : HCFSException
{
/// <summary>
/// Gets the time to wait before retrying.
/// </summary>
public double? RetryAfterSeconds { get; }
/// <summary>
/// Initializes a new instance of the <see cref="HCFSRateLimitException"/> class.
/// </summary>
/// <param name="message">The error message.</param>
public HCFSRateLimitException(string message = "Rate limit exceeded")
: base(message, "RATE_LIMIT_EXCEEDED", null, 429)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="HCFSRateLimitException"/> class.
/// </summary>
/// <param name="message">The error message.</param>
/// <param name="retryAfterSeconds">Seconds to wait before retrying.</param>
public HCFSRateLimitException(string message, double? retryAfterSeconds)
: base(BuildMessage(message, retryAfterSeconds), "RATE_LIMIT_EXCEEDED", null, 429)
{
RetryAfterSeconds = retryAfterSeconds;
}
private static string BuildMessage(string message, double? retryAfterSeconds)
{
if (retryAfterSeconds.HasValue)
{
return $"{message}. Retry after {retryAfterSeconds.Value} seconds";
}
return message;
}
}
/// <summary>
/// Thrown for server-side errors (5xx status codes).
/// </summary>
public class HCFSServerException : HCFSException
{
/// <summary>
/// Initializes a new instance of the <see cref="HCFSServerException"/> class.
/// </summary>
/// <param name="message">The error message.</param>
/// <param name="statusCode">The HTTP status code.</param>
public HCFSServerException(string message = "Internal server error", int statusCode = 500)
: base(message, "SERVER_ERROR", null, statusCode)
{
}
/// <summary>
/// Gets the error message with status code.
/// </summary>
public override string Message => $"Server error (HTTP {StatusCode}): {base.Message}";
}
/// <summary>
/// Thrown when a request times out.
/// </summary>
public class HCFSTimeoutException : HCFSException
{
/// <summary>
/// Gets the timeout duration that was exceeded.
/// </summary>
public TimeSpan? Timeout { get; }
/// <summary>
/// Initializes a new instance of the <see cref="HCFSTimeoutException"/> class.
/// </summary>
/// <param name="message">The error message.</param>
public HCFSTimeoutException(string message = "Request timed out")
: base(message, "TIMEOUT")
{
}
/// <summary>
/// Initializes a new instance of the <see cref="HCFSTimeoutException"/> class.
/// </summary>
/// <param name="message">The error message.</param>
/// <param name="timeout">The timeout duration.</param>
public HCFSTimeoutException(string message, TimeSpan timeout)
: base($"{message} after {timeout.TotalMilliseconds}ms", "TIMEOUT")
{
Timeout = timeout;
}
}
/// <summary>
/// Thrown for cache-related errors.
/// </summary>
public class HCFSCacheException : HCFSException
{
/// <summary>
/// Gets the cache operation that failed.
/// </summary>
public string? Operation { get; }
/// <summary>
/// Initializes a new instance of the <see cref="HCFSCacheException"/> class.
/// </summary>
/// <param name="message">The error message.</param>
public HCFSCacheException(string message = "Cache operation failed")
: base(message, "CACHE_ERROR")
{
}
/// <summary>
/// Initializes a new instance of the <see cref="HCFSCacheException"/> class.
/// </summary>
/// <param name="message">The error message.</param>
/// <param name="operation">The cache operation.</param>
public HCFSCacheException(string message, string operation)
: base(message, "CACHE_ERROR")
{
Operation = operation;
}
/// <summary>
/// Gets the error message with operation details.
/// </summary>
public override string Message
{
get
{
if (!string.IsNullOrEmpty(Operation))
{
return $"Cache error during {Operation}: {base.Message}";
}
return $"Cache error: {base.Message}";
}
}
}
/// <summary>
/// Thrown for batch operation errors.
/// </summary>
public class HCFSBatchException : HCFSException
{
/// <summary>
/// Gets the items that failed in the batch operation.
/// </summary>
public IReadOnlyList<BatchFailureItem>? FailedItems { get; }
/// <summary>
/// Initializes a new instance of the <see cref="HCFSBatchException"/> class.
/// </summary>
/// <param name="message">The error message.</param>
public HCFSBatchException(string message = "Batch operation failed")
: base(message, "BATCH_ERROR")
{
}
/// <summary>
/// Initializes a new instance of the <see cref="HCFSBatchException"/> class.
/// </summary>
/// <param name="message">The error message.</param>
/// <param name="failedItems">The failed items.</param>
public HCFSBatchException(string message, IReadOnlyList<BatchFailureItem> failedItems)
: base(message, "BATCH_ERROR")
{
FailedItems = failedItems;
}
/// <summary>
/// Gets the error message with failure details.
/// </summary>
public override string Message
{
get
{
var message = base.Message;
if (FailedItems != null && FailedItems.Count > 0)
{
message += $" ({FailedItems.Count} failed items)";
}
return message;
}
}
}
/// <summary>
/// Batch operation failure item.
/// </summary>
public record BatchFailureItem
{
/// <summary>
/// Gets the index of the failed item.
/// </summary>
[JsonPropertyName("index")]
public int Index { get; init; }
/// <summary>
/// Gets the error message for the failed item.
/// </summary>
[JsonPropertyName("error")]
public string Error { get; init; } = string.Empty;
/// <summary>
/// Gets the item data that failed.
/// </summary>
[JsonPropertyName("item")]
public object? Item { get; init; }
}
/// <summary>
/// Thrown for search operation errors.
/// </summary>
public class HCFSSearchException : HCFSException
{
/// <summary>
/// Gets the search query that failed.
/// </summary>
public string? Query { get; }
/// <summary>
/// Gets the search type that was used.
/// </summary>
public string? SearchType { get; }
/// <summary>
/// Initializes a new instance of the <see cref="HCFSSearchException"/> class.
/// </summary>
/// <param name="message">The error message.</param>
public HCFSSearchException(string message = "Search failed")
: base(message, "SEARCH_ERROR")
{
}
/// <summary>
/// Initializes a new instance of the <see cref="HCFSSearchException"/> class.
/// </summary>
/// <param name="message">The error message.</param>
/// <param name="query">The search query.</param>
/// <param name="searchType">The search type.</param>
public HCFSSearchException(string message, string? query, string? searchType)
: base(message, "SEARCH_ERROR")
{
Query = query;
SearchType = searchType;
}
/// <summary>
/// Gets the error message with search details.
/// </summary>
public override string Message
{
get
{
var message = $"Search error: {base.Message}";
if (!string.IsNullOrEmpty(SearchType))
{
message += $" (type: {SearchType})";
}
if (!string.IsNullOrEmpty(Query))
{
message += $" (query: '{Query}')";
}
return message;
}
}
}
/// <summary>
/// Thrown for streaming/WebSocket errors.
/// </summary>
public class HCFSStreamException : HCFSException
{
/// <summary>
/// Initializes a new instance of the <see cref="HCFSStreamException"/> class.
/// </summary>
/// <param name="message">The error message.</param>
public HCFSStreamException(string message = "Stream operation failed")
: base(message, "STREAM_ERROR")
{
}
/// <summary>
/// Initializes a new instance of the <see cref="HCFSStreamException"/> class.
/// </summary>
/// <param name="message">The error message.</param>
/// <param name="innerException">The inner exception.</param>
public HCFSStreamException(string message, Exception innerException)
: base(message, innerException)
{
}
}
/// <summary>
/// Error response from the API.
/// </summary>
internal record ApiErrorResponse
{
[JsonPropertyName("error")]
public string? Error { get; init; }
[JsonPropertyName("message")]
public string? Message { get; init; }
[JsonPropertyName("details")]
public Dictionary<string, object>? Details { get; init; }
}