Skip to content

Commit 84eee51

Browse files
authored
Merge pull request #39 from linuxfoundation/andrest50/indexer-message
[LFXV2-968] Integrate indexer-service types for NATS messaging
2 parents d830254 + 34d2ad2 commit 84eee51

File tree

14 files changed

+289
-361
lines changed

14 files changed

+289
-361
lines changed

README.md

Lines changed: 6 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -47,45 +47,21 @@ This service publishes the following NATS events:
4747

4848
### Project Tags
4949

50-
The LFX v2 Project Service generates a set of tags for projects and project settings that are sent to the indexer-service. These tags enable searchability and discoverability of projects through OpenSearch.
50+
The LFX v2 Project Service generates tags for projects that are sent to the indexer-service.
5151

5252
#### Tags Generated for Projects
5353

54-
When projects are created or updated, the following tags are automatically generated:
54+
When projects are created or updated, the following tag is generated:
5555

5656
| Project Field | Tag Format | Example | Purpose |
5757
|--------------|-----------|---------|---------|
58-
| UID | Plain value | `f1545930-b9b7-420d-942b-eb53c1a63428` | Direct lookup by ID |
59-
| UID | `project_uid:<value>` | `project_uid:f1545930-b9b7-420d-942b-eb53c1a63428` | Namespaced lookup by ID |
60-
| ParentUID | `parent_uid:<value>` | `parent_uid:efc80205-b0b3-4943-9395-2b634985a142` | Find child projects of a parent |
61-
| Slug | Plain value | `test-project-tags-indexed` | Direct lookup by slug |
62-
| Slug | `project_slug:<value>` | `project_slug:test-project-tags-indexed` | Namespaced lookup by slug |
63-
| Name | Plain value | `Updated Foo Foundation` | Text search by project name |
64-
| Description | Plain value | `Updated description for tag testing` | Full-text search in descriptions |
58+
| Slug | `project_slug:<value>` | `project_slug:test-project` | Namespaced lookup by slug |
6559

66-
#### Tags Generated for Project Settings
67-
68-
Project settings generate a separate set of tags:
69-
70-
| Settings Field | Tag Format | Example | Purpose |
71-
|---------------|-----------|---------|---------|
72-
| UID | Plain value | `f1545930-b9b7-420d-942b-eb53c1a63428` | Direct lookup by ID |
73-
| UID | `project_uid:<value>` | `project_uid:f1545930-b9b7-420d-942b-eb53c1a63428` | Namespaced lookup by ID |
74-
| MissionStatement | Plain value | `Updated mission statement for testing tags` | Full-text search in mission statements |
75-
76-
#### How Tags Are Used
60+
**Note**: Additional project metadata (UID, ParentUID, Name, Description, etc.) is sent via the `IndexingConfig` field.
7761

78-
Tags serve multiple important purposes in the LFX system:
79-
80-
1. **Indexed Search**: Tags are indexed in OpenSearch, enabling fast lookups and text searches across projects
81-
82-
2. **Relationship Navigation**: Parent-child relationships can be traversed using the parent_uid tags
83-
84-
3. **Multiple Access Patterns**: Both plain value and prefixed tags support different query patterns:
85-
- Plain values support general text search (e.g., "find projects containing 'foo'")
86-
- Prefixed values support field-specific search (e.g., "find projects with slug 'test-project'")
62+
#### Tags Generated for Project Settings
8763

88-
4. **Data Synchronization**: When projects or settings are updated, their tags are automatically updated, ensuring search results remain current
64+
Project settings generate no tags. All metadata is sent via the `IndexingConfig` field.
8965

9066
## Quick Start
9167

charts/lfx-v2-project-service/Chart.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,5 @@ apiVersion: v2
55
name: lfx-v2-project-service
66
description: LFX Platform V2 Project Service chart
77
type: application
8-
version: 0.5.4
8+
version: 0.5.5
99
appVersion: "latest"

cmd/project-api/service_endpoint_project_test.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -153,9 +153,8 @@ func TestCreateProject(t *testing.T) {
153153
// Mock successful project creation
154154
mockRepo.On("CreateProject", mock.Anything, mock.AnythingOfType("*models.ProjectBase"), mock.AnythingOfType("*models.ProjectSettings")).Return(nil)
155155
// Mock message sending
156-
mockMsg.On("SendIndexerMessage", mock.Anything, mock.AnythingOfType("string"), mock.AnythingOfType("models.ProjectIndexerMessage"), mock.AnythingOfType("bool")).Return(nil)
156+
mockMsg.On("SendIndexerMessage", mock.Anything, mock.AnythingOfType("string"), mock.AnythingOfType("types.IndexerMessageEnvelope"), mock.AnythingOfType("bool")).Return(nil).Times(2)
157157
mockMsg.On("SendAccessMessage", mock.Anything, mock.AnythingOfType("string"), mock.AnythingOfType("models.ProjectAccessMessage"), mock.AnythingOfType("bool")).Return(nil)
158-
mockMsg.On("SendIndexerMessage", mock.Anything, mock.AnythingOfType("string"), mock.AnythingOfType("models.ProjectSettingsIndexerMessage"), mock.AnythingOfType("bool")).Return(nil)
159158
},
160159
expectedError: false,
161160
},

