PHP отправляет SOAP ответ раньше? - PullRequest
1 голос
/ 28 июня 2010

Что ж, это старая проблема, с которой я сталкивался и до сих пор не решена, поэтому пытаюсь применить новый подход.

Как я могу отправить SOAP-ответ раньше (до завершения выполнения скрипта)?

Эти проблемы возникают, когда файл ACK не отправляется до 30 секунд, поскольку процесс занимает больше времени, чем выделенное время.

flush () не работает, получите эту ошибку:

org.xml.sax.SAXParseException: структуры документа XML должны начинаться и заканчиваться в одной и той же сущности.

без флеша () Я получаю это

org.xml.sax.SAXParseException: преждевременное завершение файла.

Процесс сценария может занять 180 секунд для завершения, и сервер, ожидающий ответа, подождет около 30 секунд, прежде чем истечет время ожидания (что является причиной вышеуказанной ошибки).

есть мысли, как мне это исправить?

Вот часть кода: Вот как я принимаю и отправляю ACK-файл для предстоящего SOAP-запроса

$data = 'php://input';
$content = file_get_contents($data);

if($content) {
    respond('true');
} else {
    respond('false');
}

Функция ответа

function respond($tf) {
    $ACK = <<<ACK
<?xml version = "1.0" encoding = "utf-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <soapenv:Body>
        <notifications xmlns="http://soap.sforce.com/2005/09/outbound">
            <Ack>$tf</Ack>
        </notifications>
    </soapenv:Body>
</soapenv:Envelope>
ACK;

    print trim($ACK); 
}

PHP использует однопотоковый подход и не будет отправлять обратно файл ACK, пока поток не завершит свою обработку. Есть ли способ закрыть сокет после отправки ACK и продолжить обработку, чтобы у меня не возникало этих проблем с таймаутом на отправляющем сервере?

Ответы [ 2 ]

1 голос
/ 28 июня 2010

Насколько я знаю, мы не можем ничего сделать с 30-секундным пределом, и вывод не будет сброшен до завершения сценария. Можете ли вы попробовать разбить свою логику обработки на 2 части?

  1. Сценарий «Слушатель», который принимает сообщения, регистрирует выполняемое задание и мгновенно отправляет ACK, а затем завершает работу.
  2. Фактическая обработка на вашей стороне, которая может занять больше времени.

«Работа, которую необходимо выполнить» может быть новым процессом (ознакомьтесь с комментариями к функции pcntl_fork () , но они не выглядят для меня слишком многообещающе) или каким-либо способом сохранить данные в файле или базе данных и периодически обрабатывать их с помощью другого сценария, например, запуск по расписанию каждые 5 минут?

Если 60 секунд как-то вас спасут, вы можете переписать исходящее сообщение в выноску из Apex. Затем вы пишете свой собственный конверт SOAP и отправляете его на любой http-адрес. Вы можете поставить его в курок. См. здесь об ограничениях этого подхода.


Другое разглагольствование:

  1. Я не думаю, что ваш ACK действительно "имеет значение" для отдела продаж. Исходящие сообщения - это просто уведомления. Вы полагаетесь где-то еще в своем приложении на Ack = true / false? Если нет - слушатель, который вслепую отправляет ack = true и планирует, что задание действительно может быть подходящим;)
  2. Из другого квеста я понял, что вам просто нужно хранить обновления в БД на вашей стороне. Вы понимаете, что не следует использовать ОМ в целях аудита, верно? ( Ссылка , поиск «аудит»).
  3. Не проще ли сделать PHP активной стороной? сделать запрос в Salesforce для [SELECT Id, Имя ОТ учетной записи, ГДЕ LastModifiedDate>: lastTimeYouQueried]? Таким образом, вы можете потратить все время на обработку результатов :)
1 голос
/ 28 июня 2010

а) (необязательно), вы можете использовать set_time_limit () для увеличения лимита времени выполнения.

b) Вы должны увеличить время для объекта клиента wsdl, например:

$clientwsdl->setOpt('timeout', 300); // if you are using PEAR:SOAP.

Большинство классов wsdl позволяют определять время ожидания.

в) и нет, вы не можете ответить рано, используя SOAP, по крайней мере, одним вызовом. Примите во внимание, что SOAP возвращает XML, поэтому частичный XML обычно недопустим (он пропускает закрывающий тег).

d) Альтернативно, вы можете использовать другой метод, кроме SOAP, например, чтение URL:

$fp=fopen("http://www.mysite.com/url.php","r");

где url.php возвращает столбцы (или какое-либо значение без использования xml:

30|50|70|80|20 
30|50|70|80|20
30|50|70|80|20
...