-
-
Notifications
You must be signed in to change notification settings - Fork 116
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[udp] make response message cache configurable #590
base: master
Are you sure you want to change the base?
Conversation
WalkthroughThe changes introduce a new caching mechanism for CoAP messages in the Changes
Poem
📜 Recent review detailsConfiguration used: CodeRabbit UI 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media? 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
c447896
to
b1f7350
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// getResponseFromCache gets a message from the response message cache. | ||
func (cc *Conn) getResponseFromCache(mid int32, resp *pool.Message) (bool, error) { | ||
return cc.responseMsgCache.Load(strconv.Itoa(int(mid)), resp) | ||
} | ||
|
||
// addResponseToCache adds a message to the response message cache. | ||
func (cc *Conn) addResponseToCache(resp *pool.Message) error { | ||
marshaledResp, err := resp.MarshalWithEncoder(coder.DefaultCoder) | ||
if err != nil { | ||
return err | ||
} | ||
cacheMsg := make([]byte, len(marshaledResp)) | ||
copy(cacheMsg, marshaledResp) | ||
cc.responseMsgCache.LoadOrStore(cc.responseMsgCacheID(resp.MessageID()), cache.NewElement(cacheMsg, time.Now().Add(ExchangeLifetime), nil)) | ||
return nil | ||
} | ||
|
||
func (cc *Conn) getResponseFromCache(mid int32, resp *pool.Message) (bool, error) { | ||
cachedResp := cc.responseMsgCache.Load(cc.responseMsgCacheID(mid)) | ||
if cachedResp == nil { | ||
return false, nil | ||
} | ||
if rawMsg := cachedResp.Data(); len(rawMsg) > 0 { | ||
_, err := resp.UnmarshalWithDecoder(coder.DefaultCoder, rawMsg) | ||
if err != nil { | ||
return false, err | ||
} | ||
return true, nil | ||
} | ||
return false, nil | ||
return cc.responseMsgCache.Store(strconv.Itoa(int(resp.MessageID())), resp) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Potential cache key collision due to Message ID reuse across different remote addresses
Using only the Message ID (MID) as the cache key may lead to collisions when the same MID is used by different remote endpoints. According to the CoAP specification, MIDs are unique per endpoint but can be reused over time and across different clients. To prevent cache key collisions and ensure correct message handling, consider incorporating the remote address (e.g., IP address and port) into the cache key.
Apply this diff to modify the cache key to include the remote address:
func (cc *Conn) getResponseFromCache(mid int32, resp *pool.Message) (bool, error) {
+ key := cc.RemoteAddr().String() + ":" + strconv.Itoa(int(mid))
- return cc.responseMsgCache.Load(strconv.Itoa(int(mid)), resp)
+ return cc.responseMsgCache.Load(key, resp)
}
func (cc *Conn) addResponseToCache(resp *pool.Message) error {
+ key := cc.RemoteAddr().String() + ":" + strconv.Itoa(int(resp.MessageID()))
- return cc.responseMsgCache.Store(strconv.Itoa(int(resp.MessageID())), resp)
+ return cc.responseMsgCache.Store(key, resp)
}
You'll also need to update calls to these functions to ensure the remote address is available when constructing the cache key.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
// getResponseFromCache gets a message from the response message cache. | |
func (cc *Conn) getResponseFromCache(mid int32, resp *pool.Message) (bool, error) { | |
return cc.responseMsgCache.Load(strconv.Itoa(int(mid)), resp) | |
} | |
// addResponseToCache adds a message to the response message cache. | |
func (cc *Conn) addResponseToCache(resp *pool.Message) error { | |
marshaledResp, err := resp.MarshalWithEncoder(coder.DefaultCoder) | |
if err != nil { | |
return err | |
} | |
cacheMsg := make([]byte, len(marshaledResp)) | |
copy(cacheMsg, marshaledResp) | |
cc.responseMsgCache.LoadOrStore(cc.responseMsgCacheID(resp.MessageID()), cache.NewElement(cacheMsg, time.Now().Add(ExchangeLifetime), nil)) | |
return nil | |
} | |
func (cc *Conn) getResponseFromCache(mid int32, resp *pool.Message) (bool, error) { | |
cachedResp := cc.responseMsgCache.Load(cc.responseMsgCacheID(mid)) | |
if cachedResp == nil { | |
return false, nil | |
} | |
if rawMsg := cachedResp.Data(); len(rawMsg) > 0 { | |
_, err := resp.UnmarshalWithDecoder(coder.DefaultCoder, rawMsg) | |
if err != nil { | |
return false, err | |
} | |
return true, nil | |
} | |
return false, nil | |
return cc.responseMsgCache.Store(strconv.Itoa(int(resp.MessageID())), resp) | |
// getResponseFromCache gets a message from the response message cache. | |
func (cc *Conn) getResponseFromCache(mid int32, resp *pool.Message) (bool, error) { | |
key := cc.RemoteAddr().String() + ":" + strconv.Itoa(int(mid)) | |
return cc.responseMsgCache.Load(key, resp) | |
} | |
// addResponseToCache adds a message to the response message cache. | |
func (cc *Conn) addResponseToCache(resp *pool.Message) error { | |
key := cc.RemoteAddr().String() + ":" + strconv.Itoa(int(resp.MessageID())) | |
return cc.responseMsgCache.Store(key, resp) | |
} |
Modifies UDP conn implementation to allow for a custom response message cache to be provided. This change is implemented in such a way that API compatibility with previous v3 releases is preserved. Users may now provide an option to supply their own cache implementation. Structured messages, rather than their serialized representation, are now passed to the cache implementation to allow for caching decisions to be made in the cache implementation. For example, it may be desirable to skip caching blockwise message responses if the entire underlying data being transferred is also cached. The cache implementation is responsible for cloning messages or otherwise ensuring that it is not storing data that may subsequently be modified. Signed-off-by: Daniel Mangum <[email protected]>
b1f7350
to
b80b7a8
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@jkralik any thoughts here? 🙂
Modifies UDP conn implementation to allow for a custom response message cache to be provided. This change is implemented in such a way that API compatibility with previous v3 releases is preserved. Users may now provide an option to supply their own cache implementation. Structured messages, rather than their serialized representation, are now passed to the cache implementation to allow for caching decisions to be made in the cache implementation. For example, it may be desirable to skip caching blockwise message responses if the entire underlying data being transferred is also cached. The cache implementation is responsible for cloning messages or otherwise ensuring that it is not storing data that may subsequently be modified.
Replaces #589
Summary by CodeRabbit
New Features
Improvements