<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Alt om ingenting og litt i mellom &#187; asynkront</title>
	<atom:link href="http://hovenko.no/blog/tag/asynkront/feed/" rel="self" type="application/rss+xml" />
	<link>https://hovenko.no/blog</link>
	<description>En blogg av Knut-Olav</description>
	<lastBuildDate>Mon, 10 Mar 2025 19:25:02 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>Asynkron Perl med Proc::Simple</title>
		<link>https://hovenko.no/blog/2009/03/05/asynkron-perl-med-procsimple/</link>
		<comments>https://hovenko.no/blog/2009/03/05/asynkron-perl-med-procsimple/#comments</comments>
		<pubDate>Thu, 05 Mar 2009 20:28:53 +0000</pubDate>
		<dc:creator>Knut-Olav</dc:creator>
				<category><![CDATA[Programmering]]></category>
		<category><![CDATA[asynkront]]></category>
		<category><![CDATA[Catalyst]]></category>
		<category><![CDATA[Perl]]></category>

		<guid isPermaLink="false">http://hovenko.no/blog/?p=257</guid>
		<description><![CDATA[Jeg har nettopp skrevet en web-applikasjon i Perl basert på web-rammeverket Catalyst. Noe av det denne applikasjonen gjør er å flytte filer, og ofte er dette store filer, på nærmere 1 GB hver. Dette tar tid, spesielt når det skjer mellom to maskiner over en SSH-forbindelse. Siden dette er en web-applikasjon medfører dette at koblinga [...]]]></description>
			<content:encoded><![CDATA[<p>Jeg har nettopp skrevet en web-applikasjon i Perl basert på web-rammeverket <a href="http://www.catalystframework.org/">Catalyst</a>.</p>
<p>Noe av det denne applikasjonen gjør er å flytte filer, og ofte er dette store filer, på nærmere 1 GB hver. Dette tar tid, spesielt når det skjer mellom to maskiner over en SSH-forbindelse. Siden dette er en web-applikasjon medfører dette at koblinga til brukerens nettleser timer ut og brukeren blir presentert med en lite hyggelig feilmelding. Løsningen min måtte være å kjøre filkopieringen asynkront, men hvordan?</p>
<p>Jeg kjører Catalyst som en FastCGI-server med 20 prosesser, bak en Apache web-server. Disse Catalyst-prosessene står og går, selv når brukeren ikke laster noen nettside, og er dermed ypperlig for å kjøre bakgrunnsprosesser i, og samtidig kunne ta imot eventuelle feilmeldinger som kan oppstå.</p>
<p>Jeg kom over <a href="http://search.cpan.org/perldoc?Proc::Simple">Proc::Simple</a>, en Perl-modul som tilbyr å kjøre Perl-funksjoner i bakgrunnen av den normale eksekveringen av koden din. Det jeg gjorde var å lage en ny funksjon, med alt det tidkrevende arbeidet, som jeg tilordnet en variabel. Så sendte jeg med referansen til denne funksjonen inn i Proc::Simple. Ved feil så logges feilmeldingen til en database og brukeren ser feilmeldingen neste gang nettsiden lastes.</p>
<p>Jeg har laget en modell, som du ser nedenfor, som pakker inn Proc::Simple-modulen. For sikkerhets skyld så drepes alle kjørende bakgrunnsprosesser hvis Catalyst skulle avsluttes før disse er ferdige. Vi vil ikke ha løse prosesser kjørende, vil vi?</p>
<p>Jeg tar gjerne imot tilbakemeldinger om forbedringer. Den er ikke så avansert, den er noe dokumentert, og jeg håper den kan være til nytte.</p>
<div class="perl-code">
<pre class="hl"><span class="kwa">package</span> MyApp<span class="sym">::</span>Model<span class="sym">::</span>ProcSimple<span class="sym">;</span>

<span class="kwa">use</span> strict<span class="sym">;</span>
<span class="kwa">use</span> warnings<span class="sym">;</span>
<span class="kwa">use</span> parent qw<span class="sym">/</span>
    Catalyst<span class="sym">::</span>Model
    Class<span class="sym">::</span>Accessor<span class="sym">::</span>Fast
<span class="sym">/;</span>

<span class="kwa">use</span> Proc<span class="sym">::</span>Simple<span class="sym">;</span>

__PACKAGE__<span class="sym">-&gt;</span><span class="kwd">mk_accessors</span><span class="sym">(</span>qw<span class="sym">/</span>procs<span class="sym">/);</span>

<span class="sym">=</span>head1 NAME

MyApp<span class="sym">::</span>Model<span class="sym">::</span>ProcSimple <span class="sym">-</span> Catalyst Model

<span class="sym">=</span>head1 DESCRIPTION

Catalyst Model.

<span class="sym">=</span>head1 METHODS

<span class="sym">=</span>head2 start

 Args<span class="sym">:</span> <span class="kwb">$selv</span><span class="sym">,</span> <span class="kwb">$subref</span>

Takes a subroutine reference as a parameter <span class="kwa">and</span> starts to execute this
in the background.

It stores a reference to the process in an instance variable<span class="sym">,</span>
so the process wont get killed after this method returns.

Ended processes will be cleaned up in L<span class="sym">&lt;/</span>ACCEPT_CONTEXT<span class="sym">&gt;</span>.

<span class="sym">=</span>cut

<span class="kwa">sub</span> start <span class="sym">{</span>
    <span class="kwc">my</span> <span class="sym">(</span><span class="kwb">$self</span><span class="sym">,</span> <span class="kwb">$subref</span><span class="sym">) =</span> <span class="kwb">&#64;_</span><span class="sym">;</span>

    <span class="kwc">my</span> <span class="kwb">$proc</span> <span class="sym">=</span> Proc<span class="sym">::</span>Simple<span class="sym">-&gt;</span><span class="kwd">new</span><span class="sym">();</span>

    <span class="kwb">$proc</span><span class="sym">-&gt;</span><span class="kwd">start</span><span class="sym">(</span><span class="kwb">$subref</span><span class="sym">);</span>

    <span class="slc"># Kill the process if the object is destroyed (app is stopped)</span>
    <span class="kwb">$proc</span><span class="sym">-&gt;</span><span class="kwd">kill_on_destroy</span><span class="sym">(</span><span class="num">1</span><span class="sym">);</span>

    <span class="kwc">my</span> <span class="kwb">%procinfo</span> <span class="sym">= (</span>
        <span class="str">'proc'</span>      <span class="sym">=&gt;</span> <span class="kwb">$proc</span><span class="sym">,</span>
        <span class="str">'started'</span>   <span class="sym">=&gt;</span> DateTime<span class="sym">-&gt;</span>now<span class="sym">,</span>
    <span class="sym">);</span>

    push &#64;<span class="sym">{</span><span class="kwb">$self</span><span class="sym">-&gt;</span>procs<span class="sym">},</span> <span class="esc">\%</span>procinfo<span class="sym">;</span>

    <span class="kwa">return</span> <span class="num">1</span><span class="sym">;</span>
<span class="sym">}</span>

<span class="sym">=</span>head2 ACCEPT_CONTEXT

 Args<span class="sym">:</span> <span class="kwb">$self</span><span class="sym">,</span> <span class="kwb">$c</span>

Iterates over all background processes that has been running
since <span class="kwa">last</span> time this model was called <span class="kwa">for</span>.

All ended processes will be removed from the list.

<span class="sym">=</span>cut

<span class="kwa">sub</span> ACCEPT_CONTEXT <span class="sym">{</span>
    <span class="kwc">my</span> <span class="sym">(</span><span class="kwb">$self</span><span class="sym">,</span> <span class="kwb">$c</span><span class="sym">) =</span> <span class="kwb">&#64;_</span><span class="sym">;</span>

    <span class="kwb">$self</span><span class="sym">-&gt;</span><span class="kwd">procs</span><span class="sym">([])</span> <span class="kwa">unless</span> <span class="kwb">$self</span><span class="sym">-&gt;</span>procs<span class="sym">;</span>

    <span class="slc"># Killing and removing ended processes</span>
    <span class="kwa">if</span> <span class="sym">(</span>scalar &#64;<span class="sym">{</span><span class="kwb">$self</span><span class="sym">-&gt;</span>procs<span class="sym">}) {</span>
        <span class="kwc">my</span> <span class="kwb">&#64;to_remove</span> <span class="sym">= ();</span>

        <span class="kwb">$c</span><span class="sym">-&gt;</span>log<span class="sym">-&gt;</span><span class="kwd">debug</span><span class="sym">(</span><span class="kwd">sprintf</span><span class="sym">(</span>
            <span class="str">&quot;Looping over %d procs to look for finished processes&quot;</span><span class="sym">,</span>
            scalar &#64;<span class="sym">{</span><span class="kwb">$self</span><span class="sym">-&gt;</span>procs<span class="sym">}</span>
        <span class="sym">))</span> <span class="kwa">if</span> <span class="kwb">$c</span><span class="sym">-&gt;</span>debug<span class="sym">;</span>

        <span class="kwa">for</span> <span class="kwc">my</span> <span class="kwb">$idx</span> <span class="sym">(</span><span class="num">0</span> .. scalar &#64;<span class="sym">{</span><span class="kwb">$self</span><span class="sym">-&gt;</span>procs<span class="sym">} -</span> <span class="num">1</span><span class="sym">) {</span>
            <span class="kwc">my</span> <span class="kwb">$procinfo</span>    <span class="sym">=</span> <span class="kwb">$self</span><span class="sym">-&gt;</span>procs<span class="sym">-&gt;[</span><span class="kwb">$idx</span><span class="sym">];</span>
            <span class="kwc">my</span> <span class="kwb">$proc</span>        <span class="sym">=</span> <span class="kwb">$procinfo</span><span class="sym">-&gt;{</span><span class="str">'proc'</span><span class="sym">};</span>
            <span class="kwc">my</span> <span class="kwb">$running</span>     <span class="sym">=</span> <span class="kwb">$proc</span><span class="sym">-&gt;</span><span class="kwd">poll</span><span class="sym">()</span> <span class="kwa">if</span> <span class="kwb">$proc</span><span class="sym">;</span>
            push <span class="kwb">&#64;to_remove</span><span class="sym">,</span> <span class="kwb">$idx</span> <span class="kwa">unless</span> <span class="kwb">$running</span><span class="sym">;</span>
        <span class="sym">}</span>

        <span class="kwa">for</span> <span class="kwc">my</span> <span class="kwb">$idx</span> <span class="sym">(</span><span class="kwb">&#64;to_remove</span><span class="sym">) {</span>
            <span class="kwc">my</span> <span class="kwb">$procinfo</span> <span class="sym">=</span> <span class="kwb">$self</span><span class="sym">-&gt;</span>procs<span class="sym">-&gt;[</span><span class="kwb">$idx</span><span class="sym">];</span>
            <span class="kwc">my</span> <span class="kwb">$pid</span> <span class="sym">=</span> <span class="kwb">$procinfo</span><span class="sym">-&gt;{</span><span class="str">'proc'</span><span class="sym">}-&gt;</span>pid<span class="sym">;</span>
            <span class="kwb">$c</span><span class="sym">-&gt;</span>log<span class="sym">-&gt;</span><span class="kwd">info</span><span class="sym">(</span><span class="str">&quot;Proc::Simple process $pid has finished. Removed.&quot;</span><span class="sym">);</span>

            delete <span class="kwb">$self</span><span class="sym">-&gt;</span>procs<span class="sym">-&gt;[</span><span class="kwb">$idx</span><span class="sym">]</span>
        <span class="sym">}</span>
    <span class="sym">}</span>

    <span class="kwa">return</span> <span class="kwb">$self</span><span class="sym">;</span>
<span class="sym">}</span>

<span class="sym">=</span>head1 SEE ALSO

L<span class="sym">&lt;</span>Proc<span class="sym">::</span>Simple<span class="sym">&gt;</span>

<span class="sym">=</span>head1 AUTHOR

Knut<span class="sym">-</span>Olav Hoven<span class="sym">,</span> E<span class="sym">&lt;</span><span class="kwa">lt</span><span class="sym">&gt;</span>knutolav<span class="kwb">&#64;gmail</span>.comE<span class="sym">&lt;</span><span class="kwa">gt</span><span class="sym">&gt;</span>

<span class="sym">=</span>head1 LICENSE

This library is free software<span class="sym">,</span> you can redistribute it <span class="kwa">and</span><span class="sym">/</span><span class="kwa">or</span> modify
it under the same terms as Perl itself.

<span class="sym">=</span>cut

<span class="num">1</span><span class="sym">;</span>
</pre>
</div>
]]></content:encoded>
			<wfw:commentRss>https://hovenko.no/blog/2009/03/05/asynkron-perl-med-procsimple/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>
