feat(mining-blockchain-service): mining_ 前缀隔离,与 blockchain-service 100% 资源分离

mining-blockchain-service 的所有共享资源全部加上 mining_ 前缀,
确保与 1.0 blockchain-service 完全隔离,互不干扰。

## Kafka Topic 隔离 — 生产者 (event-publisher.service.ts)

- source header: 'blockchain-service' → 'mining-blockchain-service'
- topic 映射全部加 mining_ 前缀:
  - blockchain.deposits → mining_blockchain.deposits
  - blockchain.wallets → mining_blockchain.wallets
  - blockchain.transactions → mining_blockchain.transactions
  - mpc.SigningRequested → mining_mpc.SigningRequested
  - blockchain.market_maker.deposits → mining_blockchain.market_maker.deposits
  - 默认 fallback: blockchain.events → mining_blockchain.events

## Domain Event eventType 隔离 (5 个事件类)

- deposit-detected.event.ts: mining_blockchain.deposit.detected
- deposit-confirmed.event.ts: mining_blockchain.deposit.confirmed
- wallet-address-created.event.ts: mining_blockchain.wallet.address.created
- transaction-broadcasted.event.ts: mining_blockchain.transaction.broadcasted
- market-maker-deposit-confirmed.event.ts: mining_blockchain.market_maker.deposit.confirmed

## Kafka Topic 隔离 — 消费者 (3 个 consumer)

- mpc-event-consumer: mining_mpc.KeygenCompleted / SigningCompleted / SessionFailed
- withdrawal-event-consumer: mining_wallet.withdrawals / mining_wallet.system-withdrawals
  - 事件类型检查: mining_wallet.withdrawal.requested / mining_wallet.system-withdrawal.requested
- deposit-ack-consumer: mining_wallet.acks
  - 事件类型检查: mining_wallet.deposit.credited
  - outbox ACK 匹配: mining_blockchain.deposit.confirmed

## Kafka 事件类型 — Event Handlers

- mpc-signing.client.ts:
  - MPC_SIGNING_TOPIC → mining_mpc.SigningRequested
  - eventType → mining_blockchain.mpc.signing.requested
- withdrawal-requested.handler.ts:
  - mining_blockchain.withdrawal.confirmed / failed / status
- system-withdrawal-requested.handler.ts:
  - mining_blockchain.system-withdrawal.confirmed / failed

## Redis Key 前缀隔离

- address-cache: blockchain:monitored_addresses: → mining_blockchain:monitored_addresses:
- hot-wallet-balance: hot_wallet:dusdt_balance: → mining_hot_wallet:dusdt_balance:
- hot-wallet-balance: hot_wallet:native_balance: → mining_hot_wallet:native_balance:

## 数据库名称隔离

- docker-compose.yml: rwa_blockchain → rwa_mining_blockchain
- docker-compose.2.0.yml: rwa_blockchain → rwa_mining_blockchain
- deploy-mining.sh: MINING_DATABASES + SERVICE_DB 映射 → rwa_mining_blockchain

## 下游服务需配套更新 (不在本次修改范围)

- mpc-service: 消费 mining_mpc.SigningRequested, 发布 mining_mpc.* 结果
- mining-wallet-service: 发布 mining_wallet.*, 消费 mining_blockchain.*
- trading-service: 消费 mining_blockchain.market_maker.deposits

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
hailin 2026-01-30 01:58:45 -08:00
parent 08cf4681f2
commit 454b379f6c
17 changed files with 39 additions and 39 deletions

View File

@ -87,7 +87,7 @@ MINING_DATABASES=(
"rwa_mining_admin"
"rwa_auth"
"rwa_mining_wallet"
"rwa_blockchain"
"rwa_mining_blockchain"
)
# Service to Database mapping
@ -98,7 +98,7 @@ declare -A SERVICE_DB=(
["mining-admin-service"]="rwa_mining_admin"
["auth-service"]="rwa_auth"
["mining-wallet-service"]="rwa_mining_wallet"
["mining-blockchain-service"]="rwa_blockchain"
["mining-blockchain-service"]="rwa_mining_blockchain"
)
# 2.0 Ports

View File

