Skip to content

Instantly share code, notes, and snippets.

Avatar

Francis Avila favila

View GitHub Profile
@favila
favila / safe-merge.clj
Created Feb 28, 2020
merge, but throws on conflicts
View safe-merge.clj
(defn safe-merge
"Like merge, but throws if maps have the same keys but different values."
[& maps]
(reduce
(fn [m [m2k m2v :as re]]
(if-some [[_ mv :as le] (find m m2k)]
(if (= mv m2v)
m
(throw (ex-info "Attempted to safe-merge maps with conflicting entries"
@favila
favila / datomic-client-conn-test.sh
Created Aug 28, 2019
shell one-liner to check a datomic client connection
View datomic-client-conn-test.sh
#!/bin/sh
ENDPOINT=localhost:8998 \
ACCESS=accesskey \
SECRET=secret \
ALIAS=alias \
clj -Sdeps '{:deps {com.datomic/client-pro {:mvn/version "0.8.28"}}}' \
-e "(require '[datomic.client.api :as d])" \
-e '(defmacro E [sym] `(System/getenv ~(name sym)))' \
-e '(-> (d/client {:server-type :peer-server
@favila
favila / LazyInitMapValues.java
Created May 25, 2019
Java map-like that lazily and atomically creates values for keys. Supports global shutdown also.
View LazyInitMapValues.java
package breeze.collections;
import java.util.ArrayList;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.CancellationException;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
@favila
favila / pdftree.clj
Created Sep 27, 2018
create a clojure-data-structure representation of a pdf document (from pdfbox) just for visibility into the pdf's structure
View pdftree.clj
(with-open [pdf-document (PDDocument/load (clojure.java.io/file THE-FILE))]
(let [doc (.getDocument pdf-document)
getobj (fn [^COSObject x]
[:pdf.type/object (.getObjectNumber x) (.getGenerationNumber x)])
visit (fn [^COSBase x ^ICOSVisitor vis]
(if (.isDirect x)
(if (instance? COSObject x)
(getobj x)
(.accept x vis))
(cond
@favila
favila / keys_plus.cljc
Created Sep 26, 2018
s/keys+, an s/keys variant that allows inline respec-ing of a key to narrow the range of its type
View keys_plus.cljc
(ns com.breezeehr.specs.keys-plus
"Variants of clojure.spec/keys and keys* that allow additional inline spec-ing."
(:refer-clojure :exclude [keys])
(:require [clojure.core :as c]
[clojure.spec.alpha :as s]
[clojure.spec.gen.alpha :as gen]
[clojure.walk :as walk])
#?(:cljs (:require-macros [com.breezeehr.specs.keys-plus]))
#?(:clj (:import (java.util UUID))))
@favila
favila / last-touched-tx.clj
Created Feb 27, 2018
datomic query to return the tx at which an entity or its components were last touched
View last-touched-tx.clj
(require '[datomic.api :as d])
(defn last-touched-tx
"Return the tx of the oldest assertion on `entity` or any of its components."
[db entity]
(or (d/q '[:find (max ?tx) .
:in $ % ?root
:where
(component-entities ?root ?ce)
(union ?root ?ce ?e)
[?e _ _ ?tx]]
@favila
favila / transit_uuid_reader.cljc
Created Feb 20, 2018
data readers to emit transit uuids in cljs with bits calculated at compile-time
View transit_uuid_reader.cljc
(ns favila.transit-uuid-reader
"Use as a data reader for cljs-in-cljs or clj-for-cljs compilation to emit a
transit uuid type from a uuid string.
For clj-for-cljs compilation you must require this namespace at the top of
your cljs code somehow so that the emitted code can call
`transit-uuid-from-ints`"
#?(:clj (:import
(com.cognitect.transit types)
(goog.math Long))
@favila
favila / datomic-counter.clj
Created Sep 29, 2017
Demonstrate the creation and use of an auto-increment counter (with nonce) in datomic
View datomic-counter.clj
(require '[datomic.api :as d])
(d/create-database "datomic:mem://counter-example")
;=> true
(def c (d/connect "datomic:mem://counter-example"))
;=> #'user/c
;; The essential features of creating and using an auto-increment counter in datomic:
;;
;; 1. A counter entity must store the current value and a nonce.
@favila
favila / spec-relation.clj
Last active Sep 1, 2017
Spec for a relation (tuple with named positions, optional trailing positions). Takes key + predicate pairs, and an optional final vector with key + predicate pairs. The predicates cannot be regexs. Returns a regex op that matches all values in sequence and returns a map of keys to the corresponding value, like s/cat. Unlike s/cat, values may onl…
View spec-relation.clj
(ns com.breezeehr.spec-utils
(:require [clojure.spec.alpha :as s]))
(s/def ::relation-arg-pair
(s/cat
:k (s/and keyword? #(not= % ::relation-tail))
:v #(not (s/regex? %))))
(defn- distinct-relation-keys? [{:keys [req opt]}]
(apply distinct? (concat (map :k req) (map :k opt))))
@favila
favila / unresponsive-immutant.clj
Created Jul 20, 2017
Minimum reproducible case where immutant connections seem to hang when using async/as-channel responses. This problem appears in immutant 2.1.7. The cause is not closing the InputStream from the request.
View unresponsive-immutant.clj
;;; immutant.web >= 2.1.7 will block subsequent requests on the same connection
;;; when using an async/as-channel response if the request body InputStream is
;;; not closed
;;; The essential difference seems to be the undertow dependency: 1.3.x
;;; does not care if the request is closed, but 1.4.x seems to care.
;;; Immutant 2.1.6 used undertow 1.3.x, but 2.1.7 switched to 1.4.x
;; leinigen Dependency: [[org.immutant/web "2.1.9"]]