AtpClient.StarExec (AtpClient v0.5.0)

Copy Markdown View Source

Client for self-hosted StarExec instances.

StarExec is primarily a web application backed by Tomcat, and its programmatic surface is the same set of URLs that the web UI talks to. This module authenticates against that surface and exposes the subset of operations needed to submit benchmarks to pre-configured solvers, poll for completion, and fetch solver output.

Assumptions

The standard StarExec deployment exposes:

  • Tomcat form-based authentication at /starexec/j_security_check with the j_username and j_password fields;
  • A JSON job endpoint at /services/details/job/{job_id} returning the Gson form of org.starexec.data.to.Job (used to detect completion);
  • A ZIP download of all pair stdouts at /secure/download?type=j_outputs&id={job_id}.

All of these paths are configurable; see AtpClient.Config.

Because StarExec's job-creation form accepts a large number of fields and the exact set varies by release, create_job/3 is kept minimal and deliberately flexible — consumers pass the multipart form fields their instance expects, and this module handles authentication and session cookies around the call.

Example

iex> {:ok, session} = AtpClient.StarExec.login()
iex> {:ok, job_info} = AtpClient.StarExec.get_job(session, 1234)
iex> :ok = AtpClient.StarExec.logout(session)

Configuration

config :atp_client, :starexec,
  base_url: "https://starexec.example.org",
  username: "me",
  password: System.get_env("STAREXEC_PASS")

Summary

Functions

Creates a new StarExec job. The fields map is sent as the form body and must contain everything the deployment's /secure/add/job handler expects.

Asks the StarExec instance to delete the given job, freeing the remote compute slot. Used by wait_for_job/3 and prove/3 to release resources when the calling process is cancelled.

Retrieves the JSON status of a StarExec job.

Downloads the per-pair stdout archive ("j_outputs") for a finished job. StarExec has no JSON endpoint that returns a single pair's stdout in isolation; the official StarexecCommand CLI uses this download path instead, and it works without knowing the pair ids.

Lists every benchmark in space_id.

Authenticates against the configured StarExec instance and returns a Session holding the session cookies needed for subsequent requests.

Terminates a StarExec session. Errors during logout are returned but are usually safe to ignore.

End-to-end: upload problem_text as a fresh benchmark, run it against the configured solver, wait for completion, and return the normalized result.

Low-level helper: issue an HTTP request against session.base_url carrying the session cookies. Consumers can use this to reach StarExec endpoints that are not yet wrapped by this module.

Uploads a single TPTP problem to a StarExec space.

Polls list_space_benchmarks/3 until a benchmark named name appears, then returns its id. Fails with {:error, :timeout} if the benchmark has not appeared within :timeout_ms (default 60 s).

Polls get_job/3 until the returned JSON reports that the job is complete or the per-call :timeout_ms elapses.

Types

benchmark_id()

@type benchmark_id() :: pos_integer()

job_id()

@type job_id() :: non_neg_integer() | String.t()

space_id()

@type space_id() :: pos_integer()

Functions

create_job(session, fields, opts \\ [])

@spec create_job(AtpClient.StarExec.Session.t(), map(), keyword()) ::
  {:ok, Req.Response.t()} | {:error, term()}

Creates a new StarExec job. The fields map is sent as the form body and must contain everything the deployment's /secure/add/job handler expects.

A typical field set includes "name", "desc", "queue", "sid" (space id), "cpuTimeout", "wallclockTimeout", "benchProcess", "traversal", plus any solver/benchmark selection fields. Refer to your StarExec instance's form for the authoritative list.

Returns the raw response so the caller can extract the redirect/location that typically contains the new job id.

delete_job(session, job_id, opts \\ [])

@spec delete_job(AtpClient.StarExec.Session.t(), job_id(), keyword()) ::
  :ok | {:error, term()}

Asks the StarExec instance to delete the given job, freeing the remote compute slot. Used by wait_for_job/3 and prove/3 to release resources when the calling process is cancelled.

StarExec's delete endpoint (POST /starexec/services/delete/job) expects the job id(s) in the selectedIds[] form field; the underlying servlet flips the deleted column synchronously and then queues the on-disk cleanup off-thread, so a 200 response is returned quickly even for large jobs.

The endpoint path is configurable via :delete_job_path for older StarExec instances that mount it elsewhere.

get_job(session, job_id, opts \\ [])

@spec get_job(AtpClient.StarExec.Session.t(), job_id(), keyword()) ::
  {:ok, map()} | {:error, term()}

Retrieves the JSON status of a StarExec job.

get_job_output(session, job_id, opts \\ [])

@spec get_job_output(AtpClient.StarExec.Session.t(), job_id(), keyword()) ::
  {:ok, binary()} | {:error, term()}

Downloads the per-pair stdout archive ("j_outputs") for a finished job. StarExec has no JSON endpoint that returns a single pair's stdout in isolation; the official StarexecCommand CLI uses this download path instead, and it works without knowing the pair ids.

