Skip to content

Commit 5258bc5

Browse files
authored
Merge pull request #46 from CahidArda/main
Add elixir-with-redis Example
2 parents 0798ee5 + 5c0ded1 commit 5258bc5

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+2318
-0
lines changed

Diff for: examples/elixir-with-redis/.dockerignore

+45
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
# This file excludes paths from the Docker build context.
2+
#
3+
# By default, Docker's build context includes all files (and folders) in the
4+
# current directory. Even if a file isn't copied into the container it is still sent to
5+
# the Docker daemon.
6+
#
7+
# There are multiple reasons to exclude files from the build context:
8+
#
9+
# 1. Prevent nested folders from being copied into the container (ex: exclude
10+
# /assets/node_modules when copying /assets)
11+
# 2. Reduce the size of the build context and improve build time (ex. /build, /deps, /doc)
12+
# 3. Avoid sending files containing sensitive information
13+
#
14+
# More information on using .dockerignore is available here:
15+
# https://docs.docker.com/engine/reference/builder/#dockerignore-file
16+
17+
.dockerignore
18+
19+
# Ignore git, but keep git HEAD and refs to access current commit hash if needed:
20+
#
21+
# $ cat .git/HEAD | awk '{print ".git/"$2}' | xargs cat
22+
# d0b8727759e1e0e7aa3d41707d12376e373d5ecc
23+
.git
24+
!.git/HEAD
25+
!.git/refs
26+
27+
# Common development/test artifacts
28+
/cover/
29+
/doc/
30+
/test/
31+
/tmp/
32+
.elixir_ls
33+
34+
# Mix artifacts
35+
/_build/
36+
/deps/
37+
*.ez
38+
39+
# Generated on crash by the VM
40+
erl_crash.dump
41+
42+
# Static artifacts - These should be fetched and built inside the Docker image
43+
/assets/node_modules/
44+
/priv/static/assets/
45+
/priv/static/cache_manifest.json

Diff for: examples/elixir-with-redis/.gitignore

+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
# The directory Mix will write compiled artifacts to.
2+
/_build/
3+
4+
# If you run "mix test --cover", coverage assets end up here.
5+
/cover/
6+
7+
# The directory Mix downloads your dependencies sources to.
8+
/deps/
9+
10+
# Where 3rd-party dependencies like ExDoc output generated docs.
11+
/doc/
12+
13+
# Ignore .fetch files in case you like to edit your project deps locally.
14+
/.fetch
15+
16+
# If the VM crashes, it generates a dump, let's ignore it too.
17+
erl_crash.dump
18+
19+
# Also ignore archive artifacts (built via "mix archive.build").
20+
*.ez
21+
22+
# Temporary files, for example, from tests.
23+
/tmp/
24+
25+
# Ignore package tarball (built via "mix hex.build").
26+
redix_demo_fly-*.tar
27+
28+
# Ignore assets that are produced by build tools.
29+
/priv/static/assets/
30+
31+
# Ignore digested assets cache.
32+
/priv/static/cache_manifest.json
33+
34+
# In case you use Node.js/npm, you want to ignore these.
35+
npm-debug.log
36+
/assets/node_modules/
37+

Diff for: examples/elixir-with-redis/Dockerfile

