apiVersion: apps/v1
kind: Deployment
metadata:
  name: composer-rvc
  labels:
    app: composer-rvc
spec:
  replicas: 1
  selector:
    matchLabels:
      app: composer-rvc
  template:
    metadata:
      labels:
        app: composer-rvc
    spec:
      serviceAccountName: composer-service-account
      terminationGracePeriodSeconds: 130
      nodeSelector:
        karpenter.k8s.aws/instance-family: g4dn
      containers:
      - name: composer
        image: 035363416972.dkr.ecr.us-east-1.amazonaws.com/minimal:latest
        command: [ "/opt/entrypoint.sh" ]
        env:
        - name: QUEUE_NAME
          value: composer_requests
        - name: MAX_RUNTIME
          value: "5000"
        - name: HEALTHCHECK_PATH
          value: "/composer_ready"
        - name: REDIS_HOST
          value: "prod-redis.redis.svc.cluster.local"
        - name: REDIS_PORT
          value: "26379"
        - name: REDIS_SENTINEL_NAME
          value: "wavtoolmaster"
        # PG* vars are used for KEDA ScaledObject (see below)
        - name: PGHOST
          value: "database-2.ctreuprwt6kf.us-east-1.rds.amazonaws.com"
        - name: PGPASSWORD
          valueFrom:
            secretKeyRef:
              name: composer-metrics-secret
              key: PGPASSWORD
        - name: PG_CONNECTION_STRING
          value: "postgresql://composer_metrics:$(PGPASSWORD)@$(PGHOST)/wavtool"
        envFrom:
        - secretRef:
            name: redis-secret
        resources:
          limits:
            nvidia.com/gpu: 1
        readinessProbe:
          exec:
            command:
              - cat
              - /composer_ready
          periodSeconds: 5
          failureThreshold: 10
        volumeMounts:
        - name: persistent-storage
          mountPath: /opt
          subPath: composer_production_2024-05-05
        - name: memory-backed-temp
          mountPath: /tmp
          subPath: composer
        lifecycle:
          preStop:
            exec:
              command: [ "/bin/sleep", "120" ]
      - name: rvc
        image: 035363416972.dkr.ecr.us-east-1.amazonaws.com/minimal:latest
        command: [ "/opt/entrypoint.sh" ]
        env:
        - name: RVC_MODELS_S3_BUCKET
          value: "wavtool-user-rvc-models"
        - name: RVC_SAMPLES_S3_BUCKET
          value: "samples-test-1"
        - name: RVC_CACHE_DIR
          value: "/rvc_cache"
        - name: QUEUE_NAME
          value: voice_conversion_requests_2
        - name: HEALTHCHECK_PATH
          value: "/rvc_ready"
        - name: REDIS_HOST
          value: "prod-redis.redis.svc.cluster.local"
        - name: REDIS_PORT
          value: "26379"
        - name: REDIS_SENTINEL_NAME
          value: "wavtoolmaster"
        # XXX this is an awful hack that will break if we ever use a node with more than one gpu
        # XXX fix this once karpenter supports fractional or shared resources
        - name: NVIDIA_VISIBLE_DEVICES
          value: "all"
        envFrom:
        - secretRef:
            name: redis-secret
        readinessProbe:
          exec:
            command:
              - cat
              - /rvc_ready
          periodSeconds: 5
          failureThreshold: 10
        volumeMounts:
        - name: persistent-storage
          mountPath: /opt
          subPath: rvc_production_2023-11-21
        - name: memory-backed-temp
          mountPath: /tmp
          subPath: rvc
        - name: disk-backed-temp
          mountPath: /rvc_cache
          subPath: rvc
        lifecycle:
          preStop:
            exec:
              command: [ "/bin/sleep", "120" ]
      volumes:
      - name: persistent-storage
        persistentVolumeClaim:
          claimName: efs-claim
      - name: memory-backed-temp
        emptyDir:
          medium: Memory
          sizeLimit: 4Gi
      - name: disk-backed-temp
        emptyDir:
          sizeLimit: 8Gi
---
apiVersion: keda.sh/v1alpha1
kind: ScaledObject
metadata:
  name: composer-rvc-scaler
#  annotations:
#    autoscaling.keda.sh/paused: "true"
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: composer-rvc
    envSourceContainerName: composer
  pollingInterval:  15
  minReplicaCount:  1
  maxReplicaCount:  5
  fallback:
    failureThreshold: 3
    replicas: 1
  advanced:
    horizontalPodAutoscalerConfig:
      behavior:
        scaleDown:
          stabilizationWindowSeconds: 600
          policies:
          - type: Pods
            value: 1
            periodSeconds: 600
        scaleUp:
          stabilizationWindowSeconds: 60
          policies:
          - type: Pods
            value: 1
            periodSeconds: 160
          selectPolicy: Max
  triggers:
    - type: postgresql
      name: queries-per-second
      metricType: AverageValue
      metadata:
        connectionFromEnv: "PG_CONNECTION_STRING"
        query: "select coalesce(count(*), 0) / 15.0 from composer_requests where created_at > now() - interval '15 seconds'"
        # 90p composer response time calculated using:
        # with xs as ( select (response->'perf'->'records'->'request'->'value')::double precision as dur from composer_requests where response->'perf'->'records'->'request'->>'value' is not null order by id desc limit 10000 ) select percentile_cont(0.90) within group (order by dur) from xs;
        targetQueryValue: "0.80"  # requests / (pod * second)
