2013-10-21 9 views
5

एक Mojolicious ऐप में, मैं एक लिंक क्लिक होने पर ओडीटी फ़ाइलों को एचटीएमएल में बदलने की कोशिश कर रहा हूं। मैं फ़ाइलों को "सोफिस", एक शेल कमांड का उपयोग करके रूपांतरित करता हूं। फ़ाइलों को कनवर्ट करने में कुछ समय लगता है। मैं प्रगति के बारे में सूचित करने के लिए उपयोगकर्ता को स्टेटस संदेश भेजता हूं। मैं उन स्थिति अपडेट संदेशों को एक Mojo :: लॉग ऑब्जेक्ट पर लिखकर भेजता हूं। फिर, मैं इस लॉग ऑब्जेक्ट को इवेंटसोर्स रूट में सब्सक्राइब करता हूं।Mojolicious में AnyEvent run_cmd का उपयोग करके, मुझे यह त्रुटि मिलती है: "AnyEvent :: CondVar: रिकर्सिव अवरुद्ध प्रतीक्षा का प्रयास किया गया"

फिर मैं फ़ाइलों के माध्यम से लूप करता हूं और बाहरी "सोफिस" प्रोग्राम निष्पादित करने के लिए run_cmd तक AnyEvent :: का उपयोग करता हूं।

for my $file (@{ $filelist }) { 
    my $output_dir = './output_dir'; 
    my $cmd = "soffice --headless --convert-to html --outdir '$output_dir' '$file'"; 
    my $cv = AnyEvent->condvar; 
    my $w; 
    $w = run_cmd($cmd, 
       '>' => sub { my $out = shift; 
           &WriteToLog({ status => "cmd output '$out'..." }); 
           undef $w; 
           $cv->send; 
       }, 

       '2>' => sub { my $err = shift; 
           &WriteToLog({ status => "ERROR '$err'..." }); 
           undef $w; 
           $cv->send; 
       } 
      ); 

    $cv->recv; 
} 

मुख्य एनीएवेंट ट्यूटोरियल से बहुत अधिक कॉपी और पेस्ट किया गया। यदि कनवर्ट करने के लिए केवल कुछ फ़ाइलें हैं (लगभग 2 या 3), तो सब ठीक हो जाता है। इवेंटसोर्स कनेक्शन के माध्यम से भेजे गए स्टेटस संदेश क्लाइंट ब्राउज़र पर दिखाई देते हैं। फिर सभी फ़ाइलों को परिवर्तित करने के बाद, वेब पेज प्रस्तुत किया जाता है।

यदि अधिक फ़ाइलों को संसाधित किया जाना है, तो कुछ फ़ाइलें परिवर्तित हो जाती हैं तो थ्रेड शीर्षक में त्रुटि संदेश होता है।

my $initdocs = $r->under->to('docroute#initdocs'); 
$initdocs->get('/showdocs')->to('docroute#showdocs'); 

कोड के ऊपर "initdocs" मार्ग में है:

ऊपर कोड युक्त मार्ग के लिए मार्ग यह है।

किसी भी मदद की सराहना की है। अग्रिम में धन्यवाद।

+2

बस भविष्य में, एक [टैग: perl] टैग जोड़कर अधिक लोगों को आपके मोज़ेक प्रश्नों को देखने में मदद मिलेगी। –

उत्तर

3

Creating single Thread Server with AnyEvent

AnyEvent recursive Blocking..

आप AnyEvent का उपयोग कर रहे हैं, तो आप आमतौर पर CondVars से निपटने के लिए। कोंडवार के साथ आप दो चीजें कर सकते हैं: या तो आप एक कॉलबैक पंजीकृत करते हैं जिसे कोंडवायर ट्रिगर होने पर बुलाया जाएगा, या आप आरईवी कॉल करेंगे और कंडवार ट्रिगर होने तक यह अवरुद्ध होगा। अपने मोजो :: कंट्रोलर के मार्ग में, संभवतः आप तब तक ब्लॉक करना चाहते हैं जब तक कि आप अपने उपयोगकर्ता को प्रदर्शित करने वाले सभी डेटा प्राप्त न करें।

निम्नलिखित (बना अप) उदाहरण है जो एक CondVar का उपयोग करता लें:

अपरीक्षित:

get '/' => sub { 
    ... 
    my $cv = AnyEvent->condvar; 
    my $timer = AnyEvent->timer(after => 1, cb => sub { $cv->send(1) }); 
    my $result = $cv->recv; 
    ... 
}; 

