【问题标题】:Programmatically change database for heroku dataclips以编程方式更改 heroku 数据剪辑的数据库
【发布时间】:2021-02-21 21:56:47
【问题描述】:

我们刚刚使用follower changeover 方法升级了我们的Heroku postgres 数据库。我们有超过 50 个数据剪辑附加到旧数据库,现在我们需要将它们移动到新数据库。但是,一个一个地做会花费很多时间。

是否有一种编程方式来更新数据剪辑附加到的数据库,也许使用 CLI 工具?

【问题讨论】:

    标签: heroku heroku-postgres


    【解决方案1】:

    至少在取消配置旧数据库后,您现在可以(截至 2016 年 3 月)将它们重新附加到另一个数据库:

    转到https://dataclips.heroku.com/clips/recoverable。它将显示您的旧数据库和一组“孤立”数据剪辑,您可以选择将它们转移到另一个数据库(在我的情况下,是从转换中提升的追随者)。

    请注意,这只影响创建的数据剪辑,它影响您的团队成员之一创建并且您只能访问的数据剪辑。所以他们也必须经历这个过程。

    开发中心官方文章:https://devcenter.heroku.com/articles/dataclips#dataclip-recovery

    【讨论】:

    • 我应该补充一点,我只是这样做了,它并没有恢复我的 所有 数据剪辑。 ;) 我不确定这是什么原因,可能只是我的打嗝或错误。我正在与 Heroku 支持人员联系。
    • 更新:似乎恢复过程有效,但它是每个用户基于谁最初创建了一个数据剪辑,所以每个团队成员都必须经历这个过程并恢复他们的自己的数据剪辑。
    【解决方案2】:

    感谢 Heroku CSRF 措施,以编程方式更新数据剪辑比您想象的要困难得多。你需要接受它并开始手动点击按钮,或者请求他们的支持团队为你做这件事,这同样困难。


    官方不支持以编程方式移动数据剪辑。话虽如此,您可以针对他们的 HTTP API 编写脚本。

    基本 URL 是 https://dataclips.heroku.com/api/v1/。共有三个相关端点:

    • 剪辑/clips
    • 资源(数据库)/heroku_resources
    • 移动剪辑/clips/:slug/move

    找到你要移动的剪辑的slug,找到新数据库的资源id,并发布到移动剪辑端点:

    POST /api/v1/clips/fjhwieufysdufnjqqueyuiewsr/move
    Content-Type: application/json
    
    {"heroku_resource_id":"resource123456789@heroku.com"}
    

    【讨论】:

    • 在同一页面上没有 CSRF 问题!我想以你的知识和the batch hack I've found 有可能有一些高效的东西?
    【解决方案3】:

    我有 300 多个数据剪辑要移动。我使用以下技术来更新它们(本质上是对数据剪辑 API 进行逆向工程)。

    1. 使用 Web 开发者工具打开 Chrome,网络选项卡。
    2. 登录 Heroku Dataclips
    3. 观察以 JSON (https://dataclips.heroku.com/api/v1/clips) 格式返回所有数据剪辑的网络调用。获取此响应并提取所有 dataclip slug。
    4. 为一个数据剪辑更新数据库。观察执行此操作的网络调用 (https://dataclips.heroku.com/api/v1/clips/:slug/move)。右键单击,复制为 cURL。这是获取所有正确参数的最简单方法,因为 API 使用 cookie 进行身份验证。
    5. 编写一个循环遍历每个 dataclip slug 的脚本,然后执行 curl。在 Ruby 中,这看起来像:

      slugs = <paste ids here>.split("\n")
      slugs.each do |slug|
        command = %Q(curl -v 'https://dataclips.heroku.com/api/v1/clips/#{slug}/move' -H 'Cookie: ...' --data '{"heroku_resource_id":"resource1234567@heroku.com"}')
        puts command
        system(command)
      end
      

    【讨论】:

      【解决方案4】:

      您可以联系 Heroku 支持,他们会为您将数据剪辑批量传输到您的新数据库。

      【讨论】:

        【解决方案5】:

        批量处理数据剪辑

        我终于找到了一个解决方案,可以使用 javascript 控制台和一些抓取技术批量处理我的 Dataclips。我需要它来检索每个数据剪辑。但它猜测它可以这样更新:

        // Go to the dataclip listing (https://data.heroku.com/dataclips).
        // Then execute this script in your console.
        // Be careful, this will focus a new window every 4 seconds, preventing
        // you from working 4 seconds times the number of dataclips you have.
        
        // Retrieve urls and titles
        let dataclips = Array.
            from(document.querySelectorAll('.rt-td:first-child a')).
            map(el => ({ url: el.href, title: el.innerText }))
        
        
        /**
         * Allows waiting for a given timeout before execution.
         * @param {number} seconds
         */
        const timeout = function(seconds) {
            return new Promise(resolve => {
                setTimeout(() => {
                    resolve()
                }, seconds);
            })
        }
        
        /**
         * Here are all the changes you want to apply to every single
         * dataclip.
         * @param {object} window
         */
        const applyChanges = function(window) {
        }
        
        // With a fast connection, 4 seconds is OK. Dial it down if you
        // have errors.
        const expectedLoadTime = 4000 // ms
        
        // This is the main loop, windows are opened one by one to ensure focus and a
        // correct loading time.
        for (const dataclip of dataclips) {
            // This opens another window from the script, having access to its DOM.
            // See https://github.com/buonomo/kazoo for a funnier example usage!
            // And don't be shy to star and share :D
            const externWindow = window.open(dataclip.url)
            // A hack to wait for loading, this could be improved for sure.
            await timeout(expectedLoadTime)
            
          applyChanges(externWindow)
          
            externWindow.close()
        }
        

        您仍然需要自己实现applyChanges,我承认这有点乏味,而且我没有时间知道(如果有,请分享!)。但至少它可以在一个函数中对所有数据剪辑完成。

        有关此脚本的示例用法,您可以查看the gist I made to scrape every dataclips and related errors

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-04-27
          • 1970-01-01
          • 1970-01-01
          • 2011-06-12
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多