Tuesday, February 24, 2015¶
Bank statements¶
I continued to work on the bank statements. Here is my plan for what to do when there is more than one payment suggestion for a partner.
Lino should show a dialog box with a selection list where the user can select one or multiple of these suggestions. This would be a subclass of SuggestionsByVoucher
If the user selects more than one suggestion, Lino should do it better
than TIM. While in TIM this would create one line per suggestion in
the bank statement, Lino creates a grouper for these suggestions.
If there is already another (unregistered) grouper for this partner,
Lino should raise a warning There is already an open grouper
for partner X
.
Mahmoud and the Lino test suite¶
Mahmoud and I are currently trying to get the Lino test suite pass on his machine. We discovered that there was one important line missing in tests/test_appy_pod.py.
Don’t forget to optimize your tables!¶
Today I passed most of my day on a performance problem in Châtelet. And the users there had to live with a slow Lino for a whole day. And at the same time Estonia was celebrating Independence Day. Thanks to Pierre and especially Mahmoud for their help.
I learned some tricks for analyzing such situations. For example this shows the number of Apache worker processes:
$ ps aux |grep apache |wc -l
Or this shows the IP addresses of all connected clients:
$ netstat -atn |grep 'tcp\|udp' | awk '{print $5}' | cut -d: -f1 | sort | uniq -c | sort -n
We saw that the apache error log said:
[Tue Feb 24 11:43:07 2015] [error] server is within MinSpareThreads of MaxClients, consider raising the MaxClients setting
[Tue Feb 24 11:46:11 2015] [error] server reached MaxClients setting, consider raising the MaxClients setting
Or we used the MySQLTuner-perl to analyze Lino’s database usage and it warned us:
[!!] Joins performed without indexes: 143
[!!] Temporary tables created on disk: 37% (334 on disk / 892 total)
All these were very interesting, but the real reason was: last
night during a routine upgrade with database snapshot and restore, I
also used the occasion to manually delete about 8600 rows from one
table (changes.Change
)
which was still hanging around but no longer used in Châtelet. I did
not yet know that “after deleting a large part of a MyISAM or ARCHIVE
table” it is recommended to run an OPTIMIZE TABLE on that
table!
assert profile == jsgen._for_user_profile¶
The performance problem forced me to investigate on another problem which looks as follows:
201502-24 16:38:21 ERROR base : Internal Server Error: /
Traceback (most recent call last):
File ".../env/local/lib/python2.7/site-packages/django/core/handlers/base.py", line 112, in get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File ".../env/local/lib/python2.7/site-packages/django/views/generic/base.py", line 69, in view
return self.dispatch(request, *args, **kwargs)
File ".../env/local/lib/python2.7/site-packages/django/views/generic/base.py", line 87, in dispatch
return handler(request, *args, **kwargs)
File ".../env/repositories/lino/lino/modlib/extjs/views.py", line 128, in get
return http.HttpResponse(renderer.html_page(request, **kw))
File ".../env/repositories/lino/lino/modlib/extjs/ext_renderer.py", line 442, in html_page
self.build_js_cache_for_profile(user.profile, False)
File ".../env/repositories/lino/lino/modlib/extjs/ext_renderer.py", line 624, in build_js_cache_for_profile
return settings.SITE.kernel.make_cache_file(fn, write, force)
File ".../env/repositories/lino/lino/core/kernel.py", line 719, in make_cache_file
write(f)
File ".../env/repositories/lino/lino/modlib/extjs/ext_renderer.py", line 622, in write
self.write_lino_js(f, profile)
File ".../env/repositories/lino/lino/modlib/extjs/ext_renderer.py", line 650, in write_lino_js
assert profile == jsgen._for_user_profile
AssertionError
This is simply because lino.utils.jsgen
is not thread-safe.
Sounds simple, but it took me some time to understand it. Ticket
#107. The problem occured only if two different user
profiles made a request at the same time (i.e. the second request
coming in while build_js_cache_for_profile
of the first request is still running. And that method takes a few
seconds.)
While #107 is not solved, it is recommended to configure mod_wsgi so that it does not use multithreading.
Another result of this day is #108 (new ideas for the
diag
django-admin command).