Hallo Jan,
Jan P. schrieb:
Hi Jan,
vielleicht kannst Du den net/http-Aufruf einmal darstellen.
Du schreibst, dass das net/http Object EINIGE Anfragen im Hintergrund
absetzt. Sind dies mehr als acht Anfragen? Setze doch mal jeweis eine
Anfrage ab und schließe den request dann einmal korrekt. Vielleicht bleibt
der geöffnete request “offen” bis alle Anfragen beendet sind und blockiert
solange auch den mongrel. Meine Vermutung ist, dass sehr schnelle alle
mongrel-instanzen belegt sind bis das net/http-Objekt geschlossen wird.
Also wenn ich die Action aufrufe, wird tatsächlich immer nur ein
net/http Object instanziert. Die Funktionen dazu sehen ungefähr so aus:
es gibt Users mit Benutzername und Passwort für je einen WebService
weiterhin gibt es den Table UserConditions mit User has many
UserConditions
Benutzername und Passwort wird nun nach dem Aufruf samt Service ID
an eine protected Action übergeben
def do_my_very_important_stuff
@user_condition = UserCondition.find(params[:id])
@user_condition.status = get_query_result(@user_condition.user.name,
@user_condition.user.password, @user_condition.service_id)
@user_condition.save!
respond_to do |format|
format.js
end
end
protected Action
def get_query_result(username, password, service_id)
@service = Service.find(service_id)
@item_list = get_item_list(12,18) # returniert eine Liste mit 12 bis
18 items
# holt sich dynamisch eine Instanz vom Service Object, das genauere
Daten zum anzusprechenden WebService enthält
# nicht schön, ich weiss …
eval("@service_runner = #{@service.object.camelize}.new(username,
password, service_id)")
status = nil
# erst der Login am Service
if @service_runner.login
logger.warn("Successfully logged in")
@error = false
for item in @item_list
# dann die eigentliche Action am WebService
if not @service_runner.do_stuff_with(item)
logger.warn("!!! runner for item #{item} returned with an
error, aborting")
@error = true
break
end
end
if not @error
status = ‘do_stuff_with returned successfully’
else
logger.warn("!!! do_stuff_with returned with errors")
status = ‘do_stuff_with failed’
end
else
logger.warn(“Error while logging in”)
status = ‘login failed’
end
return status
end
Und ein einfaches Object sieht in etwa so aus, auch dirty, aber die
Services bieten leider alle kein REST Interface, da wäre das einfacher:
require “erb”
require “net/http”
class ServiceXYZ < ActiveRecord::Base
def initialize(username, password, service_id)
@USERNAME = username
@PASSWORD = password
@SERVICE = Service.find(service_id) # Hier finden sich die ganzen
Daten des eigentlichen WebService, den ich ansprechen will
@USERAGENT = ‘Mozilla/5.0 (Windows; U; Windows NT 5.1; de-DE;
rv:1.8.0.1) Gecko/20060111 Firefox/1.5.0.1’
end
der Login läuft indem ich meisst erst ein GET absetze, dann Cookie
setze und die Benutzerdaten danach POST’e
def login
@success = true
unless @HEADERS.nil?
logger.warn(“You should already be logged in!”)
end
@http = Net::HTTP.new(@SERVICE.domain, 80)
resp, data = @http.get(@SERVICE.login_path_1, {‘User-Agent’ =>
@USERAGENT})
if resp.code == “200”
@COOKIE = resp.response[‘set-cookie’]
data =
“username=#{ERB::Util.url_encode(@USERNAME)}&password=#{ERB::Util.url_encode(@PASSWORD)}”
@HEADERS = {
‘Cookie’ => @COOKIE,
‘Referer’ => 'http://'[email protected][email protected]_path_1,
‘Content-Type’ => ‘application/x-www-form-urlencoded’,
‘User-Agent’ => @USERAGENT
}
resp, data = @http.post(@SERVICE.login_path_1, data, @HEADERS)
if resp.code == “302”
@COOKIE = resp.response[‘set-cookie’]
@logged_in = false
data.each_line do |line|
@logged_in = true if line.match(/my/archive/) # Text Check,
der nur nach positivem Login ok ist
end
@success = false if not @logged_in
else
@success = false
end
else
@success = false
end
return(@success)
end
hier nun die eigentliche Schulball Veranstaltung
def do_stuff_with(content_id)
@success = false
@content = Content.find(content_id)
data = “item%5Bbla%5D=#{ERB::Util.url_encode(@content.bla)}&item%
5Bblu%5D=#{ERB::Util.url_encode(@content.blu)”
@HEADERS = {
‘Cookie’ => @COOKIE,
‘Content-Type’ => ‘application/x-www-form-urlencoded’,
‘User-Agent’ => @USERAGENT
}
resp, data = @http.post(@SERVICE.save_path, data, @HEADERS)
if resp.code == “200”
data.each_line do |line|
@success = true if line.match(/Your\sitem\shas\sbeen\ssaved/)
end
else
@success = false
end
return(@success)
end
end
Was ich nicht tue, ist ein explizites Close auf die Connection. Ich
dachte auch nicht, dass das bei HTTP notwendig sei, vielleicht ein
Fehler. Da man hier aber sieht, dass pro Aufruf der Action wirklich nur
ein Object instanziert wird, kann dieses keine Mongrelinstanzen belegen.
Vorallem weil es ja server side kreiert wird. ps zeigt ja auch keine
weiteren Instanzen, wenn ich diese Action aufrufe.
Bitte nicht spekulieren, was ich hier tue, es ist nicht, wonach es
aussieht ;o)
Und bitte keine bösen Worte, ich weiss, dass der Code 'ne Katastrophe
ist, ist auch nur eine schnelle Idee, pragmatisch umgesetzt.
Grüße
Jan