diff --git a/localinfra/pds.env b/localinfra/pds.env --- a/localinfra/pds.env +++ b/localinfra/pds.env @@ -10,4 +10,9 @@ PDS_DID_PLC_URL=http://localhost:8080 PDS_HOSTNAME=pds.tngl.boltless.dev PDS_PORT=3000 + +# firehose backfill window. default is 24h (DAY), which makes cursor=0 emit an +# OutdatedCursor #info once history is >24h old; hydrant mishandles that info +# frame and loops. widen the window so cursor=0 streams from seq 1 cleanly. +PDS_REPO_BACKFILL_LIMIT_MS=31536000000 # PDS_CRAWLERS=https://relay.tngl.boltless.dev diff --git a/lexicons/string/getString.json b/lexicons/string/getString.json new file mode 100644 --- /dev/null +++ b/lexicons/string/getString.json @@ -0,0 +1,41 @@ +{ + "lexicon": 1, + "id": "sh.tangled.string.getString", + "defs": { + "main": { + "type": "query", + "parameters": { + "type": "params", + "required": ["string"], + "properties": { + "string": { + "type": "string", + "format": "at-uri", + "description": "AT-URI of the sh.tangled.string record to fetch." + } + } + }, + "output": { + "encoding": "application/json", + "schema": { + "type": "object", + "required": ["uri", "value"], + "properties": { + "uri": { + "type": "string", + "format": "at-uri" + }, + "cid": { + "type": "string", + "format": "cid" + }, + "value": { + "type": "unknown", + "description": "Embedded sh.tangled.string record." + } + } + } + } + } + } +} diff --git a/bobbin/crates/xrpc/src/lib.rs b/bobbin/crates/xrpc/src/lib.rs --- a/bobbin/crates/xrpc/src/lib.rs +++ b/bobbin/crates/xrpc/src/lib.rs @@ -74,7 +74,9 @@ Member as SpindleMember, MemberRecord as SpindleMemberRecord, }; use bobbin_types::sh_tangled::spindle::{Spindle, SpindleRecord}; -use bobbin_types::sh_tangled::string::{TangledString, TangledStringRecord}; +use bobbin_types::sh_tangled::string::{ + TangledString, TangledStringGetRecordOutput, TangledStringRecord, +}; use futures::Stream; use futures::stream::{self, StreamExt, TryStreamExt}; use jacquard_common::types::did::Did; @@ -401,6 +403,7 @@ "/xrpc/sh.tangled.spindle.countMembers", get(count_spindle_members), ) + .route("/xrpc/sh.tangled.string.getString", get(get_string)) .route("/xrpc/sh.tangled.string.listStrings", get(list_strings)) .route("/xrpc/sh.tangled.string.countStrings", get(count_strings)) .route("/xrpc/sh.tangled.search.query", get(search_query)) @@ -617,6 +620,11 @@ #[derive(Debug, Deserialize)] struct GetPullQuery { pull: AtUri, +} + +#[derive(Debug, Deserialize)] +struct GetStringQuery { + string: AtUri, } #[derive(Debug, Deserialize)] @@ -1313,6 +1321,19 @@ ) -> Result>>, XrpcError> { let (body, value) = fetch::>(&state, &q.pull).await?; Ok(Json(Deduped(PullGetRecordOutput { + cid: Some(body.cid.clone()), + uri: body.uri.clone(), + value, + }))) +} + +async fn get_string( + State(state): State, + XrpcQuery(q): XrpcQuery, +) -> Result>>, XrpcError> { + let (body, value) = + fetch::>(&state, &q.string).await?; + Ok(Json(Deduped(TangledStringGetRecordOutput { cid: Some(body.cid.clone()), uri: body.uri.clone(), value,