Необходимые действия
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_priority
→time.messenger.hp
time_cluster_low_priority
→time.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):
- Пользователи:
- В пункте "Очистить индекс пользователей" нажмите кнопку "Очистить индекс"
- В пункте "Индексация пользователей" нажмите кнопку "Индексировать сейчас" и дождитесь успешного выполнения переиндексации пользователей
- Каналы:
- В пункте "Очистить индекс каналов" нажмите кнопку "Очистить индекс"
- В пункте "Индексация каналов" нажмите кнопку "Индексировать сейчас" и дождитесь успешного выполнения переиндексации каналов
v6.0.0
Раскрыть
При использовании SAML, необходимо проверить: если настройка Enable Admin Attribute
включена, то нужно заполнить поле Admin Attibute
v5.1.0
Раскрыть
После переименования бинарников и папок, развернутые в виде Docker Compose инсталляции могут столкнуться с проблемами отсутствия данных по старым путям / настройкам БД.
В случае, если у вас используется инсталляция Time, развернутая в Docker Compose, для сохранения предыдущих настроек, вы можете использовать файл docker-compose-custom.yml
, который необходимо создать в папке time-docker-compose
:
---
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), могут отображаться иначе (все пустые строчки из поста будут отображаться). В случае, если это представляет проблему, можно применить скрипты из инструкции ниже:
-
Вытаскиваем все 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
); -
Батчами достаем
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(); -
Сверяем выполненные изменения — считаем количество некорректных постов в оригинальной таблице (запрос должен показать пустой результат):
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
); -
Если результат из предыдущего пункта — пустой, тогда удаляем таблицу
temp_incorrect_post
и процедуруupdate_incorrect_posts
:DROP TABLE temp_incorrect_post;
DROP PROCEDURE update_incorrect_posts; -
Запасной запрос на случай, если что-то пошло не так, тогда мы должны откатиться к состоянию как было до запуска процедуры:
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:
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 /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ca-certificates.crt
# Add custom plugins
COPY ./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 без простоя.
-
Подготовить кластер OpenSearch с такими же характеристиками и того же размера, как и кластер Elasticsearch. На первом шаге необходимо настроить time-server, таким образом, чтобы на период индексации данных в OpenSearch поиск продолжил работать через Elasticsearch. Для этого нужно в файле настроек
config.json
обновить параметры подключения: -
Доступ к 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
-
Убедимся что в файле настроек
ElasticsearchSettings.PostIndexName
иElasticsearchSettings.PostIndexNameToSearch
выставлены в одно и то же значение. Если значения настроек отличаются, выставитьElasticsearchSettings.PostIndexName
в значение из настройкиElasticsearchSettings.PostIndexNameToSearch
.То же самое проделать для аналогичных настроек других индексов:
ElasticsearchSettings.FileIndexName
иElasticsearchSettings.FileIndexNameToSearch
ElasticsearchSettings.UserIndexName
иElasticsearchSettings.UserIndexNameToSearch
ElasticsearchSettings.ChannelIndexName
иElasticsearchSettings.ChannelIndexNameToSearch
ElasticsearchSettings.HashtagIndexName
иElasticsearchSettings.HastagIndexNameToSearch
В результате получаем файл конфигурации, похожий на:
{
"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"
}
}
-
Запускаем полную переиндексацию. Для этого в системной консоли заходим во вкладку "Elasticsearch" и нажимаем кнопку "Индексировать сейчас". В этой же вкладке можно следить за прогрессом выполнения индексации.
-
После того, как закончится индексация, из файла настроек полностью удаляем настройки:
ElasticsearchSettings.ConnectionURLToSearch
,ElasticsearchSettings.UsernameToSearch
,ElasticsearchSettings.PasswordToSearch
либо соответсвующие переменные окруженияTIME_ELASTICSEARCHSETTINGS_CONNECTIONURLTOSEARCH
,TIME_ELASTICSEARCHSETTINGS_USERNAMETOSEARCH
,TIME_ELASTICSEARCHSETTINGS_PASSWORDTOSEARCH
и перезапускаем time-server.
v3.2.0
Раскрыть
-
После обновления необходимо запустить переиндексацию в системной консоли (подробней — см. Руководство системного администратора Time):
- сначала нужно в пункте "Очистить индексы" (Purge Indexes) нажать кнопку "Очистить индексы" (Purge Indexes)
- потом в пункте "Массовая индексация" (Bulk Indexing) нажать кнопку "Индексировать сейчас" (Index Now)
-
Выполнение миграций БД может долго идти — возможно падание выполнения миграций по таймауту или может не подниматься контейнер в 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
-
Удалить параметр
.MfaSettings.CodeSettings.DeliveryService
, если он установлен. -
Требуется создать два новых топика в 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 (или выше).