Перейти к основному содержимому

Необходимые действия

time-server

v10.0.0

Раскрыть

Метрика mattermost_jobs_active отмечена как устаревшая. Используйте метрику time_jobs_status{status="in_progress"} вместо неё.

v9.2.0

Раскрыть

Была добавлена возможность присылать push сообщений для PWA приложения.

Для этого необходимо установить следующие environment переменные у сервиса time-push-notification-server:

  • WEBPUSH_VAPID_PUBLIC_KEY
  • WEBPUSH_VAPID_PRIVATE_KEY

Для получения этих ключей необходимо запустить консольную утилиту vapid-gen: https://data.tinkoff.ru/apps/files/?dir=/time/PNS_secret_generator. Примерный вывод утилиты:

WEBPUSH_VAPID_PUBLIC_KEY=BA48p1r4un...zfVpZk7RNPLPP4Q
WEBPUSH_VAPID_PRIVATE_KEY=5e3QYVt5s...AlyXoRI0lTc

Эти ключи будут использоваться для верификации отправителя и подписи web push сообщений.


Методы API POST /users/{user_id}/promote и POST /users/{user_id}/demote объявлены устаревшими в пользу PUT /users/{user_id}/roles.

v9.0.0

Раскрыть
  • В Data Retention были внесены изменения, ломающие обратную совместимость.

    Теперь запуски политик хранения выполняются каждый день в настроенное время (раньше можно было настроить раз в неделю).

    Кастомные политики хранения выполняются всегда, независимо от настроек глобальной политики. Удостоверьтесь, что у вас отключены настройки:

    • .DataRetentionSettings.EnableMessageDeletion
    • .DataRetentionSettings.EnableFileDeletion
    • .DataRetentionSettings.EnableBoardsDeletion
    • .DataRetentionSettings.EnableChannelViewDeletion
  • В Docker-образ time-server был добавлен плагин Jira версии v4.1.1. В случае, если вы ранее пересобирали docker-образ time-server для добавления в него плагина Jira, то необходимо убрать этот плагин из вашей сборки (для избежания конфликтов).

  • Бот bot-admin удален с поставки и больше не поддерживается. Для миграции авторов ботов, созданных через bot-admin, нужно установить переменную среды TIME_SQLSETTINGS_ENABLEUSERBOTSMIGRATION: 'true' и перезапустить сервер Time.

  • Начиная с этой версии в time-server для подключения к базе данных используется новый драйвер. Если вы не используете балансировщики нагрузки для PostgreSQL, то этот пункт можно пропустить.

    Для корректной работы драйвера, необходимо заменить в DataSource, DataSourceReplicas и AllDataSources параметр подключения binary_parameters=yes на default_query_exec_mode=simple_protocol.

    Если этого не сделать, Time сам попробует заменить параметры. В случае, если это не выйдет, то time-server не сможет запуститься после перезагрузки.

  • Для развития в будущем поиска по эмодзи требуется добавить топики в Kafka:

    • messenger.time.emojis.events.private
    • messenger.time.dl.emojis.events.private

v8.0.0

Раскрыть

После обновления необходимо запустить переиндексацию сообщений для корректной работы поиска: Системная консоль (System Console) → Окружение (Environment) → Elasticsearch — в пункте "Индексация сообщений" (Messages Indexing) нажмите кнопку "Индексировать сейчас" (Index Now) и дождитесь успешного выполнения переиндексации сообщений.

v7.2.1

Раскрыть

Был актуализирован список топиков Kafka для установки через kustomize — некоторые топики заменены:

  • time_cluster_high_prioritytime.messenger.hp
  • time_cluster_low_prioritytime.messenger.lp

Перед обновлением важно проверить, что в Kafka топики созданы и у time-server есть права на чтение/запись в них:

  • time.messenger.hp
  • time.messenger.lp

v7.1.0

Раскрыть

В Docker Compose был изменен сервис для поиска: Elasticsearch был заменен на OpenSearch. Так как перенос данных из Elasticsearch в Opensearch не предусмотрен, то требуется выполнить полную индексацию.

  • полностью остановить Time:

    ./docker-compose down
  • после обновления файлов из архива выполните:

    ./docker-compose up --detach
  • после запуска Time необходимо выполнить полную переиндексацию: Системная консольОкружениеElasticsearch

    • Очистить индексы — нажмите кнопку "Очистить индексы"
    • Массовая индексация — нажмите кнопку "Индексировать сейчас"

v7.0.0

Раскрыть

