Page MenuHomePhabricator

Rewrite wmf_content.mediawiki_content_*_v1 tables with a new column for origin_rev_id
Closed, ResolvedPublic

Description

Because of T388793: When doing ADD COLUMN to a struct under a map, Iceberg fails to SELECT it, we cannot reliably add a column to the revision_content_slots map column under existing wmf_content.mediawiki_content_*_v1 table.

To go around this, we will create a new table, copy all data while adding the new column, and then replace the original table.

Here is the plan so far:

Some notes from a meeting with @Antoine_Quhen:

We confirmed that an ALTER TABLE x RENAME TO y works for iceberg tables. This seems to be a Hive Metastore metadata transaction, and doesn't affect any underlying Iceberg content.

We figured we need to follow this plan:

  1. Antoine to continue testing a script that will copy data wiki by wiki, while adding the new origin_rev_id column. The script will copy revision_id on the new origin_rev_id column. This will be correct data for all wikis except commonswiki
  1. Xabriel to start modifying reconcile script to take into account origin_rev_id. We expect to do a future run in which commonswiki will have to reconcile all the wrong origin_rev_id, but all other wikis should be fine.
  1. Xabriel to also start modyfing ingestion scripts to account for origin_rev_id. We will not merge this yet but want to have it ready.
  1. Once we are happy with testing from (1), we will launch the job to start writing to wmf_content.mediawiki_content_v2.
  1. After (4) is done, we will do spot checks and count checks on the data.
  1. If we are happy, then we rename mediawiki_content_v1 to mediawiki_content_v1_backup, and mediawiki_content_v2 to mediawiki_content_v1.
  1. Deploy changes from (2) and (3).
  1. Observer behavior.

Considering the plan above is specifically related to wmf_content.mediawiki_content_v1 and we are not changing Iceberg, I will open a separate ticket for this work.

Details

Other Assignee
xcollazo
Related Changes in GitLab:
TitleReferenceAuthorSource BranchDest Branch
main: bump mw-content artifact to pickup changes to ingest origin_rev_id. take 3.repos/data-engineering/airflow-dags!1740xcollazobump-to-pickup-cast-fixmain
CAST origin_rev_id to avoid schema issues.repos/data-engineering/mediawiki-content-pipelines!79xcollazofix-cast-issuemain
main: bump mw-content artifact to pickup changes to ingest origin_rev_id. take 2.repos/data-engineering/airflow-dags!1736xcollazobump-mw-content-take-2main
Honor origin_rev_id on reconcile event emit.repos/data-engineering/mediawiki-content-pipelines!78xcollazoreconcile-origin_rev_idmain
main: bump mw-content artifact to pickup changes to ingest origin_rev_id.repos/data-engineering/airflow-dags!1735xcollazobump-mw-contentmain
Add column origin_rev_id to support MCR.repos/data-engineering/mediawiki-content-pipelines!77xcollazoorigin_rev_idmain
Customize query in GitLab

Event Timeline

Linking here the strategy that worked for us before to recreate the table, namely doing INSERTs for all data except enwiki, wikidatawiki, commonswiki, and then doing INSERTs for those 3 separately:

Now running the following to backfill all wikis except the usual suspects:

hostname -f
an-launcher1002.eqiad.wmnet

screen -S mw-content-history-backfill

sudo -u analytics bash

kerberos-run-command analytics spark3-sql --driver-cores 8 --driver-memory 32G --master yarn --conf spark.dynamicAllocation.maxExecutors=128 --conf spark.executor.memoryOverhead=3G --conf spark.sql.shuffle.partitions=2048 --executor-memory 16G --executor-cores 2 --name xcollazo-mw-content-history-backfill


INSERT INTO wmf_content.mediawiki_content_history_v1
SELECT
  page_id,
  page_namespace AS page_namespace_id,
  page_title,
  page_redirect_title AS page_redirect_target,
  user_id,
  user_text,
  user_is_visible,
  revision_id,
  revision_parent_id,
  revision_timestamp AS revision_dt,
  revision_is_minor_edit,
  revision_comment,
  revision_comment_is_visible,
  revision_sha1,
  revision_size,
  revision_content_slots,
  revision_content_is_visible,
  wiki_db AS wiki_id,
  row_last_update AS row_content_update_dt,
  row_visibility_last_update AS row_visibility_update_dt,
  row_move_last_update AS row_move_update_dt
