Skip to content
This repository has been archived by the owner on Sep 16, 2024. It is now read-only.

fix(s3): remove s3 use in service, update litestream and add to docker-compose #115

Merged
merged 6 commits into from
May 28, 2024
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .env.test
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,3 @@ LOG_FORMAT=simple
NODE_VERSION=18.17.0
BLOCKLIST_CONTRACT_IDS=''
PREFETCH_CONTRACTS=false
BOOTSTRAP_CONTRACTS=false
21 changes: 15 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,19 @@ docker run -e GATEWAY_HOST=arweave.net -p 3000:3000 ghcr.io/ar-io/arns-service:l

You can run on a different port by changing the `-e PORT=3000 -p 3000:3000` to `-e PORT=4000 -p 4000:4000`, for example, or specify a `.env` file with `--env-file` flag.

#### Profiles

The service can be run with different profiles to facilitate different environments. The following profiles are supported:

- `test`: runs the service and other containers for executing integration tests
- `litestream`: runs the service with [Litestream] for syncing SQLite data to S3

To run the service with a profile, you can use the `--profile` flag:

```shell
docker compose --env-file .env --profile litestream up --build
```

## Warp

The service leverages [Warp SDK] to retrieve, evaluate and cache contract state. To request a contract state, run:
Expand Down Expand Up @@ -92,7 +105,6 @@ The service can be configured using environment variables. The following environ
- `PREFETCH_CONTRACTS`: boolean to enable/disable prefetching of contracts on startup. Defaults to `true`.
- `PREFETCH_CONTRACT_IDS`: comma separated list of contract IDs to prefetch on startup
- `ARNS_CONTRACT_TX_ID`: the ArNS contract transaction ID. Defaults to `bLAgYxAdX2Ry-nt6aH2ixgvJXbpsEYm28NgJgyqfs-U` and when `PREFETCH_CONTRACTS` is `true`, will be prefetched on startup.
- `BOOTSTRAP_CACHE`: loads warp cache from S3 on startup. Defaults to `false`.
- `BLOCKLISTED_CONTRACT_IDS`: comma separated list of contract IDs to block evaluation. These contracts will return `403` when requested.

