Is This a Timer Issue?

A file has a timer running to call a procedure that triggers any one of several tasks based on circumstances. Most of the time it runs perfectly hour after hour as long as the tasks are somewhat modest.

One task of compiling reports can take about 20 minutes. It runs and completes properly.

At the end of the called procedure, all tasks get run through the same ending process:

OpenFile gvMonitor

gvStatus = "Idle @ "+timepattern(now(),"hh:mm am/pm")+¶+arrayrange(gvStatus,1,30,¶)
ShowVariables gvStatus

fileappend dbpath()+"Logs",datepattern(today(),"mm.dd.yy ")+"Monitor.txt","TEXTttxt",cr()+"Idle @ "+timepattern(now(),"hh:mm am/pm")


After running a lengthy task, the variable display and the log file both confirm that it has reached this point just as it does for shorter tasks. The difference is that on the longer task a spinning beachball is on the screen and a ForceQuit is required. The Stop was inserted to replace Rtn as part of my troubleshooting to ensure it wasn’t somehow running on to something else.

My best guess is that the timer is somehow getting backed up due to the time for the procedure to run. I need it to run more often than every 30 minutes, which would be a required padding for the long processes. As it is, every test run requires about 25 minutes, so every tested tweak is costly time wise.

The particular task I’m working on has a loop array to generate reports for a list of recipients. The full array is just over 300. If I trim it to 100, the whole procedure runs as before and still ends with a beachball. If I trim it to 50, it works as intended and there/s no beachball.

I have no idea why the size of the array matters, especially since the procedure completes its task either way.

I’ve also tried StopTimer when the procedure starts, then recreate the timer when it’s done. Notes added to my log file show that it gets beyond the timer restart and all the way to the code posted above. That hasn’t ended the beachball result.

It appears that the workaround is to break the array into smaller pieces and run each separately.

After many hours of working on this I’ve seemingly overcome whatever the issue is. Breaking the array into 30 elements at a time it would successfully 6 or 7 times then start ignoring a large part of the procedure for no discernable reason.

There was no select or selectwithin or other code that would provide a reason for the block of code to be skipped.

To be sure it wasn’t data related, I rearranged the data more than once.

Now it seems to be working by stopping the timer when the procedure starts, the starting the timer again when the procedure finishes.

Each full test takes just under an hour so “time will tell”.

My guess is the timer is executing while the long procedure code is still running and Panorama is getting confused with two procedure trying to run at the same time and, like the beach ball, just goes around in circles. Besides stopping and restarting the timer you can simply suspend it at the start of the long procedure and un-suspend it when the procedure finishes.

changetimer “MyTimer”,“suspend”,“yes”
// Time intensive procedure code
changetimer “MyTimer”,“suspend”,“no”

You could also try just putting a trap in the timer code to see if your long procdeure is still running.

If info(“procedurename”)=“MyLongProcedure”
// The normal timer code

Of course the problem may be something totally unrelated - just my best guess.

Panorama will not run a timer while procedure code is running. So it won’t get confused and run two procedures at a time.

However, your guess is still possible, because if it takes longer to run a procedure than the time between timer intervals, it will immediately run the timer again when the first timer finishes. So that would have essentially the same effect of having code run continuously, so you would never be able to do anything else.

For example, suppose you have a timer that runs every 10 seconds, but the code takes 15 seconds to run. When the timer code finishes running the first time, it will notice that it was supposed to run the timer again 5 seconds ago, so it will run it immediately. It will never catch up.

The original post provided very limited information about what the code does or how the timer is set up, so who knows - all of this may have nothing to do with the problem.

Before posting again, I wanted to gather all the info I could and to carefully observe the timer’s actions, as well as to examine all of my code for errors.

The timer is on a Mini running Ventura and PanoramaX Server. This timer is intended to run 24/7 on PanoramaX and there are typically no active users on the machine.

The idea is that at a regular interval, the timer checks a database of “chores” to see if anything needs to be done. There are several once a day tasks which would be expected to run after midnight and be completed within an hour or so, leaving it available for an occasional one-off chore to be handled at all other hours.

The timer code:

starttimer "DoChores","background","yes","interval",60,"next",supernow()+30,"scope","global", "code",{FarCall Monitor,".processQueue"
ShowVariables gvStatus}

