From 1c40d5452537eb8cb50149ab36b0598a41885a68 Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Thu, 31 Mar 2022 11:00:14 +0100 Subject: [PATCH 1/4] More profiling --- daemon.py | 25 +++++++++++++-- webapp_person_options.py | 69 +++++++++++++++++++++++++++++++++++++++- 2 files changed, 91 insertions(+), 3 deletions(-) diff --git a/daemon.py b/daemon.py index 54a5b6d51..8f81000d0 100644 --- a/daemon.py +++ b/daemon.py @@ -7786,6 +7786,8 @@ class PubServer(BaseHTTPRequestHandler): curr_session, proxy_type: str) -> None: """Show person options screen """ + fitness_performance(getreq_start_time, self.server.fitness, + '_GET', '_show_person_options start', debug) back_to_path = '' options_str = path.split('?options=')[1] origin_path_str = path.split('?options=')[0] @@ -7831,12 +7833,16 @@ class PubServer(BaseHTTPRequestHandler): locked_account = False also_known_as = None moved_to = '' + fitness_performance(getreq_start_time, self.server.fitness, + '_GET', '_show_person_options 2', debug) actor_json = \ get_person_from_cache(base_dir, options_actor, self.server.person_cache, True) if actor_json: + fitness_performance(getreq_start_time, self.server.fitness, + '_GET', '_show_person_options 3', debug) if actor_json.get('movedTo'): moved_to = actor_json['movedTo'] if '"' in moved_to: @@ -7861,14 +7867,26 @@ class PubServer(BaseHTTPRequestHandler): pgp_fingerprint = get_pgp_fingerprint(actor_json) if actor_json.get('alsoKnownAs'): also_known_as = actor_json['alsoKnownAs'] + fitness_performance(getreq_start_time, self.server.fitness, + '_GET', '_show_person_options 4', debug) if curr_session: + fitness_performance(getreq_start_time, self.server.fitness, + '_GET', '_show_person_options 5', debug) + check_actor_timeout = 2 + if self.server.domain.endswith('.onion') or \ + self.server.domain.endswith('.i2p'): + # allow more time for a slower response + check_actor_timeout = 5 check_for_changed_actor(curr_session, self.server.base_dir, self.server.http_prefix, self.server.domain_full, options_actor, options_profile_url, - self.server.person_cache, 5) + self.server.person_cache, + check_actor_timeout) + fitness_performance(getreq_start_time, self.server.fitness, + '_GET', '_show_person_options 6', debug) access_keys = self.server.access_keys if '/users/' in path: @@ -7902,7 +7920,10 @@ class PubServer(BaseHTTPRequestHandler): self.server.text_mode_banner, self.server.news_instance, authorized, - access_keys, is_group) + access_keys, is_group, + getreq_start_time, + self.server.fitness, + debug) if msg: msg = msg.encode('utf-8') msglen = len(msg) diff --git a/webapp_person_options.py b/webapp_person_options.py index 8b7cb1b25..fddedff0b 100644 --- a/webapp_person_options.py +++ b/webapp_person_options.py @@ -29,6 +29,7 @@ from webapp_utils import html_header_with_external_style from webapp_utils import html_footer from webapp_utils import get_broken_link_substitute from webapp_utils import html_keyboard_navigation +from fitnessFunctions import fitness_performance def html_person_options(default_timeline: str, @@ -62,19 +63,33 @@ def html_person_options(default_timeline: str, news_instance: bool, authorized: bool, access_keys: {}, - is_group: bool) -> str: + is_group: bool, + getreq_start_time, + fitness: {}, debug: bool) -> str: """Show options for a person: view/follow/block/report """ + fitness_performance(getreq_start_time, fitness, + '_GET', 'html_person_options start', + debug) + options_domain, options_port = get_domain_from_actor(options_actor) if not options_domain: return None options_domain_full = get_full_domain(options_domain, options_port) + fitness_performance(getreq_start_time, fitness, + '_GET', 'html_person_options get domain', + debug) + if os.path.isfile(base_dir + '/accounts/options-background-custom.jpg'): if not os.path.isfile(base_dir + '/accounts/options-background.jpg'): copyfile(base_dir + '/accounts/options-background.jpg', base_dir + '/accounts/options-background.jpg') + fitness_performance(getreq_start_time, fitness, + '_GET', 'html_person_options background', + debug) + dormant = False follow_str = 'Follow' if is_group: @@ -110,6 +125,10 @@ def html_person_options(default_timeline: str, options_nickname, options_domain_full): block_str = 'Block' + fitness_performance(getreq_start_time, fitness, + '_GET', 'html_person_options 1', + debug) + options_link_str = '' if options_link: options_link_str = \ @@ -119,6 +138,10 @@ def html_person_options(default_timeline: str, if os.path.isfile(base_dir + '/options.css'): css_filename = base_dir + '/options.css' + fitness_performance(getreq_start_time, fitness, + '_GET', 'html_person_options 2', + debug) + # To snooze, or not to snooze? That is the question snooze_button_str = 'Snooze' if nickname: @@ -132,10 +155,19 @@ def html_person_options(default_timeline: str, ' tabindex="-1"">\n' + fitness_performance(getreq_start_time, fitness, + '_GET', 'html_person_options 3', + debug) + instance_title = \ get_config_param(base_dir, 'instanceTitle') options_str = \ html_header_with_external_style(css_filename, instance_title, None) + + fitness_performance(getreq_start_time, fitness, + '_GET', 'html_person_options 4', + debug) + options_str += html_keyboard_navigation(text_mode_banner, {}, {}) options_str += '

