Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Freezing in certain strings #8668

Closed
2 tasks done
dbaio opened this issue Jan 24, 2023 · 16 comments · Fixed by #8675
Closed
2 tasks done

Freezing in certain strings #8668

dbaio opened this issue Jan 24, 2023 · 16 comments · Fixed by #8675
Assignees
Labels
bug Something is broken.
Milestone

Comments

@dbaio
Copy link
Contributor

dbaio commented Jan 24, 2023

Describe the issue

Hi.

We just updated Weblate to 4.15.1, and our instance is hanging when we access certain strings, weird strings (that should be ignored when creating the PO files, I know).

Instance logs, sometimes show this:

[2023-01-24 12:54:51,272: DEBUG/90183] git: failure fatal: bad object 93f0b5592a265aa1ba11131707a710dbdcca0040
[2023-01-24 12:54:51,272: DEBUG/90183] git: failure fatal: bad object 93f0b5592a265aa1ba11131707a710dbdcca0040

This is an example of the string that cause the issue:

https://github.com/freebsd/freebsd-doc-translate/blob/main/documentation/content/es/articles/serial-uart/_index.po#L38-L52

#. type: Plain text
#: documentation/content/en/articles/serial-uart/_index.adoc:48
msgid "'''"
msgstr "'''"

postgres be stuck in selects.

Do you know if there is something we can do here?

Regards.

I already tried

  • I've read and searched the documentation.
  • I've searched for similar issues in this repository.

Steps to reproduce the behavior

Go to any string like this:

#. type: Plain text
#: documentation/content/en/articles/serial-uart/_index.adoc:48
msgid "'''"
msgstr "'''"

Expected behavior

No response

Screenshots

No response

Exception traceback

Only this:


[2023-01-24 12:54:51,272: DEBUG/90183] git: failure fatal: bad object 93f0b5592a265aa1ba11131707a710dbdcca0040
[2023-01-24 12:54:51,272: DEBUG/90183] git: failure fatal: bad object 93f0b5592a265aa1ba11131707a710dbdcca0040

How do you run Weblate?

weblate.org service

Weblate versions

4.15.1
We have updated docker containers from 4.10.1.

Weblate deploy checks

No response

Additional context

No response

@nijel
Copy link
Member

nijel commented Jan 24, 2023

Just tried importing the referenced PO file to my test instance, and it works just fine.

[2023-01-24 12:54:51,272: DEBUG/90183] git: failure fatal: bad object 93f0b5592a265aa1ba11131707a710dbdcca0040

This typically indicates repository corruption. Was the server forcibly restarted? Maybe the disk is faulty? That could break some other things as well.

@nijel nijel added the question This is more a question for the support than an issue. label Jan 24, 2023
@github-actions
Copy link

This issue looks more like a support question than an issue. We strive to answer these reasonably fast, but purchasing the support subscription is not only more responsible and faster for your business but also makes Weblate stronger.

In case your question is already answered, making a donation is the right way to say thank you!

@dbaio
Copy link
Contributor Author

dbaio commented Jan 24, 2023

I just updated the source files as usual:
docker exec -it --user weblate weblate-docker_weblate_1 weblate updategit documentation

I update this way because it takes many hours to finish; there are too many components. Updating through the web interface, I received a few timeouts in the past.

In the past, some updates/merges were stuck in the middle of the process, but strangely, those strings have been working until now.

I restarted everything and accessed this string, and I didn't receive any error, but Postgres keeps running on 100% CPU
postgres: weblate weblate 172.18.0.4(49476) SELECT

@dbaio
Copy link
Contributor Author

dbaio commented Jan 24, 2023

