github.com/filecoin-project/bacalhau@v0.3.23-0.20230228154132-45c989550ace/pkg/model/v1beta1/task.go (about)

     1  package v1beta1
     2  
     3  import (
     4  	"fmt"
     5  	"strings"
     6  	"time"
     7  
     8  	"github.com/c2h5oh/datasize"
     9  	"github.com/ipld/go-ipld-prime/codec/json"
    10  	"github.com/ipld/go-ipld-prime/datamodel"
    11  )
    12  
    13  type TaskType string
    14  
    15  const (
    16  	TaskTypeDocker TaskType = "docker/run"
    17  	TaskTypeWasm   TaskType = "wasm32-wasi/run"
    18  	TaskTypeNoop   TaskType = "noop"
    19  )
    20  
    21  type Task struct {
    22  	With   string
    23  	Do     TaskType
    24  	Inputs datamodel.Node
    25  	Meta   IPLDMap[string, datamodel.Node]
    26  }
    27  
    28  type Resource struct {
    29  	IPFS *IPFSResource
    30  	HTTP *HTTPResource
    31  }
    32  
    33  type IPFSResource string
    34  type HTTPResource string
    35  
    36  type BacalhauConfig struct {
    37  	Publisher   Publisher
    38  	Verifier    Verifier
    39  	Timeout     time.Duration
    40  	Resources   ResourceSpec
    41  	Annotations []string
    42  	Dnt         bool
    43  }
    44  
    45  type ResourceSpec struct {
    46  	Cpu    Millicores //nolint:stylecheck // name required by IPLD
    47  	Disk   datasize.ByteSize
    48  	Memory datasize.ByteSize
    49  	Gpu    int
    50  }
    51  
    52  type JobType interface {
    53  	UnmarshalInto(with string, spec *Spec) error
    54  }
    55  
    56  type NoopTask struct{}
    57  
    58  func (n NoopTask) UnmarshalInto(with string, spec *Spec) error {
    59  	spec.Engine = EngineNoop
    60  	return nil
    61  }
    62  
    63  var _ JobType = (*NoopTask)(nil)
    64  
    65  func (task *Task) ToSpec() (*Spec, error) {
    66  	var inputs JobType
    67  	var err error
    68  	switch task.Do {
    69  	case TaskTypeDocker:
    70  		inputs, err = Reinterpret[DockerInputs](task.Inputs, BacalhauTaskSchema)
    71  	case TaskTypeWasm:
    72  		inputs, err = Reinterpret[WasmInputs](task.Inputs, BacalhauTaskSchema)
    73  	case TaskTypeNoop:
    74  		inputs = NoopTask{}
    75  	default:
    76  		return nil, fmt.Errorf("TODO: task type %q", task.Do)
    77  	}
    78  	if err != nil {
    79  		return nil, err
    80  	}
    81  
    82  	spec := new(Spec)
    83  	err = inputs.UnmarshalInto(task.With, spec)
    84  	if err != nil {
    85  		return nil, err
    86  	}
    87  
    88  	for key, node := range task.Meta.Values {
    89  		switch key {
    90  		case "bacalhau/config":
    91  			config, err := Reinterpret[BacalhauConfig](node, BacalhauTaskSchema)
    92  			if err != nil {
    93  				return nil, err
    94  			}
    95  
    96  			spec.Verifier = config.Verifier
    97  			spec.Publisher = config.Publisher
    98  			spec.Annotations = config.Annotations
    99  			spec.Timeout = config.Timeout.Seconds()
   100  			spec.Resources = ResourceUsageConfig{
   101  				CPU:    config.Resources.Cpu.String(),
   102  				Memory: config.Resources.Memory.String(),
   103  				Disk:   config.Resources.Disk.String(),
   104  				GPU:    fmt.Sprint(config.Resources.Gpu),
   105  			}
   106  			spec.DoNotTrack = config.Dnt
   107  		default:
   108  			return nil, fmt.Errorf("TODO: config type %q", key)
   109  		}
   110  	}
   111  
   112  	return spec, nil
   113  }
   114  
   115  func parseStorageSource(path string, resource *Resource) StorageSpec {
   116  	storageSpec := StorageSpec{Path: path}
   117  	if resource.IPFS != nil {
   118  		storageSpec.StorageSource = StorageSourceIPFS
   119  		storageSpec.CID = strings.TrimLeft(string(*resource.IPFS), ":/")
   120  	} else if resource.HTTP != nil {
   121  		storageSpec.StorageSource = StorageSourceURLDownload
   122  		storageSpec.URL = "http" + string(*resource.HTTP)
   123  	}
   124  	return storageSpec
   125  }
   126  
   127  func parseInputs(mounts IPLDMap[string, Resource]) ([]StorageSpec, error) {
   128  	inputs := []StorageSpec{}
   129  	for path, resource := range mounts.Values {
   130  		resource := resource
   131  		inputs = append(inputs, parseStorageSource(path, &resource))
   132  	}
   133  	return inputs, nil
   134  }
   135  
   136  func parseResource(uri string) (*Resource, error) {
   137  	return UnmarshalIPLD[Resource]([]byte(`"`+uri+`"`), json.Decode, BacalhauTaskSchema)
   138  }