Skip to content

Conversation

nicknezis
Copy link

What This Code Does

This is a catch block that intercepts any Exception thrown during proxy connection operations and
transforms it into a more specific ServerError type.

The when Expression Logic

The when expression acts like a sophisticated error classifier:

val connectionError = when (exception) {
is ServerError -> exception // Already structured, pass through
is java.net.ConnectException -> ServerError.ConnectionError.GraphConnectionFailure(graph.toString(),
exception)
is java.net.SocketTimeoutException -> ServerError.ConnectionError.ConnectionTimeout(30000L)
is java.io.IOException -> ServerError.ConnectionError.ConnectionClosed(exception.message)
else -> ServerError.ConnectionError.AcceptFailure(exception)
}

Each Case Explained:

  1. is ServerError -> exception
    - If it's already one of our structured errors, don't double-wrap it
    - Just pass it through unchanged
  2. is java.net.ConnectException
    - Network connection was refused (e.g., Neo4j server not running)
    - Creates GraphConnectionFailure with the graph URL for context
    - Original exception preserved as cause
  3. is java.net.SocketTimeoutException
    - Connection took too long to establish
    - Creates ConnectionTimeout with a hardcoded 30-second timeout
    - Provides clear timeout context
  4. is java.io.IOException
    - Generic I/O error (connection reset, broken pipe, etc.)
    - Creates ConnectionClosed with the error message
    - Covers unexpected connection drops
  5. else -> AcceptFailure
    - Catch-all for any other unexpected exceptions
    - Wraps unknown errors as connection accept failures
    - Ensures no exception goes unhandled

Benefits of This Approach

Before (Generic Handling):

} catch (exception: Exception) {
LOGGER.error("Proxy connection failure", exception)
}

  • ❌ Vague error message
  • ❌ No context about failure type
  • ❌ Hard to implement specific recovery logic
  • ❌ Poor observability

After (Structured Handling):

} catch (exception: Exception) {
val connectionError = when (exception) { /* ... */ }
LOGGER.error("Proxy connection failure: {}", connectionError.message, connectionError)
}

  • ✅ Specific error messages: "Failed to connect to graph at 'bolt://localhost:7687'"
  • ✅ Error categorization: Know if it's timeout vs connection refused vs I/O error
  • ✅ Better logging: Structured error messages with context
  • ✅ Recovery potential: Different error types can trigger different recovery strategies
  • ✅ Monitoring: Can alert differently based on error type

Real-World Example

If Neo4j is down, instead of:
ERROR: Proxy connection failure java.net.ConnectException: Connection refused

You get:
ERROR: Proxy connection failure: Failed to connect to graph at 'bolt://localhost:7687'

This immediately tells operators:

  • What failed: Connection to the graph database
  • Where: The specific Neo4j instance URL
  • Why: Connection was refused (likely server down)
  • How to fix: Check if Neo4j is running on that address

This pattern transforms low-level technical exceptions into business-meaningful error descriptions that
help with debugging, monitoring, and automated recovery.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant