mirror of
https://github.com/metosin/reitit.git
synced 2025-12-25 11:18:25 +00:00
Segment-router to rule 'em all
This commit is contained in:
parent
607e34c671
commit
8019cebdc7
2 changed files with 70 additions and 1 deletions
50
modules/reitit-core/src/reitit/segment.cljc
Normal file
50
modules/reitit-core/src/reitit/segment.cljc
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
(ns reitit.segment
|
||||
(:require [reitit.impl :as impl]))
|
||||
|
||||
(defrecord Match [data params])
|
||||
|
||||
(defprotocol Segment
|
||||
(-insert [this ps data])
|
||||
(-lookup [this ps params]))
|
||||
|
||||
(extend-protocol Segment
|
||||
nil
|
||||
(-insert [this ps data])
|
||||
(-lookup [this ps params]))
|
||||
|
||||
(defn- segments [^String path]
|
||||
(mapv
|
||||
(fn [^String p]
|
||||
(if (impl/wild-param? p) (-> p (subs 1) keyword) p))
|
||||
(.split path "/")))
|
||||
|
||||
;; TODO: catch-all
|
||||
(defn- segment
|
||||
([]
|
||||
(segment {} #{} nil))
|
||||
([children wilds data]
|
||||
(let [children' (impl/fast-map children)]
|
||||
(reify
|
||||
Segment
|
||||
(-insert [_ [p & ps] data]
|
||||
(if-not p
|
||||
(segment children wilds data)
|
||||
(let [wilds (if (keyword? p) (conj wilds p) wilds)
|
||||
children (update children p #(-insert (or % (segment)) ps data))]
|
||||
(segment children wilds data))))
|
||||
(-lookup [_ [p & ps] params]
|
||||
(if (nil? p)
|
||||
(assoc data :params params)
|
||||
(or (-lookup (impl/fast-get children' p) ps params)
|
||||
(some #(-lookup (impl/fast-get children' %) ps (assoc params % p)) wilds))))))))
|
||||
|
||||
(defn create [paths]
|
||||
(reduce
|
||||
(fn [segment [p data]]
|
||||
(let [ps (segments p)]
|
||||
(-insert segment ps (map->Match {:data data}))))
|
||||
(segment) paths))
|
||||
|
||||
(defn lookup [segment ^String path]
|
||||
(let [ps (.split path "/")]
|
||||
(-lookup segment ps {})))
|
||||
|
|
@ -2,6 +2,7 @@
|
|||
(:require [clojure.test :refer :all]
|
||||
[io.pedestal.http.route.prefix-tree :as p]
|
||||
[reitit.trie :as trie]
|
||||
[reitit.segment :as segment]
|
||||
[criterium.core :as cc]))
|
||||
|
||||
;;
|
||||
|
|
@ -75,6 +76,9 @@
|
|||
(trie/insert acc p d))
|
||||
nil routes))
|
||||
|
||||
(def reitit-segment
|
||||
(segment/create routes))
|
||||
|
||||
(defn bench! []
|
||||
|
||||
;; 2.3ms
|
||||
|
|
@ -99,7 +103,22 @@
|
|||
;; 0.8ms (fix payloads)
|
||||
(cc/quick-bench
|
||||
(dotimes [_ 1000]
|
||||
(trie/lookup reitit-tree "/v1/orgs/1/topics" {}))))
|
||||
(trie/lookup reitit-tree "/v1/orgs/1/topics" {})))
|
||||
|
||||
;; 0.9ms (initial)
|
||||
;; 0.5ms (protocols)
|
||||
;; 1.0ms (with path params)
|
||||
;; 1.0ms (Match records)
|
||||
;; 0.63ms (Single sweep path params)
|
||||
;; 0.51ms (Cleanup)
|
||||
(cc/quick-bench
|
||||
(dotimes [_ 1000]
|
||||
(segment/lookup reitit-segment "/v1/orgs/1/topics"))))
|
||||
|
||||
(comment
|
||||
(bench!))
|
||||
|
||||
(comment
|
||||
(p/lookup pedestal-tree "/v1/orgs/1/topics")
|
||||
(trie/lookup reitit-tree "/v1/orgs/1/topics" {})
|
||||
(segment/lookup reitit-segment "/v1/orgs/1/topics"))
|
||||
|
|
|
|||
Loading…
Reference in a new issue