freakingwildchild has asked for the wisdom of the Perl Monks concerning the following question:

Hi Monks, I'm trying to make a routine which will return the same value for a short period of time, but, that value must stay the same for over a timeframe of 10 minutes.

print join(" ", localtime());
This will give me the values as SEC, MIN, HRS, .... ; but; I got a "five before twelve time-problem" with it; since; when it is 40, 59, that value will only stay the same for the last 20 seconds.

Any of you know anything which I can compare to; any modules available that will give me a number or value which changes only every 5 to 10 minutes on this planet ? Or any other ideas?

The meaning of this is to write a stateless seed/salt-id which does not depend on a written entry in a database but rather on its values (encrypted).

Replies are listed 'Best First'.
Re: A value that stays a value (for some time)
by liverpole (Monsignor) on Jun 18, 2006 at 14:35 UTC
    Hi freakingwildchild,

    Have you considered using a closure for this?  It sounds like you want the value to not change for at least 10 minutes after the first time you create the value; if that's the case, I'd suggest something like:

    #!/usr/bin/perl -w # Strict use strict; use warnings; # Test code my $psub = same_value_for_time_period(5); while (1) { my $x = $psub->(); printf "Value is %s\n", $x; sleep 1; } # Subroutines sub same_value_for_time_period { my ($duration) = @_; # Eg. 600 = 10 minutes my $start_time = time; my $value = get_new_value(); sub { my $now = time; if ($now - $start_time < $duration) { return $value; } else { $start_time = $now; $value = get_new_value(); } } } sub get_new_value { my $value; # Your code for creating a new value here ... $value = rand 1000; return $value; }

    Here, you call the subroutine same_value_for_time_period with a duration (the number of seconds you wish the value to remain constant for).  It returns a pointer to a closure; a subroutine which, each time you call it after it's first created, gives you the same value within the specified duration, and then changes after that.  The subroutine get_new_value is called when the duration is up, to give a new value.  As you can see, I've tested it for a short duration (5 seconds), and just using a random number whenever the value changes.

    Is that the kind of thing you're looking for?


    s''(q.S:$/9=(T1';s;(..)(..);$..=substr+crypt($1,$2),2,3;eg;print$..$/
      This code has some interesting ideas for running a server returning such value; but; this would mean it isn't a stateless number calculated for that moment ; if I restart the proces (which happens in my cgi's, I don't use mod_perl (yet)) it will change numbers

      It would give me the same results if I would do a time() and change the last 2 digits to a 00 and use that as "current string for this time"; what I need is a sort of "random-but-still-the-same for 10 minutes".

      Next to that the "five-before-twelve problem" is still in the air with both methods...

        I'm unable to see how you can choose a stateless value which is guaranteed to not change for a finite period of time.

        Since the number is stateless, it must depend on some external reference (eg. a timet).  However, you want the value to change, there's no way to avoid getting the value at some arbitrary number of seconds N prior to the number changing, for some N less than the duration you're interested in (here 600 seconds).  So unless I've misunderstood your requirements, I don't see how you what you're looking for is possible.

        Now, if you're willing to accept numbers which are the same for a 10-minute period, just use:

        my $value = int(time / 600);

        But, of course, you still have the problem of having the value change very soon after you choose it.


        s''(q.S:$/9=(T1';s;(..)(..);$..=substr+crypt($1,$2),2,3;eg;print$..$/
Re: A value that stays a value (for some time)
by davidrw (Prior) on Jun 18, 2006 at 15:20 UTC
    "value must stay the same for over a timeframe of 10 minutes." reads to me as "need caching" .. so have a look at Cache::FileCache or Memoize::Expire (or any other caching module on cpan)
      That would involve writing to the disk; which is a overhead I want to save for the perlscript processing ; it's already too heavy as it is ; I wonder if there is any way I can "modularize" loading and deloading of certain modules ...
        That would involve writing to the disk; which is a overhead I want to save for the perlscript processing...

        In a network application? You have much bigger overheads, unless you've overcome the speed of light.

Re: A value that stays a value (for some time)
by CountZero (Bishop) on Jun 18, 2006 at 15:24 UTC
    The easiest way to do it is to save a random value in a file and refresh this value through a cron job.

    As only the cron job is allowed to write a new value you do not get into trouble through race conditions.

    Update: Reading through all messages till now, I might have misunderstood your question. If I have it right now, you need a value which stays the same for x minutes PER USER. It looks to me that what you need can be done through a cookie, which you set to expire in x minutes.

    CountZero

    "If you have four groups working on a compiler, you'll get a 4-pass compiler." - Conway's Law

Re: A value that stays a value (for some time)
by davido (Cardinal) on Jun 18, 2006 at 15:41 UTC

    You may be looking for Tie::Scalar::Timeout. If you really do want a subroutine to be returning the value you could build a closure around the sub, and declare the tied variable into the broader-scope of the closure. It can be tied within the sub, as needed.


    Dave

      this is for mod_perl ;

      I'm using normal cgi sessions. It can also be used for a added security to downloaders ; because the path changes as soon as the ip / user / "token" or "ticket" expires.

      I'd need such thing as this, but based on a formula of information including an expiration value ; which is now set to 900 currently (15 minutes).

      The problem is, since there is no mod_perl:

      1. I have no statefull connection
      2. hereby the system will have to "guess" it by itself and do the appropriate addings/encrypting and powdering afterwards.
      3. it introduces a "five-before-twelve" bug which means; if you are 1 minute before the expiration timeframe of 900 seconds ends,
        • you either have to be fast entering your password and bark like a dog 3 times or
        • have the inconvience of seriously discomforted/discombulated electrons; because "your logintime just ended" ... awwww
        this is for mod_perl
        Don't count on it! Even in mod_perl you are never guaranteed that your request will be handled by the same worker/thread as before.

        CountZero

        "If you have four groups working on a compiler, you'll get a 4-pass compiler." - Conway's Law

        this is for mod_perl ;

        Why didn't you say so in the first place... didn't seem relevant at the time?


        Dave

Re: A value that stays a value (for some time)
by sgifford (Prior) on Jun 18, 2006 at 16:17 UTC
      10 * 60 * 60 would give 36000; thats an awfull long time for the "ticket" to expire :)