+97
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
# Find eligible builder and runner images on Docker Hub. We use Ubuntu/Debian
2+
# instead of Alpine to avoid DNS resolution issues in production.
3+
#
4+
# https://hub.docker.com/r/hexpm/elixir/tags?page=1&name=ubuntu
5+
# https://hub.docker.com/_/ubuntu?tab=tags
6+
#
7+
# This file is based on these images:
8+
#
9+
# - https://hub.docker.com/r/hexpm/elixir/tags - for the build image
10+
# - https://hub.docker.com/_/debian?tab=tags&page=1&name=bullseye-20240130-slim - for the release image
11+
# - https://pkgs.org/ - resource for finding needed packages
12+
# - Ex: hexpm/elixir:1.16.1-erlang-26.2.2-debian-bullseye-20240130-slim
13+
#
14+
ARG ELIXIR_VERSION=1.16.1
15+
ARG OTP_VERSION=26.2.2
16+
ARG DEBIAN_VERSION=bullseye-20240130-slim
17+
18+
ARG BUILDER_IMAGE="hexpm/elixir:${ELIXIR_VERSION}-erlang-${OTP_VERSION}-debian-${DEBIAN_VERSION}"
19+
ARG RUNNER_IMAGE="debian:${DEBIAN_VERSION}"
20+
21+
FROM ${BUILDER_IMAGE} as builder
22+
23+
# install build dependencies
24+
RUN apt-get update -y && apt-get install -y build-essential git \
25+
&& apt-get clean && rm -f /var/lib/apt/lists/*_*
26+
27+
# prepare build dir
28+
WORKDIR /app
29+
30+
# install hex + rebar
31+
RUN mix local.hex --force && \
32+
mix local.rebar --force
33+
34+
# set build ENV
35+
ENV MIX_ENV="prod"
36+
37+
# install mix dependencies
38+
COPY mix.exs mix.lock ./
39+
RUN mix deps.get --only $MIX_ENV
40+
RUN mkdir config
41+
42+
# copy compile-time config files before we compile dependencies
43+
# to ensure any relevant config change will trigger the dependencies
44+
# to be re-compiled.
45+
COPY config/config.exs config/${MIX_ENV}.exs config/
46+
RUN mix deps.compile
47+
48+
COPY priv priv
49+
50+
COPY lib lib
51+
52+
COPY assets assets
53+
54+
# compile assets
55+
RUN mix assets.deploy
56+
57+
# Compile the release
58+
RUN mix compile
59+
60+
# Changes to config/runtime.exs don't require recompiling the code
61+
COPY config/runtime.exs config/
62+
63+
COPY rel rel
64+
RUN mix release
65+
66+
# start a new build stage so that the final image will only contain
67+
# the compiled release and other runtime necessities
68+
FROM ${RUNNER_IMAGE}
69+
70+
RUN apt-get update -y && \
71+
apt-get install -y libstdc++6 openssl libncurses5 locales ca-certificates \
72+
&& apt-get clean && rm -f /var/lib/apt/lists/*_*
73+
74+
# Set the locale
75+
RUN sed -i '/en_US.UTF-8/s/^# //g' /etc/locale.gen && locale-gen
76+
77+
ENV LANG en_US.UTF-8
78+
ENV LANGUAGE en_US:en
79+
ENV LC_ALL en_US.UTF-8
80+
81+
WORKDIR "/app"
82+
RUN chown nobody /app
83+
84+
# set runner ENV
85+
ENV MIX_ENV="prod"
86+
87+
# Only copy the final release from the build stage
88+
COPY --from=builder --chown=nobody:root /app/_build/${MIX_ENV}/rel/redix_demo ./
89+
90+
USER nobody
91+
92+
# If using an environment that doesn't automatically reap zombie processes, it is
93+
# advised to add an init process such as tini via `apt-get install`
94+
# above and adding an entrypoint. See https://github.com/krallin/tini for details
95+
# ENTRYPOINT ["/tini", "--"]
96+
97+
CMD ["/app/bin/server"]

Diff for: examples/elixir-with-redis/README.md

+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
---
2+
title: Elixir with Redis
3+
products: ["redis"]
4+
stack: ["Elixir", "Phoenix", "fly.io"]
5+
languages: ["elixir"]
6+
use_cases: ["State Store"]
7+
author: "CahidArda"
8+
---
9+
10+
<br />
11+
<div align="center">
12+
13+
<h3 align="center">Elixir with Redis</h3>
14+
15+
<p align="center">
16+
Discover the capabilities of deploying a Phoenix app on Fly with an Upstash Redis database, improving your application's performance and scalability. Harness the power of Redis as a high-performance data store, seamlessly integrated with an Phoenix app.
17+
</p>
18+
</div>
19+
20+
A sample Phoneix app deployed on Fly which uses Redis to store results of requests to an external API.
21+
22+
See the [tutorial](https://upstash.com/docs/redis/tutorials/elixir_with_redis) for details.
23+
24+
### Learn More
25+
26+
To learn more about Upstash and its services, check out the following resources:
27+
28+
- [Documentation](https://docs.upstash.com)
29+
- [Website](https://upstash.com)
30+
- [Blog](https://upstash.com/blog)
31+
- [Console](https://console.upstash.com)
32+
- [Discord](https://upstash.com/discord)
33+
34+

Diff for: examples/elixir-with-redis/assets/css/app.css

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
@import "tailwindcss/base";
2+
@import "tailwindcss/components";
3+
@import "tailwindcss/utilities";
4+
5+
/* This file is for your main application CSS */

Diff for: examples/elixir-with-redis/assets/js/app.js

