Skip to contents

What is artcore?

artcore is the infrastructure foundation for the Artalytics platform. It provides the low-level building blocks that all other platform packages depend on:

appPlatform / mod* packages (application layer)
        |
    artutils (data access layer)
        |
    artcore (infrastructure layer)  ← This package

Key principle: artcore handles how to connect to databases and CDN. artutils handles what data to query. Your app handles why (business logic).

artcore provides:

  • Database connectivity - PostgreSQL connections via environment credentials
  • CDN asset management - Upload, verify, and delete files in DigitalOcean Spaces
  • UUID generation - Platform-specific IDs with recognizable prefixes
  • Environment validation - Verify required variables before operations fail

A Complete Workflow: Authenticating an Artwork

Let’s walk through the complete workflow when a new artwork is authenticated on the platform. This demonstrates how artcore functions work together.

Step 1: Validate Environment

Before any CDN or database operations, validate that credentials are configured. This catches missing variables immediately instead of cryptic errors later.

library(artcore)

# Check database credentials
check_env_dba()
#> ✔ DATABASE... user@host:5432/artalytics

# Check CDN credentials
check_env_cdn()
#> ✔ CDN DATA... Id=DO00..XY, Key=abc1..99

# Check API keys (OpenAI, OpenSea, Resend)
check_env_api()
#> ✔ API AUTH... [OpenAI] sk-proj.., [OpenSea] abc1.., [Resend] re_12..

# Check application mode
check_env_app()
#> ✔ APP MODE... User Access

Each function returns TRUE invisibly on success, or stops with a clear error listing the missing variables.

Step 2: Generate Platform UUIDs

When a new artist or artwork is created, generate a UUID with the platform prefix. This makes it easy to identify entity types at a glance:

# Artist UUIDs start with "88"
artist <- genArtistID()
# Returns: "88xxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"

# Artwork UUIDs start with "99"
artwork <- genArtworkID()
# Returns: "99xxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"

# Collection UUIDs start with "77"
collection <- genCollectionID()
# Returns: "77xxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"

# For testing, use extended prefixes for easy identification
test_artwork <- genArtworkID(test = TRUE)
# Returns: "90000000-xxxx-xxxx-xxxx-xxxxxxxxxxxx"

Step 3: Upload to CDN

With the UUIDs generated, upload the authenticated artwork bundle to the vault. The vault stores original, unprocessed files that are never exposed publicly.

# Artist already exists
artist <- "88xxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"

# Generate ID for new artwork
artwork <- genArtworkID()

# Upload the original bundle (directory of files)
bundle_path <- "path/to/authenticated/bundle/"
write_art_vault(artist, artwork, local_path = bundle_path)
#> ℹ (art-vault) Upload to Prefix -> uploads/88xxx.../99xxx.../
#> ℹ art-vault Uploading 5 file(s) => uploads/88xxx.../99xxx.../
#> ✔ art-vault Vault upload complete: 5 objects

The function: - Validates artist and artwork UUIDs - Ensures the prefix doesn’t already exist (no overwrites) - Uploads all files in the directory - Verifies each file exists after upload

Step 4: Verify Upload

After upload, verify the files are present before continuing:

# Check if any objects exist under the prefix
vault_prefix <- paste0("uploads/", artist, "/", artwork)
has_prefix("art-vault", vault_prefix)
#> ℹ PREFIX FOUND (art-vault) uploads/88xxx.../99xxx.../
#> [1] TRUE

# List the specific keys
cdn_list_keys("art-vault", vault_prefix)
#> [1] "uploads/88xxx.../99xxx.../canvas.procreate"
#> [2] "uploads/88xxx.../99xxx.../metadata.json"
#> [3] "uploads/88xxx.../99xxx.../signature.png"
#> ...

Step 5: Store Metadata in Database

With files safely in the vault, record the artwork in the database:

# Open database connection
cn <- ..dbc()
#> ✔ Connected user@host:5432/artalytics

# Insert artwork record (using DBI directly)
DBI::dbExecute(cn, "
  INSERT INTO app.artwork_index (artist_uuid, art_uuid, art_title, created_utc)
  VALUES ($1, $2, $3, NOW())
", params = list(artist, artwork, "Mountain Sunrise"))

# Close connection when done
..dbd(cn)
#> ℹ Disconnected

Note: For higher-level data operations, use artutils which provides helper functions like addArtwork() that handle the SQL for you.

Connection Management

Auto-managed (Simple)

Most artutils functions handle connections internally:

# Connection opens, query runs, connection closes - all automatic
result <- artutils::get_artist_stats(artist)

Shared Connection (Efficient)

For multiple operations, share a connection to reduce overhead:

# Open once
cn <- ..dbc()
on.exit(..dbd(cn))  # Ensures cleanup even on error

# Use for multiple operations
# ... multiple DBI calls using cn ...

# Connection closes when function exits

Why Two Functions?

..dbc() and ..dbd() have short names because you’ll type them frequently. The .. prefix indicates they’re infrastructure-level helpers, not user-facing functions.

Error Handling Philosophy

artcore follows fail-fast principles:

  1. Validate early - Check environment variables before operations
  2. Never overwrite - CDN write functions error if key exists
  3. Verify after write - Confirm uploads before proceeding
  4. Clear errors - Include the missing variable/key in error messages
# Missing environment variable
check_env_dba()
#> ✖ Envvars Missing ART_PGHOST, ART_PGPASS

# Attempting to overwrite existing key
write_art_vault(artist, artwork, local_path = bundle)
#> Error: Vault prefix already exists: uploads/88xxx.../99xxx.../

Next Steps