@ -257,7 +257,7 @@ services:
TZ: Asia/Shanghai
PORT: 3026
# PostgreSQL - 使用独立的数据库
DATABASE_URL: postgresql://${POSTGRES_USER:-postgres}:${POSTGRES_PASSWORD:-postgres}@postgres:5432/rwa_blockchain?schema=public
DATABASE_URL: postgresql://${POSTGRES_USER:-postgres}:${POSTGRES_PASSWORD:-postgres}@postgres:5432/rwa_mining_blockchain?schema=public
# Redis - 使用 DB 8 隔离 (0-15 有效范围)
REDIS_HOST: redis
REDIS_PORT: 6379

View File

@ -22,7 +22,7 @@ services:
APP_PORT: 3012
API_PREFIX: api/v1
# Database (shared PostgreSQL)
DATABASE_URL: postgresql://rwa_user:rwa_secure_password@rwa-postgres:5432/rwa_blockchain?schema=public
DATABASE_URL: postgresql://rwa_user:rwa_secure_password@rwa-postgres:5432/rwa_mining_blockchain?schema=public
# Redis (shared)
REDIS_HOST: rwa-redis
REDIS_PORT: 6379

View File

@ -77,7 +77,7 @@ export class SystemWithdrawalRequestedHandler implements OnModuleInit {
this.logger.log(`[SUCCESS] Block: ${result.blockNumber}`);
await this.eventPublisher.publish({
eventType: 'blockchain.system-withdrawal.confirmed',
eventType: 'mining_blockchain.system-withdrawal.confirmed',
toPayload: () => ({
orderNo: payload.orderNo,
fromAccountSequence: payload.fromAccountSequence,
@ -108,7 +108,7 @@ export class SystemWithdrawalRequestedHandler implements OnModuleInit {
// 发布失败事件
await this.eventPublisher.publish({
eventType: 'blockchain.system-withdrawal.failed',
eventType: 'mining_blockchain.system-withdrawal.failed',
toPayload: () => ({
orderNo: payload.orderNo,
fromAccountSequence: payload.fromAccountSequence,

View File

@ -83,7 +83,7 @@ export class WithdrawalRequestedHandler implements OnModuleInit {
this.logger.log(`[SUCCESS] Block: ${result.blockNumber}`);
await this.eventPublisher.publish({
eventType: 'blockchain.withdrawal.confirmed',
eventType: 'mining_blockchain.withdrawal.confirmed',
toPayload: () => ({
orderNo: payload.orderNo,
accountSequence: payload.accountSequence,
@ -113,7 +113,7 @@ export class WithdrawalRequestedHandler implements OnModuleInit {
// 发布失败事件
await this.eventPublisher.publish({
eventType: 'blockchain.withdrawal.failed',
eventType: 'mining_blockchain.withdrawal.failed',
toPayload: () => ({
orderNo: payload.orderNo,
accountSequence: payload.accountSequence,
@ -141,7 +141,7 @@ export class WithdrawalRequestedHandler implements OnModuleInit {
message: string,
): Promise<void> {
await this.eventPublisher.publish({
eventType: 'blockchain.withdrawal.status',
eventType: 'mining_blockchain.withdrawal.status',
toPayload: () => ({
orderNo: payload.orderNo,
accountSequence: payload.accountSequence,

View File

@ -33,8 +33,8 @@ export class HotWalletBalanceScheduler implements OnModuleInit, OnModuleDestroy
private readonly logger = new Logger(HotWalletBalanceScheduler.name);
// Redis key 前缀
private readonly REDIS_KEY_PREFIX_DUSDT = 'hot_wallet:dusdt_balance:';
private readonly REDIS_KEY_PREFIX_NATIVE = 'hot_wallet:native_balance:';
private readonly REDIS_KEY_PREFIX_DUSDT = 'mining_hot_wallet:dusdt_balance:';
private readonly REDIS_KEY_PREFIX_NATIVE = 'mining_hot_wallet:native_balance:';
// 缓存过期时间(秒)
private readonly CACHE_TTL_SECONDS = 30;

View File

@ -18,7 +18,7 @@ export interface DepositConfirmedPayload {
*
*/
export class DepositConfirmedEvent extends DomainEvent {
readonly eventType = 'blockchain.deposit.confirmed';
readonly eventType = 'mining_blockchain.deposit.confirmed';
constructor(private readonly payload: DepositConfirmedPayload) {
super();

View File

@ -21,7 +21,7 @@ export interface DepositDetectedPayload {
*
*/
export class DepositDetectedEvent extends DomainEvent {
readonly eventType = 'blockchain.deposit.detected';
readonly eventType = 'mining_blockchain.deposit.detected';
constructor(private readonly payload: DepositDetectedPayload) {
super();

View File

@ -22,7 +22,7 @@ export interface MarketMakerDepositConfirmedPayload {
* trading-service
*/
export class MarketMakerDepositConfirmedEvent extends DomainEvent {
readonly eventType = 'blockchain.market_maker.deposit.confirmed';
readonly eventType = 'mining_blockchain.market_maker.deposit.confirmed';
constructor(private readonly payload: MarketMakerDepositConfirmedPayload) {
super();

View File

@ -17,7 +17,7 @@ export interface TransactionBroadcastedPayload {
* 广
*/
export class TransactionBroadcastedEvent extends DomainEvent {
readonly eventType = 'blockchain.transaction.broadcasted';
readonly eventType = 'mining_blockchain.transaction.broadcasted';
constructor(private readonly payload: TransactionBroadcastedPayload) {
super();

View File

@ -20,7 +20,7 @@ export interface WalletAddressCreatedPayload {
*
*/
export class WalletAddressCreatedEvent extends DomainEvent {
readonly eventType = 'blockchain.wallet.address.created';
readonly eventType = 'mining_blockchain.wallet.address.created';
constructor(private readonly payload: WalletAddressCreatedPayload) {
super();

View File

@ -11,7 +11,7 @@ import { Kafka, Consumer, logLevel, EachMessagePayload } from 'kafkajs';
import { OutboxPublisherService } from '@/application/services/outbox-publisher.service';
export const ACK_TOPICS = {
WALLET_ACKS: 'wallet.acks',
WALLET_ACKS: 'mining_wallet.acks',
} as const;
export interface DepositCreditedPayload {
@ -114,7 +114,7 @@ export class DepositAckConsumerService implements OnModuleInit, OnModuleDestroy
this.logger.log(`[RECEIVE] ACK event type: ${eventType}`);
if (eventType === 'wallet.deposit.credited') {
if (eventType === 'mining_wallet.deposit.credited') {
await this.handleDepositCredited(payload as DepositCreditedPayload);
} else {
this.logger.debug(`[RECEIVE] Unknown ACK event type: ${eventType}`);
@ -140,7 +140,7 @@ export class DepositAckConsumerService implements OnModuleInit, OnModuleDestroy
await this.outboxPublisher.handleAck(
'DepositTransaction',
payload.depositId,
'blockchain.deposit.confirmed',
'mining_blockchain.deposit.confirmed',
);
this.logger.log(`[ACK] Deposit ${payload.depositId} ACK processed successfully`);

View File

@ -43,7 +43,7 @@ export class EventPublisherService implements OnModuleInit, OnModuleDestroy {
}),
headers: {
eventType: event.eventType,
source: 'blockchain-service',
source: 'mining-blockchain-service',
},
};
@ -84,7 +84,7 @@ export class EventPublisherService implements OnModuleInit, OnModuleDestroy {
}),
headers: {
eventType: event.eventType,
source: 'blockchain-service',
source: 'mining-blockchain-service',
},
};
@ -97,17 +97,17 @@ export class EventPublisherService implements OnModuleInit, OnModuleDestroy {
}
private getTopicForEvent(eventType: string): string {
// 事件类型到 topic 的映射
// 事件类型到 topic 的映射mining_ 前缀隔离,与 blockchain-service 100% 隔离)
const topicMap: Record<string, string> = {
'blockchain.deposit.detected': 'blockchain.deposits',
'blockchain.deposit.confirmed': 'blockchain.deposits',
'blockchain.wallet.address.created': 'blockchain.wallets',
'blockchain.transaction.broadcasted': 'blockchain.transactions',
'mining_blockchain.deposit.detected': 'mining_blockchain.deposits',
'mining_blockchain.deposit.confirmed': 'mining_blockchain.deposits',
'mining_blockchain.wallet.address.created': 'mining_blockchain.wallets',
'mining_blockchain.transaction.broadcasted': 'mining_blockchain.transactions',
// MPC 签名请求 - 发送到 mpc-service 消费的 topic
'blockchain.mpc.signing.requested': 'mpc.SigningRequested',
'mining_blockchain.mpc.signing.requested': 'mining_mpc.SigningRequested',
// 做市商充值事件 - 发送到 trading-service 消费的 topic
'blockchain.market_maker.deposit.confirmed': 'blockchain.market_maker.deposits',
'mining_blockchain.market_maker.deposit.confirmed': 'mining_blockchain.market_maker.deposits',
};
return topicMap[eventType] || 'blockchain.events';
return topicMap[eventType] || 'mining_blockchain.events';
}
}

View File

@ -13,9 +13,9 @@ import { Kafka, Consumer, logLevel, EachMessagePayload } from 'kafkajs';
// MPC Event Topics (events from mpc-service)
export const MPC_TOPICS = {
KEYGEN_COMPLETED: 'mpc.KeygenCompleted',
SIGNING_COMPLETED: 'mpc.SigningCompleted',
SESSION_FAILED: 'mpc.SessionFailed',
KEYGEN_COMPLETED: 'mining_mpc.KeygenCompleted',
SIGNING_COMPLETED: 'mining_mpc.SigningCompleted',
SESSION_FAILED: 'mining_mpc.SessionFailed',
} as const;
export interface KeygenCompletedPayload {

View File

@ -10,8 +10,8 @@ import { ConfigService } from '@nestjs/config';
import { Kafka, Consumer, logLevel, EachMessagePayload } from 'kafkajs';
export const WITHDRAWAL_TOPICS = {
WITHDRAWAL_REQUESTED: 'wallet.withdrawals',
SYSTEM_WITHDRAWAL_REQUESTED: 'wallet.system-withdrawals',
WITHDRAWAL_REQUESTED: 'mining_wallet.withdrawals',
SYSTEM_WITHDRAWAL_REQUESTED: 'mining_wallet.system-withdrawals',
} as const;
export interface WithdrawalRequestedPayload {
@ -145,7 +145,7 @@ export class WithdrawalEventConsumerService implements OnModuleInit, OnModuleDes
this.logger.log(`[RECEIVE] Event type: ${eventType}`);
if (eventType === 'wallet.withdrawal.requested') {
if (eventType === 'mining_wallet.withdrawal.requested') {
this.logger.log(`[HANDLE] Processing WithdrawalRequested event`);
this.logger.log(`[HANDLE] orderNo: ${payload.orderNo}`);
this.logger.log(`[HANDLE] chainType: ${payload.chainType}`);
@ -158,7 +158,7 @@ export class WithdrawalEventConsumerService implements OnModuleInit, OnModuleDes
} else {
this.logger.warn(`[HANDLE] No handler registered for WithdrawalRequested`);
}
} else if (eventType === 'wallet.system-withdrawal.requested') {
} else if (eventType === 'mining_wallet.system-withdrawal.requested') {
this.logger.log(`[HANDLE] Processing SystemWithdrawalRequested event`);
this.logger.log(`[HANDLE] orderNo: ${payload.orderNo}`);
this.logger.log(`[HANDLE] fromAccountSequence: ${payload.fromAccountSequence}`);

View File

@ -34,7 +34,7 @@ export interface SigningResult {
type SigningCallback = (signature: string | null, error?: string) => void;
// MPC 签名请求 Topic
export const MPC_SIGNING_TOPIC = 'mpc.SigningRequested';
export const MPC_SIGNING_TOPIC = 'mining_mpc.SigningRequested';
@Injectable()
export class MpcSigningClient implements OnModuleInit {
@ -232,7 +232,7 @@ export class MpcSigningClient implements OnModuleInit {
// 发布签名请求事件到 Kafka
try {
await this.eventPublisher.publish({
eventType: 'blockchain.mpc.signing.requested',
eventType: 'mining_blockchain.mpc.signing.requested',
toPayload: () => ({
sessionId,
userId: 'system',

View File

@ -9,7 +9,7 @@ import { ChainType } from '@/domain/value-objects';
@Injectable()
export class AddressCacheService implements OnModuleInit {
private readonly logger = new Logger(AddressCacheService.name);
private readonly CACHE_KEY_PREFIX = 'blockchain:monitored_addresses:';
private readonly CACHE_KEY_PREFIX = 'mining_blockchain:monitored_addresses:';
constructor(private readonly redis: RedisService) {}