All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.netflix.spinnaker.keel.sql.SqlDismissibleNotificationRepository.kt Maven / Gradle / Ivy

There is a newer version: 1.4.1
Show newest version
package com.netflix.spinnaker.keel.sql

import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.module.kotlin.convertValue
import com.netflix.spinnaker.keel.api.UID
import com.netflix.spinnaker.keel.events.EventLevel
import com.netflix.spinnaker.keel.notifications.DismissibleNotification
import com.netflix.spinnaker.keel.persistence.DismissibleNotificationRepository
import com.netflix.spinnaker.keel.persistence.metamodel.Tables.DISMISSIBLE_NOTIFICATION
import com.netflix.spinnaker.keel.sql.RetryCategory.READ
import com.netflix.spinnaker.keel.sql.RetryCategory.WRITE
import de.huxhorn.sulky.ulid.ULID
import org.jooq.DSLContext
import org.jooq.Field
import org.jooq.impl.DSL
import org.slf4j.LoggerFactory
import org.springframework.context.event.EventListener
import java.time.Clock

/**
 * SQL implementation of [DismissibleNotificationRepository].
 */
class SqlDismissibleNotificationRepository(
  private val jooq: DSLContext,
  private val sqlRetry: SqlRetry,
  private val objectMapper: ObjectMapper,
  private val clock: Clock
) : DismissibleNotificationRepository {

  companion object {
    private val log by lazy { LoggerFactory.getLogger(SqlDismissibleNotificationRepository::class.java) }
  }

  @EventListener
  fun storeNotificationFromEvent(notification: DismissibleNotification) {
    log.debug("Storing notification from event: $notification")
    storeNotification(notification)
  }

  override fun storeNotification(notification: DismissibleNotification): UID {
    return sqlRetry.withRetry(WRITE) {
      val uid = ULID().nextULID()
      jooq
        .insertInto(DISMISSIBLE_NOTIFICATION)
        .set(DISMISSIBLE_NOTIFICATION.UID, uid.toString())
        .set(DISMISSIBLE_NOTIFICATION.JSON, notification)
        .execute()
      ULID.parseULID(uid)
    }
  }

  override fun notificationHistory(
    application: String,
    onlyActive: Boolean,
    levels: Set,
    limit: Int
  ): List {
    return sqlRetry.withRetry(READ) {
      jooq
        .select(DISMISSIBLE_NOTIFICATION.UID, DISMISSIBLE_NOTIFICATION.JSON)
        .from(DISMISSIBLE_NOTIFICATION)
        .where(DISMISSIBLE_NOTIFICATION.APPLICATION.eq(application))
        .apply {
          if (onlyActive) {
            and(DISMISSIBLE_NOTIFICATION.IS_ACTIVE.eq(1))
          }
          if (levels.isNotEmpty()) {
            and(DISMISSIBLE_NOTIFICATION.LEVEL.`in`(*levels.map { it.name }.toTypedArray()))
          }
        }
        .orderBy(DISMISSIBLE_NOTIFICATION.TRIGGERED_AT.desc())
        .limit(limit)
        .fetch { (uid, notification) ->
          notification.uid = ULID.parseULID(uid)
          notification
        }
    }
  }

  private fun generateDismissalJson(user: String? = null): Field {
    val dismissedAt: String = objectMapper.convertValue(clock.instant())
    return field(
      "json_set(json, '$.isActive', 'false', '$.dismissedBy', '$user', '$.dismissedAt', '$dismissedAt')"
    )
  }

  override fun dismissNotificationById(application: String, notificationUid: UID, user: String): Boolean {
    val updatedJson = generateDismissalJson(user)
    return sqlRetry.withRetry(WRITE) {
      jooq
        .update(DISMISSIBLE_NOTIFICATION)
        .set(DISMISSIBLE_NOTIFICATION.JSON, updatedJson)
        .where(DISMISSIBLE_NOTIFICATION.UID.eq(notificationUid.toString()))
        .and(DISMISSIBLE_NOTIFICATION.APPLICATION.eq(application))
        .execute()
    } > 0
  }

  override fun  dismissNotification(type: Class, application: String, branch: String, user: String?): Boolean {
    val updatedJson = generateDismissalJson(user)
    return sqlRetry.withRetry(WRITE) {
      jooq
        .update(DISMISSIBLE_NOTIFICATION)
        .set(DISMISSIBLE_NOTIFICATION.JSON, updatedJson)
        .where(DISMISSIBLE_NOTIFICATION.APPLICATION.eq(application))
        .and(DISMISSIBLE_NOTIFICATION.TYPE.eq(type.simpleName))
        .apply {
          if (branch.isNullOrEmpty()) {
            and(DISMISSIBLE_NOTIFICATION.BRANCH.isNull)
          } else {
            and(DISMISSIBLE_NOTIFICATION.BRANCH.eq(branch))
          }
        }
        .execute()
    } > 0
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy