18 KiB
گزارش تحلیل خطای location_data برای Remote Sensing Run
این سند بر اساس payload دریافتی از endpoint زیر تهیه شده است:
GET /api/location-data/remote-sensing/runs/{task_id}/status/
نمونه run بررسیشده:
task_id:02959179-63b2-4388-bb2e-a4d79176eca2run.id:6- بازه زمانی:
2026-04-09تا2026-05-09 - وضعیت API:
failed - وضعیت Celery:
RETRY
1) خلاصه خیلی کوتاه
این run تا مرحله واکشی metricها و ذخیره observationها جلو رفته، اما در مرحله ساخت subdivision دادهمحور شکست خورده است.
خطای نهایی:
هیچ observation قابل استفادهای برای خوشهبندی باقی نماند.
این خطا در کد دقیقاً زمانی رخ میدهد که سیستم بعد از بارگذاری observationها، هیچ ردیفی را برای clustering قابل استفاده تشخیص ندهد.
مسیر کد:
location_data/tasks.pylocation_data/data_driven_subdivision.py
2) جدول مدلها / جدولهای درگیر
| مدل | جدول Django | نقش |
|---|---|---|
SoilLocation |
location_data_soillocation |
اطلاعات location و farm boundary |
BlockSubdivision |
location_data_blocksubdivision |
تقسیمبندی بلوک/مزرعه |
RemoteSensingRun |
location_data_remotesensingrun |
وضعیت اجرای pipeline سنجشازدور |
AnalysisGridCell |
location_data_analysisgridcell |
سلولهای شبکه تحلیلی |
AnalysisGridObservation |
location_data_analysisgridobservation |
مقادیر metricها برای هر cell |
RemoteSensingSubdivisionResult |
location_data_remotesensingsubdivisionresult |
نتیجه clustering و subdivision نهایی |
RemoteSensingClusterAssignment |
location_data_remotesensingclusterassignment |
نسبت هر cell به cluster |
3) جدول معنی فیلدهای سطح اول response
| فیلد | مقدار نمونه | توضیح |
|---|---|---|
code |
200 |
پاسخ HTTP موفق از API؛ لزوماً به معنای موفق بودن task نیست |
msg |
success |
پیام wrapper API |
data.status |
failed |
وضعیت client-facing run |
data.source |
database |
payload از دادههای ذخیرهشده در DB ساخته شده |
data.task_id |
UUID | شناسه Celery task |
data.run |
object | snapshot اصلی run |
data.task |
object | جزئیات stageها، timestamps و وضعیت Celery |
4) جدول معنی فیلدهای run
| فیلد | مقدار نمونه | توضیح |
|---|---|---|
id |
6 |
شناسه رکورد run در DB |
block_code |
"" |
خالی یعنی کل مزرعه، نه یک بلوک خاص |
chunk_size_sqm |
900 |
اندازه هر cell به متر مربع |
temporal_start |
2026-04-09 |
شروع بازه تحلیل |
temporal_end |
2026-05-09 |
پایان بازه تحلیل |
status |
failure |
مقدار خام DB |
status_label |
failed |
نسخه نرمالشده برای client |
pipeline_status |
failed |
تکرار client-facing status |
stage |
observations_persisted |
آخرین stage ذخیرهشده در metadata |
selected_features |
ndvi, ndwi, lst_c, soil_vv_db, dem_m, slope_deg |
featureهایی که pipeline فکر میکند برای clustering لازماند |
requested_cluster_count |
null |
تعداد cluster صریح از کاربر نیامده و الگوریتم باید تصمیم بگیرد |
error_message |
متن فارسی خطا | خطای نهایی ثبتشده روی run |
started_at |
timestamp | زمان شروع واقعی run |
finished_at |
timestamp | زمان ثبت failure روی run |
created_at |
timestamp | زمان ایجاد رکورد run |
updated_at |
timestamp | آخرین بهروزرسانی رکورد run |
5) جدول معنی فیلدهای run.metadata
| فیلد | توضیح |
|---|---|
scope |
scope اجرای تحلیل؛ در این نمونه all_blocks |
stage |
stage فعلی/آخر ذخیرهشده |
task_id |
شناسه Celery task |
pipeline.name |
نام pipeline |
pipeline.version |
نسخه pipeline |
farm_uuid |
شناسه مزرعه |
timestamps |
زمان ورود به هر stage |
status_label |
وضعیت client-facing ذخیرهشده در metadata |
requested_via |
مبدا درخواست؛ در این نمونه api |
stage_details |
جزئیات هر stage |
failure_reason |
دلیل نهایی ثبت failure |
selected_features |
featureهای مورد استفاده برای clustering |
requested_cluster_count |
cluster count درخواستی، اگر وجود داشته باشد |
6) جدول معنی stageها در این run
| stage | وضعیت مشاهدهشده | معنی |
|---|---|---|
queued |
completed | task در صف قرار گرفته |
preparing_analysis_grid |
completed | آمادهسازی grid تحلیلی |
analysis_grid_ready |
completed | grid سلولها آماده بوده |
analysis_cells_selected |
completed | 12 سلول برای پردازش انتخاب شدهاند |
fetching_remote_metrics |
completed | metricها از openEO درخواست شدهاند |
remote_metrics_fetched |
completed | jobهای openEO تمام شدهاند |
observations_persisted |
failed | observationها ذخیره شدهاند ولی pipeline بعد از این مرحله fail شده |
failed |
completed | stage شکست نهایی ثبت شده |
نکته مهم:
- در payload فعلی،
run.stageهنوزobservations_persistedاست اماdata.statusبرابرfailedاست. - این یعنی status و stage با هم perfectly sync نیستند.
7) جدول معنی stage_details
7.1) preparing_analysis_grid
| فیلد | توضیح |
|---|---|
block_code |
بلوک هدف |
temporal_extent.start_date |
شروع بازه |
temporal_extent.end_date |
پایان بازه |
7.2) analysis_grid_ready
| فیلد | توضیح |
|---|---|
grid_summary.created |
آیا grid همین run ساخته شده یا از قبل وجود داشته |
grid_summary.block_code |
کد بلوک |
grid_summary.total_count |
تعداد کل cellها |
grid_summary.created_count |
تعداد cell تازه ایجادشده |
grid_summary.chunk_size_sqm |
اندازه cell |
grid_summary.existing_count |
تعداد cellهای موجود از قبل |
7.3) analysis_cells_selected
| فیلد | توضیح |
|---|---|
force_refresh |
آیا cache نادیده گرفته شده |
total_cell_count |
تعداد کل cellها |
existing_cell_count |
تعداد cellهایی که داده از قبل داشتهاند |
cell_count_to_process |
تعداد cellهایی که باید پردازش شوند |
7.4) fetching_remote_metrics
| فیلد | توضیح |
|---|---|
target_cells |
لیست cellهای هدف |
requested_cell_count |
تعداد cellهای هدف |
metric_progress.total_metrics |
تعداد metricهایی که pipeline انتظار دارد |
metric_progress.completed_metric_count |
تعداد metricهای کاملشده |
metric_progress.completed_metrics |
metricهای کاملشده واقعی |
metric_progress.failed_metrics |
metricهای fail شده |
metric_progress.states |
وضعیت هر metric از نگاه progress tracker |
7.5) remote_metrics_fetched
| فیلد | توضیح |
|---|---|
failed_metric_count |
تعداد metric fail شده |
service_metadata.backend |
backend مورد استفاده |
service_metadata.job_refs |
job id هر metric در openEO |
service_metadata.backend_url |
آدرس backend |
service_metadata.failed_metrics |
خطاهای metric-level |
service_metadata.collections_used |
collectionهای مصرفشده |
7.6) observations_persisted
| فیلد | توضیح |
|---|---|
created_count |
تعداد observation ساختهشده |
updated_count |
تعداد observation بهروزشده |
8) جدول معنی task
| فیلد | مقدار نمونه | توضیح |
|---|---|---|
current_stage |
observations_persisted |
stage فعلی/آخرین stage ثبتشده |
current_stage_details |
created_count=12, updated_count=0 |
جزئیات stage جاری |
timestamps |
object | timeline کامل stageها |
stages |
list | نسخه ترتیبی از stageها |
metric_progress |
object | وضعیت پیشرفت metricها |
failure_reason |
متن فارسی | خطای ثبتشده |
celery.state |
RETRY |
Celery task هنوز final نشده و در retry است |
celery.ready |
false |
نتیجه نهایی هنوز آماده نیست |
celery.successful |
false |
task هنوز success نشده |
celery.failed |
false |
task هنوز fail نهایی نشده |
celery.info |
متن خطا | پیام retry فعلی Celery |
9) دلیل دقیق خطا
دلیل مستقیم خطا از خود کد:
- در
location_data/data_driven_subdivision.pyاگر بعد از ساخت dataset، هیچ observation قابل استفاده برای clustering باقی نماند، این exception پرتاب میشود:هیچ observation قابل استفادهای برای خوشهبندی باقی نماند.
این یعنی pipeline به این نقطه رسیده:
- cellها ساخته شدهاند
- metricها از openEO درخواست شدهاند
- observationها در DB ذخیره شدهاند
- اما در زمان ساخت dataset برای clustering، ردیف قابل مصرفی پیدا نشده است
معنی عملی این خطا
یعنی برای همه observationهای این run، سیستم نتوانسته feature vector قابل استفاده بسازد.
در کد فعلی، observation وقتی از clustering حذف میشود که:
- همه featureهای انتخابشده برای آن observation برابر
Noneباشند
پس این خطا معمولاً یعنی:
- یا تمام metricهای لازم برای همه cellها
nullشدهاند - یا feature set انتخابی با دادههایی که واقعاً ذخیره شدهاند mismatch دارد
- یا persistence / selection طوری انجام شده که clustering به داده قابل استفاده دسترسی پیدا نکرده است
10) محتملترین علتها برای همین run
علت 1: featureهای حذفشده هنوز در pipeline زنده هستند
در payload میبینیم:
selected_featuresهنوز شاملdem_mوslope_degاست- اما در
location_data/openeo_service.pyاین metricها از محاسبه حذف شدهاند
نتیجه:
- API و metadata هنوز فکر میکنند این دو feature بخشی از clustering هستند
- ولی openEO دیگر آنها را تولید نمیکند
- بنابراین در observationها این فیلدها عملاً
Noneمیمانند
نکته مهم:
- فقط
Noneبودنdem_mوslope_degبهتنهایی برای تولید این خطا کافی نیست - اما این mismatch یکی از مهمترین نشانههای ناسازگاری pipeline است
علت 2: metricهای اصلی احتمالاً برای همه cellها مقدار قابل استفاده نداشتهاند
چون این خطا فقط وقتی رخ میدهد که هیچ observation usable باقی نماند، محتمل است که برای همه 12 cell:
ndvindwilst_csoil_vv_db
هم عملاً None شده باشند یا آنطور که clustering انتظار دارد قابل مصرف نبوده باشند.
این حالت ممکن است از اینجا آمده باشد:
- داده خام provider برای این محدوده/بازه تهی یا نامعتبر بوده
- masking یا aggregation مقدار usable تولید نکرده
- یا در persistence، featureهای محاسبهشده بهدرستی به ستونهای clustering نرسیدهاند
علت 3: progress tracker با metricهای واقعی sync نیست
در payload:
completed_metricsشاملsoil_vvاست- ولی
statesشاملsoil_vv_dbبه حالتpendingاست
یعنی tracker با metric واقعی اجراشده sync نیست:
- metric واقعی remote:
soil_vv - metric مشتقشده محلی:
soil_vv_db
این باعث میشود progress ظاهراً ناقص دیده شود، حتی وقتی داده remote کامل شده است.
علت 4: وضعیت DB و Celery با هم متناقضاند
در payload:
data.status = failed- ولی
task.celery.state = RETRY
یعنی:
- از نظر DB، run شکست خورده ثبت شده
- از نظر Celery، task هنوز در حال retry است و failure نهایی نشده
این برای client گیجکننده است، چون معلوم نیست باید run را تمامشده و fail شده بداند یا منتظر retry بماند.
11) مشکلات فعلی location_data که از کد مشخص هستند
مشکل 1: DEFAULT_CLUSTER_FEATURES هنوز metricهای حذفشده را نگه داشته
فایل:
location_data/data_driven_subdivision.py
وضعیت فعلی:
dem_mslope_deg
هنوز داخل DEFAULT_CLUSTER_FEATURES هستند.
اثر:
selected_featuresاشتباه در run metadata- progress tracker اشتباه
- clustering contract قدیمی باقی میماند
مشکل 2: serializer و summary هنوز dem_m و slope_deg را به API برمیگردانند
فایلها:
location_data/serializers.pylocation_data/views.py
اثر:
- response API هنوز metricهای حذفشده را نمایش میدهد
- summary میانگین
dem_m_meanوslope_deg_meanمیسازد - مصرفکننده API فکر میکند این metricها هنوز پشتیبانی میشوند
مشکل 3: _upsert_grid_observations هنوز فیلدهای حذفشده را persist میکند
فایل:
location_data/tasks.py
اثر:
- ستونهای
dem_mوslope_degهمچنان نوشته میشوند، اما عملاً باNone - metadata هنوز
slope_supportedرا ذخیره میکند، در حالی که openEO service دیگر این مفهوم را برنمیگرداند
مشکل 4: progress metricها با metricهای واقعی اجراشده mismatch دارد
فایل:
location_data/tasks.py
نمونه mismatch:
- remote metric واقعی:
soil_vv - feature مورد انتظار برای clustering:
soil_vv_db
اثر:
completed_metricsوstatesبا هم ناسازگار میشوندsoil_vv_dbدر response به شکلpendingدیده میشود، با اینکه ازsoil_vvمشتق میشود
مشکل 5: stage و status همیشه هماهنگ نیستند
در payload فعلی:
run.status_label = failedrun.stage = observations_persisted
اثر:
- client نمیفهمد خطا دقیقاً در کدام stage رخ داده
task.current_stageهم گمراهکننده میشود
مشکل 6: DB failure و Celery retry همزمان به client داده میشود
اثر:
- API برای یک run همزمان پیام
failedوRETRYمیدهد - از نگاه UX، کاربر نمیداند باید retry خودکار را صبر کند یا خطا را final بداند
12) جمعبندی عملی برای همین خطا
بر اساس payload و کد، نتیجه عملی این است:
- openEO jobها برای
ndvi,ndwi,lst_c,soil_vvاجرا شدهاند - 12 observation در DB ساخته شدهاند
- pipeline وارد مرحله clustering شده
- clustering هیچ observation usable پیدا نکرده
- run در DB به حالت
failedرفته - اما Celery هنوز task را در حالت
RETRYنگه داشته
13) پیشنهادهای اصلاح
اصلاح ضروری
-
dem_mوslope_degرا از این نقاط هم حذف کنید:location_data/data_driven_subdivision.pylocation_data/serializers.pylocation_data/views.pylocation_data/tasks.py
-
DEFAULT_CLUSTER_FEATURESرا با metricهای واقعی sync کنید:ndvindwilst_csoil_vv_db
-
progress tracker را طوری اصلاح کنید که:
- completion
soil_vvبه completionsoil_vv_dbهم map شود - metricهای حذفشده اصلاً در state دیده نشوند
- completion
-
منطق status endpoint را طوری تنظیم کنید که:
- اگر Celery در
RETRYاست، status client نهاییfailedنباشد - یا حداقل یک فیلد صریح مثل
final_status=falseبرگردد
- اگر Celery در
-
قبل از clustering، یک diagnostic بهتر ذخیره شود:
- تعداد observationهای usable
- تعداد observationهای all-null
- تعداد null برای هر feature
اصلاح پیشنهادی برای debug بهتر
در stage_details این موارد اضافه شود:
usable_observation_countall_features_missing_cell_codesfeature_null_countsselected_features_effective
14) نتیجه نهایی
این run به احتمال زیاد به خاطر ناسازگاری بین featureهای مورد انتظار pipeline و featureهای واقعاً تولید/ذخیرهشده شکست خورده است، و علاوه بر آن چند inconsistency مهم در location_data وجود دارد:
- metricهای حذفشده هنوز در feature contract حضور دارند
- progress report با metricهای واقعی sync نیست
- DB status و Celery status با هم تناقض دارند
- stage نهایی برای failure به شکل واضح و قابل اتکا به client نمایش داده نمیشود
اگر بخواهید، مرحله بعدی میتواند این باشد که همین موارد را در کد هم اصلاح کنیم، نه فقط مستندسازی.