Files
herolib/lib/clients/runpod/utils.v
Mahmoud Emad 7486d561ec feat: update runpod example and client
- Update the RunPod example to use a new API key and
- reduce resource allocation for pods.
- Added stop pod functionality to the RunPod client and example.
- Updated the RunPod client to use new API endpoints.
- Updated the base URL for the RunPod client.
- Added authorization header to HTTP client.

Co-authored-by: mariobassem12 <mariobassem12@gmail.com>
2025-01-21 15:54:48 +02:00

201 lines
4.5 KiB
V

module runpod
import freeflowuniverse.herolib.core.httpconnection
import json
// Represents the main structure for interacting with the RunPod API.
// Provides utilities to manage HTTP connections and perform GraphQL queries.
fn (mut rp RunPod) httpclient() !&httpconnection.HTTPConnection {
mut http_conn := httpconnection.new(
name: 'runpod_vclient_${rp.name}'
url: rp.base_url
cache: true
retry: 3
)!
http_conn.default_header.add(.authorization, 'Bearer ${rp.api_key}')
return http_conn
}
// Retrieves the field name from the `FieldData` struct, either from its attributes or its name.
fn get_field_name(field FieldData) string {
mut field_name := ''
if field.attrs.len > 0 {
for attr in field.attrs {
attrs := attr.trim_space().split(':')
if attrs.len == 2 && attrs[0] == 'json' {
field_name = attrs[1].trim_space()
continue
}
}
} else {
field_name = field.name
}
return field_name
}
// Constructs JSON-like request fields from a struct.
fn get_request_fields[T](struct_ T) string {
mut body_ := '{ '
mut fields := []string{}
$for field in T.fields {
mut string_ := ''
omit := 'omitempty' in field.attrs
mut empty_string := false
$if field.typ is string {
empty_string = struct_.$(field.name) == ''
}
if !omit || !empty_string {
string_ += get_field_name(field)
string_ += ': '
$if field.is_enum {
string_ += struct_.$(field.name).to_string()
} $else $if field.typ is string {
item := struct_.$(field.name)
string_ += "\"${item}\""
} $else $if field.is_array {
string_ += '['
for i in struct_.$(field.name) {
string_ += get_request_fields(i)
}
string_ += ']'
} $else $if field.is_struct {
string_ += get_request_fields(struct_.$(field.name))
} $else {
item := struct_.$(field.name)
string_ += '${item}'
}
fields << string_
}
}
body_ += fields.join(', ')
body_ += ' }'
return body_
}
// Constructs JSON-like response fields for a given struct.
fn get_response_fields[R](struct_ R) string {
mut body_ := '{ '
$for field in R.fields {
$if field.is_struct {
// Recursively process nested structs
body_ += '${field.name} '
body_ += get_response_fields(struct_.$(field.name))
} $else {
body_ += get_field_name(field)
body_ += ' '
}
}
body_ += ' }'
return body_
}
// Enum representing the type of GraphQL operation.
pub enum QueryType {
query
mutation
}
// Struct for building GraphQL queries with request and response models.
@[params]
pub struct BuildQueryArgs[T, R] {
pub:
query_type QueryType // query or mutation
method_name string
request_model T @[required]
response_model R @[required]
}
// Builds a GraphQL query or mutation string from provided arguments.
fn build_query[T, R](args BuildQueryArgs[T, R]) string {
mut request_fields := T{}
mut response_fields := R{}
if args.request_model {
request_fields = get_request_fields(args.request_model)
}
if args.response_model {
response_fields = get_response_fields(args.response_model)
}
mut query := ''
if args.request_model && args.response_model{
query := '${args.query_type.to_string()} { ${args.method_name}(input: ${request_fields}) ${response_fields} }'
}
if args.response_model && !args.request_model{
query := '${args.query_type.to_string()} { ${response_fields} }'
}
// Wrap in the final structure
gql := GqlQuery{
query: query
}
// Return the final GraphQL query as a JSON string
return json.encode(gql)
}
// Converts the `QueryType` enum to its string representation.
fn (q QueryType) to_string() string {
return match q {
.query {
'query'
}
.mutation {
'mutation'
}
}
}
// Enum representing HTTP methods.
enum HTTPMethod {
get
post
put
delete
}
// Sends an HTTP request to the RunPod API with the specified method, path, and data.
fn (mut rp RunPod) make_request[T](method HTTPMethod, path string, data string) !T {
mut request := httpconnection.Request{
prefix: path
data: data
debug: true
dataformat: .json
}
mut http := rp.httpclient()!
mut response := T{}
match method {
.get {
request.method = .get
response = http.get_json_generic[T](request)!
}
.post {
request.method = .post
response = http.post_json_generic[T](request)!
}
.put {
request.method = .put
response = http.put_json_generic[T](request)!
}
.delete {
request.method = .delete
response = http.delete_json_generic[T](request)!
}
}
if response.errors.len > 0 {
return error('Error while sending the request due to: ${response.errors[0]['message']}')
}
return response
}