SELECT pid, now() - pg_stat_activity.query_start AS duration, query, state
FROM pg_stat_activity
WHERE (now() - pg_stat_activity.query_start) > interval '5 minutes';


 82 | 00:17:39.792607 | SELECT "trans_unit"."id", "trans_unit"."translation_id", "trans_unit"."id_hash", "trans_unit"."location", "trans_unit"."context", "trans_unit"."note", "trans_unit"."flags", "trans_unit"."source", "trans_unit"."previous_source", "trans_unit"."target", "trans_unit"."state", "trans_unit"."original_state", "trans_unit"."details", "trans_unit"."position", "trans_unit"."num_words", "trans_unit"."priority", "trans_unit"."pending", "trans_unit"."timestamp", "trans_unit"."extra_flags", "trans_unit"."explanation", "trans_unit"."variant_id", "trans_unit"."source_unit_id", CASE WHEN ("trans_unit"."source" = '''''''' AND "trans_unit"."context" = '') THEN 1 ELSE 0 END AS "matches_current", "trans_translation"."id", "trans_translation"."component_id", "trans_translation"."language_id", "trans_translation"."plural_id", "trans_translation"."revision", "trans_translation"."filename", "trans_translation"."language_code", "trans_translation"."check_flags", "trans_component"."id", "trans_component"."name", "trans_component"."slu | active
(1 row)

@dbaio
Copy link
Contributor Author

dbaio commented Jan 24, 2023

explain  SELECT "trans_unit"."id", "trans_unit"."translation_id", "trans_unit"."id_hash", "trans_unit"."location", "trans_unit"."context", "trans_unit"."note", "trans_unit"."flags", "trans_unit"."source", "trans_unit"."previous_source", "trans_unit"."target", "trans_unit"."state", "trans_unit"."original_state", "trans_unit"."details", "trans_unit"."position", "trans_unit"."num_words", "trans_unit"."priority", "trans_unit"."pending", "trans_unit"."timestamp", "trans_unit"."extra_flags", "trans_unit"."explanation", "trans_unit"."variant_id", "trans_unit"."source_unit_id", CASE WHEN ("trans_unit"."source" = '''''''' AND "trans_unit"."context" = '') THEN 1 ELSE 0 END AS "matches_current", "trans_translation"."id", "trans_translation"."component_id", "trans_translation"."language_id", "trans_translation"."plural_id", "trans_translation"."revision", "trans_translation"."filename", "trans_translation"."language_code", "trans_translation"."check_flags", "trans_component"."id", "trans_component"."name", "trans_component"."slug", "trans_component"."project_id", "trans_component"."vcs", "trans_component"."repo", "trans_component"."linked_component_id", "trans_component"."push", "trans_component"."repoweb", "trans_component"."git_export", "trans_component"."report_source_bugs", "trans_component"."branch", "trans_component"."push_branch", "trans_component"."filemask", "trans_component"."template", "trans_component"."edit_template", "trans_component"."intermediate", "trans_component"."new_base", "trans_component"."file_format", "trans_component"."locked", "trans_component"."allow_translation_propagation", "trans_component"."enable_suggestions", "trans_component"."suggestion_voting", "trans_component"."suggestion_autoaccept", "trans_component"."check_flags", "trans_component"."enforced_checks", "trans_component"."license", "trans_component"."agreement", "trans_component"."new_lang", "trans_component"."language_code_style", "trans_component"."manage_units", "trans_component"."merge_style", "trans_component"."commit_message", "trans_component"."add_message", "trans_component"."delete_message", "trans_component"."merge_message", "trans_component"."addon_message", "trans_component"."pull_message", "trans_component"."push_on_commit", "trans_component"."commit_pending_age", "trans_component"."auto_lock_error", "trans_component"."source_language_id", "trans_component"."language_regex", "trans_component"."variant_regex", "trans_component"."priority", "trans_component"."restricted", "trans_component"."is_glossary", "trans_component"."glossary_color", "trans_component"."remote_revision", "trans_component"."local_revision", "trans_project"."id", "trans_project"."name", "trans_project"."slug", "trans_project"."web", "trans_project"."instructions", "trans_project"."set_language_team", "trans_project"."use_shared_tm", "trans_project"."contribute_shared_tm", "trans_project"."access_control", "trans_project"."translation_review", "trans_project"."source_review", "trans_project"."enable_hooks", "trans_project"."language_aliases", "trans_project"."machinery_settings", T6."id", T6."code", T6."name", T6."direction", T6."population", "lang_language"."id", "lang_language"."code", "lang_language"."name", "lang_language"."direction", "lang_language"."population", "lang_plural"."id", "lang_plural"."source", "lang_plural"."number", "lang_plural"."formula", "lang_plural"."type", "lang_plural"."language_id" FROM "trans_unit" INNER JOIN "trans_translation" ON ("trans_unit"."translation_id" = "trans_translation"."id") INNER JOIN "trans_component" ON ("trans_translation"."component_id" = "trans_component"."id") INNER JOIN "trans_project" ON ("trans_component"."project_id" = "trans_project"."id") INNER JOIN "lang_language" ON ("trans_translation"."language_id" = "lang_language"."id") INNER JOIN "lang_language" T6 ON ("trans_component"."source_language_id" = T6."id") INNER JOIN "lang_plural" ON ("trans_translation"."plural_id" = "lang_plural"."id") WHERE ("trans_unit"."source" ILIKE '''''''' AND "trans_component"."project_id" = 5 AND "trans_translation"."language_id" = 246) ORDER BY "matches_current" DESC LIMIT 20 ;
                                                                           QUERY PLAN
-----------------------------------------------------------------------------------------------------------------------------------------------------------------
 Limit  (cost=29024.20..29024.25 rows=20 width=2601)
   ->  Sort  (cost=29024.20..29024.29 rows=33 width=2601)
         Sort Key: (CASE WHEN ((trans_unit.source = ''''''''::text) AND (trans_unit.context = ''::text)) THEN 1 ELSE 0 END) DESC
         ->  Nested Loop  (cost=1070.34..29023.37 rows=33 width=2601)
               ->  Nested Loop  (cost=1070.07..29011.35 rows=33 width=2549)
                     ->  Bitmap Heap Scan on lang_language  (cost=8.41..12.42 rows=1 width=30)
                           Recheck Cond: (id = 246)
                           ->  Bitmap Index Scan on lang_language_pkey  (cost=0.00..8.41 rows=1 width=0)
                                 Index Cond: (id = 246)
                     ->  Nested Loop  (cost=1061.66..28998.60 rows=33 width=2519)
                           ->  Index Scan using trans_project_pkey on trans_project  (cost=0.14..8.16 rows=1 width=804)
                                 Index Cond: (id = 5)
                           ->  Nested Loop  (cost=1061.52..28990.11 rows=33 width=1715)
                                 ->  Hash Join  (cost=900.27..1059.09 rows=169 width=1421)
                                       Hash Cond: (trans_translation.component_id = trans_component.id)
                                       ->  Seq Scan on trans_translation  (cost=0.00..154.89 rows=598 width=103)
                                             Filter: (language_id = 246)
                                       ->  Hash  (cost=898.14..898.14 rows=170 width=1318)
                                             ->  Merge Join  (cost=889.08..898.14 rows=170 width=1318)
                                                   Merge Cond: (t6.id = trans_component.source_language_id)
                                                   ->  Index Scan using lang_language_pkey on lang_language t6  (cost=0.40..4024.35 rows=618 width=30)
                                                   ->  Sort  (cost=406.66..407.09 rows=170 width=1288)
                                                         Sort Key: trans_component.source_language_id
                                                         ->  Bitmap Heap Scan on trans_component  (cost=13.59..400.36 rows=170 width=1288)
                                                               Recheck Cond: (project_id = 5)
                                                               ->  Bitmap Index Scan on trans_component_project_id_04a8b52c  (cost=0.00..13.55 rows=170 width=0)
                                                                     Index Cond: (project_id = 5)
                                 ->  Bitmap Heap Scan on trans_unit  (cost=161.25..165.26 rows=1 width=294)
                                       Recheck Cond: ((source ~~* ''''''''::text) AND (translation_id = trans_translation.id))
                                       ->  Bitmap Index Scan on unit_source_fulltext  (cost=0.00..161.25 rows=1 width=0)
                                             Index Cond: ((source ~~* ''''''''::text) AND (translation_id = trans_translation.id))
               ->  Index Scan using lang_plural_pkey on lang_plural  (cost=0.28..0.36 rows=1 width=48)
                     Index Cond: (id = trans_translation.plural_id)
(33 rows)

@dbaio
Copy link
Contributor Author

dbaio commented Jan 24, 2023

@nijel

You can ignore the fatal: bad object errors...the issue is the query.

I reverted this 8170d1d
the ilike's to iexact's and it's performing fast again.

Seems that with ilike and special characters, it performs poorly.

@nijel
Copy link
Member

nijel commented Jan 25, 2023