आप बताते हुए एक रनटाइम त्रुटि मिल जाएगा "AnyEvent :: CondVar: पुनरावर्ती अवरुद्ध का पता चला प्रतीक्षा करें"। शायद ऐसा इसलिए है क्योंकि मोर्बो अनगिनत लंबे समय तक चलने के लिए बाहर निकलने के लिए बाहर निकलने के लिए कोंडवायर का उपयोग करता है (मुख्य लूप चलाने के लिए कोंडवायर पर अवरुद्ध करना एक आसान तरीका है)।

मेरे दृष्टिकोण EV रूप में एक विशिष्ट eventloop, इस तरह के उपयोग करने के लिए और इसके बदले एक CondVar पर अवरुद्ध EV- फोन> पाश होगा:

EV->loop 
4

मुझे लगता है कि तुम क्या करने की कोशिश कर रहे हैं कॉल करने के लिए है सर्वर सर्वर थ्रेड को अवरुद्ध किए बिना सोफिस (अवरुद्ध) प्रक्रिया। मैं एई पर कोई विशेषज्ञ नहीं हूं लेकिन मुझे नहीं लगता कि run_cmd करता है। यह fork_call के करीब है हालांकि यह करता है।

#!/usr/bin/env perl 

use Mojolicious::Lite; 
use EV; 
use AnyEvent::Util 'fork_call'; 

any '/' => sub { 
    my $c = shift; 
    $c->render_later; 
    fork_call { `sleep 5 && echo 'hi'` } sub { 
    my $data = shift; 
    $c->render(text => $data); 
    }; 
}; 

app->start; 

मेरे उदाहरण में मैं बस एक साधारण अवरुद्ध कॉल करते हैं, लेकिन आप के रूप में आसानी soffice के लिए बाहर कह सकते हैं: शायद आप क्या करना चाहते हैं तो इस तरह के और अधिक कुछ है।

अब जब आप कहते हैं कि आपको क्लाइंट पर लौटने से पहले कई अलग-अलग फाइलों को परिवर्तित करना पड़ सकता है, तो आप प्रक्रियाओं को प्रबंधित करने के लिए उत्कृष्ट Mojo::IOLoop::Delay का उपयोग करना चाह सकते हैं।

#!/usr/bin/env perl 

use Mojolicious::Lite; 
use EV; 
use AnyEvent::Util 'fork_call'; 

my @jobs = (
    q{sleep 5 && echo 'hi'}, 
    q{sleep 5 && echo 'bye'}, 
); 

any '/' => sub { 
    my $c = shift; 
    $c->render_later; 
    my $delay = Mojo::IOLoop->delay; 
    $delay->on(finish => sub { 
    shift; $c->render(text => join '', @_); 
    }); 
    fork_call { `$_` } $delay->begin(0) for @jobs; 
}; 

app->start; 

एक बार फिर, मैं सिर्फ उत्पादन पर कब्जा कर रहा हूँ और यह कॉल प्रस्तुत करने के लिए भेज रहा है, लेकिन लगता है कि यह इंतजार कर रहा है सभी नौकरियों लौटने से पहले खत्म करने के लिए के लिए। कुछ अपने वास्तविक यूज-केस के करीब हो सकता:

#!/usr/bin/env perl 

use Mojolicious::Lite; 
use EV; 
use AnyEvent::Util 'fork_call'; 
use Capture::Tiny 'capture'; 

any '/' => sub { 
    my $c = shift; 
    my $files = $c->every_param('file'); 
    $c->render_later; 
    my $delay = Mojo::IOLoop->delay; 
    $delay->on(finish => sub { 
    shift; $c->render(json => \@_); 
    }); 
    my $output_dir = './output_dir'; 
    for my $file (@$files) { 
    my $cmd = "soffice --headless --convert-to html --outdir '$output_dir' '$file'"; 
    fork_call { [ capture { system $cmd } ] } $delay->begin(0); 
    } 
}; 

app->start; 

यह प्रत्येक फ़ाइल नाम मार्ग (/?file=myfile&file=otherfile) के लिए एक परम के रूप में पारित पर soffice चलाता है। फिर stdout, stderr और रिटर्न कोड (अच्छी तरह से होना चाहिए, मैंने इसे स्पष्ट रूप से नहीं चलाया है) क्लाइंट को जेसन के रूप में प्रस्तुत किया गया है (आप इसे आसानी से लॉग कर सकते हैं)।

+0

मैं बस उल्लेख करना चाहता था (चूंकि यह पोस्ट पॉप अप हुआ) कि इस प्रश्न ने अंततः मुझे इस मॉड्यूल को सीपीए पर बनाने के लिए प्रेरित किया: https://metacpan.org/pod/Mojo::IOLoop::ForkCall –

संबंधित मुद्दे