Для успешного переключения на новый улучшенный поиск по пользователям и каналам необходимо выполнить переиндексацию, в противном случае поиск по пользователям/каналам после обновления может деградировать.

Перед этим важно проверить, что параметры ниже имеют одинаковые значения, иначе реиндексация будет сделана для одного индекса, а поиск будет осуществляться по второму:

  • TIME_ELASTICSEARCHSETTINGS_USERINDEXNAME
  • TIME_ELASTICSEARCHSETTINGS_USERINDEXNAMETOSEARCH

Для этого необходимо выполнить следующие действия в админ. консоли (Окружение → Elasticsearch):

  1. Пользователи:
    • В пункте "Очистить индекс пользователей" нажмите кнопку "Очистить индекс"
    • В пункте "Индексация пользователей" нажмите кнопку "Индексировать сейчас" и дождитесь успешного выполнения переиндексации пользователей
  2. Каналы:
    • В пункте "Очистить индекс каналов" нажмите кнопку "Очистить индекс"
    • В пункте "Индексация каналов" нажмите кнопку "Индексировать сейчас" и дождитесь успешного выполнения переиндексации каналов

v6.0.0

Раскрыть

При использовании SAML, необходимо проверить: если настройка Enable Admin Attribute включена, то нужно заполнить поле Admin Attibute

v5.1.0

Раскрыть

После переименования бинарников и папок, развернутые в виде Docker Compose инсталляции могут столкнуться с проблемами отсутствия данных по старым путям / настройкам БД.

В случае, если у вас используется инсталляция Time, развернутая в Docker Compose, для сохранения предыдущих настроек, вы можете использовать файл docker-compose-custom.yml, который необходимо создать в папке time-docker-compose:

time-docker-compose/docker-compose-custom.yml
---
version: "3.9"
name: time

services:
time-server:
volumes:
- ${TIME_SERVER_LICENSE_PATH}:/time/license/
- ${TIME_SERVER_CONFIG_PATH}:/time/config/
environment:
TIME_SQLSETTINGS_DATASOURCE: postgres://mmuser:mostest@postgres.local:5432/time_test?sslmode=disable&connect_timeout=10
TIME_SERVICESETTINGS_LICENSEFILELOCATION: /time/license/tinkoff_license.txt
TIME_PLUGINSETTINGS_PLUGINS_RU.TINKOFF.MM.WORKFLOW_DSN: postgres://mmuser:mostest@postgres.local:5432/time_test?sslmode=disable&connect_timeout=10

postgres:
healthcheck:
test: pg_isready --username=mmuser --dbname=time_test --port=5432
start_period: 60s
interval: 30s
timeout: 30s
retries: 5
environment:
POSTGRES_DB: time_test
POSTGRES_USER: mmuser
POSTGRES_PASSWORD: mostest

Также в случае пересборки образа time-server с целью дополнения своими плагинами — необходимо учитывать изменение пути к плагинам: папка /mattermost/prepackaged_plugins/ перемещена в /time/prepackaged_plugins/ (см. пример Dockerfile в Installation Guide → "Добавление сертификатов и плагинов").

v4.7.0

Раскрыть