\n' options_str += '
\n' @@ -196,6 +228,11 @@ def html_person_options(default_timeline: str, other_accounts_html += '

\n' if ctr > 0: options_str += other_accounts_html + + fitness_performance(getreq_start_time, fitness, + '_GET', 'html_person_options 5', + debug) + if email_address: options_str += \ '

' + translate['Email'] + \ @@ -259,6 +296,11 @@ def html_person_options(default_timeline: str, options_actor + '">\n' options_str += ' \n' + + fitness_performance(getreq_start_time, fitness, + '_GET', 'html_person_options 6', + debug) + if authorized: if origin_path_str == '/users/' + nickname: if options_nickname: @@ -273,6 +315,10 @@ def html_person_options(default_timeline: str, 'name="submitPetname">' + \ translate['Submit'] + '
\n' + fitness_performance(getreq_start_time, fitness, + '_GET', 'html_person_options petname', + debug) + # Notify when a post arrives from this person if is_following_actor(base_dir, nickname, domain, options_actor): checkbox_str = \ @@ -301,6 +347,10 @@ def html_person_options(default_timeline: str, checkbox_str = checkbox_str.replace(' checked>', '>') options_str += checkbox_str + fitness_performance(getreq_start_time, fitness, + '_GET', 'html_person_options following', + debug) + # checkbox for permission to post to newswire newswire_posts_permitted = False if options_domain_full == domain_full: @@ -325,6 +375,9 @@ def html_person_options(default_timeline: str, else: newswire_posts_permitted = True options_str += checkbox_str + fitness_performance(getreq_start_time, fitness, + '_GET', 'html_person_options news 1', + debug) # whether blogs created by this account are moderated on # the newswire @@ -343,6 +396,9 @@ def html_person_options(default_timeline: str, if not os.path.isfile(moderated_filename): checkbox_str = checkbox_str.replace(' checked>', '>') options_str += checkbox_str + fitness_performance(getreq_start_time, fitness, + '_GET', 'html_person_options news 2', + debug) # checkbox for permission to post to featured articles if news_instance and options_domain_full == domain_full: @@ -362,6 +418,13 @@ def html_person_options(default_timeline: str, options_domain): checkbox_str = checkbox_str.replace(' checked>', '>') options_str += checkbox_str + fitness_performance(getreq_start_time, fitness, + '_GET', 'html_person_options news 3', + debug) + + fitness_performance(getreq_start_time, fitness, + '_GET', 'html_person_options 7', + debug) options_str += options_link_str back_path = '/' @@ -440,6 +503,10 @@ def html_person_options(default_timeline: str, 'accesskey="' + access_keys['enterNotes'] + '">' + \ person_notes + '\n' + fitness_performance(getreq_start_time, fitness, + '_GET', 'html_person_options 8', + debug) + options_str += \ ' \n' + \ '\n' + \ From 815fd3dd8832e4a10270d49602bd8f71ccf40ac2 Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Thu, 31 Mar 2022 11:13:45 +0100 Subject: [PATCH 2/4] Remove profiling --- daemon.py | 5 +-- webapp_person_options.py | 66 +--------------------------------------- 2 files changed, 2 insertions(+), 69 deletions(-) diff --git a/daemon.py b/daemon.py index 8f81000d0..a53c2ea67 100644 --- a/daemon.py +++ b/daemon.py @@ -7920,10 +7920,7 @@ class PubServer(BaseHTTPRequestHandler): self.server.text_mode_banner, self.server.news_instance, authorized, - access_keys, is_group, - getreq_start_time, - self.server.fitness, - debug) + access_keys, is_group) if msg: msg = msg.encode('utf-8') msglen = len(msg) diff --git a/webapp_person_options.py b/webapp_person_options.py index fddedff0b..bf012bd2b 100644 --- a/webapp_person_options.py +++ b/webapp_person_options.py @@ -29,7 +29,6 @@ from webapp_utils import html_header_with_external_style from webapp_utils import html_footer from webapp_utils import get_broken_link_substitute from webapp_utils import html_keyboard_navigation -from fitnessFunctions import fitness_performance def html_person_options(default_timeline: str, @@ -63,33 +62,19 @@ def html_person_options(default_timeline: str, news_instance: bool, authorized: bool, access_keys: {}, - is_group: bool, - getreq_start_time, - fitness: {}, debug: bool) -> str: + is_group: bool) -> str: """Show options for a person: view/follow/block/report """ - fitness_performance(getreq_start_time, fitness, - '_GET', 'html_person_options start', - debug) - options_domain, options_port = get_domain_from_actor(options_actor) if not options_domain: return None options_domain_full = get_full_domain(options_domain, options_port) - fitness_performance(getreq_start_time, fitness, - '_GET', 'html_person_options get domain', - debug) - if os.path.isfile(base_dir + '/accounts/options-background-custom.jpg'): if not os.path.isfile(base_dir + '/accounts/options-background.jpg'): copyfile(base_dir + '/accounts/options-background.jpg', base_dir + '/accounts/options-background.jpg') - fitness_performance(getreq_start_time, fitness, - '_GET', 'html_person_options background', - debug) - dormant = False follow_str = 'Follow' if is_group: @@ -125,10 +110,6 @@ def html_person_options(default_timeline: str, options_nickname, options_domain_full): block_str = 'Block' - fitness_performance(getreq_start_time, fitness, - '_GET', 'html_person_options 1', - debug) - options_link_str = '' if options_link: options_link_str = \ @@ -138,10 +119,6 @@ def html_person_options(default_timeline: str, if os.path.isfile(base_dir + '/options.css'): css_filename = base_dir + '/options.css' - fitness_performance(getreq_start_time, fitness, - '_GET', 'html_person_options 2', - debug) - # To snooze, or not to snooze? That is the question snooze_button_str = 'Snooze' if nickname: @@ -155,19 +132,11 @@ def html_person_options(default_timeline: str, ' tabindex="-1"">\n' - fitness_performance(getreq_start_time, fitness, - '_GET', 'html_person_options 3', - debug) - instance_title = \ get_config_param(base_dir, 'instanceTitle') options_str = \ html_header_with_external_style(css_filename, instance_title, None) - fitness_performance(getreq_start_time, fitness, - '_GET', 'html_person_options 4', - debug) - options_str += html_keyboard_navigation(text_mode_banner, {}, {}) options_str += '

