Я пишу приложение Go, чтобы запускаться во время выполнения App Engine.Как я могу управлять контекстом среды App Engine Go, чтобы избежать блокировки App Engine?
Я заметил, что практически любая операция, использующая сервис App Engine (например, Datastore, Mail или даже Capabilities), требует, чтобы вы передали ему экземпляр appengine.Context
, который должен быть получен с помощью функции appengine.NewContext(req *http.Request) Context
.
Хотя я пишу это приложение для App Engine, я хочу легко и быстро перенести его на другую платформу (возможно, такую, которая не поддерживает какой-либо API App Engine), если я так хочу.
Итак, я абстрагирую фактическое взаимодействие с сервисами App Engine и API, написав небольшие обертки вокруг любого взаимодействия с App Engine, включая функции обработки запросов. При таком подходе, если я когда-либо захочу перейти на другую платформу, я просто переписал те конкретные модули, которые привязывают мое приложение к App Engine. Легко и просто.
Единственная проблема в том, что appengine.Context
объект. Я не могу передать это из своих обработчиков запросов через свои слои логики в модули, которые обрабатывают эти API, не связывая почти весь мой код с App Engine. Я мог бы передать объект http.Request
, из которого можно получить объект appengine.Context
, но для этого потребуется связать вещи, которые, вероятно, не должны быть связаны. (Я считаю, что ни одно из моих приложений не может даже понять, что это веб-приложение, за исключением тех частей, которые специально предназначены для обработки HTTP-запросов.)
Первое решение, которое возникло из виду, состояло в том, чтобы просто создать постоянную переменную в некотором модуле , Что-то вроде этого:
package context
import (
"appengine"
)
var Context appengine.Context
Тогда в моих обработчиков запросов, я могу установить эту переменную с context.Context = appengine.NewContext(r)
и в модулях, которые непосредственно используют App Engine службы, я могу принести контекст экранным context.Context
. Ни один из промежуточных кодов не должен знать о существовании объекта appengine.Context
. Единственная проблема заключается в том, что "multiple requests may be handled concurrently by a given instance", что может привести к условиям гонки и неожиданному поведению с этим планом. (Один запрос устанавливает его, другой устанавливает это, первый обращается к нему и получает неправильный appengine.Context
объект.)
я мог бы теоретически хранить appengine.Context
к хранилищу данных, но тогда я должен был бы пройти некоторый запрос конкретного идентификатора вниз по логическим уровням к модулям, специфичным для службы, определяющим, какой объект appengine.Context
в хранилище данных является единственным для текущего запроса, который снова соединит вещи, которые, как я думаю, не следует связывать. (И, это приведет к увеличению использования хранилища данных моего приложения.)
Я мог бы также передать appengine.Context
объект вниз по всей логической цепочки с типом interface{}
весь путь и иметь какой-либо модуль, который не нуждается в appengine.Context
объект игнорировать его. Это позволит избежать привязки большей части моего приложения к чему-либо специфическим. Однако это также кажется очень беспорядочным.
Итак, я немного потрудился, как обеспечить чистоту модулей App-Engine, которым нужен объект appengine.Context
, и получить его. Надеюсь, вы, ребята, можете дать мне решение, о котором я еще не подумал.
Заранее благодарен!
Спасибо за ваш ответ! Я думаю, у меня есть идея, которая может работать для моего конкретного приложения. Я не уверен, что это будет работать в целом, но может работать для некоторых значительных процентов приложений App Engine. Если моя идея станет полу-общим решением, я обязательно выпущу ее как проект с открытым исходным кодом. : D – AntiMS
Большая часть моего приложения имеет доступ к идентификатору пользователя или идентификатору сеанса. Мой план состоит в том, чтобы создать постоянную карту, привязанную к значениям, полученным непосредственно из идентификатора сеанса или идентификатора пользователя. Обработчики запросов могут создавать и хранить объекты контекста, а модули, которые нуждаются в контексте, могут получить их аналогичным образом. Хотя я не совсем уверен, что это сработает. (Могут быть некоторые модули, которые не имеют доступа к идентификатору сеанса или идентификатору пользователя. Возможно, в некоторых случаях мне придется проявить творческий подход). – AntiMS