FROM
  wmf_dumps.wikitext_raw_rc2
WHERE
  wiki_db NOT IN ('enwiki', 'commonswiki', 'wikidatawiki')
ORDER BY wiki_db, page_id, revision_timestamp

Yarn app: https://yarn.wikimedia.org/proxy/application_1734703658237_837267/

Job failed. Reattempting with:

kerberos-run-command analytics spark3-sql --driver-cores 8 --driver-memory 32G --master yarn --conf spark.dynamicAllocation.maxExecutors=160 --conf spark.executor.memoryOverhead=3G --conf spark.sql.shuffle.partitions=10240 --executor-memory 16G --executor-cores 1 --name xcollazo-mw-content-history-backfill

Yarn app: https://yarn.wikimedia.org/proxy/application_1734703658237_839578/


Done:

Response code
Time taken: 18165.134 seconds

That's 5 hours.

Another wrench we discussed:

It would be quite involved to modify the reconcile algorithm to check teh equivalent of origin_rev_id in MariaDB.

But we do sqoop the wmf_raw.mediawiki_slots table in the datalake:

hive (wmf_raw)> describe mediawiki_slots;
OK
col_name	data_type	comment
slot_revision_id    	bigint              	Reference to revision.rev_id or archive.ar_rev_id. slot_revision_id and slot_role_id together comprise the primary key with wiki_db.
slot_role_id        	int                 	Reference to slot_roles.role_id
slot_content_id     	bigint              	Reference to content.content_id
slot_origin         	bigint              	The revision.rev_id of the revision that originated the slot's content. To find revisions that changed slots, look for slot_origin = slot_revision_id.
snapshot            	string              	Versioning information to keep multiple datasets (YYYY-MM for regular labs imports)
wiki_db             	string              	The wiki_db project 
	 	 
# Partition Information	 	 
# col_name            	data_type           	comment             
	 	 
snapshot            	string              	Versioning information to keep multiple datasets (YYYY-MM for regular labs imports)
wiki_db             	string              	The wiki_db project 
Time taken: 3.26 seconds, Fetched: 12 row(s)

In this table, slot_revision_id refers to revision_id, and slot_origin is origin_rev_id. Thus we could JOIN with it, and perhaps broadcast the table to make it performant. Further, only commonswiki would have data where revision_id != origin_rev_id, so we only need to apply the JOIN when ingesting commonswiki.

Today's daily ingestion is done, thus, we just paused all mediawiki_content DAGs.

We will attempt the migration in the next ~24 hours. Will announce it on #talk-to-data-engineering.

Did a couple test to see if we could backfill wmf_content.mediawiki_content_current_v1 from empty, but they failed spectacularly.

A simpler approach we used when we created the table is as follows:

Backfilled the table via:

hostname -f
an-launcher1002.eqiad.wmnet

sudo -u analytics bash

kerberos-run-command analytics spark3-sql \
 --driver-cores 4 \
 --master yarn \
 --conf spark.driver.maxResultSize=8G \
 --conf spark.dynamicAllocation.maxExecutors=64 \
 --conf spark.sql.shuffle.partitions=10240 \
 --conf spark.sql.iceberg.locality.enabled=true \
 --executor-cores 2 \
 --executor-memory 32G \
 --driver-memory 16G \
 --name xcollazo_backfill_mw_content_merge_changes_to_mw_content_current_daily


INSERT INTO wmf_content.mediawiki_content_current_v1
SELECT *
FROM xcollazo.mediawiki_content_current_v2
ORDER BY wiki_id;

Took 11.3h (Spark History), most of the time just swapping out to disk when doing the sort on 3 tasks, likely commonswiki, wikidatawiki and enwiki. This of course could be optimized by INSERTing those 3 wikis separately, but I ran this overnight, there was no incentive to do anything fancier.

I will modify this to our use case and run it overnight.

Now running the following:

hostname -f
an-launcher1002.eqiad.wmnet

sudo -u analytics bash

screen -S xcollazo_cp_mediawiki_content_current_v2

kerberos-run-command analytics spark3-sql \
 --driver-cores 4 \
 --master yarn \
 --conf spark.driver.maxResultSize=8G \
 --conf spark.dynamicAllocation.maxExecutors=48 \
 --conf spark.sql.shuffle.partitions=1024 \
 --conf spark.sql.iceberg.locality.enabled=false \
 --executor-cores 2 \
 --executor-memory 32G \
 --driver-memory 16G \
 --name xcollazo_cp_mediawiki_content_current_v2