Pasted Graphic 1

Usually it would be set to run every 5 minutes but for the sake of testing within a reasonable time-frame I often run it at 1 minute intervals. The results don’t seem to be effected one way or the other.

.processQueue is a procedure consisting of a series of Case statements for the various chores to be evaluated and run as conditions indicate.

As previously noted, the biggest chore is fairly involved and had to be broken into several cycles before it would run correctly.

When there are none of the routine chores to be run, it cycles through its checks, notes a few items, then idles until the next run. I’ve created a log to track its activities, sometimes in minutiae.

One issue is that if PanoramaX is not the active application, the timer runs, but fails to deal with windows or databases properly. For instance, it opens the Chores database but fails to search it or close it as it would if Panorama was the active application. It seems that variables update but no other activity takes place.

So if anyone should click on the Desktop or do anything else on this server, it can cause the timer to “short cycle”. We check on the machine via screen sharing. Sometimes when logging off, moving the mouse across the screen may inadvertently cause something else to become active.

I’m on the machine right now using TextEdit to write this, and it’s failing to run fully. If I click on Panorama to make it active, it kicks back into the full process.

Panorama has no built in “Activate” that I know of to make itself active, but my next effort will be to add an AppleScript to the timer’s code in order to make Panorama active. Then I can see if all of the failures are cleared up.

For now that’s all I can reliably report about it.

Is it my error to think that Panorama can run in the background?

Somewhere early on with X, I got the impression that it can, and sometimes it does seem to. I do know that I’ve taught clients to keep their hands off the computer during the run of some procedures, especially when files are initializing.

It appears that a file can do things while in the background, but that it cannot interact with other databases.

1 Like

This capability was added a year or two ago.

There is also a function that allows you to check if Panorama is active.

It can, as long as the procedure does not involve switching windows.

When a window becomes the frontmost window, macOS sends a notification to the application so that it can make the necessary adjustments. If the application is not the frontmost application, macOS does not send this notification, so Panorama does not properly make the front window it’s active window.

Probably the easiest solution for you would be to put the bringpanoramaforward statement at the start of your .processQueue procedure. I don’t think that’s the best solution, however. The best solution would be to design your “chores” code so that it all runs correctly without using windows at all - using opensecret and setactivedatabase. I practice what I preach here - this is how Panorama Server works. The downside is that this might take a lot of work for you if you didn’t design the code that way in the first place.

If you do rewrite your code to eliminate reliance on windows, you could even run hidden, so that it is never in the foreground and cannot be clicked on. In fact, that is what I would recommend for the type of unattended operation you are looking for.

What triggers these one off chores? If such a chore is triggered by a change to a file, you should consider using startfilesystemmonitor instead of a timer. Instead of your timer needing to constantly check whether or not the file has changed, the monitor system will immediately trigger your code when the specified file (or files) have changed. For example your server code might write (or append to) a file, which then triggers a chore on (leaving the server free for… serving).

Basically this is another type of timer, but instead of being triggered chronologically, the code is triggered by changes to a file and/or folder. It’s really great for irregular chores. It is based on a system Apple built into macOS for their own use so it is a very robust system.

Note that the same restrictions on running code in the background discussed above. Ideally, I would write code triggered by a file system monitor to not use windows.

I assume that you are carefully coding this long running task so that it won’t conflict with whatever the server is doing while it is running. For example, if the task uses a shared database, you wouldn’t want to do something like a new generation if the server is using the same database. You’d also want to be careful about things like accessing the same text files, etc.

1 Like

Thank you. That’s an informative and useful post.

I had searched for something like bringpanoramaforward but obviously used the wrong words for my searches.

Since a lot of the one-off chores rely on code within various files, it may not be possible to convert to secret windows but I certainly intend to look.

And just to fill in some blanks taht you noted, the daily chores involve opening a few shared files, then moving their data into a matching set of single user files that will be used for other chores. A daily update is sufficient. Each is handled on a separate pass by the timer, so the hour I referred to represents a handful of timer triggered processes. The biggest is to generate more than 300 PDFs of account info for clients to access though a web portal.

