at protocol indexer with flexible filtering, xrpc queries, and a cursor-backed event stream, built on fjall
at-protocol atproto indexer rust fjall
at e558361eb571e7e019a4a7967bb4ae7e666f3f25 141 lines 4.5 kB view raw
1#!/usr/bin/env nu 2 3def test-repos [url: string] { 4 print "verifying /repos pagination and filtering..." 5 6 # 1. Test limit 7 print " testing limit=1..." 8 let items = (http get $"($url)/repos?limit=1" | from json -o) 9 let count = ($items | length) 10 print $" count: ($count)" 11 if $count != 1 { 12 print " FAILED: expected 1 item" 13 exit 1 14 } 15 16 # 2. Test partition=all 17 print " testing partition=all..." 18 let all_items = (http get $"($url)/repos?partition=all" | from json -o) 19 print $" count: ($all_items | length)" 20 21 # 3. Test cursor (if we have items) 22 if ($all_items | length) > 1 { 23 let first_did = ($all_items | get 0).did 24 print $" testing cursor with did ($first_did)..." 25 let cursor_items = (http get $"($url)/repos?cursor=($first_did)&limit=1" | from json -o) 26 if ($cursor_items | length) > 0 { 27 let next_did = ($cursor_items | get 0).did 28 if $first_did == $next_did { 29 print " FAILED: cursor did should be excluded" 30 exit 1 31 } 32 print $" next did: ($next_did)" 33 } 34 } 35 36 # 4. Test partition=pending 37 print " testing partition=pending..." 38 let pending_items = (http get $"($url)/repos?partition=pending" | from json -o) 39 print $" pending count: ($pending_items | length)" 40 41 # 5. Test partition=resync 42 print " testing partition=resync..." 43 let resync_items = (http get $"($url)/repos?partition=resync" | from json -o) 44 print $" resync count: ($resync_items | length)" 45 46 print "all /repos pagination and filtering tests passed!" 47} 48 49def test-errors [url: string] { 50 print "verifying /repos error handling..." 51 52 # 1. Invalid DID in PUT 53 print " testing PUT /repos with invalid DID..." 54 let resp_put = (http put -f -e -t application/json $"($url)/repos" { did: "invalid" }) 55 if $resp_put.status != 400 { 56 print $" FAILED: expected 400, got ($resp_put.status)" 57 exit 1 58 } 59 60 # 2. Invalid DID in DELETE 61 print " testing DELETE /repos with invalid DID..." 62 let resp_del = (http delete -f -e -t application/json $"($url)/repos" --data { did: "invalid" }) 63 if $resp_del.status != 400 { 64 print $" FAILED: expected 400, got ($resp_del.status)" 65 exit 1 66 } 67 68 # 3. Invalid cursor in GET 69 print " testing GET /repos with invalid cursor..." 70 let resp_get_cursor = (http get -f -e $"($url)/repos?cursor=invalid") 71 if $resp_get_cursor.status != 400 { 72 print $" FAILED: expected 400, got ($resp_get_cursor.status)" 73 exit 1 74 } 75 76 # 4. Invalid partition in GET 77 print " testing GET /repos with invalid partition..." 78 let resp_get_part = (http get -f -e $"($url)/repos?partition=invalid") 79 if $resp_get_part.status != 400 { 80 print $" FAILED: expected 400, got ($resp_get_part.status)" 81 exit 1 82 } 83 84 print "all /repos error handling tests passed!" 85} 86 87def main [] { 88 let port = 3001 89 let url = $"http://localhost:($port)" 90 let db_path = (mktemp -d -t hydrant_api_test.XXXXXX) 91 92 print $"starting hydrant for API verification..." 93 let binary = (build-hydrant) 94 let instance = (start-hydrant $binary $db_path $port) 95 96 if (wait-for-api $url) { 97 # add a few repos 98 let dids = [ 99 "did:plc:dfl62fgb7wtjj3fcbb72naae" 100 "did:plc:q6gjnv26m4ay3m42ojvzx2m4" 101 ] 102 http put -t application/json $"($url)/repos" ($dids | each { |d| { did: $d } }) 103 104 test-repos $url 105 test-errors $url 106 } 107 108 kill $instance.pid 109} 110 111# Helper to build hydrant 112def build-hydrant [] { 113 cargo build --release --quiet 114 "./target/release/hydrant" 115} 116 117# Helper to start hydrant 118def start-hydrant [binary: string, db_path: string, port: int] { 119 let log_file = $"($db_path)/hydrant.log" 120 let pid = (with-env { 121 HYDRANT_DATABASE_PATH: $db_path, 122 HYDRANT_API_PORT: ($port | into string), 123 HYDRANT_DEBUG_PORT: (($port + 1) | into string), 124 HYDRANT_MODE: "filter", 125 HYDRANT_LOG_LEVEL: "info" 126 } { 127 sh -c $"($binary) >($log_file) 2>&1 & echo $!" | str trim | into int 128 }) 129 { pid: $pid, log: $log_file } 130} 131 132# Helper to wait for api 133def wait-for-api [url: string] { 134 for i in 1..20 { 135 if (try { (http get $"($url)/health") == "OK" } catch { false }) { 136 return true 137 } 138 sleep 500ms 139 } 140 false 141}