Skip to content

Commit 4e3bc74

Browse files
authored
Merge pull request #10 from joshjms/add-client-library
client: Add client library
2 parents 6197c30 + d4a5e63 commit 4e3bc74

9 files changed

Lines changed: 1558 additions & 0 deletions

File tree

client/README.md

Lines changed: 414 additions & 0 deletions
Large diffs are not rendered by default.

client/builder.go

Lines changed: 187 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,187 @@
1+
package client
2+
3+
// RequestBuilder provides a fluent API for building execution requests.
4+
type RequestBuilder struct {
5+
req *ExecRequest
6+
}
7+
8+
// NewRequest creates a new RequestBuilder.
9+
func NewRequest() *RequestBuilder {
10+
return &RequestBuilder{
11+
req: &ExecRequest{
12+
Files: []File{},
13+
Steps: []Process{},
14+
},
15+
}
16+
}
17+
18+
// WithID sets the job ID for the request.
19+
func (b *RequestBuilder) WithID(id string) *RequestBuilder {
20+
b.req.ID = id
21+
return b
22+
}
23+
24+
// AddFile adds a file to the request.
25+
func (b *RequestBuilder) AddFile(name, content string) *RequestBuilder {
26+
b.req.Files = append(b.req.Files, File{
27+
Name: name,
28+
Content: content,
29+
})
30+
return b
31+
}
32+
33+
// AddStep adds a process/step to the request using a ProcessBuilder.
34+
func (b *RequestBuilder) AddStep(fn func(*ProcessBuilder)) *RequestBuilder {
35+
pb := NewProcess()
36+
fn(pb)
37+
b.req.Steps = append(b.req.Steps, pb.Build())
38+
return b
39+
}
40+
41+
// Build returns the constructed ExecRequest.
42+
func (b *RequestBuilder) Build() *ExecRequest {
43+
return b.req
44+
}
45+
46+
// ProcessBuilder provides a fluent API for building process specifications.
47+
type ProcessBuilder struct {
48+
proc Process
49+
}
50+
51+
// NewProcess creates a new ProcessBuilder.
52+
func NewProcess() *ProcessBuilder {
53+
return &ProcessBuilder{
54+
proc: Process{
55+
Cmd: []string{},
56+
Files: []string{},
57+
Persist: []string{},
58+
},
59+
}
60+
}
61+
62+
// WithImage sets the container image for the process.
63+
func (p *ProcessBuilder) WithImage(image string) *ProcessBuilder {
64+
p.proc.Image = image
65+
return p
66+
}
67+
68+
// WithCommand sets the command and arguments for the process.
69+
func (p *ProcessBuilder) WithCommand(cmd ...string) *ProcessBuilder {
70+
p.proc.Cmd = cmd
71+
return p
72+
}
73+
74+
// WithStdin sets the standard input for the process.
75+
func (p *ProcessBuilder) WithStdin(stdin string) *ProcessBuilder {
76+
p.proc.Stdin = stdin
77+
return p
78+
}
79+
80+
// WithMemoryLimit sets the memory limit in megabytes.
81+
func (p *ProcessBuilder) WithMemoryLimit(mb int64) *ProcessBuilder {
82+
p.proc.MemoryLimitMB = mb
83+
return p
84+
}
85+
86+
// WithTimeLimit sets the time limit in milliseconds.
87+
func (p *ProcessBuilder) WithTimeLimit(ms uint64) *ProcessBuilder {
88+
p.proc.TimeLimitMs = ms
89+
return p
90+
}
91+
92+
// WithProcLimit sets the maximum number of processes.
93+
func (p *ProcessBuilder) WithProcLimit(limit int64) *ProcessBuilder {
94+
p.proc.ProcLimit = limit
95+
return p
96+
}
97+
98+
// WithFiles specifies which files to make available in this step.
99+
func (p *ProcessBuilder) WithFiles(files ...string) *ProcessBuilder {
100+
p.proc.Files = append(p.proc.Files, files...)
101+
return p
102+
}
103+
104+
// WithPersist specifies which files to persist to the next step.
105+
func (p *ProcessBuilder) WithPersist(files ...string) *ProcessBuilder {
106+
p.proc.Persist = append(p.proc.Persist, files...)
107+
return p
108+
}
109+
110+
// Build returns the constructed Process.
111+
func (p *ProcessBuilder) Build() Process {
112+
return p.proc
113+
}
114+
115+
// Common helper functions for building requests
116+
117+
// SimpleExecRequest creates a simple single-step execution request.
118+
// This is a convenience function for common use cases.
119+
func SimpleExecRequest(image string, cmd []string, files map[string]string) *ExecRequest {
120+
req := NewRequest()
121+
122+
// Add all files
123+
for name, content := range files {
124+
req.AddFile(name, content)
125+
}
126+
127+
// Add single step with all files
128+
fileNames := make([]string, 0, len(files))
129+
for name := range files {
130+
fileNames = append(fileNames, name)
131+
}
132+
133+
req.AddStep(func(p *ProcessBuilder) {
134+
p.WithImage(image).
135+
WithCommand(cmd...).
136+
WithFiles(fileNames...)
137+
})
138+
139+
return req.Build()
140+
}
141+
142+
// CompileAndRunRequest creates a two-step request for compile-then-run scenarios.
143+
// This is useful for compiled languages like C++, Java, etc.
144+
func CompileAndRunRequest(
145+
compileImage string,
146+
compileCmd []string,
147+
runImage string,
148+
runCmd []string,
149+
sourceFiles map[string]string,
150+
compiledOutputs []string,
151+
stdin string,
152+
) *ExecRequest {
153+
req := NewRequest()
154+
155+
// Add source files
156+
for name, content := range sourceFiles {
157+
req.AddFile(name, content)
158+
}
159+
160+
// Get source file names
161+
sourceFileNames := make([]string, 0, len(sourceFiles))
162+
for name := range sourceFiles {
163+
sourceFileNames = append(sourceFileNames, name)
164+
}
165+
166+
// Step 1: Compile
167+
req.AddStep(func(p *ProcessBuilder) {
168+
p.WithImage(compileImage).
169+
WithCommand(compileCmd...).
170+
WithFiles(sourceFileNames...).
171+
WithPersist(compiledOutputs...).
172+
WithMemoryLimit(512).
173+
WithTimeLimit(10000)
174+
})
175+
176+
// Step 2: Run
177+
req.AddStep(func(p *ProcessBuilder) {
178+
p.WithImage(runImage).
179+
WithCommand(runCmd...).
180+
WithFiles(compiledOutputs...).
181+
WithStdin(stdin).
182+
WithMemoryLimit(256).
183+
WithTimeLimit(5000)
184+
})
185+
186+
return req.Build()
187+
}

0 commit comments

Comments
 (0)