Returns the raw ZIP bytes. Use :zip.extract(bytes, [:memory]) (Erlang stdlib) to read the individual stdout files out of the archive.

list_space_benchmarks(session, space_id, opts \\ [])

@spec list_space_benchmarks(AtpClient.StarExec.Session.t(), space_id(), keyword()) ::
  {:ok, [%{id: benchmark_id(), name: String.t()}]} | {:error, term()}

Lists every benchmark in space_id.

StarExec's REST surface for this is a DataTables-style endpoint that returns each row as [anchor_html, type_html]; this function parses the anchor to recover the structured [%{id: …, name: …}] we want.

login(opts \\ [])

@spec login(keyword()) :: {:ok, AtpClient.StarExec.Session.t()} | {:error, term()}

Authenticates against the configured StarExec instance and returns a Session holding the session cookies needed for subsequent requests.

Options

  • :base_url, :username, :password — override configuration;
  • :login_path — override the auth endpoint (default /starexec/j_security_check);
  • :request_timeout_ms.

logout(session, opts \\ [])

@spec logout(
  AtpClient.StarExec.Session.t(),
  keyword()
) :: :ok | {:error, term()}

Terminates a StarExec session. Errors during logout are returned but are usually safe to ignore.

prove(session, problem_text, opts \\ [])

End-to-end: upload problem_text as a fresh benchmark, run it against the configured solver, wait for completion, and return the normalized result.

This is the "single shot" entry point that mirrors the other backends' prove/2-style helpers. It is implemented purely in terms of the lower-level functions in this module, so anything it does can be done by hand for finer control.

Required options

  • :space_id — target StarExec space (used for both the upload and the job).
  • :solver_cfg_id — solver configuration id (not solver id).

Common options

  • :queue_id (default from config; 1 if unset) — worker queue id.
  • :cpu_timeout_s (default from config; 60 if unset).
  • :wallclock_timeout_s (default cpu_timeout_s * 2).
  • :benchmark_type (default 1).
  • :timeout_ms — wall-clock budget for the whole pipeline; passed to both wait_for_benchmark/4 and wait_for_job/3.

All other StarExec options (:base_url, :username, :password, …) are consumed by request/4 as usual.

request(session, method, path, opts \\ [])

@spec request(AtpClient.StarExec.Session.t(), atom(), String.t(), keyword()) ::
  {:ok, Req.Response.t()} | {:error, term()}

Low-level helper: issue an HTTP request against session.base_url carrying the session cookies. Consumers can use this to reach StarExec endpoints that are not yet wrapped by this module.

Supported options include anything Req.request/1 accepts, plus :request_timeout_ms which is translated to :receive_timeout.

upload_benchmark(session, space_id, problem_text, opts \\ [])

@spec upload_benchmark(
  AtpClient.StarExec.Session.t(),
  space_id(),
  binary(),
  keyword()
) ::
  {:ok, %{name: String.t(), status_id: pos_integer() | nil}} | {:error, term()}

Uploads a single TPTP problem to a StarExec space.

StarExec accepts only archives (.zip / .tar / .tgz) at the benchmark upload endpoint, so this function wraps problem_text in an in-memory ZIP whose sole entry is the new benchmark file. The benchmark's name inside StarExec becomes the entry's filename.

The upload is processed asynchronously on the server, so this function returns as soon as the request is accepted. Use wait_for_benchmark/4 (or prove/3, which composes both) to obtain the new benchmark id once StarExec has finished extracting and validating it.

Options

  • :name — base name (without .p) for the uploaded file. Defaults to a random UUID-ish string so concurrent uploads don't collide.
  • :benchmark_type — benchmark processor id. Defaults to 1 (StarExec's "no type" processor), which accepts any text.
  • :request_timeout_ms.

wait_for_benchmark(session, space_id, name, opts \\ [])

@spec wait_for_benchmark(
  AtpClient.StarExec.Session.t(),
  space_id(),
  String.t(),
  keyword()
) ::
  {:ok, benchmark_id()} | {:error, term()}

Polls list_space_benchmarks/3 until a benchmark named name appears, then returns its id. Fails with {:error, :timeout} if the benchmark has not appeared within :timeout_ms (default 60 s).

wait_for_job(session, job_id, opts \\ [])

@spec wait_for_job(AtpClient.StarExec.Session.t(), job_id(), keyword()) ::
  {:ok, map()} | {:error, term()}

Polls get_job/3 until the returned JSON reports that the job is complete or the per-call :timeout_ms elapses.

"Complete" is defined as a completed field equal to the totalJobPairs field (or a jobComplete flag being truthy). The exact JSON shape depends on the StarExec version; if it differs on your deployment, pass a custom predicate via :complete_fun, which receives the decoded job map and returns a boolean.

Cancellation

This call installs a small helper process that monitors the calling process. If the caller dies (Process.exit, Task.shutdown, …) while the job is still running, the helper issues delete_job/3 so the remote StarExec job does not run to completion on the cluster. If the job has already reached a terminal state (complete_fun.(info) is true) by the time the caller dies, the delete_job request is skipped.