После обновления time-front (веб и десктоп клиенты) валидация количества пустых строчек теперь не происходит на Frontend во момент рендеринга, поэтому теперь старые посты, в которых когда-то было много пустых строчек (больше 5), могут отображаться иначе (все пустые строчки из поста будут отображаться). В случае, если это представляет проблему, можно применить скрипты из инструкции ниже:

  1. Вытаскиваем все id постов, у которых подряд идут больше 5 переносов строк (\n) и складываем их во временную таблицу (бэкап):

    -- Создаем временную таблицу
    CREATE TABLE temp_incorrect_post (
    id VARCHAR(26) PRIMARY KEY,
    message VARCHAR(65535)
    );

    -- Перекладываем все сообщения из каналов off-topic и town-square,
    -- а из всех остальных каналов — за последние 14 дней, во временную таблицу
    INSERT INTO temp_incorrect_post (id, message)
    SELECT id, message
    FROM posts
    WHERE message like CONCAT('%',CHR(10),CHR(10),CHR(10),CHR(10),CHR(10),CHR(10),'%')
    and (
    -- id каналов off-topic и town-square можно найти в веб/десктоп клиенте в информации о канала
    channelid = 'zg5unqrakjydtkfjkyf76bajxh' or channelid = 'jgipdxh8ziyy78zfuq9gpjjkho')
    and deleteat = 0
    or createat****(extract(epoch from (current_date - interval '14 days')) * 1000)::bigint
    );
  2. Батчами достаем id некорректных постов через limit и делаем update оригинальной таблицы, удаляя лишние \n, оставляя только 5 \n:

    CREATE PROCEDURE update_incorrect_posts()
    LANGUAGE plpgsql
    AS $$
    DECLARE
    count integer := 1;
    BEGIN
    while count****0 LOOP
    update posts
    set message = regexp_replace(message, CONCAT(CHR(10),'{6,}'), CONCAT(CHR(10),CHR(10),CHR(10),CHR(10),CHR(10)))
    where id in (select id from temp_incorrect_post limit 10000) and message like CONCAT('%',CHR(10),CHR(10),CHR(10),CHR(10),CHR(10),CHR(10),'%');
    get diagnostics count = row_count;
    Raise Notice 'Rows Found : total_rows: %', count;
    commit;
    end loop;
    END;
    $$;

    CALL update_incorrect_posts();
  3. Сверяем выполненные изменения — считаем количество некорректных постов в оригинальной таблице (запрос должен показать пустой результат):

    select count(*)
    from posts
    where
    message like CONCAT('%',CHR(10),CHR(10),CHR(10),CHR(10),CHR(10),CHR(10),'%')
    and (
    ( -- id каналов off-topic и town-square можно найти в веб/десктоп клиенте в информации о канала
    channelid = 'zg5unqrakjydtkfjkyf76bajxh' or channelid = 'jgipdxh8ziyy78zfuq9gpjjkho'
    ) and deleteat = 0
    or
    createat****(extract(epoch from (current_date - interval '14 days')) * 1000)::bigint
    );
  4. Если результат из предыдущего пункта — пустой, тогда удаляем таблицу temp_incorrect_post и процедуру update_incorrect_posts:

    DROP TABLE temp_incorrect_post;
    DROP PROCEDURE update_incorrect_posts;
  5. Запасной запрос на случай, если что-то пошло не так, тогда мы должны откатиться к состоянию как было до запуска процедуры:

    CREATE PROCEDURE revert_update_incorrect_posts()
    LANGUAGE plpgsql
    AS $$
    DECLARE
    count integer := 1;
    BEGIN
    while count****0 LOOP
    update posts
    set message = tip.message
    from (select temp_incorrect_post.id, temp_incorrect_post.message from temp_incorrect_post limit 10000) as tip
    where tip.id = posts.id and posts.message like CONCAT('%',CHR(10),CHR(10),CHR(10),CHR(10),CHR(10),CHR(10),'%');
    get diagnostics count = row_count;
    Raise Notice 'Rows Found : total_rows: %', count;
    commit;
    end loop;
    END;
    $$;

    CALL revert_update_incorrect_posts();

v4.4.0

Раскрыть

Образы компонент Time были пересобраны с целью сделать образы более безопасными. Поэтому в случае, если вы ранее пересобирали образ time-server и подкладывали туда сертификаты, а также другие необходимые для работы вещи (например, плагины), важно учитывать что в образе теперь:

  • нет пользователя root
  • нет ничего кроме runtime (только бинарник time-server)

Для пересборки образа можно использовать примерно такой Dockerfile:

Dockerfile
ARG TIME_SERVER_VERSION
ARG PREPARE_IMAGE="ubuntu:jammy"
ARG TIME_SERVER_IMAGE="docker.registry.tinkoff.ru/time/time-server/time-server:${TIME_SERVER_VERSION}"
ARG PUID=2000
ARG PGID=2000


FROM ${PREPARE_IMAGE} as prepare
COPY cert/ /usr/local/share/ca-certificates/
RUN apt update -y && \
apt install ca-certificates -y && \
update-ca-certificates


FROM ${TIME_SERVER_IMAGE} as time-server
ARG PUID
ARG PGID

# Copy certificates
COPY --chown=${PUID}:${PGID} --from=prepare /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ca-certificates.crt

# Add custom plugins
COPY --chown=${PUID}:${PGID} ./plugins/some-plugin.tar.gz /mattermost/prepackaged_plugins/

v4.2.0

Раскрыть

В случае использования Elasticsearch как Managed Service в Yandex Cloud, необходимо перенастроить путь к сертификату:

Если для настроек используются переменные окружения:

  - name: TIME_ELASTICSEARCHSETTINGS_PEMFILE
value: /usr/local/share/ca-certificates/Yandex/YandexInternalRootCA.crt

Если для настроек испольуется конфигурационный файл config.json:

"ElasticsearchSettings": {
"PemFile": "/usr/local/share/ca-certificates/Yandex/YandexInternalRootCA.crt"
},

