mirror of
https://github.com/go-i2p/go-i2cp.git
synced 2025-12-01 06:54:57 -05:00
fixup example dir
This commit is contained in:
92
examples/context-usage/README.md
Normal file
92
examples/context-usage/README.md
Normal file
@@ -0,0 +1,92 @@
|
||||
# Context Usage Example
|
||||
|
||||
This example demonstrates context-aware operations in the go-i2cp library.
|
||||
|
||||
## Features Demonstrated
|
||||
|
||||
- **Connection with Timeout**: Using `context.WithTimeout` to prevent hanging connections
|
||||
- **Session Creation with Cancellation**: Manual cancellation using `context.WithCancel`
|
||||
- **Graceful Shutdown**: Proper cleanup using the `Close()` method
|
||||
- **Background Processing**: Running I/O loops with context support
|
||||
|
||||
## What You'll Learn
|
||||
|
||||
- How to use `context.Context` for timeouts and cancellation
|
||||
- Proper error handling for context-related errors
|
||||
- Graceful shutdown patterns with resource cleanup
|
||||
- Session lifecycle management
|
||||
- Background task management with context
|
||||
|
||||
## Running the Example
|
||||
|
||||
```bash
|
||||
cd examples/context-usage
|
||||
go run context_usage.go
|
||||
```
|
||||
|
||||
## Building the Example
|
||||
|
||||
```bash
|
||||
cd examples/context-usage
|
||||
go build
|
||||
./context-usage
|
||||
```
|
||||
|
||||
## Example Output
|
||||
|
||||
The example will demonstrate four scenarios:
|
||||
|
||||
1. **Connection with Timeout** - Shows how to connect with a 10-second timeout
|
||||
2. **Session with Cancellation** - Demonstrates manual cancellation after 5 seconds
|
||||
3. **Graceful Shutdown** - Shows proper cleanup of multiple sessions
|
||||
4. **Background Processing** - Demonstrates I/O processing with context
|
||||
|
||||
Note: Most scenarios will fail to fully execute without a running I2P router, but they demonstrate proper API usage and error handling.
|
||||
|
||||
## Code Highlights
|
||||
|
||||
### Connection with Timeout
|
||||
```go
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
||||
defer cancel()
|
||||
|
||||
err := client.Connect(ctx)
|
||||
// Context will automatically cancel after 10 seconds
|
||||
```
|
||||
|
||||
### Graceful Shutdown
|
||||
```go
|
||||
// Close will:
|
||||
// 1. Destroy all sessions
|
||||
// 2. Wait for pending operations (max 5 seconds)
|
||||
// 3. Close TCP connection
|
||||
err := client.Close()
|
||||
```
|
||||
|
||||
### Context Cancellation
|
||||
```go
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
go func() {
|
||||
time.Sleep(5 * time.Second)
|
||||
cancel() // Cancel after 5 seconds
|
||||
}()
|
||||
|
||||
err := client.CreateSession(ctx, session)
|
||||
// Will fail with context cancelled error
|
||||
```
|
||||
|
||||
## Requirements
|
||||
|
||||
- Go 1.18 or later
|
||||
- Optional: I2P router running on `127.0.0.1:7654` for full functionality
|
||||
|
||||
## Related Examples
|
||||
|
||||
- [Modern Crypto Demo](../modern-crypto/) - Demonstrates cryptographic operations
|
||||
- [Examples Overview](../) - All available examples
|
||||
|
||||
## Further Reading
|
||||
|
||||
- [Context Package Documentation](https://pkg.go.dev/context)
|
||||
- [I2CP Specification](https://geti2p.net/spec/i2cp)
|
||||
- [go-i2cp Main Documentation](../../README.md)
|
||||
178
examples/context-usage/context_usage.go
Normal file
178
examples/context-usage/context_usage.go
Normal file
@@ -0,0 +1,178 @@
|
||||
// Package main demonstrates context-aware operations in go-i2cp
|
||||
//
|
||||
// This example shows:
|
||||
// - Using context.WithTimeout for connection timeout
|
||||
// - Using context.WithCancel for manual cancellation
|
||||
// - Graceful shutdown with Close()
|
||||
// - Error handling for context cancellation
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log"
|
||||
"time"
|
||||
|
||||
i2cp "github.com/go-i2p/go-i2cp"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// Example 1: Connection with timeout
|
||||
fmt.Println("=== Example 1: Connection with Timeout ===")
|
||||
connectWithTimeout()
|
||||
|
||||
// Example 2: Session creation with cancellation
|
||||
fmt.Println("\n=== Example 2: Session with Cancellation ===")
|
||||
sessionWithCancellation()
|
||||
|
||||
// Example 3: Graceful shutdown
|
||||
fmt.Println("\n=== Example 3: Graceful Shutdown ===")
|
||||
gracefulShutdown()
|
||||
|
||||
// Example 4: Background processing with context
|
||||
fmt.Println("\n=== Example 4: Background Processing ===")
|
||||
backgroundProcessing()
|
||||
}
|
||||
|
||||
// Example 1: Connect with a timeout to prevent hanging indefinitely
|
||||
func connectWithTimeout() {
|
||||
// Create client with nil callbacks (simplest case)
|
||||
client := i2cp.NewClient(nil)
|
||||
|
||||
// Create a context with 10 second timeout
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
||||
defer cancel()
|
||||
|
||||
err := client.Connect(ctx)
|
||||
if err != nil {
|
||||
log.Printf("Connect failed: %v", err)
|
||||
return
|
||||
}
|
||||
defer client.Close()
|
||||
|
||||
fmt.Println("Connected successfully with timeout context")
|
||||
}
|
||||
|
||||
// Example 2: Session creation with manual cancellation
|
||||
func sessionWithCancellation() {
|
||||
client := i2cp.NewClient(&i2cp.ClientCallBacks{})
|
||||
|
||||
// Create a cancellable context
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
|
||||
// Simulate cancellation after 5 seconds
|
||||
go func() {
|
||||
time.Sleep(5 * time.Second)
|
||||
log.Println("Cancelling session creation...")
|
||||
cancel()
|
||||
}()
|
||||
|
||||
err := client.Connect(ctx)
|
||||
if err != nil {
|
||||
log.Printf("Connect failed: %v", err)
|
||||
return
|
||||
}
|
||||
defer client.Close()
|
||||
|
||||
// Create session with empty callbacks
|
||||
session := i2cp.NewSession(client, i2cp.SessionCallbacks{})
|
||||
|
||||
err = client.CreateSession(ctx, session)
|
||||
if err != nil {
|
||||
// This will likely fail due to cancellation
|
||||
log.Printf("Session creation failed (expected): %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Println("Session created successfully")
|
||||
}
|
||||
|
||||
// Example 3: Graceful shutdown with proper cleanup
|
||||
func gracefulShutdown() {
|
||||
client := i2cp.NewClient(&i2cp.ClientCallBacks{})
|
||||
|
||||
ctx := context.Background()
|
||||
err := client.Connect(ctx)
|
||||
if err != nil {
|
||||
log.Printf("Connect failed: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
// Create multiple sessions
|
||||
for i := 0; i < 3; i++ {
|
||||
session := i2cp.NewSession(client, i2cp.SessionCallbacks{})
|
||||
err = client.CreateSession(ctx, session)
|
||||
if err != nil {
|
||||
log.Printf("Session %d creation failed: %v", i, err)
|
||||
}
|
||||
}
|
||||
|
||||
// Close will:
|
||||
// 1. Destroy all sessions
|
||||
// 2. Wait for pending operations (max 5 seconds)
|
||||
// 3. Close TCP connection
|
||||
fmt.Println("Starting graceful shutdown...")
|
||||
err = client.Close()
|
||||
if err != nil {
|
||||
log.Printf("Close failed: %v", err)
|
||||
} else {
|
||||
fmt.Println("Shutdown completed successfully")
|
||||
}
|
||||
}
|
||||
|
||||
// Example 4: Background message processing with context
|
||||
func backgroundProcessing() {
|
||||
client := i2cp.NewClient(&i2cp.ClientCallBacks{})
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
|
||||
defer cancel()
|
||||
|
||||
err := client.Connect(ctx)
|
||||
if err != nil {
|
||||
log.Printf("Connect failed: %v", err)
|
||||
return
|
||||
}
|
||||
defer client.Close()
|
||||
|
||||
// Create session with empty callbacks
|
||||
session := i2cp.NewSession(client, i2cp.SessionCallbacks{})
|
||||
|
||||
err = client.CreateSession(ctx, session)
|
||||
if err != nil {
|
||||
log.Printf("Session creation failed: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
// Process I/O in background with context cancellation support
|
||||
go func() {
|
||||
for {
|
||||
err := client.ProcessIO(ctx)
|
||||
if err != nil {
|
||||
if err == i2cp.ErrClientClosed {
|
||||
log.Println("Client closed, stopping I/O processing")
|
||||
return
|
||||
}
|
||||
if err == context.Canceled || err == context.DeadlineExceeded {
|
||||
log.Printf("Context cancelled: %v", err)
|
||||
return
|
||||
}
|
||||
log.Printf("ProcessIO error: %v", err)
|
||||
}
|
||||
|
||||
// Small delay to prevent busy loop
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
|
||||
// Check if context is done
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
log.Println("Context done, stopping processing")
|
||||
return
|
||||
default:
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
// Simulate some work
|
||||
time.Sleep(2 * time.Second)
|
||||
fmt.Println("Background processing completed")
|
||||
}
|
||||
Reference in New Issue
Block a user