+44
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
// If you want to use Phoenix channels, run `mix help phx.gen.channel`
2+
// to get started and then uncomment the line below.
3+
// import "./user_socket.js"
4+
5+
// You can include dependencies in two ways.
6+
//
7+
// The simplest option is to put them in assets/vendor and
8+
// import them using relative paths:
9+
//
10+
// import "../vendor/some-package.js"
11+
//
12+
// Alternatively, you can `npm install some-package --prefix assets` and import
13+
// them using a path starting with the package name:
14+
//
15+
// import "some-package"
16+
//
17+
18+
// Include phoenix_html to handle method=PUT/DELETE in forms and buttons.
19+
import "phoenix_html"
20+
// Establish Phoenix Socket and LiveView configuration.
21+
import {Socket} from "phoenix"
22+
import {LiveSocket} from "phoenix_live_view"
23+
import topbar from "../vendor/topbar"
24+
25+
let csrfToken = document.querySelector("meta[name='csrf-token']").getAttribute("content")
26+
let liveSocket = new LiveSocket("/live", Socket, {
27+
longPollFallbackMs: 2500,
28+
params: {_csrf_token: csrfToken}
29+
})
30+
31+
// Show progress bar on live navigation and form submits
32+
topbar.config({barColors: {0: "#29d"}, shadowColor: "rgba(0, 0, 0, .3)"})
33+
window.addEventListener("phx:page-loading-start", _info => topbar.show(300))
34+
window.addEventListener("phx:page-loading-stop", _info => topbar.hide())
35+
36+
// connect if there are any LiveViews on the page
37+
liveSocket.connect()
38+
39+
// expose liveSocket on window for web console debug logs and latency simulation:
40+
// >> liveSocket.enableDebug()
41+
// >> liveSocket.enableLatencySim(1000) // enabled for duration of browser session
42+
// >> liveSocket.disableLatencySim()
43+
window.liveSocket = liveSocket
44+

Diff for: examples/elixir-with-redis/assets/tailwind.config.js

+75
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
// See the Tailwind configuration guide for advanced usage
2+
// https://tailwindcss.com/docs/configuration
3+
4+
const plugin = require("tailwindcss/plugin")
5+
const fs = require("fs")
6+
const path = require("path")
7+
8+
module.exports = {
9+
content: [
10+
"./js/**/*.js",
11+
"../lib/redix_demo_web.ex",
12+
"../lib/redix_demo_web/**/*.*ex"
13+
],
14+
theme: {
15+
extend: {
16+
colors: {
17+
brand: "#FD4F00",
18+
}
19+
},
20+
},
21+
plugins: [
22+
require("@tailwindcss/forms"),
23+
// Allows prefixing tailwind classes with LiveView classes to add rules
24+
// only when LiveView classes are applied, for example:
25+
//
26+
// <div class="phx-click-loading:animate-ping">
27+
//
28+
plugin(({addVariant}) => addVariant("phx-no-feedback", [".phx-no-feedback&", ".phx-no-feedback &"])),
29+
plugin(({addVariant}) => addVariant("phx-click-loading", [".phx-click-loading&", ".phx-click-loading &"])),
30+
plugin(({addVariant}) => addVariant("phx-submit-loading", [".phx-submit-loading&", ".phx-submit-loading &"])),
31+
plugin(({addVariant}) => addVariant("phx-change-loading", [".phx-change-loading&", ".phx-change-loading &"])),
32+
33+
// Embeds Heroicons (https://heroicons.com) into your app.css bundle
34+
// See your `CoreComponents.icon/1` for more information.
35+
//
36+
plugin(function({matchComponents, theme}) {
37+
let iconsDir = path.join(__dirname, "../deps/heroicons/optimized")
38+
let values = {}
39+
let icons = [
40+
["", "/24/outline"],
41+
["-solid", "/24/solid"],
42+
["-mini", "/20/solid"],
43+
["-micro", "/16/solid"]
44+
]
45+
icons.forEach(([suffix, dir]) => {
46+
fs.readdirSync(path.join(iconsDir, dir)).forEach(file => {
47+
let name = path.basename(file, ".svg") + suffix
48+
values[name] = {name, fullPath: path.join(iconsDir, dir, file)}
49+
})
50+
})
51+
matchComponents({
52+
"hero": ({name, fullPath}) => {
53+
let content = fs.readFileSync(fullPath).toString().replace(/\r?\n|\r/g, "")
54+
let size = theme("spacing.6")
55+
if (name.endsWith("-mini")) {
56+
size = theme("spacing.5")
57+
} else if (name.endsWith("-micro")) {
58+
size = theme("spacing.4")
59+
}
60+
return {
61+
[`--hero-${name}`]: `url('data:image/svg+xml;utf8,${content}')`,
62+
"-webkit-mask": `var(--hero-${name})`,
63+
"mask": `var(--hero-${name})`,
64+
"mask-repeat": "no-repeat",
65+
"background-color": "currentColor",
66+
"vertical-align": "middle",
67+
"display": "inline-block",
68+
"width": size,
69+
"height": size
70+
}
71+
}
72+
}, {values})
73+
})
74+
]
75+
}

0 commit comments

Comments
 (0)