CREATE TABLE wmf_content.mediawiki_content_current_v2 (
    page_id                     BIGINT    COMMENT 'The (database) page ID of the page.',
    page_namespace_id           INT       COMMENT 'The id of the namespace this page belongs to.',
    page_title                  STRING    COMMENT 'The normalized title of the page. If page_namespace_id = 0, then this is the non namespaced title. If page_namespace_id != 0, then the title is prepended with the localized namespace. Examples for "enwiki": "Main_Page" and "Talk:Main_Page".',
    page_redirect_target        STRING    COMMENT 'title of the redirected-to page, if any. Same rules as page_title.',
    user_id                     BIGINT    COMMENT 'id of the user that made the revision; null if anonymous, zero if old system user, and -1 when deleted or malformed XML was imported',
    user_text                   STRING    COMMENT 'text of the user that made the revision (either username or IP)',
    user_is_visible             BOOLEAN   COMMENT 'Whether the user that made the revision is visible. If this is false, then the user should be redacted when shown publicly. See RevisionRecord->DELETED_USER.',
    revision_id                 BIGINT    COMMENT 'The (database) revision ID.',
    revision_parent_id          BIGINT    COMMENT 'The (database) revision ID. of the parent revision',
    revision_dt                 TIMESTAMP COMMENT 'The (database) time this revision was created. This is rev_timestamp in the MediaWiki database.',
    revision_is_minor_edit      BOOLEAN   COMMENT 'True if the editor marked this revision as a minor edit.',
    revision_comment            STRING    COMMENT 'The comment left by the user when this revision was made.',
    revision_comment_is_visible BOOLEAN   COMMENT 'Whether the comment of the revision is visible. If this is false, then the comment should be redacted when shown publicly. See RevisionRecord->DELETED_COMMENT.',
    revision_sha1               STRING    COMMENT 'Nested SHA1 hash of hashes of all content slots. See https://www.mediawiki.org/wiki/Manual:Revision_table#rev_sha1',
    revision_size               BIGINT    COMMENT 'the sum of the content_size of all content slots',
    revision_content_slots      MAP<
                                    STRING,
                                    STRUCT<content_body:   STRING,
                                           content_format: STRING,
                                           content_model:  STRING,
                                           content_sha1:   STRING,
                                           content_size:   BIGINT,
                                           origin_rev_id:  BIGINT
                                    >
                                >         COMMENT 'a MAP containing all the content slots associated to this revision. Typically just the "main" slot, but also "mediainfo" for commonswiki.',
    revision_content_is_visible BOOLEAN   COMMENT 'Whether revision_content_slots is visible. If this is false, then any content should be redacted when shown publicly. See RevisionRecord->DELETED_TEXT.',
    wiki_id                     STRING    COMMENT 'The wiki ID, which is usually the same as the MediaWiki database name. E.g. enwiki, metawiki, etc.',
    row_update_dt               TIMESTAMP COMMENT 'Control column to efficiently update this table from source at wmf_content.mediawiki_content_history_v1.'
)
USING ICEBERG
PARTITIONED BY (wiki_id)                             -- wiki_id partitioning is familiar to users
TBLPROPERTIES (
    'format-version' = '2',                                -- allow merge-on-read
    'write.merge.mode' = 'merge-on-read',                  -- enable merge-on-read when doing MERGE INTO
    'write.update.mode' = 'merge-on-read',                 -- enable merge-on-read when doing UPDATE
    'write.delete.mode' = 'merge-on-read',                 -- enable merge-on-read when doing DELETE
    'write.format.default' = 'parquet',                    -- parquet is currently the only format with min/max stats
    'write.target-file-size-bytes' = '134217728',          -- cap files at 128MB files so executors with 1 core, 16GB RAM can read the entire table
    'write.metadata.delete-after-commit.enabled' = 'true'  -- don't hoard old metadata files. T393012#10781930.
)
COMMENT 'Contains the latest revision for all pages for all wikis. Updated on a daily basis.'
LOCATION 'hdfs://analytics-hadoop/wmf/data/wmf_content/mediawiki_content_current_v1_1'




