Я не могу найти ни одного ORM для Go, который поддерживает несколько арендаторов.Является ли мой собственный вариант поверх пакета sqlx верным вариантом?
ORM в Go - спорная тема!Некоторые пользователи Go любят их, другие ненавидят их и предпочитают писать SQL вручную.Это вопрос личных предпочтений.Запрашивать конкретные рекомендации по библиотекам здесь не по теме, и в любом случае я не знаю ни одной мультитенантной библиотеки ORM - но ничто не мешает вам использовать оболочку sqlx
(я ежедневно работаю в системе, котораяделает именно это).
Другие службы в будущем также потребуют поддержки мультитенантов, поэтому я думаю, что мне все равно придется создать какую-нибудь библиотеку / пакет.
Было бы целесообразно абстрагировать это поведение от этих внутренних служб таким образом, чтобы это соответствовало вашим программным и интерфейсным схемам, но здесь нет более подробной информации, чтобы ответить более конкретно.
Сегодня я разрешаю арендаторов с помощьюиспользование промежуточного программного обеспечения ResolveTenantBySubdomain для публичного сервера API.Затем я помещаю решенный идентификатор арендатора в значение контекста, которое отправляется с вызовом менеджеру.Внутри разных методов в менеджере я получаю идентификатор клиента из значения контекста.Затем он используется с каждым вызовом SQL-запроса / exec или возвращает ошибку, если отсутствует или неверный идентификатор клиента.Должен ли я даже использовать контекст для этой цели?
context.Context
в основном касается отмены, а не распространения запроса.Хотя ваше использование допустимо в соответствии с документацией для функции WithValue
, широко считается неприятным запахом кода для использования пакета context
в настоящее времяреализовано для передачи значений.Вместо того, чтобы использовать неявное поведение, в котором отсутствует безопасность типов и многие другие свойства, почему бы не быть явным в сигнатуре функции ваших нижестоящих слоев данных, передавая идентификатор клиента соответствующим вызовам функций?
РазрешениеАрендатор на сервере gRPC, я считаю, что я должен использовать функцию UnaryInterceptor для обработки промежуточного программного обеспечения.Поскольку доступ к интерфейсу API gRPC будет доступен только другим внутренним службам, я думаю, что разрешение по поддомену здесь не нужно.Но как мне вставить идентификатор арендатора?В шапке?[sic]
Библиотека gRPC не учитывает ваш выбор дизайна.Можно использовать значение заголовка (для передачи идентификатора клиента в качестве параметра «ambient» в запрос) или явно добавить параметр идентификатора клиента в каждый вызов удаленного метода, для которого он требуется.
Обратите внимание, что передача идентификатора клиентатаким образом между вашими службами создается внешнее доверие между ними - если служба A делает запрос службы B и аннотирует его идентификатором клиента, вы предполагаете, что служба A выполнила необходимые проверки контроля доступа для проверки пользователяэтого арендатора действительно делает запрос.В этой простой модели нет ничего, что мешало бы мошеннической службе C запрашивать у службы B информацию о некотором произвольном идентификаторе арендатора.В альтернативной реализации будет реализована более сложная политика «никто не доверяет», в соответствии с которой каждой службе предоставляется достаточная информация об управлении доступом для принятия собственного решения о том, должен ли выполняться конкретный запрос, относящийся к конкретному арендатору.