feat(server): wire device_id through delivery proto and v2 handlers
Add device_id field to FetchRequest, FetchWaitRequest, PeekRequest, and AckRequest proto messages. V2 handlers now build composite queue keys (identity_key + device_id) when device_id is provided, enabling per-device fetch/ack scoping.
This commit is contained in:
@@ -35,6 +35,19 @@ pub async fn handle_enqueue(state: Arc<ServerState>, ctx: RequestContext) -> Han
|
||||
return HandlerResult::err(RpcStatus::RateLimited, "rate limit exceeded");
|
||||
}
|
||||
|
||||
// Idempotency dedup: if message_id is provided and already seen, return the cached seq.
|
||||
if !req.message_id.is_empty() {
|
||||
if let Some(entry) = state.seen_message_ids.get(&req.message_id) {
|
||||
let (cached_seq, _ts) = *entry;
|
||||
let proto = v1::EnqueueResponse {
|
||||
seq: cached_seq,
|
||||
delivery_proof: Vec::new(),
|
||||
duplicate: true,
|
||||
};
|
||||
return HandlerResult::ok(Bytes::from(proto.encode_to_vec()));
|
||||
}
|
||||
}
|
||||
|
||||
let svc = DeliveryService {
|
||||
store: Arc::clone(&state.store),
|
||||
waiters: Arc::clone(&state.waiters),
|
||||
@@ -49,6 +62,12 @@ pub async fn handle_enqueue(state: Arc<ServerState>, ctx: RequestContext) -> Han
|
||||
|
||||
match svc.enqueue(domain_req) {
|
||||
Ok(resp) => {
|
||||
// Record message_id for dedup.
|
||||
if !req.message_id.is_empty() {
|
||||
let now = crate::auth::current_timestamp();
|
||||
state.seen_message_ids.insert(req.message_id, (resp.seq, now));
|
||||
}
|
||||
|
||||
// Fire hook.
|
||||
let action = state.hooks.on_message_enqueue(&MessageEvent {
|
||||
sender_identity: Some(identity_key),
|
||||
@@ -64,6 +83,7 @@ pub async fn handle_enqueue(state: Arc<ServerState>, ctx: RequestContext) -> Han
|
||||
let proto = v1::EnqueueResponse {
|
||||
seq: resp.seq,
|
||||
delivery_proof: resp.delivery_proof,
|
||||
duplicate: false,
|
||||
};
|
||||
HandlerResult::ok(Bytes::from(proto.encode_to_vec()))
|
||||
}
|
||||
@@ -87,12 +107,19 @@ pub async fn handle_fetch(state: Arc<ServerState>, ctx: RequestContext) -> Handl
|
||||
waiters: Arc::clone(&state.waiters),
|
||||
};
|
||||
|
||||
let base_key = if req.recipient_key.is_empty() {
|
||||
identity_key
|
||||
} else {
|
||||
req.recipient_key
|
||||
};
|
||||
let recipient_key = if req.device_id.is_empty() {
|
||||
base_key
|
||||
} else {
|
||||
DeliveryService::device_recipient_key(&base_key, &req.device_id)
|
||||
};
|
||||
|
||||
let domain_req = FetchReq {
|
||||
recipient_key: if req.recipient_key.is_empty() {
|
||||
identity_key
|
||||
} else {
|
||||
req.recipient_key
|
||||
},
|
||||
recipient_key,
|
||||
channel_id: req.channel_id,
|
||||
limit: req.limit,
|
||||
};
|
||||
@@ -126,11 +153,16 @@ pub async fn handle_fetch_wait(state: Arc<ServerState>, ctx: RequestContext) ->
|
||||
Err(e) => return HandlerResult::err(RpcStatus::BadRequest, &format!("decode: {e}")),
|
||||
};
|
||||
|
||||
let recipient_key = if req.recipient_key.is_empty() {
|
||||
let base_key = if req.recipient_key.is_empty() {
|
||||
identity_key
|
||||
} else {
|
||||
req.recipient_key
|
||||
};
|
||||
let recipient_key = if req.device_id.is_empty() {
|
||||
base_key
|
||||
} else {
|
||||
DeliveryService::device_recipient_key(&base_key, &req.device_id)
|
||||
};
|
||||
|
||||
let timeout_ms = if req.timeout_ms == 0 {
|
||||
30_000
|
||||
@@ -221,12 +253,19 @@ pub async fn handle_peek(state: Arc<ServerState>, ctx: RequestContext) -> Handle
|
||||
waiters: Arc::clone(&state.waiters),
|
||||
};
|
||||
|
||||
let base_key = if req.recipient_key.is_empty() {
|
||||
identity_key
|
||||
} else {
|
||||
req.recipient_key
|
||||
};
|
||||
let recipient_key = if req.device_id.is_empty() {
|
||||
base_key
|
||||
} else {
|
||||
DeliveryService::device_recipient_key(&base_key, &req.device_id)
|
||||
};
|
||||
|
||||
let domain_req = PeekReq {
|
||||
recipient_key: if req.recipient_key.is_empty() {
|
||||
identity_key
|
||||
} else {
|
||||
req.recipient_key
|
||||
},
|
||||
recipient_key,
|
||||
channel_id: req.channel_id,
|
||||
limit: req.limit,
|
||||
};
|
||||
@@ -265,12 +304,19 @@ pub async fn handle_ack(state: Arc<ServerState>, ctx: RequestContext) -> Handler
|
||||
waiters: Arc::clone(&state.waiters),
|
||||
};
|
||||
|
||||
let base_key = if req.recipient_key.is_empty() {
|
||||
identity_key
|
||||
} else {
|
||||
req.recipient_key
|
||||
};
|
||||
let recipient_key = if req.device_id.is_empty() {
|
||||
base_key
|
||||
} else {
|
||||
DeliveryService::device_recipient_key(&base_key, &req.device_id)
|
||||
};
|
||||
|
||||
let domain_req = AckReq {
|
||||
recipient_key: if req.recipient_key.is_empty() {
|
||||
identity_key
|
||||
} else {
|
||||
req.recipient_key
|
||||
},
|
||||
recipient_key,
|
||||
channel_id: req.channel_id,
|
||||
seq_up_to: req.seq_up_to,
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user