INSERT INTO wmf_content.mediawiki_content_current_v2
SELECT
    page_id,
    page_namespace_id,
    page_title,
    page_redirect_target,
    user_id,
    user_text,
    user_is_visible,
    revision_id,
    revision_parent_id,
    revision_dt,
    revision_is_minor_edit,
    revision_comment,
    revision_comment_is_visible,
    revision_sha1,
    revision_size,
    transform_values(revision_content_slots,
             (k, v) -> (
                v.content_body,
                v.content_format,
                v.content_model,
                v.content_sha1,
                v.content_size,
                revision_id as origin_rev_id
             )
    ) as revision_content_slots,
    revision_content_is_visible,
    wiki_id,
    row_update_dt
FROM wmf_content.mediawiki_content_current_v1
ORDER BY wiki_id;

Similarly as in T391282#10764842, I expect it to take 11-12 hours to finish.

From slack:

Antoine Quhen:
First try failed: application_1758550516505_495012
Second try: application_1758550516505_497903

Antoine Quhen
  Job complete at 2nd try.
25/10/09 01:12:36 INFO MediawikiContentHistoryMigration: === MIGRATION VERIFICATION ===
25/10/09 01:12:36 INFO MediawikiContentHistoryMigration: Source table: 1017 wikis, 7429585869 total rows
25/10/09 01:12:36 INFO MediawikiContentHistoryMigration: Target table: 1017 wikis, 7429585869 total rows
25/10/09 01:12:36 INFO MediawikiContentHistoryMigration: ✓ All wiki row counts match between source and target tables
Now switching tables.

Antoine Quhen
  wmf_content.mediawiki_content_history_v1
now points to hdfs://analytics-hadoop/wmf/data/wmf_content/mediawiki_content_history_v1_1
and has the new field origin_rev_id

Antoine Quhen
  Same with mediawiki_content_current_v1 .

Antoine Quhen
  Old tables are still here: mediawiki_content_history_v1_old and mediawiki_content_current_v1_old

Antoine Quhen
  With data in: /wmf/data/wmf_content/mediawiki_content_history_v1 and /wmf/data/wmf_content/mediawiki_content_current_v1

Antoine Quhen
  Basic request on the new tables performed :white_check_mark:

Antoine Quhen
  Dags tagged mw_content resumed. (ex: mw_content_xml_export_current_mid_month @xcollazo not sure it was activated)

Antoine Quhen
  Pausing them all again. mediawiki-content-dump repo needs a new release + airflow-dags needs to point to it.

With both tables now migrated, will start merging pipeline changes.

xcollazo renamed this task from Rewrite wmf_content.mediawiki_content_v1 with a new column for origin_rev_id to Rewrite wmf_content.mediawiki_content_*_v1 tables with a new column for origin_rev_id.Oct 9 2025, 1:12 PM
xcollazo changed the task status from Open to In Progress.
xcollazo triaged this task as High priority.
xcollazo updated the task description. (Show Details)

New wmf_content.mediawiki_content_current_v1 looks good compared to old:

spark.sql("""
SELECT count(1) as count,
       wiki_id
FROM wmf_content.mediawiki_content_current_v1
GROUP BY wiki_id
ORDER BY count DESC
  """).show()

+---------+------------+
|    count|     wiki_id|
+---------+------------+
|166168117| commonswiki|
|124617943|wikidatawiki|
| 64373818|      enwiki|
| 19529122|      viwiki|
| 13989995|  ruwikinews|
| 13695549|      frwiki|
| 12831912|    metawiki|
| 11232295|     cebwiki|
| 10432572|enwiktionary|
|  8949355|      arwiki|
|  8523058|      eswiki|
|  8435288|      ruwiki|
|  8415394|      itwiki|
|  8411916|      dewiki|
|  8207016|      zhwiki|
|  7583869|frwiktionary|
|  6342310|      svwiki|
|  5995765|      ptwiki|
|  5983749|      fawiki|
|  5831919|mgwiktionary|
+---------+------------+
only showing top 20 rows


spark.sql("""
SELECT count(1) as count,
       wiki_id
FROM wmf_content.mediawiki_content_current_v1_old
GROUP BY wiki_id
ORDER BY count DESC
  """).show()
