Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/six-books-drum.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"chainlink-deployments-framework": minor
---

JD Memory Client now supports filtering in `ListJobs`
102 changes: 102 additions & 0 deletions offchain/jd/memory/job_filter.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
package memory

import (
"slices"

jobv1 "github.com/smartcontractkit/chainlink-protos/job-distributor/v1/job"
"github.com/smartcontractkit/chainlink-protos/job-distributor/v1/shared/ptypes"
)

// applyJobFilter applies the filter to the list of jobs and returns the filtered results.
func applyJobFilter(
jobs []*jobv1.Job, filter *jobv1.ListJobsRequest_Filter,
) []*jobv1.Job {
var filtered []*jobv1.Job

for _, job := range jobs {
if jobMatchesFilter(job, filter) {
filtered = append(filtered, job)
}
}

return filtered
}

// jobMatchesFilter checks if a job matches the given filter criteria.
func jobMatchesFilter(job *jobv1.Job, filter *jobv1.ListJobsRequest_Filter) bool {
// Check if job is soft-deleted and should be excluded
if !jobMatchesDeletedFilter(job, filter) {
return false
}

// Check job IDs
if len(filter.Ids) > 0 {
if !jobMatchesJobIds(job, filter.Ids) {
return false
}
}

// Check UUIDs
if len(filter.Uuids) > 0 {
if !jobMatchesUuids(job, filter.Uuids) {
return false
}
}

// Check node IDs
if len(filter.NodeIds) > 0 {
if !jobMatchesNodeIds(job, filter.NodeIds) {
return false
}
}

// Check selectors
if len(filter.Selectors) > 0 {
for _, selector := range filter.Selectors {
if !jobMatchesSelector(job, selector) {
return false
}
}
}

return true
}

// jobMatchesJobIds checks if a job's ID is in the provided list of job IDs.
func jobMatchesJobIds(job *jobv1.Job, jobIds []string) bool {
return slices.Contains(jobIds, job.Id)
}

// jobMatchesUuids checks if a job's UUID is in the provided list of UUIDs.
func jobMatchesUuids(job *jobv1.Job, uuids []string) bool {
return slices.Contains(uuids, job.Uuid)
}

// jobMatchesNodeIds checks if a job's node ID is in the provided list of node IDs.
func jobMatchesNodeIds(job *jobv1.Job, nodeIds []string) bool {
return slices.Contains(nodeIds, job.NodeId)
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could these 3 function be a general jobMatches function since they have the same signature and perform the same check?

eg

func jobMatches(target string, filter []string) bool {
	return slices.Contains(filter, target)
}

// jobMatchesDeletedFilter checks if a job should be included based on its deleted status.
// By default, soft-deleted jobs (with DeletedAt set) are excluded unless IncludeDeleted is true.
func jobMatchesDeletedFilter(job *jobv1.Job, filter *jobv1.ListJobsRequest_Filter) bool {
// If job is soft-deleted (DeletedAt is not nil)
if job.DeletedAt != nil {
// Only include if IncludeDeleted is explicitly set to true
return filter.IncludeDeleted
}

// If job is not soft-deleted, always include it
return true
}

// jobMatchesSelector checks if a job matches a specific selector.
func jobMatchesSelector(job *jobv1.Job, selector *ptypes.Selector) bool {
// Get the job's labels as a map for easier lookup
jobLabels := make(map[string]*string)
for _, label := range job.Labels {
jobLabels[label.Key] = label.Value
}

return matchesSelector(jobLabels, selector)
}
Loading
Loading