@@ -13,6 +13,9 @@ pub enum ServeError {
1313 #[ error( "not found" ) ]
1414 NotFound ,
1515
16+ #[ error( "not found: {0} [error:{1}]" ) ]
17+ NotFoundWithId ( String , uuid:: Uuid ) ,
18+
1619 #[ error( "duplicate" ) ]
1720 Duplicate ,
1821
@@ -25,8 +28,14 @@ pub enum ServeError {
2528 #[ error( "internal error: {0}" ) ]
2629 Internal ( String ) ,
2730
31+ #[ error( "internal error: {0} [error:{1}]" ) ]
32+ InternalWithId ( String , uuid:: Uuid ) ,
33+
2834 #[ error( "not implemented: {0}" ) ]
2935 NotImplemented ( String ) ,
36+
37+ #[ error( "not implemented: {0} [error:{1}]" ) ]
38+ NotImplementedWithId ( String , uuid:: Uuid ) ,
3039}
3140
3241impl ServeError {
@@ -42,15 +51,107 @@ impl ServeError {
4251 // Pass through application-specific error codes
4352 Self :: Closed ( code) => * code,
4453 // TRACK_DOES_NOT_EXIST (0x4) from SUBSCRIBE_ERROR codes
45- Self :: NotFound => 0x4 ,
54+ Self :: NotFound | Self :: NotFoundWithId ( _ , _ ) => 0x4 ,
4655 // This is more of a session-level error, but keeping a reasonable code
4756 Self :: Duplicate => 0x5 ,
4857 // NOT_SUPPORTED (0x3) - appears in multiple error code registries
4958 Self :: Mode => 0x3 ,
5059 Self :: Size => 0x3 ,
51- Self :: NotImplemented ( _) => 0x3 ,
60+ Self :: NotImplemented ( _) | Self :: NotImplementedWithId ( _ , _ ) => 0x3 ,
5261 // INTERNAL_ERROR (0x0) - per-request error registries use 0x0
53- Self :: Internal ( _) => 0x0 ,
62+ Self :: Internal ( _) | Self :: InternalWithId ( _ , _ ) => 0x0 ,
5463 }
5564 }
65+
66+ /// Create NotFound error with correlation ID but no additional context.
67+ /// Uses generic messages for both logging and wire protocol.
68+ ///
69+ /// Example: `ServeError::not_found_id()`
70+ #[ track_caller]
71+ pub fn not_found_id ( ) -> Self {
72+ let id = uuid:: Uuid :: new_v4 ( ) ;
73+ let loc = std:: panic:: Location :: caller ( ) ;
74+ log:: warn!( "[{}] Not found at {}:{}" , id, loc. file( ) , loc. line( ) ) ;
75+ Self :: NotFoundWithId ( "Track not found" . to_string ( ) , id)
76+ }
77+
78+ /// Create NotFound error with correlation ID and internal context.
79+ /// The internal context is logged but a generic message is sent on the wire.
80+ ///
81+ /// Example: `ServeError::not_found_ctx("subscribe_id=123 not in map")`
82+ #[ track_caller]
83+ pub fn not_found_ctx ( internal_context : impl Into < String > ) -> Self {
84+ let context = internal_context. into ( ) ;
85+ let id = uuid:: Uuid :: new_v4 ( ) ;
86+ let loc = std:: panic:: Location :: caller ( ) ;
87+ log:: warn!(
88+ "[{}] Not found: {} at {}:{}" ,
89+ id,
90+ context,
91+ loc. file( ) ,
92+ loc. line( )
93+ ) ;
94+ Self :: NotFoundWithId ( "Track not found" . to_string ( ) , id)
95+ }
96+
97+ /// Create NotFound error with full control over internal and external messages.
98+ /// The internal context is logged, and the external message is sent on the wire.
99+ ///
100+ /// Example: `ServeError::not_found_full("subscribe_id=123 not in map", "Subscription expired")`
101+ #[ track_caller]
102+ pub fn not_found_full (
103+ internal_context : impl Into < String > ,
104+ external_message : impl Into < String > ,
105+ ) -> Self {
106+ let context = internal_context. into ( ) ;
107+ let message = external_message. into ( ) ;
108+ let id = uuid:: Uuid :: new_v4 ( ) ;
109+ let loc = std:: panic:: Location :: caller ( ) ;
110+ log:: warn!(
111+ "[{}] Not found: {} at {}:{}" ,
112+ id,
113+ context,
114+ loc. file( ) ,
115+ loc. line( )
116+ ) ;
117+ Self :: NotFoundWithId ( message, id)
118+ }
119+
120+ /// Create Internal error with correlation ID and internal context.
121+ /// The internal context is logged but a generic message is sent on the wire.
122+ ///
123+ /// Example: `ServeError::internal_ctx("subscriber map in bad state")`
124+ #[ track_caller]
125+ pub fn internal_ctx ( internal_context : impl Into < String > ) -> Self {
126+ let context = internal_context. into ( ) ;
127+ let id = uuid:: Uuid :: new_v4 ( ) ;
128+ let loc = std:: panic:: Location :: caller ( ) ;
129+ log:: error!(
130+ "[{}] Internal error: {} at {}:{}" ,
131+ id,
132+ context,
133+ loc. file( ) ,
134+ loc. line( )
135+ ) ;
136+ Self :: InternalWithId ( "Internal error" . to_string ( ) , id)
137+ }
138+
139+ /// Create NotImplemented error with correlation ID and feature context.
140+ /// The feature name is logged but a generic message is sent on the wire.
141+ ///
142+ /// Example: `ServeError::not_implemented_ctx("datagrams")`
143+ #[ track_caller]
144+ pub fn not_implemented_ctx ( feature : impl Into < String > ) -> Self {
145+ let feature = feature. into ( ) ;
146+ let id = uuid:: Uuid :: new_v4 ( ) ;
147+ let loc = std:: panic:: Location :: caller ( ) ;
148+ log:: warn!(
149+ "[{}] Not implemented: {} at {}:{}" ,
150+ id,
151+ feature,
152+ loc. file( ) ,
153+ loc. line( )
154+ ) ;
155+ Self :: NotImplementedWithId ( "Feature not implemented" . to_string ( ) , id)
156+ }
56157}
0 commit comments