Thanks for analysis. What PostgreSQL version do you use?

@dbaio
Copy link
Contributor Author

dbaio commented Jan 25, 2023

still using PostgreSQL 11.18.

@nijel
Copy link
Member

nijel commented Jan 25, 2023

Okay, we've benchmarked this on 13, where it typically showed significant gain.

When I try it now, the scheduler doesn't use the trigram index, so the performance will be about the same as with the original lookups. The difference is that besides that we're only on the index scans:

 Limit  (cost=1712.71..1712.71 rows=1 width=1951)
   ->  Sort  (cost=1712.71..1712.71 rows=1 width=1951)
         Sort Key: (CASE WHEN ((trans_unit.source = ''''''''::text) AND (trans_unit.context = ''::text)) THEN 1 ELSE 0 END) DESC
         ->  Nested Loop  (cost=2.37..1712.70 rows=1 width=1951)
               ->  Nested Loop  (cost=2.10..1711.97 rows=1 width=1913)
                     ->  Nested Loop  (cost=1.82..1709.47 rows=1 width=1882)
                           ->  Nested Loop  (cost=1.54..1706.96 rows=1 width=1851)
                                 ->  Nested Loop  (cost=1.27..1704.46 rows=1 width=1656)
                                       ->  Nested Loop  (cost=0.70..12.64 rows=1 width=1470)
                                             ->  Index Scan using trans_component_project_id_04a8b52c on trans_component  (cost=0.29..4.70 rows=3 width=1357)
                                                   Index Cond: (project_id = 5)
                                             ->  Index Scan using trans_translation_component_id_language_id_331fa2a7_uniq on trans_translation  (cost=0.42..2.64 rows=1 width=113)
                                                   Index Cond: ((component_id = trans_component.id) AND (language_id = 246))
                                       ->  Index Scan using trans_unit_translation_id_513bb910 on trans_unit  (cost=0.56..1691.81 rows=1 width=186)
                                             Index Cond: (translation_id = trans_translation.id)
                                             Filter: (source ~~* ''''''''::text)
                                 ->  Index Scan using trans_project_pkey on trans_project  (cost=0.28..2.49 rows=1 width=195)
                                       Index Cond: (id = 5)
                           ->  Index Scan using lang_language_pkey on lang_language  (cost=0.28..2.50 rows=1 width=31)
                                 Index Cond: (id = 246)
                     ->  Index Scan using lang_language_pkey on lang_language t6  (cost=0.28..2.50 rows=1 width=31)
                           Index Cond: (id = trans_component.source_language_id)
               ->  Index Scan using lang_plural_pkey on lang_plural  (cost=0.28..0.72 rows=1 width=34)
                     Index Cond: (id = trans_translation.plural_id)

Maybe using ILIKE in this case is not that reasonable as we thought...

@dbaio
Copy link
Contributor Author

dbaio commented Jan 25, 2023

I've just upgraded PostgreSQL to 15.1 and it is still taking long time.
Just sharing.

