update
This commit is contained in:
-22
@@ -1,22 +0,0 @@
|
||||
# API Service Plan
|
||||
|
||||
## Stack
|
||||
- http-kit (HTTP server)
|
||||
- reitit (routing) + Ring middleware
|
||||
- next.jdbc + HoneySQL (via shared/)
|
||||
- PostgreSQL everywhere (dev + prod)
|
||||
|
||||
## Responsibilities
|
||||
- Stateless REST API: all reads & writes for messages, channels, users
|
||||
- Only service (besides Auth GW) with a direct PG connection
|
||||
- Publishes events to NATS after DB writes
|
||||
- No live connections — pure request/response
|
||||
- Sits behind auth gateway (all requests pre-authenticated)
|
||||
|
||||
## TODO
|
||||
- [ ] Define reitit route table
|
||||
- [ ] http-kit server setup
|
||||
- [ ] Design message/channel/user API endpoints
|
||||
- [ ] Ring middleware: error handling, content negotiation, request logging
|
||||
- [ ] NATS publish on write (message sent, channel created, etc.)
|
||||
- [ ] Database migrations
|
||||
@@ -42,9 +42,10 @@
|
||||
|
||||
(defn- get-message-row [ds message-id]
|
||||
(or (db/execute-one! ds
|
||||
{:select [:*]
|
||||
:from [:messages]
|
||||
:where [:= :id [:cast message-id :uuid]]})
|
||||
{:select [:m.* :u.username :u.display-name :u.avatar-url]
|
||||
:from [[:messages :m]]
|
||||
:join [[:users :u] [:= :m.user-id :u.id]]
|
||||
:where [:= :m.id [:cast message-id :uuid]]})
|
||||
(throw (ex-info "Message not found" {:type :ajet.chat/not-found}))))
|
||||
|
||||
(defn- nats-subject-for-channel
|
||||
@@ -140,19 +141,19 @@
|
||||
|
||||
(check-channel-member! ds channel-id user-id)
|
||||
|
||||
(let [base-where [:= :channel-id [:cast channel-id :uuid]]
|
||||
(let [base-where [:= :m.channel-id [:cast channel-id :uuid]]
|
||||
;; Cursor-based pagination using subquery on created_at
|
||||
where-clause (cond
|
||||
before
|
||||
[:and base-where
|
||||
[:< :created-at
|
||||
[:< :m.created-at
|
||||
{:select [:created-at]
|
||||
:from [:messages]
|
||||
:where [:= :id [:cast before :uuid]]}]]
|
||||
|
||||
after
|
||||
[:and base-where
|
||||
[:> :created-at
|
||||
[:> :m.created-at
|
||||
{:select [:created-at]
|
||||
:from [:messages]
|
||||
:where [:= :id [:cast after :uuid]]}]]
|
||||
@@ -160,10 +161,11 @@
|
||||
:else base-where)
|
||||
order-dir (if after :asc :desc)
|
||||
messages (db/execute! ds
|
||||
{:select [:*]
|
||||
:from [:messages]
|
||||
{:select [:m.* :u.username :u.display-name :u.avatar-url]
|
||||
:from [[:messages :m]]
|
||||
:join [[:users :u] [:= :m.user-id :u.id]]
|
||||
:where where-clause
|
||||
:order-by [[:created-at order-dir]]
|
||||
:order-by [[:m.created-at order-dir]]
|
||||
:limit limit})
|
||||
;; Always return newest-last ordering
|
||||
messages (if (= order-dir :desc)
|
||||
@@ -213,19 +215,22 @@
|
||||
(when resolved-parent-id
|
||||
(create-thread-notifications! tx message-id resolved-parent-id user-id)))
|
||||
|
||||
;; Publish event
|
||||
;; Publish event with user info for real-time display
|
||||
(let [channel (get-channel-row ds channel-id)
|
||||
subject (nats-subject-for-channel channel)
|
||||
message (get-message-row ds message-id)]
|
||||
message (get-message-row ds message-id)
|
||||
user (db/execute-one! ds
|
||||
{:select [:username :display-name :avatar-url]
|
||||
:from [:users]
|
||||
:where [:= :id [:cast user-id :uuid]]})]
|
||||
|
||||
(publish-event! nats subject :message/created
|
||||
{:message-id message-id
|
||||
:channel-id channel-id
|
||||
:user-id user-id
|
||||
:body-md body-md
|
||||
:parent-id resolved-parent-id
|
||||
:community-id (when (:community-id channel)
|
||||
(str (:community-id channel)))})
|
||||
(merge message
|
||||
{:username (:username user)
|
||||
:display-name (:display-name user)
|
||||
:avatar-url (:avatar-url user)
|
||||
:community-id (when (:community-id channel)
|
||||
(str (:community-id channel)))}))
|
||||
|
||||
(mw/json-response 201 message)))))
|
||||
|
||||
@@ -360,12 +365,13 @@
|
||||
|
||||
(check-channel-member! ds (str (:channel-id message)) user-id)
|
||||
|
||||
;; Get root message + all replies
|
||||
;; Get root message + all replies (with user info)
|
||||
(let [replies (db/execute! ds
|
||||
{:select [:*]
|
||||
:from [:messages]
|
||||
:where [:= :parent-id [:cast message-id :uuid]]
|
||||
:order-by [[:created-at :asc]]})]
|
||||
{:select [:m.* :u.username :u.display-name :u.avatar-url]
|
||||
:from [[:messages :m]]
|
||||
:join [[:users :u] [:= :m.user-id :u.id]]
|
||||
:where [:= :m.parent-id [:cast message-id :uuid]]
|
||||
:order-by [[:m.created-at :asc]]})]
|
||||
(mw/json-response {:root message
|
||||
:replies replies}))))
|
||||
|
||||
|
||||
Reference in New Issue
Block a user