A lot has gone into keeping the server activities separate so that the server is always responsive. (That’s been a habit of mine since long before PanX was issued) For instance, among the one-off chores is when a client posts info through the web. The server saves it as a text file (just as you suggest) and a timer triggered chore is set to discover and process it into the system. Other chores are when the office staff has a report to be emailed to one or many clients. A note is added to a shared Chores database that the timer is checking at regular intervals. The timer generates the PDF reports, then emails them. Sometimes a hundred or more sent a few at a time.

Aside from the nightly update, the timer finds nothing to do most of the time.

This is exactly what startfilesystemmonitor is for.

This is the advantage of using the file system monitor. When there is nothing to do, nothing happens at all, not even a timer running. Using the file system monitor allows you to respond faster without using a frequently triggered timer. It’s as if the timer ran every second but without the overhead of frequent timer activations.

Of course there’s nothing wrong with using a timer for this, other than somewhat slower performance. But the file system monitor is quite simple to use, very similar to the way a timer works, so I hope you check it out (perhaps you already have).

Unless you have some additional suggestion (not an unusual thought) startfilesystemmonitor wouldn’t know to do the once each day chores when the calendar changes. On that one I think the timer is still needed.

Yes, that sounds correct to me.

:confounded: Of course this couldn’t go without one more twist…

It now works perfectly as long as I’m logged on with screen sharing. If I log off, it stops working until I come on again. Then it starts right back up in an instant.

By stopping, I mean the activity brought on by bringpanoramaforward ceases. The variables update the whole time so the timer is running but it’s back to behaving as if Panorama is not the active app.

The possible cause: Another user account was added with Admin privileges. Could it be that when I’m off with screen sharing, there’s some root user activity being missed?

If so, is there a way to overcome it? Or do I need to ask that the other account be eliminated?

What do you mean by “logged on” vs. “logged off”? You seem to be connecting screen sharing with being logged on, but those are not connected as far as I know.

I have no experience running a server with multiple accounts. As far as I know that should make no difference, unless you are somehow switching accounts.

Does this computer have a monitor attached? If not, perhaps it should have a dummy HDMI plug installed. If you search Amazon for “dummy HDMI plug” you’ll find lots of matches. This will fake the computer into thinking a monitor is attached whether you are running screen sharing or not. I don’t know if this would solve the problem, but these plugs are inexpensive so I think it is worth a try.

When connecting via screen sharing, it is always required to log in on the welcome screen.

When finished, it’s just a matter of closing the window, not actually logging off, but if I reconnect immedialtely or much later, it requires that I log in to the account again.

With a second admin account now present, there are two users displayed. Thus my question.

1 Like

This is due of course to the settings of the OS of the controlled computer’s security settings. One of my controlled servers sits in a locked IT closet. The security settings are not set to automatically log out after inactivity, nor at the end of the screen sharing session, etc, and thus, when I share with that server, there is no log in process required.

Yup, but add a second admin account and it’s another ballgame.

When you say another Admin account, is that another macOS Admin account, or another Panorama X Admin account?

It’s a Mac OS admin account which requires you to choose who is signing in via screen sharing. All set up in the OS Settings for Users.

Using the Mac’s Sharing features does not require a unique sign in. Using Screen Sharing can be done via a separate unique account (which need not be an Admin account), the same account that might already be signed in, a different account than that which is currently signed it, and also without any sign in. It is not clear which situation you are working in but the difficulties with Panorama will likely be different based on the specific situation that exists.

If the situation that we’re speaking about requires a different sign in than the currently signed in user, I would expect some sort of issues with Panorama.

From your description, it’s apparent that when you close the sharing window, that is also logging you off of the account, even though you can’t see it. Panorama definitely will not work unless you are logged in.

At this point, this isn’t really a Panorama question – it’s a question about macOS and screen sharing. I’ve never heard of screen sharing working the way you are describing - in my experience screen sharing just shows a copy of whatever is on the local monitor, and closing screen sharing does not log off. When you come back you simply see the screen in whatever state you left it. On the other hand, my experience doesn’t include using a server computer with more than one system account. Maybe that’s just the way it works, but that seems very odd to me.

Unfortunately, I don’t know the solution to your problem, and it sounds like no one else on this forum does either. But that doesn’t mean there isn’t a solution. If you can’t find one, then hopefully deleting the second account will get you back on the air.