仕事で使うちょっとしたコードをOSSとして開発メンテしていく- Django...
-
Upload
takayuki-shimizukawa -
Category
Technology
-
view
468 -
download
5
Transcript of 仕事で使うちょっとしたコードをOSSとして開発メンテしていく- Django...
仕事で使うちょっとしたコードを OSS として開発メンテしていく- Django Redshift Backend の開発 -
1
Takayuki Shimizukawa
おまえ誰よ / Who are you
@shimizukawa (清水川)BeProud co, ltd.
Sphinx committer
一般社団法人 PyCon JP 理事Board member of PyCon JP committee
株式会社 BeProud 所属
3
Hello, Здравствуйте, 안녕하세요 , 你好
niche, not just tech
Why don’t you share your code snippet for your jobas a Open Source Software
仕事で使うちょっとしたコードをOSS として公開しよう
The person who want to know …以下のことを知りたい方Sharing them source code for job as a OSS.仕事で使うコードを OSS として公開することStructure of Django database backend
Django の database backend 周りの構造How to bring up your code.コードを育てていく方法
Target attendees
You can get some benefit if you open your (tiny) codeちょっとしたコードでも公開しておくと良いことがあるよ
「良いこと」って? / What is benefit?誰かがバグを見つけれてくれたり / Somebody find
bugs誰かがバグを直してくれたり / Somebody fix bugs誰かが機能を追加してくれたり / Somebody add
features
動機 / Motivation
こんなコードだれも使わないから公開しても無駄だよWaste my time because nobody want to use such code
公開するの面倒くさいし ..publishing is messy work..
ライセンスとかよく分からないI have no knowledge about license
会社やお客さんからどうやって許可をもらうの?We must to get permission papers from business customer
いろんな人にコードがダサイとかバグだとか言われちゃうI don’t want to hear somebody criticize my code
反論 / Objection
First MotivationMar, 2015. Version 0.1Published on only Github
Django アプリケーションの保守を仕事で引き継いだDjango アプリの DB を MySQL から Redshift に移行するお仕事Django と Redshift を接続する
First Motivation – Why I created a backend
Amazon Redshift
LIKE THIS?
© 「いらすとや」
Open Source Software (OSS)Web Application FrameworkMonolithicFull documentedSupport several databases
SQLite, MySQL, PostgreSQLand Oracle
Django ORMDjango Admin
Useful data management web console for Database
What is Django ?
Petabyte-scale data warehouse serviceon Amazon Web Service
The complicated query for which ittakes several hours in MySQL will becompleted in tens of seconds.
Alternatively the query issuing cost is expensive.
Compatible with PostgreSQL-8.0.4Many incompatibility also available…Use identity instead of sequence, No INDEX,
No ALTER COLUMN, No SET TIME ZONE, No RETURNING, No SELECT FOR UPDATE, …
What is Redshift ?
Amazon Redshift
Django から Database へは、こんな感じで繋がっている
First Motivation – Why I created a backend
Django ORM
Django AdminYour Code (View)
Django Database Backend
Database Driver
Database
Django から Database へは、こんな感じで繋がっているRedshift というやつは
Postgres 互換らしい既存の Driver でうまく動いた
First Motivation – Why I created a backend
Django ORM
Django AdminYour Code (View)
Django Postgres Backend
psycopg2 Driver
Redshift
Django から Database へは、こんな感じで繋がっているRedshift というやつは
Postgres 互換らしい既存の Driver でうまく動いたDjango Admin で行を追加したらクラッシュした!?
First Motivation – Why I created a backend
Django ORM
Django AdminYour Code (View)
Django Postgres Backend
psycopg2 Driver
Redshift
CRUSH!!
Django から Database へは、こんな感じで繋がっているRedshift というやつは
Postgres 互換らしい既存の Driver でうまく動いたDjango Admin で行を追加したらクラッシュした!?Django uses
“RETURNING” SQL statement for model.save()
Redshift doesn’t support “RETURNING”.
First Motivation – Why I created a backend
Django ORM
Django AdminYour Code (View)
Django Postgres Backendsupports postgresql 9.x or later
psycopg2 Driver
Redshiftbased upon postgresql 8.0.2
CRUSH!!
PostgreSQL supports RETURNING from 8.2.
Redshift based upon PostgreSQL 8.0.2.
(´ ・ ω ・ `)おしいnear-miss
First Motivation – Why I created a backend
Anyway, I googled
A few questions on StackOverflow are foundSO: “Redshift is compat with PostgreSQL-
8.0.2,so you can use postgresql_psycopg2 backend”(sigh) ..it’s not true
SO: “There is django-redshift repository on Github!”/shrug Oh yes, it’s using `RETURNING` ..
First Motivation – Why I created a backend
(´ ・ ω ・ `)じゃあ作るか…OK, I’ll do it…
First Motivation – Why I created a backend
ORM は、アプリケーションがやりたいデータ処理を SQLを書かずにオブジェクト操作で実現する層Django Database
Backend は ORM の処理をSQL に変換して Driver に伝える中間層
Driver は、データベース接続します。
Django database backend
Django ORM
Django AdminYour Code (View)
Django Database Backend
Database Driver
Database
ORM は、アプリケーションがやりたいデータ処理を SQLを書かずにオブジェクト操作で実現する層Django Redshift
Backend で ORM の処理をRedshift 用の SQL に変換してDriver に伝える
Driver は、 Postgresql 用のpsycopg2 をそのまま使用
Postgresql 用を参考に、新しいDatabase Backend を作るのはそんなに難しくなさそう?
Django Redshift database backend
Django ORM
Django AdminYour Code (View)
Django Redshift Backend
psycopg2 Driver
Redshift
No documentation for “How to create new Django Database Backend”
StackOverflow says “SQLite backend is quite simple if you’re looking to go that road.”
Django ライブラリのどこかにある postgresql_psycopg2 Backend の一部を変更して、 Redshift 用の SQL に変換すればよさそう
なんだかたくさんあるけど、必要なのは “ RETURNING” を使っている部分の変更だけということで。
Based upon postgresql_psycopg2
1. from django.db.backends import (2. BaseDatabaseValidation,3. )4. from django.db.backends.postgresql_psycopg2.base import (5. DatabaseFeatures as BasePGDatabaseFeatures,6. DatabaseWrapper as BasePGDatabaseWrapper,7. DatabaseOperations as BasePGDatabaseOperations,8. DatabaseClient,9. DatabaseCreation,10. DatabaseIntrospection,11. )12. 13. 14. class DatabaseFeatures(BasePGDatabaseFeatures):15. can_return_id_from_insert = False16. 17. 18. class DatabaseOperations(BasePGDatabaseOperations):19. 20. def last_insert_id(self, cursor, table_name, pk_name):21. cursor.execute('SELECT MAX({pk}) from {table}'.format(pk=pk_name, table=self.quote_name(table_name)))22. return cursor.fetchone()[0]23. 24. 25. class DatabaseWrapper(BasePGDatabaseWrapper):26. vendor = 'redshift'27. 28. def __init__(self, *args, **kwargs):29. super(DatabaseWrapper, self).__init__(*args, **kwargs)30. 31. self.features = DatabaseFeatures(self)32. self.ops = DatabaseOperations(self)33. self.client = DatabaseClient(self)34. self.creation = DatabaseCreation(self)35. self.introspection = DatabaseIntrospection(self)36. self.validation = BaseDatabaseValidation(self)
Source Code v 0.1 (2015-03-24)
Importing names to override default behavior ofpostgresql_psycopg2
Replacing attributes to override default behavior ofpostgresql_psycopg2
Replacing SQL statement “RETURNING” …
with “SELECT MAX(pk)”
1. index 1fd9e51..c4ad661 1006442. --- a/django_redshift_backend/base.py3. +++ b/django_redshift_backend/base.py4. @@ -20,6 +20,7 @@ from django.db.backends.postgresql_psycopg2.base import (5. 6. class DatabaseFeatures(BasePGDatabaseFeatures):7. can_return_id_from_insert = False8. + has_select_for_update = False9. 10. 11. class DatabaseOperations(BasePGDatabaseOperations):12. @@ -28,6 +29,9 @@ class DatabaseOperations(BasePGDatabaseOperations):13. cursor.execute('SELECT MAX({pk}) from {table}'.format(pk=pk_name,
table=self.quote_name(table_name)))14. return cursor.fetchone()[0]15. 16. + def for_update_sql(self, nowait=False):17. + raise NotImplementedError('SELECT FOR UPDATE is not implemented for
this database backend')18. +19. 20. class DatabaseWrapper(BasePGDatabaseWrapper):21. vendor = 'redshift'
Source Code v 0.1.1 (2015-03-27)
Disable SELECT FOR UPDATE
If used, raise NotImplementadError
Why do I open my code?
NEEDS for Django Redshift Backend? YES, but little.
WRONG information are there.
EXPOSED to the public eye
GIVE the code to next someone like me
個人で OSS として実装して公開した会社のコードにするとどうしても気にするべき事が増える
公開された OSS を仕事で使う← いつもやっている仕事で使いやすい Apache Software License を採用
バグがあったら修正して OSS にコントリビュートする社内に業務中に OSS にコントリビュートする文化がある結果的に仕事のコストが下がる
ライセンスは?許可は?
よかったことGithub だけで公開したので身軽この段階ではテストコードを書かなかった
今後やりたいことSET TIME ZONE を発行しない(設定で回避していた)Django migration をサポートしたい
Summary of First Motivation
Second MotivationJune, 2015. Version 0.1.2First Pull-Request
Second Motivation - First Pull Request
First Pull Request (2015-06-02)
1. index c4ad661..1d91bb4 1006442. --- a/django_redshift_backend/base.py3. +++ b/django_redshift_backend/base.py4. @@ -5,9 +5,13 @@5. """6. from __future__ import absolute_import7. 8. -from django.db.backends import (9. - BaseDatabaseValidation,10. -)11. +try:12. + from django.db.backends.base.validation import (13. + BaseDatabaseValidation,14. + )15. +except ImportError:16. + # for django < 1.817. + from django.db.backends import BaseDatabaseValidation18. from django.db.backends.postgresql_psycopg2.base import (19. DatabaseFeatures as BasePGDatabaseFeatures,20. DatabaseWrapper as BasePGDatabaseWrapper,
Second Motivation - First Pull Request
Django-1.8
Django-1.7
Django-1.7
Second Motivation - First Pull Request
このコードは使えそう。 Django-1.8対応の修正した Fork を自分で管理したくないから、修正取り込んでもらおう(想像)Django-1.8 を将来使うかもしれないし、対応しておくことでこの人が 1.8上でバグ出ししてくれるかも ?
Second Motivation - First Pull Request
6/2 23:13
6/2 23:30
6/2 23:30
6/2 23:30
6/2 23:36
6/2 23:37
Merged!
Second Motivation - First Pull Request
6/2 23:13
6/2 23:30
6/2 23:30
6/2 23:30
6/2 23:36
6/2 23:37
Tagging advice
Second Motivation - First Pull Request
6/2 23:13
6/2 23:30
6/2 23:30
6/2 23:30
6/2 23:36
6/2 23:37Live!Live!
Second Motivation - First Pull Request
6/2 23:13
6/2 23:30
6/2 23:30
6/2 23:30
6/2 23:36
6/2 23:37
FUN!FUN!
続けたいこと(よかったこと)ソースコードの公開知らない誰かとライブ感ある開発ニッチでもニーズがあることが(公開したから)分かった
こうしたらよさそう(変えたいこと)PyPI に公開したら使ってくれる人が増えるかも
Summary of Second Motivation
Third MotivationFeb, 2016. Version 0.2.1Published on PyPI
Django-1.7.x のサポートが 2015/12 末で終了Django-1.8 にバージョンアップしたら、 “ SET
TIME ZONE” SQL を発行して落ちた1.7:
settings.TIME_ZONE=None で SET TIME ZONE 抑止
1.8:settings.TIME_ZONE と DB の実際の値を比較して違っていたら SET TIME ZONE !
ドキュメント化されていない (´ ・ Д ・ )
Third Motivation – Django-1.8
0.2 (2016-01-08) SET TIME ZONE に対応0.2.1 (2016-01-28) ちょっと修正当初課題だった 3 つの問題が解決1. RETURNING2. SELECT FOR UPDATE3. SET TIME ZONE
人目に付くところに置いて、もっと広く使って貰ってもらう時期が来た気がした。
Third Motivation – Django-1.8
django-redshift-backend, PyPI debut
First PyPI release (2016-02-01)
よかったことDjango-1.8 対応しておいてよかった1年ぶりの更新だったけど、おかげで PyPI に出せた
今後やりたいこといよいよ、 Django migration をサポートしよう!
Third Motivation のまとめ
Fourth MotivationMigration 対応 PR ~ やるき低迷 ~ 復活
Fourth Motivation – migration support
PR for migration support (2016-03-07)
• Use CustomSchemaEditor to support sqlmigrate
• Map DateTimeField to “TIMESTAMP”• Map AutoField to “identity” to support
sqlmigrate
Fourth Motivation – migration support
Mar 7
Mar 7
Mar 10
Mar 23
Apr 8
Apr 8
May 14
Merged!
Fourth Motivation – migration support
Mar 7
Mar 7
Mar 10
Mar 23
Apr 8
Apr 8
May 14
Thanks!
Fourth Motivation – migration support
Mar 7
Mar 7
Mar 10
Mar 23
Apr 8
Apr 8
May 14
Plz Release0.3 to PyPI?
Motivation NOT FOUND
Mar 7
Mar 7
Mar 10
Mar 23
Apr 8
Apr 8
May 14
OK
Motivation NOT FOUND
Mar 7
Mar 7
Mar 10
Mar 23
Apr 8
Apr 8
May 14Thx
Motivation NOT FOUND
Mar 7
Mar 7
Mar 10
Mar 23
Apr 8
Apr 8
May 14Done
django migration に対応 (2016/3/5)
自分でも migration 周りをそれなりのコード量実装実装を Github に置きっぱなしでリリースはしなかった使ってバグだししよう ~ 2ヶ月放置
検証が重たかった自動テストが必要な規模へ
Motivation NOT FOUND
重たいのは一旦おいといて… 自分が楽しいことをやろう!Flake8 でコーディング規約を自動チェックテストコードを書いて Django-1.7, 1.8, 1.9 でテストTox で Python-2.7, 3.4, 3.5 と Django-1.7, 1.8, 1.9 のマトリックステストTravis-ci で自動テスト
Resume -環境整備しよう
一番の難所Django database backend のテストってどうやって書くの
Django 自体のテストコードを読み始めるそれっぽいテストを真似て必要十分になるまで調整
Travis-ci で自動テストさせようTravis-ci で psycopg2 のビルドがこけるmanylinux1 wheel ( linux 用バイナリパッケージ)を作成してリポジトリに同梱して解決
その後、 migration 対応も終えた
Testing for django-redshift-backend
manylinux1 wheel についてはこちら宣伝!
反省点「あれをやってからこれをやろう」は停滞する時間が経ってからリリースするのは気が重いPR を放置すると仲間が離れていく
よかったこと各バージョンでのテストがあると安心できるPR が自動テストされているとチェックが楽
今後の改善点完全でなくても小さい単位でリリースしていく
Fourth Motivation のまとめ
OSS 公開Before and After
社内の1プロジェクトで持ってても良いことがなさそうお荷物化(謎技術化する、更新されなくなる)社内のプロジェクト外の人に使ってもらえない1つのニーズでバグ出しできる範囲は狭い社内ライブラリにする?ニーズがニッチすぎてやはりお荷物化しそうOSS を使って仕事をしてるのだから、 OSS に還元したい
OSS 公開する時に考えたこと
自分が困ったなら、他にも困った人がいるかも運良くバグ報告をもらえたら、潜在的な問題を直せるかも自分より詳しい人が良いアドバイスをくれるかも
OSS 公開に期待したこと
同じ課題をもった仲間が数人見つかった狭い要件にひっぱられても引き戻された
VARCHAR3倍 -> settings にしようぜ回帰テスト環境が必要になったリリースに対する責任を持つことになった
リリースは自分だけができるリリースしないと Fork が乱立する
OSS 公開して起きたこと
こんなコードだれも使わないから公開しても無駄だよWaste my time because nobody want to use such code 自分より先に誰かが作って公開してくれてたら嬉しかったよね?
公開するの面倒くさいし ..publishing is messy work.. 素振りだと思ってやってみたら?
ライセンスとかよく分からないI have no knowledge about license やってればそのうち分かるよ
会社やお客さんからどうやって許可をもらうの?We must to get permission papers from business customer 伝え方は色々あるよ
いろんな人にコードがダサイとかバグだとか言われちゃうI don’t want to hear somebody criticize my code だれかが自分の代わりにバグを見つけてくれるならラッキーだよね
反論への反論 / Objection to Objection
素振りの良い機会Django, Travis-ci, マトリックステスト 等詳しく知るきっかけになった
次の自分のために、ソースコードを公開しておくOSS に還元、と言うとハードルが高い気がするけど困っているもう一人の自分に、解決方法を用意しておく感じ
気負わずに、小さく少しずつやるのがよい
OSS 公開を振り返って
Questions?@shimizukawa
Glab me anytime :)Break, Party, Sprint
61
Extra Episode
“ オープンソースソフトウェアの育て方” 第 1 章より
製作著作 © 2005-2013 Karl Fogel, 高木正弘 , Yoshinari Takaoka(a.k.a mumumu) http://producingoss.com/ja/ CC BY-SA 2.1
Thanks :)
64