[Stage 33:=================================================>(11405 + 2) / 11407]
+---------+------------+
|    count|     wiki_id|
+---------+------------+
|166168117| commonswiki|
|124617943|wikidatawiki|
| 64373818|      enwiki|
| 19529122|      viwiki|
| 13989995|  ruwikinews|
| 13695549|      frwiki|
| 12831912|    metawiki|
| 11232295|     cebwiki|
| 10432572|enwiktionary|
|  8949355|      arwiki|
|  8523058|      eswiki|
|  8435288|      ruwiki|
|  8415394|      itwiki|
|  8411916|      dewiki|
|  8207016|      zhwiki|
|  7583869|frwiktionary|
|  6342310|      svwiki|
|  5995765|      ptwiki|
|  5983749|      fawiki|
|  5831919|mgwiktionary|
+---------+------------+
only showing top 20 rows

xcollazo merged https://gitlab.wikimedia.org/repos/data-engineering/airflow-dags/-/merge_requests/1735

main: bump mw-content artifact to pickup changes to ingest origin_rev_id.

Resumed mw_content_merge_changes_to_mw_content_current_daily and mw_content_merge_events_to_mw_content_history_daily.

We have identified an issue on reconcile, so will wait on a fix before we resume the other DAGs.

xcollazo merged https://gitlab.wikimedia.org/repos/data-engineering/airflow-dags/-/merge_requests/1736

main: bump mw-content artifact to pickup changes to ingest origin_rev_id. take 2.

Resumed mw_content_merge_changes_to_mw_content_current_daily and mw_content_merge_events_to_mw_content_history_daily.

We have identified an issue on reconcile, so will wait on a fix before we resume the other DAGs.

Fix deployed for reconcile, resumed mw_content_reconcile_mw_content_history_daily and mw_content_reconcile_mw_content_history_monthly.

Coming back to T405944#11242574, we now need to fix the data in commonswiki so that origin_rev_id is accurate.

We will have to run a couple variations of a MERGE like so:

MERGE INTO wmf_content.mediawiki_content_history_v1 t
USING (
    SELECT slot_revision_id, slot_role_id, slot_origin
    FROM wmf_raw.mediawiki_slots
    WHERE snapshot = '2025-09'
      AND wiki_db = 'commonswiki'
      AND slot_revision_id != slot_origin
      AND slot_role_id = 1 -- 1 == main
) s

ON  t.wiki_id = 'commonswiki'
AND t.revision_id = s.slot_revision_id
AND t.revision_content_slots['main'].origin_rev_id != s.slot_origin

WHEN MATCHED THEN
  UPDATE SET
    t.revision_content_slots =
      transform_values(
        revision_content_slots,
        (k, v) -> CASE
                    WHEN k = 'main'
                    THEN (
                          v.content_body,
                          v.content_format,
                          v.content_model,
                          v.content_sha1,
                          v.content_size,
                          s.slot_origin AS origin_rev_id
                    )
                    ELSE v
                  END
      )

One run will take care of mediawiki_content_history_v1 main slot, another for mediainfo. Then the same variations for mediawiki_content_current_v1.

The reason we update twice, once per slot role, is to keep the complexity of the MERGE statement low.
I also thought of updating row_content_update_dt so that mediawiki_content_current_v1 would pick up the changes automatically, but that would affect future event ingests, so decided against it.

hostname -f
an-launcher1002.eqiad.wmnet

sudo -u analytics bash

screen -S xcollazo_fix_origin_rev_id_for_commonswiki

kerberos-run-command analytics spark3-sql \
 --driver-cores 4 \
 --master yarn \
 --conf spark.driver.maxResultSize=8G \
 --conf spark.dynamicAllocation.maxExecutors=48 \
 --conf spark.sql.shuffle.partitions=1024 \
 --conf spark.sql.iceberg.locality.enabled=false \
 --executor-cores 2 \
 --executor-memory 32G \
 --driver-memory 16G \
 --name xcollazo_fix_origin_rev_id_for_commonswiki
 
 spark-sql (default)>  MERGE INTO wmf_content.mediawiki_content_history_v1 t
                    >  USING (
                    >      SELECT slot_revision_id, slot_role_id, slot_origin
                    >      FROM wmf_raw.mediawiki_slots
                    >      WHERE snapshot = '2025-09'
                    >        AND wiki_db = 'commonswiki'
                    >        AND slot_revision_id != slot_origin
                    >        AND slot_role_id = 1 -- 1 == main
                    >  ) s
                    > 
                    >  ON  t.wiki_id = 'commonswiki'
                    >  AND t.revision_id = s.slot_revision_id
                    >  AND t.revision_content_slots['main'].origin_rev_id != s.slot_origin
                    > 
                    >  WHEN MATCHED THEN
                    >    UPDATE SET
                    >      t.revision_content_slots =
                    >        transform_values(
                    >          revision_content_slots,
                    >          (k, v) -> CASE
                    >                      WHEN k = 'main'
                    >                      THEN (
                    >                            v.content_body,
                    >                            v.content_format,
                    >                            v.content_model,
                    >                            v.content_sha1,
                    >                            v.content_size,
                    >                            s.slot_origin AS origin_rev_id
                    >                      )
                    >                      ELSE v
                    >                    END
                    >        );
 Response code
 Time taken: 2094.345 seconds
