Skip to content

Commit 3a80f2f

Browse files
Add Babashka support #273
Add babashka support
2 parents 3af6f4c + 9a1d307 commit 3a80f2f

File tree

18 files changed

+202
-105
lines changed

18 files changed

+202
-105
lines changed

.github/workflows/test.yml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ jobs:
5151
uses: DeLaGuardo/setup-clojure@13.1
5252
with:
5353
cli: 1.12.0.1488
54+
bb: 1.12.200
5455

5556
- name: Cache clojure dependencies
5657
uses: actions/cache@v4
@@ -74,3 +75,13 @@ jobs:
7475
AWS_SECRET_ACCESS_KEY: ${{ secrets.INTEGRATION_TEST_AWS_SECRET_ACCESS_KEY }}
7576

7677
run: clojure -M:dev:test-integration
78+
79+
- name: Run babashka tests
80+
env:
81+
# AWS_PROFILE is only required to comply with fixture check,
82+
# it's not actually used to load credentials
83+
AWS_PROFILE: aws-api-test
84+
AWS_ACCESS_KEY_ID: ${{ secrets.INTEGRATION_TEST_AWS_ACCESS_KEY_ID }}
85+
AWS_SECRET_ACCESS_KEY: ${{ secrets.INTEGRATION_TEST_AWS_SECRET_ACCESS_KEY }}
86+
87+
run: bb test-bb

CHANGES.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
# aws-api
22

3+
## DEV
4+
5+
* Add Babashka support
6+
* NOTE: the internal class `cognitect.aws.client.impl.Client` was removed
7+
38
## 0.8.741 / 2025-04-17
49

510
* Fix invalid signature for nonstandard host port [#263](https://github.com/cognitect-labs/aws-api/issues/263)

bb.edn

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{:deps {com.cognitect.aws/api {:local/root "."}}
2+
:tasks
3+
{test-bb {:doc "Run Babashka tests"
4+
:extra-paths ["src" "test/src" "test/resources"]
5+
:task bb-test-runner/run-tests}}}

src/cognitect/aws/client/impl.clj

Lines changed: 68 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -106,62 +106,71 @@
106106
(put-throwable result-ch t response-meta op-map))))
107107
result-ch))
108108

