Spring Boot Starter
cosid-spring-boot-starter is the only starter (D14). It brings cosid-core and cosid-spring-boot-autoconfigure and nothing else; add the store artifacts you use. It supports Spring Boot 4.1.2 and later (D49; not 4.0.x) on Java 21+: its published metadata requires the versions of Boot 4.1.2.
implementation(platform("me.ahoo.cosid:cosid-bom:5.0.0"))
implementation("me.ahoo.cosid:cosid-spring-boot-starter")
implementation("me.ahoo.cosid:cosid-store-redis")One configuration model
Stores are declared once and referenced by name, generators of different strategies can use different stores, and generators, stores and machines have no enabled switches: what is used follows from what is declared (a generator is switched off with disabled: true). The master switch is cosid.enabled (default true); the integrations keep switches of their own (cosid.mybatis.enabled, cosid.jdbc.enabled, cosid.activiti.enabled, cosid.flowable.enabled, see the configuration reference).
cosid:
namespace: shop
stores:
db: { type: jdbc, timeout: 2s }
cache: { type: redis, timeout: 1s, options: { uri: "redis://redis:6379", wait: auto } }
machine:
leased:
store: cache
bits: 10
ttl: 30s
tolerance: 1s
preferred-slot: ${POD_ORDINAL:}
generators:
default:
strategy: snowflake
codec: [ { radix: { radix: 62, width: 11, pad-start: true } } ]
order:
strategy: segment
store: db
codec: [ { radix: { radix: 62 } }, { prefix: "O" } ]
trace:
strategy: snowflake
codec: [ { friendly: { zone: Asia/Shanghai } } ]
bill:
strategy: periodic-segment
store: db
period: YEAR_MONTH_DAY
zone: Asia/Shanghai
codec: [ { date-prefix: { delimiter: "" } }, { radix: { radix: 10, width: 6, pad-start: true } } ]
token:
strategy: cosid80
codec: [ { radix: { radix: 62 } } ]
legacy:
strategy: segment
store: db
disabled: true # declared, not created: its bean throws GeneratorDisabledException
metrics:
generated: falseEvery property and default: configuration reference.
Beans
| Bean | Type |
|---|---|
cosIdRuntime | CosIdRuntime, closed with the context |
| one per generator, named after it | IdGenerator (snowflake, segment, custom; default is @Primary), PartsIdGenerator (cosid80), GroupedIdGenerator (periodic-segment), UuidV7Generator (uuidv7, the concrete class) |
IdFiller | runtime.filler() |
public OrderService(IdGenerator ids, // "default"
@Qualifier("order") IdGenerator orderIds,
@Qualifier("bill") GroupedIdGenerator billNos,
CosIdRuntime runtime) { ... }Text views come from the runtime: runtime.stringGenerator("order"), runtime.get("token", PartsCodec.class), runtime.get("bill", GroupedCodec.class); the concrete generators from runtime.get(name, TimeBasedGenerator.class) or SegmentGenerator.class.
Store clients
A store uses the bean named by cosid.stores.<name>.client; otherwise the single bean of its type's client in the context: a DataSource for jdbc; a Lettuce RedisClient / RedisClusterClient or Spring Data's RedisConnectionFactory for redis (through SpringDataRedisScripts); a MongoClient for mongo; a CuratorFramework for zookeeper. Without one, the store connects from its options. StoreProvider beans add store types of your own.
Changing generators in code
@Bean
static RuntimeSpecCustomizer moreGenerators() { // static: it runs while bean definitions are processed
return spec -> spec.toBuilder()
.generator("audit", GeneratorSpec.Segment.builder("db").build())
.build();
}Customizers run in @Order before the runtime starts, and the generators they add get beans too. A customizer must not depend on other beans (it is a static @Bean), as in 4.x.
An IdGenerator of your own joins the runtime by its bean name (4.x IdGeneratorProvider.set):
cosid:
generators:
legacy: { strategy: custom, ref: legacyIdGenerator, codec: [ { radix: { radix: 62 } } ] }The runtime serves it like the others (bean, IdFiller, endpoint) but does not close it, and the bean must not depend on CosIdRuntime. In code, GeneratorSpec.Instance.builder(ids).build() takes the instance itself.
Actuator, metrics, health
- Endpoint
cosid:GET /actuator/cosiddescribes every generator,/actuator/cosid/{name}one, and/actuator/cosid/{name}/longor/stringgenerates one id. It is read-only (D17); the 4.x delete operation became thedisabledproperty. - Health
cosid(/actuator/health/cosid, switchmanagement.health.cosid.enabled): the slot lease. - Micrometer: 19
cosid.*meters. See metrics and health. - The integrations (Jackson, MyBatis, Spring Data JDBC, Activiti, Flowable, Axon) set themselves up when their library and the matching CosId artifact (
cosid-jackson,cosid-mybatis, …) are on the classpath. - Native images:
CosIdRuntimeHintsregisters the reflection the runtime needs. Under AOT (a native image, orspring.aot.enabled) the set of generator beans is fixed at build time: the runtime still bindscosid.*when it starts, so a generator's settings may change at deploy time, but a generator added then has no bean (useCosIdRuntime.generator(name)), and the bean of one removed then fails when used. Add or remove generators in the configuration the build sees.
Each Spring context gets its own runtime (4.x's provider.isolated is the default and only mode).
