@@ -20,6 +20,7 @@ import { ApplicationBundle } from 'src/application/entities/application-bundle'
2020import * as assert from 'assert'
2121import { extractNumber } from 'src/utils/number'
2222import { formatK8sErrorAsJson } from 'src/utils/k8s-error'
23+ import { ServerConfig , KUBEBLOCK_V5_UPGRADE_API_TIMEOUT } from 'src/constants'
2324
2425const getDedicatedDatabaseName = ( appid : string ) => appid
2526
@@ -142,13 +143,18 @@ export class DedicatedDatabaseService {
142143 appid ,
143144 'horizontalScaling' ,
144145 )
146+
145147 if ( ! OpsRequestManifest ) {
146148 const result = await this . applyKubeBlockOpsRequestManifestForSpec (
147149 region ,
148150 appid ,
149151 spec ,
150152 'horizontalScaling' ,
151153 )
154+
155+ // Call KubeBlock v5 compatibility API if needed
156+ await this . handleKubeBlockV5Upgrade ( appid , manifest , spec . replicas )
157+
152158 results . push ( result )
153159 this . logger . log (
154160 `Applied horizontalScaling ops request for ${ appid } : replicas=${ spec . replicas } ` ,
@@ -702,4 +708,116 @@ export class DedicatedDatabaseService {
702708 return false
703709 }
704710 }
711+
712+ /**
713+ * Handle KubeBlock v5 upgrade API call for horizontal scaling
714+ * This is a compatibility feature for KubeBlock v5 mongodb-5.0 clusters
715+ *
716+ * @param appid - Application ID
717+ * @param manifest - Current deployment manifest
718+ * @param replicas - Number of replicas
719+ */
720+ private async handleKubeBlockV5Upgrade (
721+ appid : string ,
722+ manifest : KubernetesObject & { spec : any ; status : any } ,
723+ replicas : number ,
724+ ) : Promise < void > {
725+ try {
726+ // Early return if not a v5 mongodb-5.0 cluster
727+ if ( ! this . isKubeBlockV5MongoDb ( manifest ) ) {
728+ return
729+ }
730+
731+ const url = ServerConfig . KUBEBLOCK_V5_UPGRADE_URL
732+ if ( ! url ) {
733+ this . logger . warn (
734+ `KubeBlock v5 upgrade URL not configured (KUBEBLOCK_V5_UPGRADE_URL env var not set) for ${ appid } ` ,
735+ )
736+ return
737+ }
738+
739+ await this . callKubeBlockV5UpgradeAPI ( appid , manifest , replicas , url )
740+ } catch ( error ) {
741+ this . logger . error (
742+ `Failed to call KubeBlock v5 upgrade API for ${ appid } : ${ error . message } ` ,
743+ )
744+ // Don't throw error, just log it as it's a compatibility feature
745+ }
746+ }
747+
748+ /**
749+ * Check if the manifest is a KubeBlock v5 mongodb-5.0 cluster
750+ */
751+ private isKubeBlockV5MongoDb (
752+ manifest : KubernetesObject & { spec : any ; status : any } ,
753+ ) : boolean {
754+ return (
755+ manifest ?. metadata ?. labels ?. [ 'clusterversion.kubeblocks.io/name' ] ===
756+ 'mongodb-5.0'
757+ )
758+ }
759+
760+ /**
761+ * Call KubeBlock v5 upgrade API with timeout control
762+ */
763+ private async callKubeBlockV5UpgradeAPI (
764+ appid : string ,
765+ manifest : KubernetesObject & { spec : any ; status : any } ,
766+ replicas : number ,
767+ url : string ,
768+ ) : Promise < void > {
769+ const clusterName = manifest . metadata . name
770+ const namespace = manifest . metadata . namespace
771+
772+ // Create AbortController for timeout
773+ const controller = new AbortController ( )
774+ const timeoutId = setTimeout (
775+ ( ) => controller . abort ( ) ,
776+ KUBEBLOCK_V5_UPGRADE_API_TIMEOUT ,
777+ )
778+
779+ try {
780+ const response = await fetch ( url , {
781+ method : 'POST' ,
782+ headers : {
783+ 'Content-Type' : 'application/json' ,
784+ } ,
785+ body : JSON . stringify ( {
786+ namespace,
787+ database_name : clusterName ,
788+ replicas,
789+ } ) ,
790+ signal : controller . signal ,
791+ } )
792+
793+ const responseData = await this . parseKubeBlockV5Response ( response )
794+
795+ if ( ! response . ok ) {
796+ throw new Error (
797+ `HTTP error! status: ${ response . status } , statusText: ${
798+ response . statusText
799+ } , body: ${ JSON . stringify ( responseData ) } `,
800+ )
801+ }
802+
803+ this . logger . log (
804+ `Called KubeBlock v5 upgrade API for ${ appid } : cluster=${ clusterName } , replicas=${ replicas } , response: ${ JSON . stringify (
805+ responseData ,
806+ ) } `,
807+ )
808+ } finally {
809+ clearTimeout ( timeoutId )
810+ }
811+ }
812+
813+ /**
814+ * Parse response body from KubeBlock v5 API
815+ */
816+ private async parseKubeBlockV5Response ( response : Response ) : Promise < any > {
817+ const contentType = response . headers . get ( 'content-type' )
818+ if ( contentType ?. includes ( 'application/json' ) ) {
819+ return await response . json ( )
820+ }
821+ return await response . text ( )
822+ }
705823}
0 commit comments