109-
(deftype Client [client-meta info]
110-
clojure.lang.IObj
111-
(meta [_] @client-meta)
112-
(withMeta [this m] (swap! client-meta merge m) this)
113-
114-
ILookup
115-
(valAt [this k]
116-
(.valAt this k nil))
117-
118-
(valAt [this k default]
119-
(case k
120-
:api
121-
(-> info :service :metadata :cognitect.aws/service-name)
122-
:region
123-
(some-> info :region-provider region/fetch)
124-
:endpoint
125-
(some-> info :endpoint-provider (endpoint/fetch (.valAt this :region)))
126-
:credentials
127-
(some-> info :credentials-provider credentials/fetch)
128-
:service
129-
(some-> info :service (select-keys [:metadata]))
130-
:http-client
131-
(:http-client info)
132-
default))
133-
134-
client.protocol/Client
135-
(-get-info [_] info)
136-
137-
(-invoke [client op-map]
138-
(a/<!! (.-invoke-async client op-map)))
139-
140-
(-invoke-async [client {:keys [op request] :as op-map}]
141-
(let [result-chan (or (:ch op-map) (a/promise-chan))
142-
{:keys [service retriable? backoff]} (client.protocol/-get-info client)
143-
spec (and (validation/validate-requests? client) (validation/request-spec service op))]
144-
(cond
145-
(not (contains? (:operations service) (:op op-map)))
146-
(a/put! result-chan (validation/unsupported-op-anomaly service op))
147-
148-
(and spec (not (validation/valid? spec request)))
149-
(a/put! result-chan (validation/invalid-request-anomaly spec request))
150-
151-
:else
152-
;; In case :body is an InputStream, ensure that we only read
153-
;; it once by reading it before we send it to with-retry.
154-
(let [req (-> (aws.protocols/build-http-request service op-map)
155-
(update :body util/->bbuf))]
156-
(retry/with-retry
157-
#(send-request client op-map req)
158-
result-chan
159-
(or (:retriable? op-map) retriable?)
160-
(or (:backoff op-map) backoff))))
161-
162-
result-chan))
163-
164-
(-stop [aws-client]
165-
(let [{:keys [http-client]} (client.protocol/-get-info aws-client)]
166-
(when-not (#'shared/shared-http-client? http-client)
167-
(http/stop http-client)))))
109+
(defn ->Client [client-meta info]
110+
(let [; backwards compatibility: `client-meta` used to be an atom
111+
client-meta-map (if (map? client-meta)
112+
client-meta
113+
(deref client-meta))
114+
datafy-fn (get client-meta-map 'clojure.core.protocols/datafy)
115+
; don't extend protocol via metadata (babashka friendly)
116+
client-meta' (dissoc client-meta-map 'clojure.core.protocols/datafy)]
117+
(with-meta
118+
(reify
119+
ILookup
120+
(valAt [this k]
121+
(.valAt this k nil))
122+
123+
(valAt [this k default]
124+
(case k
125+
:api
126+
(-> info :service :metadata :cognitect.aws/service-name)
127+
:region
128+
(some-> info :region-provider region/fetch)
129+
:endpoint
130+
(some-> info :endpoint-provider (endpoint/fetch (.valAt this :region)))
131+
:credentials
132+
(some-> info :credentials-provider credentials/fetch)
133+
:service
134+
(some-> info :service (select-keys [:metadata]))
135+
:http-client
136+
(:http-client info)
137+
default))
138+
139+
clojure.core.protocols/Datafiable
140+
(datafy [this] (datafy-fn this))
141+
142+
client.protocol/Client
143+
(-get-info [_] info)
144+
145+
(-invoke [client op-map]
146+
(a/<!! (client.protocol/-invoke-async client op-map)))
147+
148+
(-invoke-async [client {:keys [op request] :as op-map}]
149+
(let [result-chan (or (:ch op-map) (a/promise-chan))
150+
{:keys [service retriable? backoff]} (client.protocol/-get-info client)
151+
spec (and (validation/validate-requests? client) (validation/request-spec service op))]
152+
(cond
153+
(not (contains? (:operations service) (:op op-map)))
154+
(a/put! result-chan (validation/unsupported-op-anomaly service op))
155+
156+
(and spec (not (validation/valid? spec request)))
157+
(a/put! result-chan (validation/invalid-request-anomaly spec request))
158+
159+
:else
160+
;; In case :body is an InputStream, ensure that we only read
161+
;; it once by reading it before we send it to with-retry.
162+
(let [req (-> (aws.protocols/build-http-request service op-map)
163+
(update :body util/->bbuf))]
164+
(retry/with-retry
165+
#(send-request client op-map req)
166+
result-chan
167+
(or (:retriable? op-map) retriable?)
168+
(or (:backoff op-map) backoff))))
169+
170+
result-chan))
171+
172+
(-stop [aws-client]
173+
(let [{:keys [http-client]} (client.protocol/-get-info aws-client)]
174+
(when-not (#'shared/shared-http-client? http-client)
175+
(http/stop http-client)))))
176+
client-meta')))

src/cognitect/aws/ec2_metadata_utils.clj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
(ns ^:skip-wiki cognitect.aws.ec2-metadata-utils
55
"Impl, don't call directly"
66
(:require [clojure.string :as str]
7-
[clojure.data.json :as json]
7+
[cognitect.aws.json :as json]
88
[clojure.core.async :as a]
99
[cognitect.aws.http :as http]
1010
[cognitect.aws.util :as u]

src/cognitect/aws/http.clj

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
(:require [clojure.edn :as edn]
77
[clojure.core.async :as a]
88
[clojure.string :as str]
9+
[cognitect.aws.resources :as resources]
910
[cognitect.aws.dynaload :as dynaload]))
1011

1112
(set! *warn-on-reflection* true)
@@ -72,8 +73,7 @@
7273
7374
Throws if more than one `cognitect_aws_http.edn` files are found."
7475
[]
75-
(let [cl (.. Thread currentThread getContextClassLoader)
76-
cfgs (enumeration-seq (.getResources cl "cognitect_aws_http.edn"))]
76+
(let [cfgs (resources/resources "cognitect_aws_http.edn")]
7777
(case (count cfgs)
7878
0 'cognitect.aws.http.default/create
7979
1 (-> cfgs first read-config :constructor-var)

src/cognitect/aws/json.cljc

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
(ns ^:skip-wiki cognitect.aws.json
2+
"Impl, don't call directly."
3+
(:require #?(:bb [cheshire.core]
4+
:clj [clojure.data.json])))
5+
6+
(defn read-str [string & {:as options}]
7+
#?(:bb (cheshire.core/parse-string string (:key-fn options))
8+
:clj (clojure.data.json/read-str string options)))
9+
10+
(defn write-str [x]
11+
#?(:bb (cheshire.core/generate-string x)
12+
:clj (clojure.data.json/write-str x)))

src/cognitect/aws/protocols.clj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
(ns ^:skip-wiki cognitect.aws.protocols
55
"Impl, don't call directly. "
6-
(:require [clojure.data.json :as json]
6+
(:require [cognitect.aws.json :as json]
77
[clojure.string :as str]
88
[cognitect.aws.util :as util])
99
(:import (java.time ZoneOffset ZonedDateTime)))

src/cognitect/aws/resources.clj

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
(ns cognitect.aws.resources
2-
(:require [clojure.java.io :as io])
1+
(ns ^:skip-wiki cognitect.aws.resources
2+
"Impl, don't call directly."
33
(:import (clojure.lang RT)))
44

55
(def loader
@@ -16,4 +16,9 @@
1616
(defn resource
1717
"Returns the URL for a named resource, always using Clojure's base class loader."
1818
[n]
19-
(io/resource n loader))
19+
(.getResource ^ClassLoader loader n))
20+
21+
(defn resources
22+
"Returns a seq of URLs for a named resource, always using Clojure's base class loader."
23+
[n]
24+
(enumeration-seq (.getResources ^ClassLoader loader n)))

src/cognitect/aws/shape.clj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
like list, map, and structure, include shape-refs to refer to the other shapes
2323
that represent the member shapes."
2424
(:refer-clojure :exclude [resolve])
25-
(:require [clojure.data.json :as json]
25+
(:require [cognitect.aws.json :as json]
2626
[cognitect.aws.util :as util]))
2727

2828
(set! *warn-on-reflection* true)

0 commit comments

Comments
 (0)