v4.0.16

Раскрыть

Теперь для работы с поиском Time может использовать как Elasticsearch, так и OpenSearch. Если для вашей компании предпочтительно использовать OpenSearch, то вы можете переключить Time на OpenSearch. Ниже приведена инструкция для миграции приложения с Elasticsearch на OpenSearch без простоя.

  1. Подготовить кластер OpenSearch с такими же характеристиками и того же размера, как и кластер Elasticsearch. На первом шаге необходимо настроить time-server, таким образом, чтобы на период индексации данных в OpenSearch поиск продолжил работать через Elasticsearch. Для этого нужно в файле настроек config.json обновить параметры подключения:

  2. Доступ к OpenSearch прописываем в настройках, в которых ранее был указан Elasticsearch:

    • ElasticsearchSettings.ConnectionURL
    • ElasticsearchSettings.Username
    • ElasticsearchSettings.Password

    Если для настроек используются переменные окружения:

    • TIME_ELASTICSEARCHSETTINGS_CONNECTIONURL
    • TIME_ELASTICSEARCHSETTINGS_USERNAME
    • TIME_ELASTICSEARCHSETTINGS_PASSWORD

    Доступ к Elasticsearch прописываем в новых настройках:

    • ElasticsearchSettings.ConnectionURLToSearch
    • ElasticsearchSettings.UsernameToSearch
    • ElasticsearchSettings.PasswordToSearch

    Если для настроек использаются переменные окружения:

    • TIME_ELASTICSEARCHSETTINGS_CONNECTIONURLTOSEARCH
    • TIME_ELASTICSEARCHSETTINGS_USERNAMETOSEARCH
    • TIME_ELASTICSEARCHSETTINGS_PASSWORDTOSEARCH
  3. Убедимся что в файле настроек ElasticsearchSettings.PostIndexName и ElasticsearchSettings.PostIndexNameToSearch выставлены в одно и то же значение. Если значения настроек отличаются, выставить ElasticsearchSettings.PostIndexName в значение из настройки ElasticsearchSettings.PostIndexNameToSearch.

    То же самое проделать для аналогичных настроек других индексов:

    • ElasticsearchSettings.FileIndexName и ElasticsearchSettings.FileIndexNameToSearch
    • ElasticsearchSettings.UserIndexName и ElasticsearchSettings.UserIndexNameToSearch
    • ElasticsearchSettings.ChannelIndexName и ElasticsearchSettings.ChannelIndexNameToSearch
    • ElasticsearchSettings.HashtagIndexName и ElasticsearchSettings.HastagIndexNameToSearch

В результате получаем файл конфигурации, похожий на:

config.json
{
"ElasticsearchSettings": {
"ConnectionURL": "https://opensearch:9200",
"Username": "opensearch_user",
"Password": "opensearch_password",
"ConnectionURLToSearch": "https://elasticsearch:9200",
"UsernameToSearch": "elastic_user",
"PasswordToSearch": "elastic_password",
"PostIndexName": "posts",
"PostIndexNameToSearch": "posts",
"FileIndexName": "files",
"FileIndexNameToSearch": "files",
"UserIndexName": "users",
"UserIndexNameToSearch": "users",
"ChannelIndexName": "channels",
"ChannelIndexNameToSearch": "channels",
"HashtagIndexName": "hashtags",
"HashtagIndexNameToSearch": "hashtags"
}
}
  1. Запускаем полную переиндексацию. Для этого в системной консоли заходим во вкладку "Elasticsearch" и нажимаем кнопку "Индексировать сейчас". В этой же вкладке можно следить за прогрессом выполнения индексации.

  2. После того, как закончится индексация, из файла настроек полностью удаляем настройки: ElasticsearchSettings.ConnectionURLToSearch, ElasticsearchSettings.UsernameToSearch, ElasticsearchSettings.PasswordToSearch либо соответсвующие переменные окружения TIME_ELASTICSEARCHSETTINGS_CONNECTIONURLTOSEARCH, TIME_ELASTICSEARCHSETTINGS_USERNAMETOSEARCH, TIME_ELASTICSEARCHSETTINGS_PASSWORDTOSEARCH и перезапускаем time-server.

v3.2.0

Раскрыть
  1. После обновления необходимо запустить переиндексацию в системной консоли (подробней — см. Руководство системного администратора Time):

    1. сначала нужно в пункте "Очистить индексы" (Purge Indexes) нажать кнопку "Очистить индексы" (Purge Indexes)
    2. потом в пункте "Массовая индексация" (Bulk Indexing) нажать кнопку "Индексировать сейчас" (Index Now)
  2. Выполнение миграций БД может долго идти — возможно падание выполнения миграций по таймауту или может не подниматься контейнер в k8s.

