///|
/// Writes a key-value pair to the database with a logical Time-To-Live (TTL).
pub fn DB::put_ttl(
  self : DB,
  key : String,
  value : Bytes,
  ttl : Int64,
) -> Unit raise MoonKVError {
  validate_user_key(key)
  if ttl <= 0L {
    raise MoonKVError::InvalidRecord("ttl must be greater than zero")
  }

  let timestamp = self.logical_clock
  self.logical_clock = self.logical_clock + 1L

  let record = Record::new_ttl(string_to_bytes(key), value, timestamp, ttl)
  let record_bytes = record.serialize()
  let record_len = record_bytes.length()

  // Roll active file if size limit exceeded
  if self.active_file_offset + record_len > self.max_file_size {
    self.active_file_id = self.active_file_id + 1
    self.active_file_offset = 0
  }

  let path = self.dir + "/" + self.active_file_id.to_string() + ".data"
  append_bytes_to_file(path, record_bytes)

  let entry = KeyEntry::new(
    self.active_file_id,
    value.length(),
    self.active_file_offset.to_int64(),
    timestamp,
    timestamp + ttl,
  )
  self.keydir.put(key, entry)

  self.active_file_offset = self.active_file_offset + record_len
}