mirror of
https://github.com/gogrlx/nats-server.git
synced 2026-04-17 11:24:44 -07:00
Allow stream lookup by subject.
Allow an API endpoint and public API to lookup a stream by subject. The subject needs to be an exact match or a subset. If the subject is considered a filtered subject for the stream that will also be returned. Signed-off-by: Derek Collison <derek@nats.io>
This commit is contained in:
@@ -75,6 +75,10 @@ const (
|
||||
JSApiStreamInfo = "$JS.API.STREAM.INFO.*"
|
||||
JSApiStreamInfoT = "$JS.API.STREAM.INFO.%s"
|
||||
|
||||
// JSApiStreamLookup is for obtaining a stream by a target subject.
|
||||
// Will return JSON response.
|
||||
JSApiStreamLookup = "$JS.API.STREAM.LOOKUP"
|
||||
|
||||
// JSApiStreamDelete is the endpoint to delete streams.
|
||||
// Will return JSON response.
|
||||
JSApiStreamDelete = "$JS.API.STREAM.DELETE.*"
|
||||
@@ -112,7 +116,7 @@ const (
|
||||
JSApiConsumerCreate = "$JS.API.CONSUMER.CREATE.*"
|
||||
JSApiConsumerCreateT = "$JS.API.CONSUMER.CREATE.%s"
|
||||
|
||||
// JSApiDurableCreate is the endpoint to create ephemeral consumers for streams.
|
||||
// JSApiDurableCreate is the endpoint to create durable consumers for streams.
|
||||
// You need to include the stream and consumer name in the subject.
|
||||
JSApiDurableCreate = "$JS.API.CONSUMER.DURABLE.CREATE.*.*"
|
||||
JSApiDurableCreateT = "$JS.API.CONSUMER.DURABLE.CREATE.%s.%s"
|
||||
@@ -262,6 +266,15 @@ type JSApiStreamInfoResponse struct {
|
||||
|
||||
const JSApiStreamInfoResponseType = "io.nats.jetstream.api.v1.stream_info_response"
|
||||
|
||||
// JSApiStreamLookupResponse.
|
||||
type JSApiStreamLookupResponse struct {
|
||||
ApiResponse
|
||||
Stream string `json:"stream"`
|
||||
Filtered bool `json:"is_filtered"`
|
||||
}
|
||||
|
||||
const JSApiStreamLookupResponseType = "io.nats.jetstream.api.v1.stream_lookup_response"
|
||||
|
||||
// Maximum entries we will return for streams or consumers lists.
|
||||
// TODO(dlc) - with header or request support could request chunked response.
|
||||
const JSApiNamesLimit = 1024
|
||||
@@ -480,6 +493,7 @@ var allJsExports = []string{
|
||||
JSApiStreams,
|
||||
JSApiStreamList,
|
||||
JSApiStreamInfo,
|
||||
JSApiStreamLookup,
|
||||
JSApiStreamDelete,
|
||||
JSApiStreamPurge,
|
||||
JSApiStreamSnapshot,
|
||||
@@ -509,6 +523,7 @@ func (s *Server) setJetStreamExportSubs() error {
|
||||
{JSApiStreams, s.jsStreamNamesRequest},
|
||||
{JSApiStreamList, s.jsStreamListRequest},
|
||||
{JSApiStreamInfo, s.jsStreamInfoRequest},
|
||||
{JSApiStreamLookup, s.jsStreamLookupRequest},
|
||||
{JSApiStreamDelete, s.jsStreamDeleteRequest},
|
||||
{JSApiStreamPurge, s.jsStreamPurgeRequest},
|
||||
{JSApiStreamSnapshot, s.jsStreamSnapshotRequest},
|
||||
@@ -953,6 +968,44 @@ func (s *Server) jsStreamInfoRequest(sub *subscription, c *client, subject, repl
|
||||
s.sendAPIResponse(c, subject, reply, string(msg), s.jsonResponse(resp))
|
||||
}
|
||||
|
||||
// Request to lookup a stream by target subject.
|
||||
func (s *Server) jsStreamLookupRequest(sub *subscription, c *client, subject, reply string, msg []byte) {
|
||||
if c == nil || c.acc == nil {
|
||||
return
|
||||
}
|
||||
|
||||
var resp = JSApiStreamLookupResponse{ApiResponse: ApiResponse{Type: JSApiStreamLookupResponseType}}
|
||||
if !c.acc.JetStreamEnabled() {
|
||||
resp.Error = jsNotEnabledErr
|
||||
s.sendAPIResponse(c, subject, reply, string(msg), s.jsonResponse(&resp))
|
||||
return
|
||||
}
|
||||
if isEmptyRequest(msg) {
|
||||
resp.Error = &ApiError{Code: 400, Description: "subject required"}
|
||||
s.sendAPIResponse(c, subject, reply, string(msg), s.jsonResponse(&resp))
|
||||
return
|
||||
}
|
||||
subj := string(msg)
|
||||
if !IsValidSubject(subj) {
|
||||
resp.Error = &ApiError{Code: 400, Description: "subject argument is not a valid subject"}
|
||||
s.sendAPIResponse(c, subject, reply, string(msg), s.jsonResponse(&resp))
|
||||
return
|
||||
}
|
||||
|
||||
// Lookup our stream.
|
||||
mset, filtered, err := c.acc.LookupStreamBySubject(subj)
|
||||
if err != nil {
|
||||
resp.Error = jsNotFoundError(err)
|
||||
s.sendAPIResponse(c, subject, reply, string(msg), s.jsonResponse(&resp))
|
||||
return
|
||||
}
|
||||
|
||||
resp.Stream = mset.Name()
|
||||
resp.Filtered = filtered
|
||||
|
||||
s.sendAPIResponse(c, subject, reply, string(msg), s.jsonResponse(resp))
|
||||
}
|
||||
|
||||
func isEmptyRequest(req []byte) bool {
|
||||
if len(req) == 0 {
|
||||
return true
|
||||
|
||||
Reference in New Issue
Block a user