OLD | NEW |
1 # Copyright 2016 The Chromium Authors. All rights reserved. | 1 # Copyright 2016 The Chromium Authors. All rights reserved. |
2 # Use of this source code is governed by a BSD-style license that can be | 2 # Use of this source code is governed by a BSD-style license that can be |
3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
4 | 4 |
5 """A cron job which queues old tests for deletion.""" | 5 """A cron job which queues old tests for deletion.""" |
6 | 6 |
7 import datetime | 7 import datetime |
| 8 import logging |
8 | 9 |
9 from google.appengine.api import taskqueue | 10 from google.appengine.api import taskqueue |
10 from google.appengine.datastore import datastore_query | 11 from google.appengine.datastore import datastore_query |
11 | 12 |
12 from dashboard import datastore_hooks | 13 from dashboard import datastore_hooks |
13 from dashboard import list_tests | 14 from dashboard import list_tests |
14 from dashboard import request_handler | 15 from dashboard import request_handler |
15 from dashboard import utils | 16 from dashboard import utils |
16 from dashboard.models import graph_data | 17 from dashboard.models import graph_data |
17 | 18 |
18 _CUTOFF_DATE = datetime.timedelta(days=183) # Six months ago | 19 _CUTOFF_DATE = datetime.timedelta(days=183) # Six months ago |
19 _TESTS_TO_CHECK_AT_ONCE = 100 | 20 _TESTS_TO_CHECK_AT_ONCE = 100 |
20 | 21 |
21 # Queue name needs to be listed in queue.yaml. | 22 # Queue name needs to be listed in queue.yaml. |
22 _TASK_QUEUE_NAME = 'delete-old-tests-queue' | 23 _TASK_QUEUE_NAME = 'delete-old-tests-queue' |
23 _DELETE_TASK_QUEUE_NAME = 'delete-tests-queue' | 24 _DELETE_TASK_QUEUE_NAME = 'delete-tests-queue' |
24 | 25 |
25 | 26 |
26 class DeleteOldTestsHandler(request_handler.RequestHandler): | 27 class DeleteOldTestsHandler(request_handler.RequestHandler): |
27 """Finds tests with no new data, and deletes them.""" | 28 """Finds tests with no new data, and deletes them.""" |
28 | 29 |
| 30 def get(self): |
| 31 self.post() |
| 32 |
29 def post(self): | 33 def post(self): |
30 """Query for tests, and put ones with no new data on the delete queue.""" | 34 """Query for tests, and put ones with no new data on the delete queue.""" |
31 datastore_hooks.SetPrivilegedRequest() | 35 datastore_hooks.SetPrivilegedRequest() |
| 36 logging.info('Cursor: %s', self.request.get('cursor')) |
32 cursor = datastore_query.Cursor(urlsafe=self.request.get('cursor')) | 37 cursor = datastore_query.Cursor(urlsafe=self.request.get('cursor')) |
33 tests, next_cursor, more = graph_data.TestMetadata.query().fetch_page( | 38 tests, next_cursor, more = graph_data.TestMetadata.query().fetch_page( |
34 _TESTS_TO_CHECK_AT_ONCE, keys_only=True, start_cursor=cursor) | 39 _TESTS_TO_CHECK_AT_ONCE, keys_only=True, start_cursor=cursor) |
35 if more: | |
36 taskqueue.add( | |
37 url='/delete_old_tests', | |
38 params={'cursor': next_cursor.urlsafe()}, | |
39 queue_name=_TASK_QUEUE_NAME) | |
40 for test in tests: | 40 for test in tests: |
41 # Delete this test if: | 41 # Delete this test if: |
42 # 1) It has no Rows newer than the cutoff | 42 # 1) It has no Rows newer than the cutoff |
43 # 2) It has no descendant tests | 43 # 2) It has no descendant tests |
| 44 logging.info('Checking %s', utils.TestPath(test)) |
44 no_new_rows = False | 45 no_new_rows = False |
45 last_row = graph_data.Row.query( | 46 last_row = graph_data.Row.query( |
46 graph_data.Row.parent_test == utils.OldStyleTestKey(test)).order( | 47 graph_data.Row.parent_test == utils.OldStyleTestKey(test)).order( |
47 -graph_data.Row.timestamp).get() | 48 -graph_data.Row.timestamp).get() |
48 if last_row: | 49 if last_row: |
49 if last_row.timestamp < datetime.datetime.today() - _CUTOFF_DATE: | 50 if last_row.timestamp < datetime.datetime.today() - _CUTOFF_DATE: |
50 no_new_rows = True | 51 no_new_rows = True |
51 else: | 52 else: |
52 no_new_rows = True | 53 no_new_rows = True |
53 descendants = list_tests.GetTestDescendants(test, keys_only=True) | 54 descendants = list_tests.GetTestDescendants(test, keys_only=True) |
54 descendants.remove(test) | 55 if test in descendants: |
| 56 descendants.remove(test) |
| 57 stamp = 'never' |
| 58 if last_row: |
| 59 stamp = last_row.timestamp |
55 if not descendants and no_new_rows: | 60 if not descendants and no_new_rows: |
| 61 logging.info('Deleting test %s last timestamp %s', |
| 62 utils.TestPath(test), stamp) |
56 taskqueue.add( | 63 taskqueue.add( |
57 url='/delete_test_data', | 64 url='/delete_test_data', |
58 params={ | 65 params={ |
59 'test_path': utils.TestPath(test), # For manual inspection. | 66 'test_path': utils.TestPath(test), # For manual inspection. |
60 'test_key': test.urlsafe(), | 67 'test_key': test.urlsafe(), |
61 }, | 68 }, |
62 queue_name=_DELETE_TASK_QUEUE_NAME) | 69 queue_name=_DELETE_TASK_QUEUE_NAME) |
| 70 else: |
| 71 logging.info('NOT Deleting test %s last timestamp %s', |
| 72 utils.TestPath(test), stamp) |
| 73 |
| 74 if more: |
| 75 taskqueue.add( |
| 76 url='/delete_old_tests', |
| 77 params={'cursor': next_cursor.urlsafe()}, |
| 78 queue_name=_TASK_QUEUE_NAME) |
OLD | NEW |