Rocksolid Light

News from da outaworlds

mail  files  register  groups  login

Message-ID:  

BOFH excuse #151: Some one needed the powerstrip, so they pulled the switch plug.


comp / comp.lang.tcl / Re: Endless loop in http request

Subject: Re: Endless loop in http request
From: et99
Newsgroups: comp.lang.tcl
Organization: A noiseless patient Spider
Date: Fri, 31 May 2024 19:05 UTC
References: 1 2 3 4 5 6 7 8 9 10 11 12
Path: eternal-september.org!news.eternal-september.org!.POSTED!not-for-mail
From: et99@rocketship1.me (et99)
Newsgroups: comp.lang.tcl
Subject: Re: Endless loop in http request
Date: Fri, 31 May 2024 12:05:09 -0700
Organization: A noiseless patient Spider
Lines: 237
Message-ID: <v3d715$2blu2$1@dont-email.me>
References: <a9238eb213ecbbba0915a85965e6ca68@www.novabbs.com>
<v36890$103i8$1@dont-email.me>
<d24008a8ed1172b11496634782da8e87@www.novabbs.com>
<yga4jahrnn4.fsf@akutech.de>
<93aa0e29870ed2479e94aa260149b22e@www.novabbs.com>
<v38k7k$1chat$1@dont-email.me>
<3e0c470b6f1b160110904ad4044c9113@www.novabbs.com>
<ygazfs7qxs0.fsf@akutech.de> <v3aoqu$1rk4q$1@dont-email.me>
<v3aura$1sia0$1@dont-email.me> <v3b52h$1tgiv$1@dont-email.me>
<v3ctq1$2a4ft$1@dont-email.me>
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: 7bit
Injection-Date: Fri, 31 May 2024 21:05:10 +0200 (CEST)
Injection-Info: dont-email.me; posting-host="f16b4a0107ba905d06069b14fc5f1621";
logging-data="2480066"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1/5lgTRWyMMGxZuEmKaDHsX"
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:102.0) Gecko/20100101
Thunderbird/102.6.1
Cancel-Lock: sha1:lohmKvQ/dcoeIG6bgHakAAGLdCI=
Content-Language: en-US
In-Reply-To: <v3ctq1$2a4ft$1@dont-email.me>
View all headers

On 5/31/2024 9:27 AM, Rich wrote:
> et99 <et99@rocketship1.me> wrote:
>> On 5/30/2024 3:33 PM, Rich wrote:
>>> et99 <et99@rocketship1.me> wrote:
>>>> # Send signal to main thread to update the progress variable
>>>> thread::send -async \$main_thread_id \[list handle_http_event \$increment_value \$max_progress_var\]
>>>
>>> Did it really write the above.
>>>
>>> This will try to send to the thread id "$main_thread_id" (which, btw, is
>>> not a thread ID that returns from thread::create) and will likely error
>>> out for "too many arguments" before it errors out for "thread ID not
>>> found" as thread::send takes at most three (ignoring option switches)
>>> and the third one is a varname to save the result into when the script
>>> exits.
>>>
>>> I.e., it got the quoting all messed up.
>>
>> If you look again, you will see that the script is defined using:
>>
>> set script "....
>>
>> "
>
> Ah, yes, I did miss that little bit.
>
>> I've just now asked it to stop using so many globals, so it re-wrote
>> it using a namespace.
>
> Yeah, I did notice, but did not comment on, the use of globals there.
>
> It is interesting that it did not simply go the namespace route from
> the start. Since if it could do it after you asked, it presumably
> "knew how" when it wrote the version with the globals.
>

Yeah, it seems to like to use globals a lot. Perhaps internet training data uses globals more than namespaces. In its final code it's again using some globals, but I didn't ask it to fix that.

Final thoughts. I got chatGPT to write actual http code.

When it replaced the simulated http with the real deal it dumped the use of threads, which turned out to work just fine.

The secret sauce ended up being to update the progress bar only when it has changed by 1% or more and use update idletasks. I did have to request both of those. So, we're back to the (human) response from earlier in this thread.

One puzzle: I added some puts statements and I often see the http progress callback occurring repeatedly with the same bytes transferred. But since this doesn't increase the percent done, it doesn't try to update the progress. Maybe this is why Alexandru was having problems???

Also, for progress, it needs the expected size, so I asked it to write that code and it did but took 2 tries. I had to tell it how to read pages from https however, by just giving it code I've used before (with a test for windows vs. linux).

I then tested it out on some web pages, like wikipedia home page, and one longer page I found ("https://tkdocs.com/tutorial/onepage.html") but it doesn't always return an expected size value (returning 0 in that case). Today, it's working however. I tried to force it to read less by manually changing the http call to use -blocksize 1500 but that seems to be ignored for some reason.

One caveat, it keeps context, so when I made a big change request, it would sometimes mix up variables from earlier versions even though the code that had used them wasn't there any longer. In once case it has the same variable as a global but also in a namespace variable, which was pretty annoying.

Overall, I'm not totally sure it's much faster to use it, except when asking for some prototype code. Getting it to fix mistakes and make small changes was more time consuming than just doing it myself. However, you can paste in some modified code and it will continue from that point. And I was able to get it to translate to and from python code (it uses tkinter and the threading module when it was still using the thread package).