spark-sql (default)>  MERGE INTO wmf_content.mediawiki_content_history_v1 t
                   >  USING (
                   >      SELECT slot_revision_id, slot_role_id, slot_origin
                   >      FROM wmf_raw.mediawiki_slots
                   >      WHERE snapshot = '2025-09'
                   >        AND wiki_db = 'commonswiki'
                   >        AND slot_revision_id != slot_origin
                   >        AND slot_role_id = 2 -- 2 == mediainfo
                   >  ) s
                   > 
                   >  ON  t.wiki_id = 'commonswiki'
                   >  AND t.revision_id = s.slot_revision_id
                   >  AND t.revision_content_slots['mediainfo'].origin_rev_id != s.slot_origin
                   > 
                   >  WHEN MATCHED THEN
                   >    UPDATE SET
                   >      t.revision_content_slots =
                   >        transform_values(
                   >          revision_content_slots,
                   >          (k, v) -> CASE
                   >                      WHEN k = 'mediainfo'
                   >                      THEN (
                   >                            v.content_body,
                   >                            v.content_format,
                   >                            v.content_model,
                   >                            v.content_sha1,
                   >                            v.content_size,
                   >                            s.slot_origin AS origin_rev_id
                   >                      )
                   >                      ELSE v
                   >                    END
                   >        );
Response code
Time taken: 2470.445 seconds

Unfortunately, the MERGE commands failed on wmf_content.mediawiki_content_current_v1, as that table is set to do merge-on-read, and the spark version that we can run from a command prompt in an-launcher1002.eqiad.wmnet is Spark 3.1.2 with Iceberg 1.2.1, which doesn't support merge-on-read.

Another reason to pursue T338057: Upgrade to Spark 3.5.

Let's see what we can do to go around this...

From MR 79:

We started seeing sporadic schema validation errors after merging !78:

error: instance type (number) does not match any allowed primitive type (allowed: ["integer"])
    level: "error"
    schema: {"loadingURI":"#","pointer":"/properties/revision/properties/content_slots/additionalProperties/properties/origin_rev_id"}
    instance: {"pointer":"/revision/content_slots/main/origin_rev_id"}
    domain: "validation"
    keyword: "type"
    found: "number"
    expected: ["integer"]

Turns out we forgot to CAST origin_rev_id to a MariaDB SIGNED, to avoid a recurrence of T379703.

xcollazo opened https://gitlab.wikimedia.org/repos/data-engineering/airflow-dags/-/merge_requests/1740

main: bump mw-content artifact to pickup changes to ingest origin_rev_id. take 3.

I am reopening this task as we still have a couple more things to do:

We still need to merge and confirm this fix:

From MR 79:

We started seeing sporadic schema validation errors after merging !78:

error: instance type (number) does not match any allowed primitive type (allowed: ["integer"])
    level: "error"
    schema: {"loadingURI":"#","pointer":"/properties/revision/properties/content_slots/additionalProperties/properties/origin_rev_id"}
    instance: {"pointer":"/revision/content_slots/main/origin_rev_id"}
    domain: "validation"
    keyword: "type"
    found: "number"
    expected: ["integer"]

Turns out we forgot to CAST origin_rev_id to a MariaDB SIGNED, to avoid a recurrence of T379703.

We also need to pickup the right origin_rev_ids for commonswiki on wmf_content.mediawiki_content_current_v1:

Unfortunately, the MERGE commands failed on wmf_content.mediawiki_content_current_v1, as that table is set to do merge-on-read, and the spark version that we can run from a command prompt in an-launcher1002.eqiad.wmnet is Spark 3.1.2 with Iceberg 1.2.1, which doesn't support merge-on-read.

