Ingot.AnvilClient behaviour (Ingot v0.1.0)

View Source

Behaviour for labeling operations via Anvil.

Handles queue subscriptions, assignment fetching, label submission, and stats. Supports pluggable adapters for different deployment scenarios:

  • MockAdapter: For testing without running Anvil
  • ElixirAdapter: Direct in-process calls when deployed together
  • HTTPAdapter: REST API calls for separate deployments (future)

Summary

Callbacks

Check if user has access to a queue.

Create an invite code for a queue.

Export all labels as CSV.

Get invite by code.

Get next assignment from a queue for a user.

Get queue-level statistics.

Get user roles.

Health check for Anvil service.

Redeem an invite code.

Get labeling statistics.

Store a completed label.

Submit a completed label.

Get total count of all labels.

Upsert a user (create or update).

Functions

Check if user has access to a queue.

Create an invite code for a queue.

Export all labels as CSV.

Get invite by code.

Get next assignment from a queue for a user.

Get queue-level statistics.

Get user roles.

Health check for Anvil service.

Redeem an invite code.

Get all labels for a specific session.

Get labeling statistics.

Store a completed label.

Submit a completed label.

Get total count of all labels.

Upsert a user (create or update).

Types

assignment_id()

@type assignment_id() :: String.t()

error()

@type error() ::
  :not_found
  | :no_assignments
  | :timeout
  | :not_available
  | {:validation, map()}
  | {:unexpected, term()}

queue_id()

@type queue_id() :: String.t()

user_id()

@type user_id() :: String.t()

Callbacks

check_queue_access(user_id, queue_id)

@callback check_queue_access(user_id(), queue_id()) ::
  {:ok, boolean()} | {:error, error()}

Check if user has access to a queue.

Returns true if the user has permission to access the queue.

create_invite(attrs)

@callback create_invite(attrs :: map()) :: {:ok, map()} | {:error, error()}

Create an invite code for a queue.

Generates an invite code that can be redeemed by external labelers.

export_csv()

@callback export_csv() :: {:ok, String.t()} | {:error, error()}

Export all labels as CSV.

Legacy API - maintained for backward compatibility.

get_invite(code)

@callback get_invite(code :: String.t()) ::
  {:ok, map()} | {:error, :not_found | :expired | :exhausted}

Get invite by code.

Returns invite details if the code is valid and not expired/exhausted.

get_next_assignment(queue_id, user_id)

@callback get_next_assignment(queue_id(), user_id()) ::
  {:ok, Ingot.DTO.Assignment.t()} | {:error, error()}

Get next assignment from a queue for a user.

Returns an assignment with the sample pre-fetched and any existing labels for review/adjudication scenarios.

get_queue_stats(queue_id)

@callback get_queue_stats(queue_id()) ::
  {:ok, Ingot.DTO.QueueStats.t()} | {:error, error()}

Get queue-level statistics.

Returns aggregate progress and agreement metrics.

get_user_roles(user_id)

@callback get_user_roles(user_id()) :: {:ok, [map()]} | {:error, error()}

Get user roles.

Returns a list of roles assigned to the user.

health_check()

@callback health_check() :: {:ok, :healthy} | {:error, error()}

Health check for Anvil service.

Returns :ok if Anvil is reachable and healthy, otherwise returns an error.

redeem_invite(code, user_attrs)

@callback redeem_invite(code :: String.t(), user_attrs :: map()) ::
  {:ok, map()} | {:error, :not_found | :expired | :exhausted | error()}

Redeem an invite code.

Creates a user and grants access to the queue associated with the invite.

statistics()

@callback statistics() :: map()

Get labeling statistics.

Legacy API - maintained for backward compatibility.

store_label(label)

@callback store_label(label :: map()) :: {:ok, map()} | {:error, :invalid_label | error()}

Store a completed label.

Legacy API - maintained for backward compatibility.

submit_label(assignment_id, values)

@callback submit_label(assignment_id(), values :: map()) :: :ok | {:error, error()}

Submit a completed label.

Values should conform to the schema defined in the assignment.

total_labels()

@callback total_labels() :: integer()

Get total count of all labels.

Legacy API - maintained for backward compatibility.

upsert_user(attrs)

@callback upsert_user(attrs :: map()) ::
  {:ok, map()} | {:error, :invalid_attributes | error()}

Upsert a user (create or update).

Creates a new user or updates an existing one based on external_id. Used for OIDC just-in-time provisioning.

Functions

check_queue_access(user_id, queue_id)

Check if user has access to a queue.

Examples

iex> AnvilClient.check_queue_access("user_123", "queue_abc")
{:ok, true}

create_invite(attrs)

Create an invite code for a queue.

Examples

iex> AnvilClient.create_invite(%{queue_id: "queue_abc", role: :labeler, max_uses: 10})
{:ok, %{code: "ABCD1234WXYZ", queue_id: "queue_abc", ...}}

export_csv()

Export all labels as CSV.

Examples

iex> AnvilClient.export_csv()
{:ok, "sample_id,coherence\n..."}

get_invite(code)

Get invite by code.

Examples

iex> AnvilClient.get_invite("ABCD1234WXYZ")
{:ok, %{code: "ABCD1234WXYZ", queue_id: "queue_abc", ...}}

get_next_assignment(queue_id, user_id)

Get next assignment from a queue for a user.

Examples

iex> AnvilClient.get_next_assignment("queue-1", "user-123")
{:ok, %Ingot.DTO.Assignment{...}}

iex> AnvilClient.get_next_assignment("empty-queue", "user-123")
{:error, :no_assignments}

get_queue_stats(queue_id)

Get queue-level statistics.

Examples

iex> AnvilClient.get_queue_stats("queue-1")
{:ok, %Ingot.DTO.QueueStats{total_samples: 100, labeled: 47, ...}}

get_user_roles(user_id)

Get user roles.

Examples

iex> AnvilClient.get_user_roles("user_123")
{:ok, [%{role: :labeler, scope: "queue:abc"}, ...]}

health_check()

Health check for Anvil service.

Examples

iex> AnvilClient.health_check()
{:ok, :healthy}

iex> AnvilClient.health_check()
{:error, :not_available}

redeem_invite(code, user_attrs)

Redeem an invite code.

Examples

iex> AnvilClient.redeem_invite("ABCD1234WXYZ", %{email: "labeler@example.com", name: "Labeler"})
{:ok, %{user: %{id: "user_123", ...}, queue_id: "queue_abc", role: :labeler}}

session_labels(session_id)

Get all labels for a specific session.

Legacy API - maintained for backward compatibility.

statistics()

Get labeling statistics.

Examples

iex> AnvilClient.statistics()
%{total_labels: 47, avg_coherence: 3.8, ...}

store_label(label)

Store a completed label.

Examples

iex> label = %{sample_id: "s1", ratings: %{coherence: 4}}
iex> AnvilClient.store_label(label)
{:ok, label}

submit_label(assignment_id, values)

Submit a completed label.

Examples

iex> AnvilClient.submit_label("assignment-1", %{coherence: 4})
:ok

iex> AnvilClient.submit_label("assignment-1", %{invalid: "data"})
{:error, {:validation, %{coherence: "is required"}}}

total_labels()

Get total count of all labels.

Examples

iex> AnvilClient.total_labels()
47

upsert_user(attrs)

Upsert a user (create or update).

Examples

iex> AnvilClient.upsert_user(%{external_id: "oidc_123", email: "user@example.com", name: "User"})
{:ok, %{id: "user_123", external_id: "oidc_123", ...}}