В случае проблем рекомендуется сделать что-то одно из списка:

  • увеличить параметр .SqlSettings.MigrationsStatementTimeoutSeconds и увеличить время readinessProbe для подов в k8s

  • выполнить указанные ниже миграции вручную в БД:

    • 1698744461_add_channelid_to_userreactions

      alter table userreactions add column if not exists channelid varchar(26);
      create index if not exists idx_userreactions_userid_postcreateat_desc_postid on userreactions(userid, postcreateat desc, postid);
      create index if not exists idx_userreactions_userid_lastreactat_desc_postid on userreactions(userid, lastreactat desc, postid);
      drop index if exists idx_userreactions_userid_postcreateat_desc;
      drop index if exists idx_userreactions_userid_lastreactat_desc;

      -- query to update large table
      DO $$
      declare
      count integer := 1;
      begin
      while count****0 LOOP
      update userreactions set channelid = t.channelid
      from (
      select
      userreactions.postid,
      posts.channelid
      from userreactions
      join posts on posts.id = userreactions.postid
      where userreactions.channelid is null
      limit 20000) as t
      where userreactions.postid = t.postid;
      get diagnostics count = row_count;
      commit;
      end loop;
      END$$;
    • 1698744460_add_channelid_to_postmentions

      alter table postmentions add column if not exists channelid varchar(26);
      alter table postmentions_history add column if not exists channelid varchar(26);

      -- query to update large table
      DO $$
      declare
      count integer := 1;
      begin
      while count****0 LOOP
      update postmentions set channelid = t.channelid
      from (
      select
      postmentions.postid,
      posts.channelid
      from postmentions
      join posts on posts.id = postmentions.postid
      where postmentions.channelid is null
      limit 20000) as t
      where postmentions.postid = t.postid;
      get diagnostics count = row_count;
      commit;
      end loop;
      END$$;
  • выполнить все миграции отдельной командой внутри контейнера

    ./mattermost/bin/mattermost db migrate
  1. Удалить параметр .MfaSettings.CodeSettings.DeliveryService, если он установлен.

  2. Требуется создать два новых топика в Kafka:

    • messenger.time.users.indexing.events.private
    • messenger.time.dl.users.indexing.events.private

    Количество партиций для этих топиков рекомендуется установить равным количеству брокеров в кластере Kafka.

    Так же в конфигурационном файле config.json нужно добавить новую секцию "UserIndexing" в разделе "EventsSettings":

    config.json
    {
    "EventsSettings": {
    [...]
    "UserIndexing": {
    "ConsumerGroup": "messenger.time.users.indexing",
    "HandleTimeoutSeconds": 600,
    "EnabledConsumer": true,
    "Enabled": true,
    "Topic": "messenger.time.users.indexing.events.private",
    "TopicDL": "messenger.time.dl.users.indexing.events.private",
    "RetryCount": 10,
    "ConsumerBatchSize": 50
    },
    [...]
    }
    }

    Расположение конфигурационного файла зависит от типа установки (см. Руководство по установке мессенджера Time).

v1.2.0

Раскрыть

В некоторых случаях может на завершаться миграция 000104_migrate_channel_members_to_sidebar_channels, как следствие — могут не отображаться каналы в Sidebar.

В таком случае следует выполнить миграцию вручную в БД:

INSERT INTO sidebarchannels(channelid, userid, categoryid, sortorder, teamid)
SELECT
channelid,
userid,
concat('channels_', userid, '_', teamid) as categoryid,
((select max(sortorder) from sidebarchannels where categoryid = concat('channels_', userid, '_', teamid))+(row_number() over ())*10) as sortorder,
c.teamid as teamid
FROM channelmembers LEFT JOIN channels c on channelmembers.channelid = c.id
WHERE
c.type in ('P', 'O') AND
deleteat = 0 AND
NOT EXISTS
( SELECT 1 FROM sidebarChannels
WHERE (sidebarChannels.ChannelId = ChannelMembers.ChannelId
AND sidebarChannels.UserId = channelmembers.userid AND
sidebarChannels.TeamId = c.teamid) )
ON CONFLICT DO NOTHING;

Mobile Apps

v1.61.1

Раскрыть

Для использования новых мобильных приложений из AppStore / Google Play начиная с версии v1.61.1, и успешного получения push-уведомлений — необходимо обновить Push Notification Server до версии v0.2.6.4 (или выше).