Skip to content

Commit

Permalink
add transactions-by-account service in rust
Browse files Browse the repository at this point in the history
  • Loading branch information
mxfactorial committed Mar 23, 2024
1 parent 412f504 commit 92e57bb
Show file tree
Hide file tree
Showing 6 changed files with 154 additions and 18 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ members = [
"services/requests-by-account",
"services/rule",
"services/transaction-by-id",
"services/transactions-by-account",
"tests",
]

Expand Down
40 changes: 31 additions & 9 deletions docker/dev/transactions-by-account.Dockerfile
Original file line number Diff line number Diff line change
@@ -1,17 +1,39 @@
FROM mxfactorial/go-base:v1 as builder
FROM rust:latest as builder

COPY . .
WORKDIR /app

WORKDIR /app/services/transactions-by-account
COPY . ./

RUN go build -o transactions-by-account ./cmd
RUN rustup target add x86_64-unknown-linux-musl
RUN apt update && \
apt install -y musl-tools perl make
RUN update-ca-certificates

FROM golang:alpine
ENV USER=transactions-by-account
ENV UID=10007

WORKDIR /app
RUN adduser \
--disabled-password \
--gecos "" \
--home "/nonexistent" \
--shell "/sbin/nologin" \
--no-create-home \
--uid "${UID}" \
"${USER}"

RUN USER=root cargo build \
--manifest-path=services/transactions-by-account/Cargo.toml \
--target x86_64-unknown-linux-musl \
--release

FROM alpine

COPY --from=builder /etc/passwd /etc/passwd
COPY --from=builder /etc/group /etc/group
COPY --from=builder /app/target/x86_64-unknown-linux-musl/release/transactions-by-account /usr/local/bin

COPY --from=builder /app/services/transactions-by-account/transactions-by-account .
EXPOSE 10007

EXPOSE 10008
USER transactions-by-account:transactions-by-account

CMD ["/app/transactions-by-account"]
CMD [ "/usr/local/bin/transactions-by-account" ]
4 changes: 2 additions & 2 deletions project.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -514,13 +514,13 @@ services:
- PGDATABASE
- READINESS_CHECK_PATH
transactions-by-account:
runtime: go1.x
runtime: rust1.x
min_code_cov: null
type: app
local_dev: true
params: []
deploy: true
build_src_path: cmd
build_src_path: null
dependents: []
env_var:
set:
Expand Down
18 changes: 18 additions & 0 deletions services/transactions-by-account/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
[package]
name = "transactions-by-account"
version = "0.1.0"
edition = "2021"
rust-version.workspace = true

[dependencies]
axum = "0.7.4"
tracing = "0.1.40"
tracing-subscriber = { version = "0.3.18", features = ["env-filter"] }
tokio = { version = "1.35.1", features = ["macros", "rt-multi-thread"] }
shutdown = { path = "../../crates/shutdown" }
pg = { path = "../../crates/pg" }
service = { path = "../../crates/service" }
types = { path = "../../crates/types" }

[target.x86_64-unknown-linux-musl.dependencies]
openssl = { version = "0.10", features = ["vendored"] }
21 changes: 14 additions & 7 deletions services/transactions-by-account/makefile
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
RELATIVE_PROJECT_ROOT_PATH=$(shell REL_PATH="."; while [ $$(ls "$$REL_PATH" | grep project.yaml | wc -l | xargs) -eq 0 ]; do REL_PATH="$$REL_PATH./.."; done; printf '%s' "$$REL_PATH")
include $(RELATIVE_PROJECT_ROOT_PATH)/make/shared.mk
include $(RELATIVE_PROJECT_ROOT_PATH)/make/go.mk
include $(RELATIVE_PROJECT_ROOT_PATH)/make/rust.mk

TRANSACTIONS_BY_ACCOUNT_PORT=$(shell yq '.services["$(APP_NAME)"].env_var.set.TRANSACTIONS_BY_ACCOUNT_PORT.default' $(PROJECT_CONF))
TRANSACTIONS_BY_ACCOUNT_URL=$(HOST):$(TRANSACTIONS_BY_ACCOUNT_PORT)
Expand All @@ -11,14 +11,21 @@ TEST_EVENT='{"auth_account":"$(TEST_AUTH_ACCOUNT)","account_name":"$(TEST_ACCOUN
TEST_SENDER_ACCOUNT=$(TEST_ACCOUNT)
RETURN_RECORD_LIMIT=2

