feat(api): enhance community retrieval with flexible ID handling
CI / changes (push) Successful in 6s
CI / commitlint (push) Skipped
CI / openapi (push) Skipped
CI / web (push) Skipped
CI / go (push) Successful in 1m16s
CI / bird2 (push) Successful in 14s
CI / release (push) Successful in 4m5s

Updated the GetCommunity function to accept both UUIDs and community titles for improved flexibility in community retrieval. Added error handling for invalid ID formats and adjusted related functions to ensure consistent behavior across memory and PostgreSQL storage. This change enhances the API's usability by allowing more intuitive community lookups.
This commit is contained in:
Denozordec
2026-07-23 11:30:46 +07:00
parent ff6efec4c5
commit fd3a217cbe
4 changed files with 162 additions and 18 deletions
+29 -9
View File
@@ -1237,12 +1237,32 @@ func (p *Postgres) ListCommunities(tenantID string) ([]*store.Community, error)
return out, nil
}
func (p *Postgres) GetCommunity(tenantID, id string) (*store.Community, error) {
func (p *Postgres) GetCommunity(tenantID, idOrKey string) (*store.Community, error) {
ctx := context.Background()
key := strings.TrimSpace(idOrKey)
if key == "" {
return nil, store.ErrNotFound
}
var c store.Community
c.TenantID = tenantID
err := p.pool.QueryRow(ctx, `SELECT id::text, community, title, value_json::text FROM bgp_community WHERE id=$1 AND tenant_id=$2`, id, tenantID).Scan(
&c.ID, &c.Community, &c.Title, &c.ValueJSON)
// Prefer UUID id; fall back to community / title so clients that store the
// autocomplete label (Base UI {value,label} → label) still resolve.
var err error
if _, perr := uuid.Parse(key); perr == nil {
err = p.pool.QueryRow(ctx, `SELECT id::text, community, title, value_json::text FROM bgp_community WHERE id=$1 AND tenant_id=$2`, key, tenantID).Scan(
&c.ID, &c.Community, &c.Title, &c.ValueJSON)
} else {
err = p.pool.QueryRow(ctx, `
SELECT id::text, community, title, value_json::text FROM bgp_community
WHERE tenant_id=$1 AND (
community = $2
OR title = $2
OR (NULLIF(trim(title), '') IS NOT NULL AND (community || ' · ' || title) = $2)
)
ORDER BY community
LIMIT 1`, tenantID, key).Scan(
&c.ID, &c.Community, &c.Title, &c.ValueJSON)
}
if err != nil {
if errors.Is(err, pgx.ErrNoRows) {
return nil, store.ErrNotFound
@@ -1253,9 +1273,11 @@ func (p *Postgres) GetCommunity(tenantID, id string) (*store.Community, error) {
}
func (p *Postgres) ListCommunityPrefixes(tenantID, communityID, cursor string, limit int) ([]store.PrefixRow, string, bool, error) {
if _, err := p.GetCommunity(tenantID, communityID); err != nil {
comm, err := p.GetCommunity(tenantID, communityID)
if err != nil {
return nil, "", false, err
}
resolvedID := comm.ID
if limit <= 0 {
limit = 500
}
@@ -1271,7 +1293,6 @@ func (p *Postgres) ListCommunityPrefixes(tenantID, communityID, cursor string, l
ctx := context.Background()
useSnap := prefixSnapshotTableExists(ctx, p.pool)
var rows pgx.Rows
var err error
if useSnap {
rows, err = p.pool.Query(ctx, `
WITH latest AS (
@@ -1293,7 +1314,7 @@ func (p *Postgres) ListCommunityPrefixes(tenantID, communityID, cursor string, l
)
SELECT prefix, source FROM combined
ORDER BY prefix
LIMIT $3 OFFSET $4`, tenantID, communityID, limit+1, off)
LIMIT $3 OFFSET $4`, tenantID, resolvedID, limit+1, off)
} else {
rows, err = p.pool.Query(ctx, `
WITH latest AS (
@@ -1307,20 +1328,19 @@ func (p *Postgres) ListCommunityPrefixes(tenantID, communityID, cursor string, l
JOIN latest l ON l.id = rmp.revision_id
WHERE rmp.community_id = $2::uuid
ORDER BY 1
LIMIT $3 OFFSET $4`, tenantID, communityID, limit+1, off)
LIMIT $3 OFFSET $4`, tenantID, resolvedID, limit+1, off)
}
if err != nil {
return nil, "", false, err
}
defer rows.Close()
var all []store.PrefixRow
comm := communityID
for rows.Next() {
var pr store.PrefixRow
if err := rows.Scan(&pr.Prefix, &pr.Source); err != nil {
continue
}
pr.CommunityID = &comm
pr.CommunityID = &resolvedID
all = append(all, pr)
}
more := len(all) > limit