You can `cp .env.sample .env` and modify them locally.
Expand Down Expand Up @@ -127,11 +139,7 @@ yarn test:docker
http://localhost:3000/api-docs
```

For production, the Swagger UI is available at:

```shell
https://api.arns.app/api-docs
```
For production, the Swagger UI is available at [https://api.arns.app/api-docs](https://api.arns.app/api-docs)

## Contributions

Expand All @@ -150,3 +158,4 @@ https://api.arns.app/api-docs
[Warp SDK]: https://github.com/warp-contracts/warp
[warp-contracts-sqlite]: https://github.com/warp-contracts/warp-contracts-sqlite
[D.R.E nodes]: https://academy.warp.cc/docs/dre/overview
[Litestream]: https://litestream.io/
21 changes: 19 additions & 2 deletions docker-compose.yaml
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
version: '3'

services:
arlocal:
profiles: ['test']
image: textury/arlocal:v1.1.35
ports:
- '1984:1984'
Expand All @@ -22,8 +21,26 @@ services:
WAIT_TIME_SECONDS: ${WAIT_TIME_SECONDS:-}
ports:
- '3000:3000'
volumes:
- ${WARP_SQLITE_CACHE_PATH:-./cache/warp/sqlite}:/usr/src/app/cache/sqlite

litestream:
profiles: ['litestream']
build:
context: litestream
environment:
TVAL_LOCAL_DB_PATH: ${LITESTREAM_LOCAL_DB_PATH:-/app/data/sqlite}
TVAL_S3_BUCKET_PATH: ${LITESTREAM_S3_BUCKET_PATH:-}
TVAL_S3_BUCKET: ${LITESTREAM_S3_BUCKET:-}
TVAL_AWS_ACCESS_KEY_ID: ${LITESTREAM_AWS_ACCESS_KEY_ID:-}
TVAL_AWS_SECRET_ACCESS_KEY: ${LITESTREAM_AWS_SECRET_ACCESS_KEY:-}
WAIT_TIME_SECONDS: ${LITESTREAM_WAIT_TIME_SECONDS:-}
RESTORE_FROM_BACKUP: ${LITESTREAM_RESTORE_FROM_BACKUP:-false}
volumes:
- ${WARP_SQLITE_CACHE_PATH:-./cache/warp/sqlite}:/app/data/sqlite

test-runner:
profiles: ['test']
build:
context: .
dockerfile: tests/integration/Dockerfile.integration
Expand Down
7 changes: 7 additions & 0 deletions litestream/.env.sample
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
TVAL_LOCAL_DB_PATH=/cache/warp/sqlite
TVAL_AWS_ACCESS_KEY_ID=
TVAL_AWS_SECRET_ACCESS_KEY=
TVAL_S3_BUCKET_PATH=/<sqlite-path-in-s3/
TVAL_S3_BUCKET=
WAIT_TIME_SECONDS=0
RESTORE_FROM_BACKUP=false
15 changes: 4 additions & 11 deletions litestream/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,16 +1,9 @@
# Start with a standard Ubuntu base image
FROM ubuntu:20.04 as builder
FROM litestream/litestream:0.3.13

# Install curl and other necessary tools
RUN apt-get update && apt-get install -y curl
RUN apk update && apk add --no-cache curl

# Download and install ytt
RUN curl -L https://github.com/vmware-tanzu/carvel-ytt/releases/download/v0.44.1/ytt-linux-amd64 > /usr/local/bin/ytt \
&& chmod 755 /usr/local/bin/ytt

FROM litestream/litestream:latest

COPY --from=builder /usr/local/bin/ytt /usr/local/bin/ytt
COPY install-ytt.sh /install-ytt.sh
RUN /install-ytt.sh && rm /install-ytt.sh

COPY litestream.template.yaml .
COPY docker-entrypoint.sh .
Expand Down
20 changes: 12 additions & 8 deletions litestream/docker-entrypoint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,21 @@ set -e
# Update env vars
ytt --data-values-env TVAL -f /litestream.template.yaml > /litestream.yml

# restore if needed
echo "Restoring database from backup..."
if ! /usr/local/bin/litestream restore -if-db-not-exists -if-replica-exists -parallelism 10 -config /litestream.yml $TVAL_LOCAL_DB_PATH/state.db; then
echo "Failed to restore state.db"
fi
if ! /usr/local/bin/litestream restore -if-db-not-exists -if-replica-exists -parallelism 10 -config /litestream.yml $TVAL_LOCAL_DB_PATH/contract.db; then
echo "Failed to restore contract.db"
# only restore if environment variable is set
if [[ "$RESTORE_FROM_BACKUP" = "true" ]]; then
echo "Restoring from backup..."
if ! /usr/local/bin/litestream restore -if-db-not-exists -if-replica-exists -parallelism 10 -config /litestream.yml $TVAL_LOCAL_DB_PATH/state.db; then
echo "Failed to restore state.db"
fi
if ! /usr/local/bin/litestream restore -if-db-not-exists -if-replica-exists -parallelism 10 -config /litestream.yml $TVAL_LOCAL_DB_PATH/contract.db; then
echo "Failed to restore contract.db"
fi
else
echo "No RESTORE_FROM_BACKUP environment variable set, skipping restore..."
fi

if [[ -n "$WAIT_TIME_SECONDS" ]]; then
# Sleep for the number of seconds specified in WAIT_TIME_SECONDS
# Sleep for the number of seconds specified in WAIT_TIME_SECONDS, this is useful if we are prefetching contracts
echo "Waiting for $WAIT_TIME_SECONDS seconds before starting replication..."
sleep $WAIT_TIME_SECONDS
fi
Expand Down
18 changes: 18 additions & 0 deletions litestream/install-ytt.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#!/bin/sh

case $(uname -m) in
"aarch64")
echo "aarch64"
curl -L https://github.com/vmware-tanzu/carvel-ytt/releases/download/v0.49.0/ytt-linux-arm64 > /usr/local/bin/ytt
;;
"x86_64")
echo "x86_64"
curl -L https://github.com/vmware-tanzu/carvel-ytt/releases/download/v0.49.0/ytt-linux-amd64 > /usr/local/bin/ytt
;;
*)
echo "Unknown arch"
exit 1
;;
esac

chmod 755 /usr/local/bin/ytt
13 changes: 11 additions & 2 deletions litestream/litestream.template.yaml
Original file line number Diff line number Diff line change
@@ -1,9 +1,18 @@
#@ load("@ytt:data", "data")

#@ if data.values.AWS_ACCESS_KEY_ID != "":
access-key-id: #@ data.values.AWS_ACCESS_KEY_ID
secret-access-key: #@ data.values.AWS_SECRET_ACCESS_KEY
#@ end

dbs:
- path: #@ data.values.LOCAL_DB_PATH + "/state.db"
replicas:
- url: #@ data.values.S3_BUCKET_PATH
- type: s3
bucket: #@ data.values.S3_BUCKET
path: #@ data.values.S3_BUCKET_PATH
- path: #@ data.values.LOCAL_DB_PATH + "/contract.db"
replicas:
- url: #@ data.values.S3_BUCKET_PATH
- type: s3
bucket: #@ data.values.S3_BUCKET
path: #@ data.values.S3_BUCKET_PATH
9 changes: 4 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,12 @@
"start:prod": "yarn build && node dist/app.js",
"build": "yarn clean && yarn && npx tsc --project ./tsconfig.json",
"clean": "rimraf [ node_modules dist cache ]",
"test:docker": "docker compose --env-file=.env.test up --exit-code-from test-runner --build",
"test:docker": "docker compose --env-file=.env.test --profile test up --exit-code-from test-runner --build",
"test:integration": "mocha --spec=tests/integration/**.test.ts",
"test:integration:local": "docker compose up arlocal -d ; yarn test:integration $*; docker compose down -v",
"docker:run": "docker compose up arns-service --build",
"docker:integration": "docker compose up --exit-code-from test-runner --build",
"docker:run:litestream": "docker compose --profile litestream up --build",
"docker:integration": "docker compose --profile test up --exit-code-from test-runner --build",
"format:fix": "yarn prettier --write .",
"format:check": "yarn prettier . --check",
"lint:fix": "yarn eslint . --fix",
Expand All @@ -30,8 +31,6 @@
},
"dependencies": {
"@ardrive/ardrive-promise-cache": "^1.1.4",
"@aws-sdk/client-s3": "^3.490.0",
"@aws-sdk/lib-storage": "^3.554.0",
"@koa/cors": "^4.0.0",
"@koa/router": "^12.0.0",
"arweave": "^1.14.4",
Expand All @@ -42,7 +41,7 @@
"lodash": "^4.17.21",
"p-limit": "3.1.0",
"prom-client": "^14.2.0",
"warp-contracts": "1.4.43",
"warp-contracts": "1.4.39",
"warp-contracts-lmdb": "^1.1.10",
"warp-contracts-sqlite": "^1.0.2",
"winston": "^3.8.2",
Expand Down
4 changes: 2 additions & 2 deletions src/api/warp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@
> = new ReadThroughPromiseCache({
cacheParams: {
cacheCapacity: 10_000,
cacheTTL: 1000 * 30, // 30 seconds
cacheTTL: 1000 * 60, // 60 seconds
},
readThroughFunction: readThroughToContractState,
});
Expand All @@ -109,7 +109,7 @@
constructor(
public readonly contractTxId: string,
public readonly functionName: string,
public readonly input: any,

Check warning on line 112 in src/api/warp.ts

View workflow job for this annotation

GitHub Actions / build (lint:check)

Unexpected any. Specify a different type
public readonly warp: Warp,
public readonly evaluationOptions: Partial<EvaluationOptions>,
public readonly sortKey?: string,
Expand Down Expand Up @@ -141,7 +141,7 @@
> = new ReadThroughPromiseCache({
cacheParams: {
cacheCapacity: 1_000,
cacheTTL: 1000 * 30, // 30 seconds
cacheTTL: 1000 * 60, // 60 seconds
},
readThroughFunction: readThroughToContractReadInteraction,
});
Expand Down Expand Up @@ -314,8 +314,8 @@
return new NotFoundError(error.message);
} else if (
(error instanceof Error &&
(error as any).type &&

Check warning on line 317 in src/api/warp.ts

View workflow job for this annotation

GitHub Actions / build (lint:check)

Unexpected any. Specify a different type
['TX_NOT_FOUND', 'TX_INVALID'].includes((error as any).type)) ||

Check warning on line 318 in src/api/warp.ts

View workflow job for this annotation

GitHub Actions / build (lint:check)

Unexpected any. Specify a different type
(typeof error === 'string' && (error as string).includes('TX_INVALID'))
) {
return new NotFoundError(`Contract not found. ${error}`);
Expand Down Expand Up @@ -512,7 +512,7 @@
input: ParsedUrlQuery;
sortKey?: string | undefined;
}): Promise<{
result: any;

Check warning on line 515 in src/api/warp.ts

View workflow job for this annotation

GitHub Actions / build (lint:check)

Unexpected any. Specify a different type
evaluationOptions: Partial<EvaluationOptions>;
}> {
try {
Expand Down
2 changes: 0 additions & 2 deletions src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,6 @@
import { EvaluationOptions } from 'warp-contracts';

export const PREFETCH_CONTRACTS = process.env.PREFETCH_CONTRACTS === 'true';
export const BOOTSTRAP_CACHE = process.env.BOOTSTRAP_CACHE === 'true';
export const SAVE_CACHE_TO_S3 = process.env.SAVE_CACHE_TO_S3 === 'true';
export const BLOCKLISTED_CONTRACT_IDS = new Set(
process.env.BLOCKLISTED_CONTRACT_IDS
? process.env.BLOCKLISTED_CONTRACT_IDS.split(',')
Expand Down
Loading
Loading