Another reason to pursue T338057: Upgrade to Spark 3.5.

Let's see what we can do to go around this...

@Antoine_Quhen, perhaps we can use your P83757 to run the following:

MERGE INTO wmf_content.mediawiki_content_current_v1 t
USING (
    SELECT slot_revision_id, slot_role_id, slot_origin
    FROM wmf_raw.mediawiki_slots
    WHERE snapshot = '2025-09'
      AND wiki_db = 'commonswiki'
      AND slot_revision_id != slot_origin
      AND slot_role_id = 1 -- 1 == main
) s

ON  t.wiki_id = 'commonswiki'
AND t.revision_id = s.slot_revision_id
AND t.revision_content_slots['main'].origin_rev_id != s.slot_origin

WHEN MATCHED THEN
  UPDATE SET
    t.revision_content_slots =
      transform_values(
        revision_content_slots,
        (k, v) -> CASE
                    WHEN k = 'main'
                    THEN (
                          v.content_body,
                          v.content_format,
                          v.content_model,
                          v.content_sha1,
                          v.content_size,
                          s.slot_origin AS origin_rev_id
                    )
                    ELSE v
                  END
      )

and

MERGE INTO wmf_content.mediawiki_content_current_v1 t
USING (
    SELECT slot_revision_id, slot_role_id, slot_origin
    FROM wmf_raw.mediawiki_slots
    WHERE snapshot = '2025-09'
      AND wiki_db = 'commonswiki'
      AND slot_revision_id != slot_origin
      AND slot_role_id = 2 -- 2 == mediainfo
) s

ON  t.wiki_id = 'commonswiki'
AND t.revision_id = s.slot_revision_id
AND t.revision_content_slots['mediainfo'].origin_rev_id != s.slot_origin

WHEN MATCHED THEN
  UPDATE SET
    t.revision_content_slots =
      transform_values(
        revision_content_slots,
        (k, v) -> CASE
                    WHEN k = 'mediainfo'
                    THEN (
                          v.content_body,
                          v.content_format,
                          v.content_model,
                          v.content_sha1,
                          v.content_size,
                          s.slot_origin AS origin_rev_id
                    )
                    ELSE v
                  END
      )

Done. That took ~3.5h and ~1h respectively.

select count(1)
from wmf_content.mediawiki_content_current_v1
WHERE wiki_id = 'commonswiki' ;
-- 166 490 143

select count(1)
from wmf_content.mediawiki_content_current_v1
WHERE wiki_id = 'commonswiki'
    and revision_content_slots['main'].origin_rev_id <> revision_id;
-- 89 990 930

select count(1)
from wmf_content.mediawiki_content_current_v1
WHERE wiki_id = 'commonswiki'
  and revision_content_slots['mediainfo'].origin_rev_id <> revision_id;
-- 28 808 901

xcollazo merged https://gitlab.wikimedia.org/repos/data-engineering/airflow-dags/-/merge_requests/1740

main: bump mw-content artifact to pickup changes to ingest origin_rev_id. take 3.

From MR 79:

We started seeing sporadic schema validation errors after merging !78:

error: instance type (number) does not match any allowed primitive type (allowed: ["integer"])
    level: "error"
    schema: {"loadingURI":"#","pointer":"/properties/revision/properties/content_slots/additionalProperties/properties/origin_rev_id"}
    instance: {"pointer":"/revision/content_slots/main/origin_rev_id"}
    domain: "validation"
    keyword: "type"
    found: "number"
    expected: ["integer"]

Turns out we forgot to CAST origin_rev_id to a MariaDB SIGNED, to avoid a recurrence of T379703.

I deployed this fix to prod yesterday, and the bug is now gone.

We need to do just one more thing:

The MERGE INTO fix from T405944#11261866 fixes all data till 2025-09-01, since it uses tables that were sqooped as of that date. The new streaming data from page_content_change has the origin_rev_id data as of when we deployed it, thus as per T405944#11261572, that was on 2025-10-9.

This means we have a gap between 2025-09-01 and 2025-10-9 in which data for commonswiki's origin_rev_id is incorrect still. Thus, we have to wait till the new sqooped table of 2025-11-01 comes out, and apply the fix from T405944#11261866 again. Let's track that on a separate task.