explain SELECT "trans_unit"."id", "trans_unit"."translation_id", "trans_unit"."id_hash", "trans_unit"."location", "trans_unit"."context", "trans_unit"."note", "trans_unit"."flags", "trans_unit"."source", "trans_unit"."previous_source", "trans_unit"."target", "trans_unit"."state", "trans_unit"."original_state", "trans_unit"."details", "trans_unit"."position", "trans_unit"."num_words", "trans_unit"."priority", "trans_unit"."pending", "trans_unit"."timestamp", "trans_unit"."extra_flags", "trans_unit"."explanation", "trans_unit"."variant_id", "trans_unit"."source_unit_id", CASE WHEN ("trans_unit"."source" = '''''''' AND "trans_unit"."context" = '') THEN 1 ELSE 0 END AS "matches_current", "trans_translation"."id", "trans_translation"."component_id", "trans_translation"."language_id", "trans_translation"."plural_id", "trans_translation"."revision", "trans_translation"."filename", "trans_translation"."language_code", "trans_translation"."check_flags", "trans_component"."id", "trans_component"."name", "trans_component"."slug", "trans_component"."project_id", "trans_component"."vcs", "trans_component"."repo", "trans_component"."linked_component_id", "trans_component"."push", "trans_component"."repoweb", "trans_component"."git_export", "trans_component"."report_source_bugs", "trans_component"."branch", "trans_component"."push_branch", "trans_component"."filemask", "trans_component"."template", "trans_component"."edit_template", "trans_component"."intermediate", "trans_component"."new_base", "trans_component"."file_format", "trans_component"."locked", "trans_component"."allow_translation_propagation", "trans_component"."enable_suggestions", "trans_component"."suggestion_voting", "trans_component"."suggestion_autoaccept", "trans_component"."check_flags", "trans_component"."enforced_checks", "trans_component"."license", "trans_component"."agreement", "trans_component"."new_lang", "trans_component"."language_code_style", "trans_component"."manage_units", "trans_component"."merge_style", "trans_component"."commit_message", "trans_component"."add_message", "trans_component"."delete_message", "trans_component"."merge_message", "trans_component"."addon_message", "trans_component"."pull_message", "trans_component"."push_on_commit", "trans_component"."commit_pending_age", "trans_component"."auto_lock_error", "trans_component"."source_language_id", "trans_component"."language_regex", "trans_component"."variant_regex", "trans_component"."priority", "trans_component"."restricted", "trans_component"."is_glossary", "trans_component"."glossary_color", "trans_component"."remote_revision", "trans_component"."local_revision", "trans_project"."id", "trans_project"."name", "trans_project"."slug", "trans_project"."web", "trans_project"."instructions", "trans_project"."set_language_team", "trans_project"."use_shared_tm", "trans_project"."contribute_shared_tm", "trans_project"."access_control", "trans_project"."translation_review", "trans_project"."source_review", "trans_project"."enable_hooks", "trans_project"."language_aliases", "trans_project"."machinery_settings", T6."id", T6."code", T6."name", T6."direction", T6."population", "lang_language"."id", "lang_language"."code", "lang_language"."name", "lang_language"."direction", "lang_language"."population", "lang_plural"."id", "lang_plural"."source", "lang_plural"."number", "lang_plural"."formula", "lang_plural"."type", "lang_plural"."language_id" FROM "trans_unit" INNER JOIN "trans_translation" ON ("trans_unit"."translation_id" = "trans_translation"."id") INNER JOIN "trans_component" ON ("trans_translation"."component_id" = "trans_component"."id") INNER JOIN "trans_project" ON ("trans_component"."project_id" = "trans_project"."id") INNER JOIN "lang_language" ON ("trans_translation"."language_id" = "lang_language"."id") INNER JOIN "lang_language" T6 ON ("trans_component"."source_language_id" = T6."id") INNER JOIN "lang_plural" ON ("trans_translation"."plural_id" = "lang_plural"."id") WHERE ("trans_unit"."source" ILIKE '''''''' AND "trans_component"."project_id" = 5 AND "trans_translation"."language_id" = 246) ORDER BY "matches_current" DESC LIMIT 20 ;
                                                                           QUERY PLAN
