Skip to content

Commit

Permalink
Set up example app from azavea.g8
Browse files Browse the repository at this point in the history
  • Loading branch information
jisantuc committed Mar 19, 2020
1 parent 2f3cea2 commit 3391ddd
Show file tree
Hide file tree
Showing 45 changed files with 1,521 additions and 61 deletions.
147 changes: 124 additions & 23 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,23 +1,124 @@
dist
dist-*
cabal-dev
*.o
*.hi
*.hie
*.chi
*.chs.h
*.dyn_o
*.dyn_hi
.hpc
.hsenv
.cabal-sandbox/
cabal.sandbox.config
*.prof
*.aux
*.hp
*.eventlog
.stack-work/
cabal.project.local
cabal.project.local~
.HTF/
.ghc.environment.*
# Sass Cache
.sass-cache

# css map
.css.map

# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]

# C extensions
*.so

# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec

# Installer logs
pip-log.txt
pip-delete-this-directory.txt

# Unit test / coverage reports
htmlcov/
.tox/
.coverage
.cache
nosetests.xml
coverage.xml

# Translations
*.mo
*.pot

# Django stuff:
*.log

# Ansible
deployment/ansible/roles/azavea.*
*.retry

# Vagrant
.vagrant

# NodeJS / Browserify stuff
node_modules/
npm-debug.log

# Emacs
\#*#
*~
.#*
TAGS

# Vim
.*.swp

# MacOS
.DS_Store

# Scala
*.class
*.log

