001/* 002 * Copyright 2022-2026 Revetware LLC. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package com.soklet; 018 019import org.jspecify.annotations.NonNull; 020 021import static java.util.Objects.requireNonNull; 022 023/** 024 * Contract for generating {@link Request} identifiers of a particular type (for example, sequential {@link Long} values, random {@link java.util.UUID}s, etc.) 025 * <p> 026 * Useful for incorporating request data in nonlocal deployment environments (e.g. a tracing header like <a href="https://docs.aws.amazon.com/elasticloadbalancing/latest/application/load-balancer-request-tracing.html" target="_blank">{@code X-Amzn-Trace-Id}</a>). 027 * <p> 028 * Implementations may or may not guarantee uniqueness, ordering, or repeatability of generated identifiers. Callers should not assume any such guarantees unless documented by the implementation. 029 * <p> 030 * Standard threadsafe implementations can be acquired via these factory methods: 031 * <ul> 032 * <li>{@link #defaultInstance()}</li> 033 * <li>{@link #defaultSessionInstance()}</li> 034 * <li>{@link #fromPrefix(String)}</li> 035 * </ul> 036 * 037 * @param <T> the type of identifier produced 038 * @author <a href="https://www.revetkn.com">Mark Allen</a> 039 */ 040@FunctionalInterface 041public interface IdGenerator<T> { 042 /** 043 * Generates an identifier for the given {@link Request}. 044 * <p> 045 * Implementations may choose different strategies (sequential, random, host-based, etc.) 046 * and are not required to guarantee uniqueness unless explicitly documented. 047 * <p> 048 * Implementations may choose to incorporate request data (e.g. a tracing header like {@code X-Amzn-Trace-Id}). 049 * 050 * @param request the request for which an identifier is being generated 051 * @return the generated identifier (never {@code null}) 052 */ 053 @NonNull 054 T generateId(@NonNull Request request); 055 056 /** 057 * Acquires a threadsafe {@link IdGenerator} with a best-effort local IP prefix. 058 * <p> 059 * This method is guaranteed to return a new instance. 060 * 061 * @return an {@code IdGenerator} with default settings 062 */ 063 @NonNull 064 static IdGenerator<String> defaultInstance() { 065 return DefaultIdGenerator.defaultInstance(); 066 } 067 068 /** 069 * Acquires a threadsafe, cryptographically strong session identifier generator. 070 * <p> 071 * This implementation is intended for protocol session identifiers such as MCP 072 * {@code MCP-Session-Id} values, where IDs must be globally unique, unguessable, 073 * and safe to include in HTTP header values. 074 * <p> 075 * Generated IDs contain only URL-safe visible ASCII characters. 076 * 077 * @return an {@code IdGenerator} suitable for session identifiers 078 */ 079 @NonNull 080 static IdGenerator<String> defaultSessionInstance() { 081 return DefaultSessionIdGenerator.defaultInstance(); 082 } 083 084 085 /** 086 * Acquires a threadsafe {@link IdGenerator} with the given prefix. 087 * <p> 088 * This method is guaranteed to return a new instance. 089 * 090 * @param prefix a string to prepend to the generated numeric ID 091 * @return an {@code IdGenerator} configured with the given prefix 092 */ 093 @NonNull 094 static IdGenerator<String> fromPrefix(@NonNull String prefix) { 095 requireNonNull(prefix); 096 return DefaultIdGenerator.fromPrefix(prefix); 097 } 098}