-----------------------------------------------------------------------------------------------------------------------------------------------------------------
Limit  (cost=20438.91..20438.96 rows=20 width=2586)
   ->  Sort  (cost=20438.91..20438.97 rows=22 width=2586)
         Sort Key: (CASE WHEN ((trans_unit.source = ''''''''::text) AND (trans_unit.context = ''::text)) THEN 1 ELSE 0 END) DESC
         ->  Nested Loop  (cost=208.21..20438.42 rows=22 width=2586)
               ->  Nested Loop  (cost=207.94..20430.41 rows=22 width=2551)
                     ->  Nested Loop  (cost=207.66..20418.79 rows=22 width=2520)
                           ->  Index Scan using lang_language_pkey on lang_language  (cost=0.28..8.29 rows=1 width=31)
                                 Index Cond: (id = 246)
                           ->  Nested Loop  (cost=207.39..20410.28 rows=22 width=2489)
                                 ->  Seq Scan on trans_project  (cost=0.00..1.04 rows=1 width=804)
                                       Filter: (id = 5)
                                 ->  Nested Loop  (cost=207.39..20409.02 rows=22 width=1685)
                                       ->  Hash Join  (cost=91.86..205.82 rows=169 width=1391)
                                             Hash Cond: (trans_component.id = trans_translation.component_id)
                                             ->  Seq Scan on trans_component  (cost=0.00..113.51 rows=170 width=1288)
                                                   Filter: (project_id = 5)
                                             ->  Hash  (cost=84.39..84.39 rows=598 width=103)
                                                   ->  Bitmap Heap Scan on trans_translation  (cost=8.91..84.39 rows=598 width=103)
                                                         Recheck Cond: (language_id = 246)
                                                         ->  Bitmap Index Scan on trans_translation_language_id_030f0b30  (cost=0.00..8.76 rows=598 width=0)
                                                               Index Cond: (language_id = 246)
                                       ->  Bitmap Heap Scan on trans_unit  (cost=115.52..119.54 rows=1 width=294)
                                             Recheck Cond: ((source ~~* ''''''''::text) AND (translation_id = trans_translation.id))
                                             ->  Bitmap Index Scan on unit_source_fulltext  (cost=0.00..115.52 rows=1 width=0)
                                                   Index Cond: ((source ~~* ''''''''::text) AND (translation_id = trans_translation.id))
                     ->  Index Scan using lang_language_pkey on lang_language t6  (cost=0.28..0.53 rows=1 width=31)
                           Index Cond: (id = trans_component.source_language_id)
               ->  Index Scan using lang_plural_pkey on lang_plural  (cost=0.28..0.36 rows=1 width=31)
                     Index Cond: (id = trans_translation.plural_id)
(29 rows)

Thanks!

@nijel
Copy link
Member

nijel commented Jan 25, 2023

Okay, so it ends up using the index, but is still slow? Does reverting 8170d1d fix the performance?

Is searching slow for you as well? It should utilize the same index.

@dbaio
Copy link
Contributor Author

dbaio commented Jan 25, 2023

Yes, reverting that commit fixes the performance.
The Search was ok, but I didn't try any special characters like ''' or @.

@nijel
Copy link
Member

nijel commented Jan 25, 2023

Okay, the problem is that pg_trgm ignores non-word characters (non-alphanumerics) when extracting trigrams from a string. That leads to Index Cond matching every row and Recheck cond then has a lot of work excluding them all.

My guess is that searching for such strings will be problematic as well.

nijel added a commit to nijel/weblate that referenced this issue Jan 25, 2023
Use iexact and icontains for strings that pg_trgm doesn't handle well.
It looks at alphanumeric characters and in case there are none, all
strings match the index causing huge penalty when doing recheck at the
next step.

Fixes WeblateOrg#8668
@nijel
Copy link
Member

nijel commented Jan 25, 2023

Can you please try if #8675 fixes the issue for you?

@dbaio
Copy link
Contributor Author

dbaio commented Jan 25, 2023

Yes, I've tested it, and it works perfectly. Both in translation/edit and when searching.
Thanks for your help/support.

nijel added a commit to nijel/weblate that referenced this issue Jan 26, 2023
Use iexact and icontains for strings that pg_trgm doesn't handle well.
It looks at alphanumeric characters and in case there are none, all
strings match the index causing huge penalty when doing recheck at the
next step.

Fixes WeblateOrg#8668
nijel added a commit to nijel/weblate that referenced this issue Jan 26, 2023
Use iexact and icontains for strings that pg_trgm doesn't handle well.
It looks at alphanumeric characters and in case there are none, all
strings match the index causing huge penalty when doing recheck at the
next step.

Fixes WeblateOrg#8668
@nijel nijel added this to the 4.16 milestone Jan 26, 2023
@nijel nijel added bug Something is broken. and removed question This is more a question for the support than an issue. labels Jan 26, 2023
@nijel nijel self-assigned this Jan 26, 2023
nijel added a commit that referenced this issue Jan 26, 2023
Use iexact and icontains for strings that pg_trgm doesn't handle well.
It looks at alphanumeric characters and in case there are none, all
strings match the index causing huge penalty when doing recheck at the
next step.

Fixes #8668
@github-actions
Copy link

Thank you for your report; the issue you have reported has just been fixed.

  • In case you see a problem with the fix, please comment on this issue.
  • In case you see a similar problem, please open a separate issue.
  • If you are happy with the outcome, don’t hesitate to support Weblate by making a donation.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something is broken.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants