EN · DE · RU · FR · ES

#2329: SipgateSyncService.kt

projectforge-rest/src/main/kotlin/org/projectforge/rest/sipgate/SipgateSyncService.kt Тип: Kotlin · Роль: REST Endpoint · Исходник: projectforge-rest/src/main/kotlin/org/projectforge/rest/sipgate/SipgateSyncService.kt 132 строки · 86 кода · 36 комментариев · 10 пустых
Spring-сервис для SipgateSync. Предоставляет бизнес-логику между контроллерами/REST-точками и уровнем доступа к данным.

Структура кода

Аннотации: param, micromata, Service, author, Autowired

Классы: SipgateSyncService

Функции (4): getStorage, readStorage, readFromFileOrGetFromRemote, remoteRead

Свойства (8): sipgateService, privateStorage, ps, newStorage, newStorage, userDevices, devices, storageFile

Импорты: 8 пакетов

Пакет: org.projectforge.rest.sipgate

Исходный код (сокращён)

package org.projectforge.rest.sipgate

import mu.KotlinLogging
import org.projectforge.business.sipgate.SipgateUserDevices
import org.projectforge.framework.configuration.ConfigXml
import org.projectforge.framework.json.JsonUtils
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.stereotype.Service
import java.io.File
import kotlin.concurrent.thread

private val log = KotlinLogging.logger {}

/**
 * Читает номера, устройства, пользователей и т.д. с удалённого сервера Sipgate.
 * @author K. Reinhard (k.reinhard@micromata.de)
 */
@Service
open class SipgateSyncService {
  @Autowired
  internal lateinit var sipgateService: SipgateService

  private var privateStorage: SipgateDataStorage? = null

  /**
   * Возвращает хранилище, если оно существует. Если нет, хранилище будет прочитано с удалённого сервера Sipgate.
   * Если существующее хранилище устарело, возвращается устаревшее хранилище, но
   * запускается асинхронная задача для получения новых данных хранилища.
   */
  open fun getStorage(): SipgateDataStorage {
    privateStorage?.let {
      thread(start = true) {
        readStorage() // Повторное чтение, если устарело.
      }
      return it
    }
    return readStorage()
  }

  /**
   * Получает данные с удалённого сервера Sipgate. Кэшируется в файл (work/sipgateStorage.json). Данные будут
   * автоматически перечитаны через один день.
   * @param Если forceSync установлен в true, конфигурация будет получена с удалённого сервера Sipgate. По умолчанию false.
   */
  open fun readStorage(forceSync: Boolean = false): SipgateDataStorage {
    val ps = privateStorage
    if (forceSync || ps == null || !ps.uptodate) {
      if (forceSync) {
        log.info { "Чтение конфигурации Sipgate принудительно." }
      } else if (ps == null) {
        log.info { "Конфигурация Sipgate ещё не существует.." }
      } else {
        log.info { "Конфигурация Sipgate устарела." }
      }
      readFromFileOrGetFromRemote(forceSync)
    }
    return privateStorage!!
  }

  private fun readFromFileOrGetFromRemote(forceSync: Boolean = false) {
    synchronized(this) {
      try {
        if (!forceSync && storageFile.canRead()) {
          val json = storageFile.readText()
          log.info { "Чтение данных Sipgate из '${storageFile.absolutePath}'..." }
          val newStorage = JsonUtils.fromJson(json, SipgateDataStorage::class.java)
          if (newStorage?.uptodate == true) {
            privateStorage = newStorage
            return
          }
          log.info { "Хранилище Sipgate устарело (старше одного дня), повторное чтение..." }
        }
      } catch (ex: Exception) {
        log.error("Ошибка при разборе хранилища sipgate из '${storageFile.absolutePath}': ${ex.message}", ex)
      }
      remoteRead()
    }
  }

  private fun remoteRead() {
    log.info { "Чтение данных Sipgate (пользователи, устройства и т.д.)..." }
    val newStorage = SipgateDataStorage()
    newStorage.users = sipgateService.getUsers()
    try {
      newStorage.numbers = sipgateService.getNumbers()
    } catch (ex: Exception) {
      log.error("Не удалось прочитать номера (возможно, нет доступа): ${ex.message}", ex)
    }
    val userDevices = mutableListOf<SipgateUserDevices>()
    newStorage.users?.forEach { user ->
      val devices = sipgateService.getDevices(user)
      if (devices.isNotEmpty()) {
        devices.forEach { it.deleteSecrets() }
        userDevices.add(SipgateUserDevices(user.id, devices))
      }
    }
    newStorage.userDevices = userDevices
    newStorage.addresses = sipgateService.getAddresses()
    privateStorage = newStorage
    log.info { "Запись данных Sipgate в '${storageFile.absolutePath}'..." }
    storageFile.writeText(privateStorage.toString())
  }

  companion object {
    private val storageFile by lazy {
      File(ConfigXml.getInstance().workingDirectory, "sipgateStorage.json")
    }
  }
}

История Git

868d6abb7 2025 -> 2026
63081666f Заголовки исходных файлов: 2024 -> 2025.
5bafe7941 @Repository -> @Service. @Transactional-аннотации удалены.
b6092df09 Авторские права 2023 -> 2024
031eb26c3 WIP: телефонные звонки для Sipgate