So, here's what I and it ended up with. The url it reads is in the code itself.

--------------------------

package require Tk
package require http

if { $::tcl_platform(platform) ne "windows" } {
package require tls
http::register https 443 [list ::tls::socket -ssl2 0 -ssl3 0 -tls1 1 -tls1.1 1 -tls1.2 1 ]
} else {
console show
package require twapi_crypto
http::register https 443 [list ::twapi::tls_socket]
}

wm withdraw .

namespace eval ProgressBar {
variable progress_var 0
variable max_progress_var 0
variable increment_value 1
variable percent_label ""
variable last_percent -1 ;# Initialize to -1 to ensure initial update

# Procedure to create and initialize the progress bar
proc create {title max_value} {
variable progress_var
variable max_progress_var
variable increment_value
variable percent_label

# Create the main window
set win [toplevel .progress]
wm title $win $title

# Create a label
label $win.label -text "Progress:"
pack $win.label -padx 10 -pady 5

# Initialize variables
set progress_var 0
set max_progress_var $max_value
set increment_value 1

# Create a progress bar widget
ttk::progressbar $win.progress -maximum 100 -length 300
pack $win.progress -padx 10 -pady 10

# Create a label to show the percentage done
set percent_label [label $win.percent_label -text "0%"]
pack $percent_label -padx 10 -pady 5

# Button to start simulating fast HTTP events
button $win.button -text "Start Fast Events" -command [namespace code ::ProgressBar::start_or_reset]
pack $win.button -padx 10 -pady 5

}

# Procedure to start or reset the progress
proc start_or_reset {} {
variable progress_var
variable max_progress_var
puts start
if {$progress_var >= $max_progress_var} {
# Reset progress
set progress_var 0
.progress.button configure -text "Start Fast Events"
}

# Start the HTTP request with progress tracking
start_http_request_with_progress_tracking
}

# Function to initialize progress tracking
proc init_progress_tracking {expected_total} {
global total_size segment_size
set total_size $expected_total
set segment_size [expr {$total_size / 100}]
}

# Callback function to handle HTTP progress
proc httpProgress {token total_size bytes_transferred} {
global progress_var max_progress_var increment_value last_percent

# Initialize last_percent if not already initialized
if {! [info exists last_percent]} {
set last_percent -1
}

# Initialize progress tracking if not already initialized
if {! [info exists total_size]} {
ProgressBar::init_progress_tracking $total_size
}

# Calculate the progress if the total size is available and not zero
if {$total_size > 0} {
set progress [expr {int(($bytes_transferred / double($total_size)) * 100)}]
} else {
# Handle the case where total size is not available
set progress [expr {int(($bytes_transferred / double($max_progress_var)) * 100)}]

}

# Update the progress bar only when the percentage changes
if {$progress != $last_percent} {
puts "last_percent= |$last_percent| progress= |$progress| "
set last_percent $progress

ProgressBar::update_progress_bar $progress
# after 100 ;# manually added so I can see visually the progress bar change
}

# Increment the progress variable
set progress_var [expr {$progress_var + $increment_value}]

# Ensure progress_var does not exceed max_progress_var
if {$progress_var >= $max_progress_var} {
set progress_var $max_progress_var
.progress.button configure -text "Done"
}
}

# Function to update the progress bar and label
proc update_progress_bar {percent_done} {
variable max_progress_var

# Update the label with the current percentage done
.progress.percent_label configure -text "$percent_done%"

# Update the progress bar widget
.progress.progress configure -value $percent_done
update idletasks
}

# Main procedure to start the HTTP request with progress tracking
proc start_http_request_with_progress_tracking {} {
global progress_var max_progress_var increment_value
puts inside-start
# Initialize progress tracking variables
set progress_var 0
set max_progress_var 130595 ;# Set the maximum progress value
set increment_value 100 ;# Increment value for each progress update

# Start the HTTP request with progress callback
set url "https://en.wikipedia.org/wiki/Main_Page"
set url "https://tkdocs.com/tutorial/onepage.html"
set token [::http::geturl $url -blocksize 1500 -progress [namespace code {httpProgressCallback}]]
puts "token= |$token| "
# Wait for the HTTP request to complete
::http::wait $token
puts done
}

# Callback function to handle HTTP progress
proc httpProgressCallback {token total_size bytes_transferred} {
puts "token= |$token| total_size= |$total_size| bytes_transferred= |$bytes_transferred| "

# Call httpProgress with the provided arguments
httpProgress $token $total_size $bytes_transferred
}

# Callback function to handle HTTP response
proc httpResponseCallback {token} {
global total_size
set headers [::http::meta $token]
set content_length [dict get $headers "content-length"]
set total_size [expr { $content_length != "" ? $content_length : -1 }]

# Initialize progress tracking with the total size
ProgressBar::init_progress_tracking $total_size
}
}

#Main script to run the example
ProgressBar::create "Progress Bar Example" 10000

#Start the Tk event loop
tkwait window .progress

SubjectRepliesAuthor
o Endless loop in http request

By: alexandru on Wed, 29 May 2024

20alexandru

rocksolid light 0.9.8
clearnet tor