# sbt specific
.cache
.coursier-cache
.history
.lib/
dist/*
target/
lib_managed/
src_managed/
project/boot/
project/plugins/project/
/project/.sbtboot
/project/.boot/
/project/.ivy/
/.sbtopts

# Molecule
.molecule/
*__pycache__*

# Scala-IDE specific
.scala_dependencies
.worksheet
.ensime/*
.ensime
.metals/*
.metals
/.ivy2/*
.sbt/
metals.lock.db
.metals/
.bloop/

/.env
/.envrc

.node_modules
dist/
.vscode

/data
.idea
.ensime_cache
/app-tasks/jars/rf-batch.jar
/data

.vscode

# Patch files
*.patch
scratch/

stats.json
app-lambda/opt/*
/app-lambda/package.sh

# js files from docusaurus
node_modules/*
website/build/*
12 changes: 12 additions & 0 deletions .scalafix.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
rules = [
ProcedureSyntax,
RemoveUnused,
SortImports
]

SortImports.blocks = [
"com.azavea",
"*",
"scala.",
"java.",
]
5 changes: 5 additions & 0 deletions .scalafmt.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
version = 2.1.1
align = more // For pretty alignment.
maxColumn = 120
rewrite.rules = [SortImports]
newlines.alwaysBeforeTopLevelStatements = true
13 changes: 13 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
## [Unreleased]

### Added

### Changed

### Deprecated

### Removed

### Fixed

### Security
44 changes: 20 additions & 24 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,29 +1,25 @@
# pgSockets4s
# pgsockets4s
An API project that uses `tapir`, `http4s`, and `doobie`

## Setup
### Development

### Tools you'll need
The following tools must be present for a development environment:
- Docker
- Java 8 or newer -- if this is a problem, try using [`jabba`](https://github.com/shyiko/jabba#jabba--) to manage different java versions
- Sbt 1.x -- the newer the better probably, installation instructions can be found [here](https://www.scala-sbt.org/download.html)
- [Bloop](https://scalacenter.github.io/bloop/) -- this is a scala build server that should run in the background for building the project; installation instructions can be found [here](https://scalacenter.github.io/bloop/setup)

- `psql`
- [`rambler`](https://github.com/elwinar/rambler)
### STRTA

### Initial setup
This project uses [`scripts-to-rule-them-all`](https://github.blog/2015-06-30-scripts-to-rule-them-all/) for managing the developer experience. Below is a quick explanation for the specific usage of each for this particular project.

- Copy `.env.example` to `.env` and `rambler.json.example` to `rambler.json`
- `docker-compose up -d postgres`
- After `docker-compose ps postgres` reports an `Up (healthy)` state, `./scripts/load-development-data` (password in `.env` file)
- Then apply migrations: `rambler apply`

### Prove you're all set

- `docker-compose exec postgres psql -U pgsockets -d pgsockets`
- `LISTEN new_city_channel;`
-
```sql
insert into city (
id, name, countrycode, district, population
) values (
4080, 'New City Great Place', 'ABC', 'Good Place District', 12345
);
```
- observe the async notification that gets logged
| Script | Use |
|---|---|
| `setup` | Used to provision the project from scratch |
| `update` | Update project, assemble, run migrations; assume that you can test any PR after running this script on that PR's branch |
| `console` | Open an `ammonite` shell |
| `server` | Start the server |
| `dbshell` | Open a `psql` shell connected to the database |
| `migrate` | Run migrations against the database |
| `tests` | Run tests |
| `cibuild` | Assemble jars and create containers |
12 changes: 12 additions & 0 deletions application/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
FROM openjdk:11-jre-slim

RUN \
addgroup --system pgsockets4s \
&& adduser --system --disabled-login --disabled-password --home /var/lib/pgsockets4s --shell /sbin/nologin --ingroup pgsockets4s pgsockets4s

COPY ./target/scala-2.12/application-assembly.jar /var/lib/pgsockets4s/

USER pgsockets4s
WORKDIR /var/lib/pgsockets4s

ENTRYPOINT ["java", "-jar", "application-assembly.jar"]
15 changes: 15 additions & 0 deletions application/src/main/resources/logback.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>[%thread] %highlight(%-5level) %cyan(%logger{15}) - %msg %n</pattern>
</encoder>
</appender>
<logger name="org.http4s.server.blaze" level="INFO"/>
<logger name="org.http4s.server.middleware" level="INFO" />
<logger name="org.http4s.blaze" level="WARN"/>
<logger name="org.http4s.blaze.channel.nio1" level="WARN"/>
<logger name="org.http4s" level="INFO"/>
<root level="WARN">
<appender-ref ref="STDOUT" />
</root>
</configuration>
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
CREATE EXTENSION IF NOT EXISTS postgis;
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";

CREATE TABLE users (
id uuid PRIMARY KEY DEFAULT uuid_generate_v4 (),
email text not null
);
75 changes: 75 additions & 0 deletions application/src/main/scala/api/Server.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
package com.azavea.pgsockets4s.api

import cats.effect._
import cats.implicits._
import com.azavea.pgsockets4s.api.commands.{ApiConfig, Commands, DatabaseConfig}
import com.azavea.pgsockets4s.api.endpoints.UserEndpoints
import com.azavea.pgsockets4s.api.services.UsersService
import doobie.hikari.HikariTransactor
import doobie.util.ExecutionContexts
import org.http4s.implicits._
import org.http4s.server.blaze._
import org.http4s.server.middleware._
import org.http4s.server.{Router, Server => HTTP4sServer}
import tapir.docs.openapi._
import tapir.openapi.circe.yaml._
import tapir.swagger.http4s.SwaggerHttp4s

object Server extends IOApp {

private def createServer(
apiConfig: ApiConfig,
dbConfig: DatabaseConfig
): Resource[IO, HTTP4sServer[IO]] =
for {
connectionEc <- ExecutionContexts.fixedThreadPool[IO](2)
transactionEc <- ExecutionContexts.cachedThreadPool[IO]
xa <- HikariTransactor.newHikariTransactor[IO](
"org.postgresql.Driver",
dbConfig.jdbcUrl,
dbConfig.dbUser,
dbConfig.dbPass,
connectionEc,
transactionEc
)
allEndpoints = UserEndpoints.endpoints
docs = allEndpoints.toOpenAPI("pgsockets4s", "0.0.1")
docRoutes = new SwaggerHttp4s(docs.toYaml, "open-api", "spec.yaml")
.routes[IO]
userRoutes = new UsersService[IO](xa).routes
router = CORS(
Router(
"/api" -> ResponseLogger
.httpRoutes(false, false)(userRoutes <+> docRoutes)
)
).orNotFound
server <- {
BlazeServerBuilder[IO]
.bindHttp(apiConfig.internalPort.value, "0.0.0.0")
.withHttpApp(router)
.resource
}
} yield {
server
}

override def run(args: List[String]): IO[ExitCode] = {
import Commands._

applicationCommand.parse(args) map {
case RunServer(apiConfig, dbConfig) =>
createServer(apiConfig, dbConfig)
.use(_ => IO.never)
.as(ExitCode.Success)
case RunMigrations(config) => runMigrations(config)
} match {
case Left(e) =>
IO {
println(e.toString())
} map { _ =>
ExitCode.Error
}
case Right(s) => s
}
}
}
17 changes: 17 additions & 0 deletions application/src/main/scala/api/commands/ApiConfig.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.azavea.pgsockets4s.api.commands

import eu.timepit.refined.types.numeric.PosInt
import eu.timepit.refined.types.string.NonEmptyString

case class ApiConfig(publicPort: PosInt,
internalPort: PosInt,
host: String,
scheme: String) {

val apiHost: NonEmptyString = (publicPort.value, scheme) match {
case (443, "https") => NonEmptyString.unsafeFrom(s"$scheme://$host")
case (80, "http") => NonEmptyString.unsafeFrom(s"$scheme://$host")
case _ => NonEmptyString.unsafeFrom(s"$scheme://$host:$publicPort")
}

}
Loading

0 comments on commit 3391ddd

Please sign in to comment.