run:
@$(DOCKER_ENV_VARS) \
RETURN_RECORD_LIMIT=$(RETURN_RECORD_LIMIT) \
TEST_EVENT=$(TEST_EVENT) \
go run ./cmd/main.go
start:
@$(MAKE) get-secrets ENV=local
nohup cargo watch --env-file $(ENV_FILE) -w src -w $(RELATIVE_PROJECT_ROOT_PATH)/crates -x run >> $(NOHUP_LOG) &

start-alone:
rm -f $(NOHUP_LOG)
$(MAKE) -C $(MIGRATIONS_DIR) run
$(MAKE) start
tail -F $(NOHUP_LOG)

stop:
$(MAKE) -C $(RELATIVE_PROJECT_ROOT_PATH) stop

invoke-local:
@curl -s -d $(TEST_EVENT) $(TRANSACTIONS_BY_ACCOUNT_URL) | yq -o=json
@curl -s -H 'Content-Type: application/json' -d $(TEST_EVENT) $(TRANSACTIONS_BY_ACCOUNT_URL) | yq -o=json

demo:
@printf "*** request to %s at %s\n" $(SUB_PATH) $(TRANSACTIONS_BY_ACCOUNT_URL)
Expand Down
88 changes: 88 additions & 0 deletions services/transactions-by-account/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
use axum::{
extract::{Json, State},
http::StatusCode,
routing::{get, post},
Router,
};
use pg::postgres::{ConnectionPool, DB};
use service::Service;
use shutdown::shutdown_signal;
use std::{env, net::ToSocketAddrs};
use tokio::net::TcpListener;
use types::request_response::{IntraTransactions, QueryByAccount};

// used by lambda to test for service availability
const READINESS_CHECK_PATH: &str = "READINESS_CHECK_PATH";

async fn handle_event(
State(pool): State<ConnectionPool>,
event: Json<QueryByAccount>,
) -> Result<axum::Json<IntraTransactions>, StatusCode> {
let client_request = event.0;

let svc = Service::new(pool.get_conn().await);

let account = client_request.account_name;

let record_limit = env::var("RETURN_RECORD_LIMIT")
.unwrap_or_else(|_| panic!("RETURN_RECORD_LIMIT variable assignment"))
.parse::<i64>()
.unwrap();

let transactions = svc
.get_last_n_transactions(account.clone(), record_limit)
.await
.map_err(|e| {
tracing::error!("error: {}", e);
StatusCode::INTERNAL_SERVER_ERROR
})?;

if transactions.is_empty() {
tracing::error!("transaction requests not found");
}

let response = IntraTransactions::new(account, transactions);

Ok(axum::Json(response))
}

#[tokio::main]
async fn main() {
tracing_subscriber::fmt::init();

let readiness_check_path = env::var(READINESS_CHECK_PATH)
.unwrap_or_else(|_| panic!("{READINESS_CHECK_PATH} variable assignment"));

let conn_uri = DB::create_conn_uri_from_env_vars();

let pool = DB::new_pool(&conn_uri).await;

let app = Router::new()
.route("/", post(handle_event))
.route(
readiness_check_path.as_str(),
get(|| async { StatusCode::OK }),
)
.with_state(pool);

let hostname_or_ip = env::var("HOSTNAME_OR_IP").unwrap_or("0.0.0.0".to_string());

let port = env::var("TRANSACTIONS_BY_ACCOUNT_PORT").unwrap_or("10006".to_string());

let serve_addr = format!("{hostname_or_ip}:{port}");

let mut addrs_iter = serve_addr.to_socket_addrs().unwrap_or(
format!("{hostname_or_ip}:{port}")
.to_socket_addrs()
.unwrap(),
);

let addr = addrs_iter.next().unwrap();

tracing::info!("listening on {}", addr);

axum::serve(TcpListener::bind(addr).await.unwrap(), app)
.with_graceful_shutdown(shutdown_signal())
.await
.unwrap();
}

0 comments on commit 92e57bb

Please sign in to comment.