1package fantasy
2
3import (
4 "fmt"
5 "net/http"
6
7 "github.com/charmbracelet/x/exp/slice"
8)
9
10// Error is a custom error type for the fantasy package.
11type Error struct {
12 Message string
13 Title string
14 Cause error
15}
16
17func (err *Error) Error() string {
18 if err.Title == "" {
19 return err.Message
20 }
21 return fmt.Sprintf("%s: %s", err.Title, err.Message)
22}
23
24func (err Error) Unwrap() error {
25 return err.Cause
26}
27
28// ProviderError represents an error returned by an external provider.
29type ProviderError struct {
30 Message string
31 Title string
32 Cause error
33
34 URL string
35 StatusCode int
36 RequestBody []byte
37 ResponseHeaders map[string]string
38 ResponseBody []byte
39}
40
41func (m *ProviderError) Error() string {
42 if m.Title == "" {
43 return m.Message
44 }
45 return fmt.Sprintf("%s: %s", m.Title, m.Message)
46}
47
48// IsRetryable checks if the error is retryable based on the status code.
49func (m *ProviderError) IsRetryable() bool {
50 return m.StatusCode == http.StatusRequestTimeout || m.StatusCode == http.StatusConflict || m.StatusCode == http.StatusTooManyRequests
51}
52
53// RetryError represents an error that occurred during retry operations.
54type RetryError struct {
55 Errors []error
56}
57
58func (e *RetryError) Error() string {
59 if err, ok := slice.Last(e.Errors); ok {
60 return fmt.Sprintf("retry error: %v", err)
61 }
62 return "retry error: no underlying errors"
63}
64
65func (e RetryError) Unwrap() error {
66 if err, ok := slice.Last(e.Errors); ok {
67 return err
68 }
69 return nil
70}