Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

仕事で使うちょっとしたコードをOSSとして開発メンテしていく - Django Redshift Backend の開発 - PyCon JP 2016

2,364 views

Published on

Why don’t you share your code snippet for your job as a Open Source Software

Published in: Technology
  • Be the first to comment

仕事で使うちょっとしたコードをOSSとして開発メンテしていく - Django Redshift Backend の開発 - PyCon JP 2016

  1. 1. 1 Takayuki Shimizukawa
  2. 2. おまえ誰よ / Who are you @shimizukawa (清水川)  BeProud co, ltd.  Sphinx committer  一般社団法人PyCon JP理事 Board member of PyCon JP committee 株式会社BeProud所属
  3. 3. 3 Hello, Здравствуйте,안녕하세요, 你好
  4. 4. niche, not just tech
  5. 5. 仕事で使うちょっとしたコードを OSSとして公開しよう
  6. 6. 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
  7. 7.  You can get some benefit if you open your (tiny) code ちょっとしたコードでも公開しておくと良いことが あるよ  「良いこと」って? / What is benefit?  誰かがバグを見つけれてくれたり / Somebody find bugs  誰かがバグを直してくれたり / Somebody fix bugs  誰かが機能を追加してくれたり / Somebody add features 動機 / Motivation
  8. 8.  こんなコードだれも使わないから公開しても無駄だよ 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
  9. 9. Mar, 2015. Version 0.1 Published on only Github
  10. 10.  Djangoアプリケーションの保守を仕事で引き継いだ  DjangoアプリのDBをMySQLからRedshiftに移行するお仕事  DjangoとRedshiftを接続する First Motivation – Why I created a backend Amazon Redshift LIKE THIS? ©「いらすとや」
  11. 11.  Open Source Software (OSS)  Web Application Framework  Monolithic  Full documented  Support several databases  SQLite, MySQL, PostgreSQL and Oracle  Django ORM  Django Admin  Useful data management web console for Database What is Django ?
  12. 12.  Petabyte-scale data warehouse service on Amazon Web Service  The complicated query for which it takes several hours in MySQL will be completed in tens of seconds.  Alternatively the query issuing cost is expensive.  Compatible with PostgreSQL-8.0.4  Many 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
  13. 13.  DjangoからDatabaseへは、こ んな感じで繋がっている First Motivation – Why I created a backend Django ORM Django AdminYour Code (View) Django Database Backend Database Driver Database
  14. 14.  DjangoからDatabaseへは、こ んな感じで繋がっている  RedshiftというやつはPostgres 互換らしい  既存のDriverでうまく動いた First Motivation – Why I created a backend Django ORM Django AdminYour Code (View) Django Postgres Backend psycopg2 Driver Redshift
  15. 15.  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!!
  16. 16.  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 Backend supports postgresql 9.x or later psycopg2 Driver Redshift based upon postgresql 8.0.2 CRUSH!!
  17. 17.  PostgreSQL supports RETURNING from 8.2.  Redshift based upon PostgreSQL 8.0.2. (´・ω・`) おしい near-miss First Motivation – Why I created a backend
  18. 18. Anyway, I googled  A few questions on StackOverflow are found  SO: “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
  19. 19. (´・ω・`) じゃあ作るか… OK, I’ll do it… First Motivation – Why I created a backend
  20. 20.  ORM は、アプリケーションが やりたいデータ処理をSQLを 書かずにオブジェクト操作で 実現する層  Django Database Backendは ORMの処理をSQLに変換して Driverに伝える中間層  Driver は、データベース接続 します。 Django database backend Django ORM Django AdminYour Code (View) Django Database Backend Database Driver Database
  21. 21.  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
  22. 22.  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
  23. 23. 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 = False 16. 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 of postgresql_psycopg2 Replacing attributes to override default behavior of postgresql_psycopg2 Replacing SQL statement “RETURNING” … with “SELECT MAX(pk)”
  24. 24. 1. index 1fd9e51..c4ad661 100644 2. --- a/django_redshift_backend/base.py 3. +++ b/django_redshift_backend/base.py 4. @@ -20,6 +20,7 @@ from django.db.backends.postgresql_psycopg2.base import ( 5. 6. class DatabaseFeatures(BasePGDatabaseFeatures): 7. can_return_id_from_insert = False 8. + has_select_for_update = False 9. 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
  25. 25. 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
  26. 26.  個人でOSSとして実装して公開した  会社のコードにするとどうしても気にするべき事が増 える  公開されたOSSを仕事で使う  ←いつもやっている  仕事で使いやすいApache Software Licenseを採用  バグがあったら修正してOSSにコントリビュートす る  社内に業務中にOSSにコントリビュートする文化があ る  結果的に仕事のコストが下がる ライセンスは?許可は?
  27. 27.  よかったこと  Githubだけで公開したので身軽  この段階ではテストコードを書かなかった  今後やりたいこと  SET TIME ZONE を発行しない(設定で回避してい た)  Django migration をサポートしたい Summary of First Motivation
  28. 28. June, 2015. Version 0.1.2 First Pull-Request
  29. 29. Second Motivation - First Pull Request First Pull Request (2015-06-02)
  30. 30. 1. index c4ad661..1d91bb4 100644 2. --- a/django_redshift_backend/base.py 3. +++ b/django_redshift_backend/base.py 4. @@ -5,9 +5,13 @@ 5. """ 6. from __future__ import absolute_import 7. 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.8 17. + from django.db.backends import BaseDatabaseValidation 18. 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
  31. 31. Second Motivation - First Pull Request このコードは使えそう。Django-1.8対 応の修正したForkを自分で管理した くないから、修正取り込んでもらお う(想像) Django-1.8を将来使うかもしれないし、 対応しておくことでこの人が1.8上で バグ出ししてくれるかも?
  32. 32. 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!
  33. 33. 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
  34. 34. 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 Live!Live!
  35. 35. 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
  36. 36.  続けたいこと(よかったこと)  ソースコードの公開  知らない誰かとライブ感ある開発  ニッチでもニーズがあることが(公開したから)分 かった  こうしたらよさそう(変えたいこと)  PyPIに公開したら使ってくれる人が増えるかも Summary of Second Motivation
  37. 37. Feb, 2016. Version 0.2.1 Published on PyPI
  38. 38.  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
  39. 39.  0.2 (2016-01-08) SET TIME ZONE に対応  0.2.1 (2016-01-28) ちょっと修正 当初課題だった3つの問題が解決 1. RETURNING 2. SELECT FOR UPDATE 3. SET TIME ZONE 人目に付くところに置いて、もっと広く使って貰って もらう時期が来た気がした。 Third Motivation – Django-1.8
  40. 40. django-redshift-backend, PyPI debut First PyPI release (2016-02-01)
  41. 41.  よかったこと  Django-1.8 対応しておいてよかった  1年ぶりの更新だったけど、おかげでPyPIに出せた  今後やりたいこと  いよいよ、Django migration をサポートしよう! Third Motivation のまとめ
  42. 42. Migration対応PR ~ やるき低迷 ~ 復活
  43. 43. 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
  44. 44. Fourth Motivation – migration support Mar 7 Mar 7 Mar 10 Mar 23 Apr 8 Apr 8 May 14 Merged!
  45. 45. Fourth Motivation – migration support Mar 7 Mar 7 Mar 10 Mar 23 Apr 8 Apr 8 May 14 Thanks!
  46. 46. Fourth Motivation – migration support Mar 7 Mar 7 Mar 10 Mar 23 Apr 8 Apr 8 May 14 Plz Release 0.3 to PyPI?
  47. 47. Motivation NOT FOUND Mar 7 Mar 7 Mar 10 Mar 23 Apr 8 Apr 8 May 14 OK
  48. 48. Motivation NOT FOUND Mar 7 Mar 7 Mar 10 Mar 23 Apr 8 Apr 8 May 14 Thx
  49. 49. Motivation NOT FOUND Mar 7 Mar 7 Mar 10 Mar 23 Apr 8 Apr 8 May 14 Done
  50. 50.  django migration に対応 (2016/3/5)  自分でもmigration周りをそれなりのコード量実装  実装をGithubに置きっぱなしでリリースはしなかっ た  使ってバグだししよう ~ 2ヶ月放置  検証が重たかった  自動テストが必要な規模へ Motivation NOT FOUND
  51. 51. 重たいのは一旦おいといて… 自分が楽しいことをやろう!  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 -環境整備しよう
  52. 52. 一番の難所  Django database backendのテストってどうやって書 くの  Django自体のテストコードを読み始める  それっぽいテストを真似て必要十分になるまで調整  Travis-ciで自動テストさせよう  Travis-ciでpsycopg2のビルドがこける  manylinux1 wheel(linux用バイナリパッケージ)を 作成してリポジトリに同梱して解決  その後、migration対応も終えた Testing for django-redshift-backend
  53. 53. manylinux1 wheel についてはこちら
  54. 54.  反省点  「あれをやってからこれをやろう」は停滞する  時間が経ってからリリースするのは気が重い  PRを放置すると仲間が離れていく  よかったこと  各バージョンでのテストがあると安心できる  PRが自動テストされているとチェックが楽  今後の改善点  完全でなくても小さい単位でリリースしていく Fourth Motivation のまとめ
  55. 55. 社内の1プロジェクトで持ってても良いことがなさそ う  お荷物化(謎技術化する、更新されなくなる)  社内のプロジェクト外の人に使ってもらえない  1つのニーズでバグ出しできる範囲は狭い 社内ライブラリにする?  ニーズがニッチすぎてやはりお荷物化しそう OSSを使って仕事をしてるのだから、OSSに還元した い OSS公開する時に考えたこと
  56. 56.  自分が困ったなら、他にも困った人がいるかも  運良くバグ報告をもらえたら、潜在的な問題を直せ るかも  自分より詳しい人が良いアドバイスをくれるかも OSS公開に期待したこと
  57. 57.  同じ課題をもった仲間が数人見つかった  狭い要件にひっぱられても引き戻された  VARCHAR3倍 -> settingsにしようぜ  回帰テスト環境が必要になった  リリースに対する責任を持つことになった  リリースは自分だけができる  リリースしないとForkが乱立する OSS公開して起きたこと
  58. 58.  こんなコードだれも使わないから公開しても無駄だよ 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
  59. 59.  素振りの良い機会  Django, Travis-ci, マトリックステスト 等  詳しく知るきっかけになった  次の自分のために、ソースコードを公開しておく  OSSに還元、と言うとハードルが高い気がするけど  困っているもう一人の自分に、解決方法を用意してお く感じ  気負わずに、小さく少しずつやるのがよい OSS公開を振り返って
  60. 60. Questions? @shimizukawa Glab me anytime :) Break, Party, Sprint 61
  61. 61. “オープンソースソフトウェアの育て方” 第1章より 製作著作 © 2005-2013 Karl Fogel, 高木正弘, Yoshinari Takaoka(a.k.a mumumu) http://producingoss.com/ja/ CC BY-SA 2.1
  62. 62. Thanks :) 64

×