\n' options_str += '

\n' @@ -229,10 +198,6 @@ def html_person_options(default_timeline: str, if ctr > 0: options_str += other_accounts_html - fitness_performance(getreq_start_time, fitness, - '_GET', 'html_person_options 5', - debug) - if email_address: options_str += \ '

' + translate['Email'] + \ @@ -297,10 +262,6 @@ def html_person_options(default_timeline: str, options_str += ' \n' - fitness_performance(getreq_start_time, fitness, - '_GET', 'html_person_options 6', - debug) - if authorized: if origin_path_str == '/users/' + nickname: if options_nickname: @@ -315,10 +276,6 @@ def html_person_options(default_timeline: str, 'name="submitPetname">' + \ translate['Submit'] + '
\n' - fitness_performance(getreq_start_time, fitness, - '_GET', 'html_person_options petname', - debug) - # Notify when a post arrives from this person if is_following_actor(base_dir, nickname, domain, options_actor): checkbox_str = \ @@ -347,10 +304,6 @@ def html_person_options(default_timeline: str, checkbox_str = checkbox_str.replace(' checked>', '>') options_str += checkbox_str - fitness_performance(getreq_start_time, fitness, - '_GET', 'html_person_options following', - debug) - # checkbox for permission to post to newswire newswire_posts_permitted = False if options_domain_full == domain_full: @@ -375,9 +328,6 @@ def html_person_options(default_timeline: str, else: newswire_posts_permitted = True options_str += checkbox_str - fitness_performance(getreq_start_time, fitness, - '_GET', 'html_person_options news 1', - debug) # whether blogs created by this account are moderated on # the newswire @@ -396,9 +346,6 @@ def html_person_options(default_timeline: str, if not os.path.isfile(moderated_filename): checkbox_str = checkbox_str.replace(' checked>', '>') options_str += checkbox_str - fitness_performance(getreq_start_time, fitness, - '_GET', 'html_person_options news 2', - debug) # checkbox for permission to post to featured articles if news_instance and options_domain_full == domain_full: @@ -418,13 +365,6 @@ def html_person_options(default_timeline: str, options_domain): checkbox_str = checkbox_str.replace(' checked>', '>') options_str += checkbox_str - fitness_performance(getreq_start_time, fitness, - '_GET', 'html_person_options news 3', - debug) - - fitness_performance(getreq_start_time, fitness, - '_GET', 'html_person_options 7', - debug) options_str += options_link_str back_path = '/' @@ -503,10 +443,6 @@ def html_person_options(default_timeline: str, 'accesskey="' + access_keys['enterNotes'] + '">' + \ person_notes + '\n' - fitness_performance(getreq_start_time, fitness, - '_GET', 'html_person_options 8', - debug) - options_str += \ ' \n' + \ '\n' + \ From 2edba03619049a22ab13c8660513f9e3d8982592 Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Thu, 31 Mar 2022 11:45:35 +0100 Subject: [PATCH 3/4] Check actor within separate thread --- daemon.py | 50 ++++++++++++++++++++++++-------------------------- 1 file changed, 24 insertions(+), 26 deletions(-) diff --git a/daemon.py b/daemon.py index a53c2ea67..0a0bb5532 100644 --- a/daemon.py +++ b/daemon.py @@ -7786,8 +7786,6 @@ class PubServer(BaseHTTPRequestHandler): curr_session, proxy_type: str) -> None: """Show person options screen """ - fitness_performance(getreq_start_time, self.server.fitness, - '_GET', '_show_person_options start', debug) back_to_path = '' options_str = path.split('?options=')[1] origin_path_str = path.split('?options=')[0] @@ -7833,16 +7831,12 @@ class PubServer(BaseHTTPRequestHandler): locked_account = False also_known_as = None moved_to = '' - fitness_performance(getreq_start_time, self.server.fitness, - '_GET', '_show_person_options 2', debug) actor_json = \ get_person_from_cache(base_dir, options_actor, self.server.person_cache, True) if actor_json: - fitness_performance(getreq_start_time, self.server.fitness, - '_GET', '_show_person_options 3', debug) if actor_json.get('movedTo'): moved_to = actor_json['movedTo'] if '"' in moved_to: @@ -7867,34 +7861,34 @@ class PubServer(BaseHTTPRequestHandler): pgp_fingerprint = get_pgp_fingerprint(actor_json) if actor_json.get('alsoKnownAs'): also_known_as = actor_json['alsoKnownAs'] - fitness_performance(getreq_start_time, self.server.fitness, - '_GET', '_show_person_options 4', debug) - - if curr_session: - fitness_performance(getreq_start_time, self.server.fitness, - '_GET', '_show_person_options 5', debug) - check_actor_timeout = 2 - if self.server.domain.endswith('.onion') or \ - self.server.domain.endswith('.i2p'): - # allow more time for a slower response - check_actor_timeout = 5 - check_for_changed_actor(curr_session, - self.server.base_dir, - self.server.http_prefix, - self.server.domain_full, - options_actor, options_profile_url, - self.server.person_cache, - check_actor_timeout) - fitness_performance(getreq_start_time, self.server.fitness, - '_GET', '_show_person_options 6', debug) access_keys = self.server.access_keys + nickname = 'instance' if '/users/' in path: nickname = path.split('/users/')[1] if '/' in nickname: nickname = nickname.split('/')[0] if self.server.key_shortcuts.get(nickname): access_keys = self.server.key_shortcuts[nickname] + + if curr_session: + check_actor_timeout = 5 + # because this is slow, do it in a separate thread + if self.server.thrCheckActor.get(nickname): + # kill existing thread + self.server.thrCheckActor[nickname].kill() + + self.server.thrCheckActor[nickname] = \ + thread_with_trace(target=check_for_changed_actor, + args=(curr_session, + self.server.base_dir, + self.server.http_prefix, + self.server.domain_full, + options_actor, options_profile_url, + self.server.person_cache, + check_actor_timeout), daemon=True) + self.server.thrCheckActor[nickname].start() + msg = \ html_person_options(self.server.default_timeline, self.server.css_cache, @@ -21229,6 +21223,10 @@ def run_daemon(crawlers_allowed: [], # this is the instance actor private key httpd.signing_priv_key_pem = get_instance_actor_key(base_dir, domain) + # threads used for checking for actor changes when clicking on + # avatar icon / person options + httpd.thrCheckActor = {} + if not unit_test: print('THREAD: Creating inbox queue watchdog') httpd.thrWatchdog = \ From 592fb92539817270e59fdf670ed8a6736a8fff73 Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Thu, 31 Mar 2022 13:00:36 +0100 Subject: [PATCH 4/4] Add timeout option for actor check --- daemon.py | 13 ++++++++++--- epicyon.py | 7 ++++++- tests.py | 19 ++++++++++++++----- 3 files changed, 30 insertions(+), 9 deletions(-) diff --git a/daemon.py b/daemon.py index 0a0bb5532..86d5fb8df 100644 --- a/daemon.py +++ b/daemon.py @@ -7872,7 +7872,6 @@ class PubServer(BaseHTTPRequestHandler): access_keys = self.server.key_shortcuts[nickname] if curr_session: - check_actor_timeout = 5 # because this is slow, do it in a separate thread if self.server.thrCheckActor.get(nickname): # kill existing thread @@ -7886,7 +7885,8 @@ class PubServer(BaseHTTPRequestHandler): self.server.domain_full, options_actor, options_profile_url, self.server.person_cache, - check_actor_timeout), daemon=True) + self.server.check_actor_timeout), + daemon=True) self.server.thrCheckActor[nickname].start() msg = \ @@ -20632,7 +20632,8 @@ def load_tokens(base_dir: str, tokens_dict: {}, tokens_lookup: {}) -> None: break -def run_daemon(crawlers_allowed: [], +def run_daemon(check_actor_timeout: int, + crawlers_allowed: [], dyslexic_font: bool, content_license_url: str, lists_enabled: str, @@ -20798,6 +20799,12 @@ def run_daemon(crawlers_allowed: [], 'Reminder': 'r' } + # timeout used when checking for actor changes when clicking an avatar + # and entering person options screen + if check_actor_timeout < 2: + check_actor_timeout = 2 + httpd.check_actor_timeout = check_actor_timeout + # how many hours after a post was publushed can a reply be made default_reply_interval_hrs = 9999999 httpd.default_reply_interval_hrs = default_reply_interval_hrs diff --git a/epicyon.py b/epicyon.py index f8dba4b1f..ea96d7330 100644 --- a/epicyon.py +++ b/epicyon.py @@ -195,6 +195,10 @@ parser.add_argument('--i2p_domain', dest='i2p_domain', type=str, parser.add_argument('-p', '--port', dest='port', type=int, default=None, help='Port number to run on') +parser.add_argument('--check-actor-timeout', dest='check_actor_timeout', + type=int, default=2, + help='Timeout in seconds used for checking is an actor ' + + 'has changed when clicking their avatar image') parser.add_argument('--year', dest='year', type=int, default=search_date.year, help='Year for calendar query') @@ -3425,7 +3429,8 @@ if args.defaultCurrency: if __name__ == "__main__": print('allowdeletion: ' + str(args.allowdeletion)) - run_daemon(crawlers_allowed, + run_daemon(args.check_actor_timeout, + crawlers_allowed, args.dyslexic_font, content_license_url, lists_enabled, diff --git a/tests.py b/tests.py index e7265a21c..3b3490c75 100644 --- a/tests.py +++ b/tests.py @@ -824,8 +824,10 @@ def create_server_alice(path: str, domain: str, port: int, content_license_url = 'https://creativecommons.org/licenses/by/4.0' dyslexic_font = False crawlers_allowed = [] + check_actor_timeout = 2 print('Server running: Alice') - run_daemon(crawlers_allowed, + run_daemon(check_actor_timeout, + crawlers_allowed, dyslexic_font, content_license_url, lists_enabled, default_reply_interval_hrs, @@ -979,8 +981,10 @@ def create_server_bob(path: str, domain: str, port: int, content_license_url = 'https://creativecommons.org/licenses/by/4.0' dyslexic_font = False crawlers_allowed = [] + check_actor_timeout = 2 print('Server running: Bob') - run_daemon(crawlers_allowed, + run_daemon(check_actor_timeout, + crawlers_allowed, dyslexic_font, content_license_url, lists_enabled, default_reply_interval_hrs, @@ -1057,8 +1061,10 @@ def create_server_eve(path: str, domain: str, port: int, federation_list: [], content_license_url = 'https://creativecommons.org/licenses/by/4.0' dyslexic_font = False crawlers_allowed = [] + check_actor_timeout = 2 print('Server running: Eve') - run_daemon(crawlers_allowed, + run_daemon(check_actor_timeout, + crawlers_allowed, dyslexic_font, content_license_url, lists_enabled, default_reply_interval_hrs, @@ -1137,8 +1143,10 @@ def create_server_group(path: str, domain: str, port: int, content_license_url = 'https://creativecommons.org/licenses/by/4.0' dyslexic_font = False crawlers_allowed = [] + check_actor_timeout = 2 print('Server running: Group') - run_daemon(crawlers_allowed, + run_daemon(check_actor_timeout, + crawlers_allowed, dyslexic_font, content_license_url, lists_enabled, default_reply_interval_hrs, @@ -5096,7 +5104,8 @@ def _test_functions(): 'e2e_eremove_device', 'setOrganizationScheme', 'fill_headers', - '_nothing' + '_nothing', + 'check_for_changed_actor' ] exclude_imports = [ 'link',