go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ require (
1111
github.com/aws/aws-sdk-go-v2/service/s3 v1.92.0
1212
github.com/go-viper/mapstructure/v2 v2.4.0
1313
github.com/google/uuid v1.6.0
14+
github.com/linuxfoundation/lfx-v2-indexer-service v0.4.14-0.20260109191409-7371e293d8b5
1415
github.com/nats-io/nats.go v1.47.0
1516
github.com/rustyoz/svg v0.0.0-20250705135709-8b1786137cb3
1617
github.com/stretchr/testify v1.11.1

go.sum

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,10 @@ github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aN
6262
github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
6363
github.com/klauspost/compress v1.18.1 h1:bcSGx7UbpBqMChDtsF28Lw6v/G94LPrrbMbdC3JH2co=
6464
github.com/klauspost/compress v1.18.1/go.mod h1:ZQFFVG+MdnR0P+l6wpXgIL4NTtwiKIdBnrBd8Nrxr+0=
65+
github.com/linuxfoundation/lfx-v2-indexer-service v0.4.13 h1:SANx5u+qJ+1DkMadpSDhPYJgPgnHDBPxw9Am6LC5pjk=
66+
github.com/linuxfoundation/lfx-v2-indexer-service v0.4.13/go.mod h1:j013GdKST/hMWFhciRuzJd0sy764sNtlmO3gqmsnaCA=
67+
github.com/linuxfoundation/lfx-v2-indexer-service v0.4.14-0.20260109191409-7371e293d8b5 h1:Ic06r/3OO4wP2Y2eL9InXEKRSVq2cqbNGBTsdr493YA=
68+
github.com/linuxfoundation/lfx-v2-indexer-service v0.4.14-0.20260109191409-7371e293d8b5/go.mod h1:j013GdKST/hMWFhciRuzJd0sy764sNtlmO3gqmsnaCA=
6569
github.com/manveru/faker v0.0.0-20171103152722-9fbc68a78c4d h1:Zj+PHjnhRYWBK6RqCDBcAhLXoi3TzC27Zad/Vn+gnVQ=
6670
github.com/manveru/faker v0.0.0-20171103152722-9fbc68a78c4d/go.mod h1:WZy8Q5coAB1zhY9AOBJP0O6J4BuDfbupUDavKY+I3+s=
6771
github.com/manveru/gobdd v0.0.0-20131210092515-f1a17fdd710b h1:3E44bLeN8uKYdfQqVQycPnaVviZdBLbizFhU49mtbe4=

internal/domain/models/message.go

Lines changed: 0 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -3,41 +3,6 @@
33

44
package models
55

6-
// MessageAction is a type for the action of a project message.
7-
type MessageAction string
8-
9-
// MessageAction constants for the action of a project message.
10-
const (
11-
// ActionCreated is the action for a resource creation message.
12-
ActionCreated MessageAction = "created"
13-
// ActionUpdated is the action for a resource update message.
14-
ActionUpdated MessageAction = "updated"
15-
// ActionDeleted is the action for a resource deletion message.
16-
ActionDeleted MessageAction = "deleted"
17-
)
18-
19-
// ProjectIndexerMessage is a type-safe NATS message for project indexing operations.
20-
type ProjectIndexerMessage struct {
21-
Action MessageAction `json:"action"`
22-
Data ProjectBase `json:"data"`
23-
Tags []string `json:"tags"`
24-
}
25-
26-
// ProjectSettingsIndexerMessage is a type-safe NATS message for project settings indexing operations.
27-
type ProjectSettingsIndexerMessage struct {
28-
Action MessageAction `json:"action"`
29-
Data ProjectSettings `json:"data"`
30-
Tags []string `json:"tags"`
31-
}
32-
33-
// IndexerMessageEnvelope is the actual message format sent to NATS for indexing operations.
34-
type IndexerMessageEnvelope struct {
35-
Action MessageAction `json:"action"`
36-
Headers map[string]string `json:"headers"`
37-
Data any `json:"data"`
38-
Tags []string `json:"tags"`
39-
}
40-
416
// ProjectAccessData is the schema for the data in the message sent to the fga-sync service.
427
// These are the fields that the fga-sync service needs in order to update the OpenFGA permissions.
438
type ProjectAccessData struct {

internal/domain/models/message_test.go

Lines changed: 0 additions & 155 deletions
Original file line numberDiff line numberDiff line change
@@ -9,116 +9,6 @@ import (
99
"github.com/stretchr/testify/assert"
1010
)
1111

12-
func TestMessageActionConstants(t *testing.T) {
13-
tests := []struct {
14-
name string
15-
action MessageAction
16-
expected string
17-
}{
18-
{
19-
name: "action created",
20-
action: ActionCreated,
21-
expected: "created",
22-
},
23-
{
24-
name: "action updated",
25-
action: ActionUpdated,
26-
expected: "updated",
27-
},
28-
{
29-
name: "action deleted",
30-
action: ActionDeleted,
31-
expected: "deleted",
32-
},
33-
}
34-
35-
for _, tt := range tests {
36-
t.Run(tt.name, func(t *testing.T) {
37-
assert.Equal(t, tt.expected, string(tt.action))
38-
})
39-
}
40-
}
41-
42-
func TestProjectIndexerMessage(t *testing.T) {
43-
tests := []struct {
44-
name string
45-
message ProjectIndexerMessage
46-
verify func(t *testing.T, msg ProjectIndexerMessage)
47-
}{
48-
{
49-
name: "project indexer message with all fields",
50-
message: ProjectIndexerMessage{
51-
Action: ActionCreated,
52-
Data: ProjectBase{
53-
UID: "project-123",
54-
Slug: "test-project",
55-
Name: "Test Project",
56-
},
57-
Tags: []string{"project-123", "test-project", "Test Project"},
58-
},
59-
verify: func(t *testing.T, msg ProjectIndexerMessage) {
60-
assert.Equal(t, ActionCreated, msg.Action)
61-
assert.Equal(t, "project-123", msg.Data.UID)
62-
assert.Equal(t, "test-project", msg.Data.Slug)
63-
assert.Equal(t, "Test Project", msg.Data.Name)
64-
assert.Len(t, msg.Tags, 3)
65-
},
66-
},
67-
{
68-
name: "project indexer message with minimal fields",
69-
message: ProjectIndexerMessage{
70-
Action: ActionDeleted,
71-
Data: ProjectBase{
72-
UID: "project-456",
73-
},
74-
},
75-
verify: func(t *testing.T, msg ProjectIndexerMessage) {
76-
assert.Equal(t, ActionDeleted, msg.Action)
77-
assert.Equal(t, "project-456", msg.Data.UID)
78-
assert.Empty(t, msg.Tags)
79-
},
80-
},
81-
}
82-
83-
for _, tt := range tests {
84-
t.Run(tt.name, func(t *testing.T) {
85-
tt.verify(t, tt.message)
86-
})
87-
}
88-
}
89-
90-
func TestProjectSettingsIndexerMessage(t *testing.T) {
91-
tests := []struct {
92-
name string
93-
message ProjectSettingsIndexerMessage
94-
verify func(t *testing.T, msg ProjectSettingsIndexerMessage)
95-
}{
96-
{
97-
name: "project settings indexer message with all fields",
98-
message: ProjectSettingsIndexerMessage{
99-
Action: ActionUpdated,
100-
Data: ProjectSettings{
101-
UID: "settings-123",
102-
MissionStatement: "Our mission",
103-
},
104-
Tags: []string{"settings-123", "Our mission"},
105-
},
106-
verify: func(t *testing.T, msg ProjectSettingsIndexerMessage) {
107-
assert.Equal(t, ActionUpdated, msg.Action)
108-
assert.Equal(t, "settings-123", msg.Data.UID)
109-
assert.Equal(t, "Our mission", msg.Data.MissionStatement)
110-
assert.Len(t, msg.Tags, 2)
111-
},
112-
},
113-
}
114-
115-
for _, tt := range tests {
116-
t.Run(tt.name, func(t *testing.T) {
117-
tt.verify(t, tt.message)
118-
})
119-
}
120-
}
121-
12212
func TestProjectAccessMessage(t *testing.T) {
12313
tests := []struct {
12414
name string
@@ -154,48 +44,3 @@ func TestProjectAccessMessage(t *testing.T) {
15444
})
15545
}
15646
}
157-
158-
func TestIndexerMessageEnvelope(t *testing.T) {
159-
tests := []struct {
160-
name string
161-
message IndexerMessageEnvelope
162-
verify func(t *testing.T, msg IndexerMessageEnvelope)
163-
}{
164-
{
165-
name: "indexer message envelope with all fields",
166-
message: IndexerMessageEnvelope{
167-
Action: ActionCreated,
168-
Headers: map[string]string{
169-
"request-id": "test-request-123",
170-
"user-id": "user-456",
171-
},
172-
Data: map[string]interface{}{
173-
"uid": "project-123",
174-
"slug": "test-project",
175-
"name": "Test Project",
176-
},
177-
Tags: []string{"project-123", "test-project"},
178-
},
179-
verify: func(t *testing.T, msg IndexerMessageEnvelope) {
180-
assert.Equal(t, ActionCreated, msg.Action)
181-
assert.Equal(t, "test-request-123", msg.Headers["request-id"])
182-
assert.Equal(t, "user-456", msg.Headers["user-id"])
183-
assert.NotNil(t, msg.Data)
184-
assert.Len(t, msg.Tags, 2)
185-
186-
// Verify data can be type asserted
187-
data, ok := msg.Data.(map[string]interface{})
188-
assert.True(t, ok)
189-
assert.Equal(t, "project-123", data["uid"])
190-
assert.Equal(t, "test-project", data["slug"])
191-
assert.Equal(t, "Test Project", data["name"])
192-
},
193-
},
194-
}
195-
196-
for _, tt := range tests {
197-
t.Run(tt.name, func(t *testing.T) {
198-
tt.verify(t, tt.message)
199-
})
200-
}
201-
}

0 commit comments

Comments
 (0)