Безопасно ли хранить пользовательский контент-обработчик CFC в области приложения? - PullRequest
2 голосов
/ 02 июня 2019

Я прочитал много постов о хранении CFC в области Application, и я понимаю, что если CFC хранит данные, то он не должен попадать в область Application.Все CFC, которые выполняют неиспользуемые вещи, будут хранить данные - когда вы передаете параметры, такие как имя пользователя или адрес электронной почты, - поэтому я не понимаю, когда и когда не следует использовать область применения для неиспользуемой CFC.

Мой вопрос заключается в том, что у меня есть posthandler.cfc компонент около 500 строк кода, который обрабатывает сообщения от пользователя (точно так же, как SO будет обрабатывать каждый вопрос, публикуемый на этом сайте).Компонент posthandler.cfc:

  • 'очищает' любые изображения и текст, отправленный пользователем
  • помещает изображения в правильную папку
  • записывает весь текст вбаза данных
  • возвращает URL-адрес, по которому можно просмотреть сообщение

Возвращенный URL-адрес получает простой вызов ajax Jquery, который перенаправляет пользователя на URL-адрес.

Это происходит довольно регулярно на сайте, и в данный момент для каждого сообщения создается новый экземпляр CFC.Безопасно ли вместо этого поместить его в область применения и не вызвать условия гонки / блокировки?

1 Ответ

2 голосов
/ 04 июня 2019

Просто передача параметров ничего не сохраняет.Концептуально каждый поток имеет свою собственную область видимости arguments и local, которая невидима для любого другого потока и перестает существовать при выходе из функции.Таким образом, с этой точки зрения нет конфликта.

Кроме того, хранение данных не означает сохранение их в таблице базы данных.Он относится к компонентам, которые поддерживают состояние, сохраняя данные в общей области / объекте и т. Д. Имея значение «общий», ресурс доступен для других потоков и потенциально может быть изменен несколькими потоками одновременновремя, приводящее к условиям гонки.

Например, возьмем эту (надуманную) компонентную функцию, которая «сохраняет» информацию в области действия variables.Если вы каждый раз создаете новый экземпляр этого компонента, функция безопасна, потому что каждый запрос получает свой собственный экземпляр и отдельную копию области действия variables для воспроизведения.

 public numeric function doStuff( numeric num1, numeric num2 ) {
    variables.firstNum = arguments.num1 * 12;
    variables.secondNum = arguments.num2 * 10;

    return variables.firstNum / variables.secondNum;
 }

Теперь возьмите тот же компоненти поместите это в область применения.Это больше не безопасно.Как только вы сохраните его в области действия application, экземпляр - И его variables - также станет областью приложения.Поэтому, когда функция «сохраняет» данные в области действия variables, она по существу обновляет переменную application.Очевидно, что они не являются поточно-ориентированными, поскольку они доступны для всех запросов.Таким образом, несколько потоков могут легко читать / изменять одни и те же переменные одновременно, что приводит к состоянию гонки.

// "Essentially" becomes this .... 
public numeric function doStuff( numeric num1, numeric num2 ) {
    application.firstNum = arguments.num1 * 12;
    application.secondNum = arguments.num2 * 10;

    return application.firstNum / application.secondNum;
}

Также, как Джеймс А. Мохлер указал , такая же проблема возникает, когда вы опускаете область действия. Объявление переменной функции без области видимости НЕ делает ее локальной для функции.Это делает его частью области по умолчанию: variables - (создавая ту же проблему безопасности потока, описанную выше).Такое поведение приводило ко многим ошибкам многопоточности, когда разработчики забывают ограничить область действия одной переменной запроса или даже индексом цикла.Поэтому не забудьте явно ограничить КАЖДУЮ переменную функции.

 // Implicitly creates "variables.firstNum" and "variables.secondNum"
 public numeric function doStuff( numeric num1, numeric num2 ) {
    firstNum = arguments.num1 * 12;
    secondNum = arguments.num2 * 10;

    return firstNum / secondNum;
 }

Помимо добавления блокировки, оба примера можно сделать поточно-безопасными с помощью явно , используя вместо этого local scope.Храня данные в кратковременной области local, они не видны другим потокам и перестают существовать после выхода из функции.

 public numeric function doStuff( numeric num1, numeric num2 ) {
    local.firstNum = arguments.num1 * 12;
    local.secondNum = arguments.num2 * 10;

    return local.firstNum / local.secondNum;
 }

Очевидно, что необходимо рассмотреть другие случаи, такие как сложные объекты или структуры, которые передаются по ссылке, и то, были ли эти объекты изменены в функции.Но, надеюсь, это проливает некоторый свет на то, что подразумевается под «сохранением данных» и как область видимости может иметь значение между компонентом состояния less (безопасным для области application) и состоянием ful компоненты (которых нет).

TL; DR;

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

...