pkg/

directory
v0.0.0-...-7a32a38 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 13, 2026 License: Apache-2.0

README

pkg

Public Go libraries shared across this repository's modules. Following the golang-standards/project-layout convention, only externally-usable code lives here; private implementation details live in the top-level /internal tree.

Module root: github.com/apache/airavata-custos (root go.mod).

Packages

Package Import path Purpose
models github.com/apache/airavata-custos/pkg/models Shared domain types (User, Organization, Project, allocations)
service github.com/apache/airavata-custos/pkg/service High-level API for creating, reading, updating, and deleting entities

The supporting internal/db and internal/store packages are private to this module and are not importable from outside the repository.


Requirements

  • Go 1.24+
  • MySQL 8+ or MariaDB 10.5+

Quick Start

Every service method takes a context.Context as its first argument. The context carries cancellation, deadlines, and request-scoped values down into the database driver, so an in-flight query is aborted if the caller goes away or a deadline passes. You typically derive it from one of:

  • context.Background() — root context for main, init, tests, scripts.
  • r.Context() — inside an HTTP handler; cancelled when the client disconnects.
  • The ctx argument of a gRPC handler.
  • context.WithTimeout(parent, d) — adds a deadline; always defer cancel().
  • signal.NotifyContext(ctx, os.Interrupt, syscall.SIGTERM) — cancelled on Ctrl-C / SIGTERM.

Never pass nil; use context.Background() (or context.TODO()) if you have nothing better.

import (
    "context"
    "time"

    "github.com/apache/airavata-custos/pkg/models"
    "github.com/apache/airavata-custos/pkg/service"
)

svc := service.New(database) // *sqlx.DB

// Derive a context with a 10s budget for this call chain.
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()

org, err := svc.CreateOrganization(ctx, &models.Organization{
    Name:         "University of Example",
    OriginatedID: "ACCESS-ORG-001",
})

user, err := svc.CreateUser(ctx, &models.User{
    OrganizationID: org.ID,
    FirstName:      "Ada",
    LastName:       "Lovelace",
    Email:          "ada@example.edu",
})

project, err := svc.CreateProject(ctx, &models.Project{
    Title:        "Climate Simulation 2026",
    Origination:  "ACCESS",
    OriginatedID: "ACCESS-PRJ-9000",
    ProjectPIID:  user.ID,
})
  • If ID is left empty the service generates a UUID.
  • If CreatedTime on a project is zero, the service sets it to time.Now().UTC().
  • The populated entity is returned.

Read / Update / Delete

org,  err := svc.GetOrganization(ctx, orgID)
user, err := svc.GetUserByEmail(ctx, "ada@example.edu")
proj, err := svc.GetProject(ctx, projID)

users, err    := svc.ListUsersByOrganization(ctx, orgID)
projects, err := svc.ListProjectsByPI(ctx, userID)

err = svc.UpdateUser(ctx, user)
err = svc.DeleteProject(ctx, projID)

Errors

Sentinel Returned when
service.ErrNotFound A GetX call finds no matching record
service.ErrAlreadyExists Duplicate email or duplicate originated_id
service.ErrInvalidInput Missing required field, or unknown FK reference

Use errors.Is(err, service.ErrNotFound) to check.

Schema

Tables created by the embedded migrations in /internal/db/migrations/:

organizations
users          (FK → organizations.id)
projects       (FK → users.id  via project_pi_id)

parseTime=true must be set in the DSN so MySQL TIMESTAMP columns scan into time.Time correctly.

Testing with a mock service

The service package exposes a CoreService interface (see pkg/service/interface.go) that the concrete *service.Service satisfies. Callers should depend on this interface — or one of the narrower per-domain interfaces in the same file — so tests can swap in a mock without a database.

A mock implementation, CoreServiceMock, is generated by matryer/moq into pkg/service/mock.go. Each method has a corresponding XxxFunc field; set only the funcs your test needs, and use the matching XxxCalls() helper to assert how the code under test invoked the service.

import (
    "context"
    "testing"

    "github.com/apache/airavata-custos/pkg/models"
    "github.com/apache/airavata-custos/pkg/service"
)

func TestSomething(t *testing.T) {
    svc := &service.CoreServiceMock{
        GetComputeClusterFunc: func(ctx context.Context, id string) (*models.ComputeCluster, error) {
            return &models.ComputeCluster{ID: id, Name: "test-cluster"}, nil
        },
        GetProjectFunc: func(ctx context.Context, id string) (*models.Project, error) {
            return &models.Project{ID: id, ProjectPIID: "pi-id"}, nil
        },
    }

    // ... exercise the code under test, passing svc where a service.CoreService is expected ...

    if got := len(svc.GetComputeClusterCalls()); got != 1 {
        t.Fatalf("GetComputeCluster called %d times, want 1", got)
    }
}

Methods whose Func field is left nil will panic when invoked, surfacing unexpected calls loudly.

Regenerating the mock

After adding or changing a method on any interface in interface.go, regenerate mock.go:

go generate ./pkg/service/...

The //go:generate directive at the top of interface.go invokes moq via go run, so no project-wide install is required. The Go toolchain will fetch the version of moq it needs on demand.

Directories

Path Synopsis
Package events defines message types emitted by the service for downstream consumers (audit, projections, integrations).
Package events defines message types emitted by the service for downstream consumers (audit, projections, integrations).
Package identity carries the verified caller across the request lifecycle.
Package identity carries the verified caller across the request lifecycle.
Package posix builds and validates POSIX-conformant usernames for HPC account provisioning.
Package posix builds and validates POSIX-conformant usernames for HPC account provisioning.
Package service provides high-level operations on the core domain entities (Organization, User, Project).
Package service provides high-level operations on the core domain entities (Organization, User, Project).

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL