Schrift
Wiki:Tipp zum Debugging: use Data::Dumper; local $Data::Dumper::Useqq = 1; print Dumper \@var;
[thread]11389[/thread]

"Bitte warten"-Zwischenseite

Leser: 1


<< |< 1 2 >| >> 17 Einträge, 2 Seiten
amun-ra198
 2008-02-29 23:01
#106533 #106533
User since
2007-10-11
13 Artikel
BenutzerIn
[default_avatar]
Hallo,

ich habe ein Webfrontend für eine Applikation erstellt, die bei uns im Einsatz ist. Über das Webfrontend ist es möglich einen Prozess innerhalb dieser Applikation zu starten.
Ich habe nun das altbekannte Problem, das Starten des Prozesses kann schonmal etwas dauern und ich benötige eine "Zwischenseite" mit dem Vermerk "Bitte warten". Etwas ähnliches ist in diesem Forum schonmal diskutiert worden, leider war die Lösung dann etwas gebasteltes in DHTML und Javascript und wurde hier nicht richtig dokumentiert.

Ich habe schon versucht das ganze mit einem "server-push" zu realisieren. Leider ist die Fkt. nicht kompatibel zum IE6.0 (sagt das Modul zumindest).
In Javascript habe ich bisher nur die Möglichkeit der "Bitte warten" Anzeige in der Statusleiste des Browsers entdeckt, was ich allerdings etwas suboptimal finde. Es sollte schon im Browserfenster selbst sein.

Schlußendlich hatte ich dann überlegt, ob es eventuell möglich wäre den Prozess anzustoßen (mit $| = 1) und gleichzeitig die Ausgabe "Bitte warten" zu veranlassen. Nach dem Starten des Prozesses sollte das Skript dann über einen cgi->redirect auf eine separate Seite wechseln, auf der dann der Returncode verarbeitet / angezeigt wird (damit nicht Ergebnis und "Bitte warten" auf einer Seite angezeigt werden).
Problem dabei, um den redirect einbauen zu können darf ich vorher kein content-type mitgeben. Das muss ich allerdings machen, um einen print "Bitte warten" ausgeben zu können. Ein wieder "Aufheben" des Headers im Nachhinein ist ja nicht möglich, der ist ja dann bereits gesendet...

Würde meinen, dass ich schon nah dran bin. Hat jemand eine Idee wie ich das lösen könnte?

Gruß
topeg
 2008-02-29 23:34
#106536 #106536
User since
2006-07-10
2611 Artikel
BenutzerIn

user image
Ich würde so machen:

Ein CGI-Script stößt ein anderes Script im Hintergund an, welches sich um das Starten des eigendlichen Prozesses kümmert. Die PID des Scriptes wird in einer Datei zwischen gespeichert. Über "autoreload" wird wird das CGI-Script neu geladen welches "Bitte Warten" anzeigt solange die in der Datei gespeicherte PID noch existiert.
"autoreload" wird erst dann aktiv wenn die Seite vollständig geladen ist. Das bedeutet nach dem ersten neu laden lässt man das CGI-Script solange aktiv bist der Hintergrundprozess beendet ist, Danach übergibt mit dem Script man eine Weiterleitung.
amun-ra198
 2008-03-01 01:38
#106539 #106539
User since
2007-10-11
13 Artikel
BenutzerIn
[default_avatar]
Danke für die fixe Antwort. Diese Idee hatte ich auch. Dazu müßte ich dann allerdings umfangreichere Veränderungen vornehmen (den Kernprozess auslagern), was ich nach Möglichkeit vermeiden möchte. Ich war der Meinung, dass das doch auch irgendwie einfacher gehen müßte.
Wenn es natürlich keine andere Möglichkeit gibt, werde ich eine Parallelverarbeitung umsetzen.

Hat noch jemand eine Idee?
pq
 2008-03-01 05:27
#106542 #106542
User since
2003-08-04
12208 Artikel
Admin1
[Homepage]
user image
amun-ra198+2008-03-01 00:38:00--
Danke für die fixe Antwort. Diese Idee hatte ich auch. Dazu müßte ich dann allerdings umfangreichere Veränderungen vornehmen (den Kernprozess auslagern), was ich nach Möglichkeit vermeiden möchte. Ich war der Meinung, dass das doch auch irgendwie einfacher gehen müßte.
Wenn es natürlich keine andere Möglichkeit gibt, werde ich eine Parallelverarbeitung umsetzen.

also das ist schon eine standard-lösung für dieses problem. der vorteil ist auch, dass es kein
javascript braucht.
ich habe mal ein zimmer gebucht (glaube bei wombat's hostel). der bezahlprozess ging auf eine andere
domain, ich hatte aber nur javascript für die hostel-seite erlaubt. der bezahlprozess schaltete
so eine warte-seite, die aber nur mit javascript funktionierte.
zum glück konnte ich im quelltext nachsehen, javascript anschalten und dann von hand
den prozess wieder reaktivieren. mitten in einem bezahlprozess hängenzubleiben ist
ziemlich unangenehm.

aber den prozess zu forken und eine warte-seite mit meta-refresh zu erstellen ist kein grosses problem.
ich habe mal kurz was zusammengehackt (ich bin in bastellaune):
Wiki:WieErstelleIchEineWarteSeite
Always code as if the guy who ends up maintaining your code will be a violent psychopath who knows where you live. -- Damian Conway in "Perl Best Practices"
lesen: Wiki:Wie frage ich & perlintro Wiki:brian's Leitfaden für jedes Perl-Problem
MartinR
 2008-03-01 14:19
#106546 #106546
User since
2004-06-17
305 Artikel
BenutzerIn
[default_avatar]
amun-ra198+2008-03-01 00:38:00--
Hat noch jemand eine Idee?


Schon mal überlegt das ganze mit Ajax zu realisieren? Ist zwar auch wieder Javascript, aber da kannst Du mit den verschiedenen Zständen auch arbeiten.
amun-ra198
 2008-03-03 21:05
#106599 #106599
User since
2007-10-11
13 Artikel
BenutzerIn
[default_avatar]
Bei Ajax war ich jetzt ehrlich gesagt etwas überfragt. Hab mich allerdings zwischendurch mal schlau gemacht.
Letztlich werde ich den Prozess jetzt wohl doch in einen separaten Prozess auslagern. Scheint die einfachste Lösung zu sein, auch wenn ich das bestehende Skript dann leider auseinanderpflücken muss.

Danke
Gruß
murphy
 2008-03-04 22:33
#106648 #106648
User since
2004-07-19
1776 Artikel
HausmeisterIn
[Homepage]
user image
amun-ra198+2008-03-03 20:05:36--
[...] Letztlich werde ich den Prozess jetzt wohl doch in einen separaten Prozess auslagern [...] auch wenn ich das bestehende Skript dann leider auseinanderpflücken muss. [...]

Wenn Du fork verwendest muss der Code für den zweiten Prozess nicht unbedingt in einem separaten Programm untergebracht werden.
When C++ is your hammer, every problem looks like your thumb.
pq
 2008-03-05 13:11
#106702 #106702
User since
2003-08-04
12208 Artikel
Admin1
[Homepage]
user image
murphy+2008-03-04 21:33:12--
Wenn Du fork verwendest muss der Code für den zweiten Prozess nicht unbedingt in einem separaten Programm untergebracht werden.

genau, das hatte ich ja mit meinem beispielskript auch sagen wollen.
Always code as if the guy who ends up maintaining your code will be a violent psychopath who knows where you live. -- Damian Conway in "Perl Best Practices"
lesen: Wiki:Wie frage ich & perlintro Wiki:brian's Leitfaden für jedes Perl-Problem
amun-ra198
 2008-03-07 18:36
#106813 #106813
User since
2007-10-11
13 Artikel
BenutzerIn
[default_avatar]
@pq
ok, ich hatte nun die Gelegenheit mich mal mit dem von Dir freundlicherweise erstellten Skript zu beschäftigen. Ich hab das jetzt mal für meine Zwecke angepasst, nahezu nichts verändert. Leider habe ich das Problem, dass die Datei nicht erstellt wird und das Skript ewig in der Schleife läuft. Könntest du das bei dir mal ausprobieren? Hab ich da was übersehen?

Code (perl): (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
#!/usr/bin/perl -w

# Skript Name: test1.pl
# Parameter: Aktionstyp = Prozess

use strict;
use warnings;
use CGI;
use Fcntl qw(:flock);

$| = 1;

my $cgi = CGI->new;
my $url = 'http://server/cgi-bin/test1.pl';

#print "Content-type: text/html \n\n";
#print $cgi->param('Aktionstyp');

# Aufteilen in zwei Subroutinen
my $merker = $cgi->param('Aktionstyp') || 'Anzeigen';
if ($merker eq 'Anzeigen') 
{
    show($cgi);
}
elsif ($merker eq 'Prozess')
{
    create($cgi);
}

# Erstellen des Prozesses und Redirect auf neue Seite
sub create
{
    my ($cgi) = @_;
    
    my $id = time() . $$;
    my $filename = "prozess.id$id";
    
    $SIG{CHLD} = 'IGNORE';
    
    if (my $pid = fork) 
    {
        print $cgi->redirect("$url?Aktionstyp=Anzeigen;id=$id");
        
        # Ende des Parent Prozesses
        exit;
    }
    else 
    {
                        # Beginn Anlegen der Datei
                        open my $fh, ">", $filename;
                        flock $fh, LOCK_EX;
                        close STDOUT;
                        close STDERR;
                        close STDIN;
                        
                        # Erstmal Warten (soll den Prozess simulieren)
                        sleep 10;
                        
                        close $fh;
                        # Ende Anlegen der Datei
                          
                        # Ende des Child Prozesses
                        exit;
    }
}

# Anzeigen des Ergebnisses, wenn ChildProzess fertig
sub show
{
        my ($cgi) = @_;
        my $id = $cgi->param('id') || '';
        
        print $cgi->header;
        print $cgi->start_html;
        
        my $filename = "prozess.id$id";
   
   my $meta = $cgi->start_html(
            my $meta_refresh =
            -head => $cgi->meta(
                {
                    -http_equiv => 'refresh',
                    -content    => "2; $url?w=show;id=$id",
                }
            ));
        
        if (open my $fh, "<", $filename) 
        {
                my $lock = flock $fh, LOCK_EX|LOCK_NB;
      
      if ($lock)
                {
                        print 'Fertig!';
                }
                else
                {
                        print $meta;
                        print 'Datei noch nicht freigegeben';
                }
        }
        else
        {
                print $meta;
                print 'Datei ist noch nicht da';
        }
        print $cgi->end_html;   
}


tausend dank
pq
 2008-03-07 19:07
#106814 #106814
User since
2003-08-04
12208 Artikel
Admin1
[Homepage]
user image
also beim drübergucken fällt mir jetzt nix auf. mach doch mal eine fehlerbehandlung beim
open() und schreib was in ein errorlog.
Code (perl): (dl )
1
2
3
4
# am anfang
open STDERR, '>>', '/my/log' or die "Could not open errorlog: $!";
...
open ... or die $!;


ansonsten noch ein kleiner hinweis: englische variablennamen und möglichst auch englische
kommentare sind IMHO besser. wenn irgendjemand mal dein skript anfassen muss und kein deutsch
kann, ist er aufgeschmissen. basiskentnisse in englisch kann man im schnitt eher erwarten.
Always code as if the guy who ends up maintaining your code will be a violent psychopath who knows where you live. -- Damian Conway in "Perl Best Practices"
lesen: Wiki:Wie frage ich & perlintro Wiki:brian's Leitfaden für jedes Perl-Problem
<< |< 1 2 >| >> 17 Einträge, 2 Seiten



View all threads created 2008-02-29 23:01.