diff --git a/c-historico/handler.cr b/c-historico/handler.cr new file mode 100644 index 0000000..5fb1f31 --- /dev/null +++ b/c-historico/handler.cr @@ -0,0 +1,93 @@ +require "http/client" +require "http/headers" +require "http/request" +require "ishi/html" +require "json" + +class Handler + def query(sql) + params = URI::Params.encode({"q": sql}) + response = HTTP::Client.get URI.new( + "http", + "10.61.0.1", + 4001, + "/db/query", + params) + + # This API only has a values key when there are actual results + results = JSON.parse(response.body)["results"][0].as_h + if results.has_key?("values") + return results["values"].as_a.map { |r| + [r[0].as_i, r[1].as_i] + } + end + # Return a dummy result + [[1922, 0]] + end + + nombres = [] of String + + def run(request : HTTP::Request) + unless (body = request.body).nil? + query = JSON.parse(body) + nombres = query["i"].as_s.split(",").map { |n| n.strip } + nombres.reject! { |n| n.size == 0 } + end + + if nombres.nil? || nombres.empty? + nombres = ["maria", "juan"] + end + + # Remove all diacritics and whatnot + nombres = nombres.map { |n| + normalized = n.unicode_normalize(:nfkd).chars + normalized.reject! { |c| + !c.ascii_letter? + }.join("").downcase + } + + puts "Processing #{nombres}" + + buffer = IO::Memory.new + Ishi.new(buffer) do + canvas_size(800, 300) + show_key(true) + xrange(1922..2015) + nombres.map { |nombre| + sql = "SELECT anio, contador FROM nombres WHERE nombre = '#{nombre}' ORDER BY anio" + x = Array(Int32).new + y = Array(Int32).new + query(sql).map { |r| + x << r[0] + y << r[1] + } + plot(x, y, title: nombre.titleize, style: :lines, linewidth: 3) + } + end + + # This is a whole page, we just need some bits + html = buffer.to_s.split("\n") + html = html[html.index("")] + html = html.join("\n") + %( +
+ + + +
+ + Sorry, your browser seems not to support the HTML 5 canvas element + +
+ +
+) + + { + body: html, + status_code: 200, + headers: HTTP::Headers{"Content-Type" => "text/html"}, + } + end +end diff --git a/functions.yml b/functions.yml index 18bb806..ba4fe5a 100644 --- a/functions.yml +++ b/functions.yml @@ -15,3 +15,9 @@ functions: lang: python3-flask handler: ./tapas image: ralsina/tapas:latest + c-historico: + lang: crystal-http + handler: ./c-historico + image: ralsina/c-historico:latest + build_args: + ADDITIONAL_PACKAGE: gnuplot diff --git a/template/crystal-http/Dockerfile b/template/crystal-http/Dockerfile index 2ba566e..48a382c 100644 --- a/template/crystal-http/Dockerfile +++ b/template/crystal-http/Dockerfile @@ -1,24 +1,31 @@ FROM --platform=${TARGETPLATFORM:-linux/amd64} ghcr.io/openfaas/of-watchdog:0.9.10 as watchdog - FROM --platform=${TARGETPLATFORM:-linux/amd64} alpine as build +ARG ADDITIONAL_PACKAGE COPY --from=watchdog /fwatchdog /usr/bin/fwatchdog -RUN apk update && apk upgrade && apk add crystal shards openssl-dev && apk cache clean +RUN apk update && apk upgrade && apk add crystal shards openssl-dev ${ADDITIONAL_PACKAGE} && apk cache clean WORKDIR /home/app COPY . . COPY function/shard.yml shard.yml RUN shards install -RUN crystal build main.cr -o handler --release && strip handler && rm -rf /root/.cache +RUN crystal build main.cr -o handler -p && strip handler && rm -rf /root/.cache -# Create a non-root user +FROM --platform=${TARGETPLATFORM:-linux/amd64} alpine as ship +ARG ADDITIONAL_PACKAGE +RUN apk update && apk upgrade && apk add openssl pcre2 libgcc gc libevent ${ADDITIONAL_PACKAGE} && apk cache clean +# Add non root user +# Add non root user RUN addgroup -S app && adduser app -S -G app +WORKDIR /home/app USER app -WORKDIR /home/app +COPY --from=build /home/app/function/ . +COPY --from=build /home/app/handler . +COPY --from=watchdog /fwatchdog /usr/bin/fwatchdog ENV fprocess="./handler" EXPOSE 8080