Enable the Hardware Acceleration of Chrome Browser on AWS Batch
In todayâs rapidly evolving tech landscape, optimizing performance is a critical factor, especially when dealing with large-scale processing on cloud platforms. Many of you might find yourselves needing to automate Chrome on a server for various reasons. Additionally, you might want to navigate OpenGL-intensive websites using GPU acceleration. I was one of those people. However, if your tech stack isnât perfectly aligned, this can be a daunting task.
In my quest to solve this issue, I scoured various QA sites, but I noticed that many users facing similar problems never received a conclusive answer. Therefore, Iâve written this article to address the gap and provide a comprehensive guide to enable hardware acceleration for Chrome on AWS Batch.
Steps to Enable Hardware Acceleration
Create a Docker Image with Chrome and Nvidia Support
First, youâll need a Docker image that includes Google Chrome and the necessary Nvidia drivers. Here is a basic Dockerfile to get you started:
FROM --platform=linux/amd64 nvidia/cuda:12.5.0-devel-ubuntu22.04 WORKDIR /app ENV DEBIAN_FRONTEND=noninteractive ENV TZ=Asia/Tokyo # For timezone RUN apt-get update && \ apt-get install -y software-properties-common tzdata && \ ln -fs /usr/share/zoneinfo/Asia/Tokyo /etc/localtime && \ dpkg-reconfigure --frontend noninteractive tzdata && \ apt-get clean # ldd chrome | grep found # libnss3.so => not found # libnssutil3.so => not found # libsmime3.so => not found # libnspr4.so => not found # libatk-1.0.so.0 => not found # libatk-bridge-2.0.so.0 => not found # libcups.so.2 => not found # libdrm.so.2 => not found # libxcb.so.1 => not found # libxkbcommon.so.0 => not found # libatspi.so.0 => not found # libX11.so.6 => not found # libXcomposite.so.1 => not found # libXdamage.so.1 => not found # libXext.so.6 => not found # libXfixes.so.3 => not found # libXrandr.so.2 => not found # libgbm.so.1 => not found # libpango-1.0.so.0 => not found # libcairo.so.2 => not found # libasound.so.2 => not found RUN apt-get update && apt-get install -y \ libnss3 \ libnss3-tools \ libnspr4 \ libatk1.0-0 \ libatk-bridge2.0-0 \ libcups2 \ libdrm2 \ libxcb1 \ libxkbcommon0 \ libatspi2.0-0 \ libx11-6 \ libxcomposite1 \ libxdamage1 \ libxext6 \ libxfixes3 \ libxrandr2 \ libgbm1 \ libpango-1.0-0 \ libcairo2 \ libasound2 && \ apt-get clean # [ERROR:egl_util.cc(44)] : Failed to load GLES library: libGLESv2.so.2: libGLESv2.so.2: cannot open shared object file: No such file or directory # [ERROR:egl_util.cc(52)] : Failed to load EGL library: libEGL.so.1: libEGL.so.1: cannot open shared object file: No such file or directory RUN apt-get update && apt-get install -y libgles2-mesa libegl1-mesa && apt-get clean # [ERROR:gl_display.cc(520)] : EGL Driver message (Critical) eglInitialize: xcb_connect failed RUN apt-get update && apt-get install -y xvfb && apt-get clean # xvfb-run --server-args="-screen 0 1920x1080x24 +extension GLX +render -noreset" \ # chrome \ # --enable-logging --v=1 # --headless \ # --ignore-gpu-blocklist \ # --enable-gpu-rasterization \ # --enable-zero-copy \ # --use-angle=default \ # --no-sandbox RUN apt-get update && apt-get install -y \ libva2 \ libva-x11-2 \ libva-drm2 && \ apt-get clean
To get started, youâll need a Docker image that includes the necessary Nvidia drivers. This Dockerfile will ensure Chrome runs smoothly. In my setup, I used Pythonâs Pyppeteer, which downloads Chrome, so thereâs no need to install Chrome via apt-get. Of course, Puppeteer also works, and if you prefer, you can directly install Chrome using apt-get.
Pay close attention to the comments within the Dockerfile. The comments explain the commands executed, the errors encountered, and the libraries installed to address those errors. As of July 2024, this Dockerfile is functional. However, if you encounter any errors in the future, refer to these comments to guide your troubleshooting and adjustments.
Prepare Your Project
In this step, we will show an example using Pyppeteer in Python. If you prefer using Puppeteer, feel free to substitute Python with Node.js as appropriate.
There are a few key points to keep in mind, but one of the most important is to run your Python or Node.js through xvfb-run
. This is crucial not only to allow Chrome to operate in a headless mode but also to enable GPU usage.
Here is an overview of what you need to do:
1. Prepare a shell script for running Python or Node.js on X
xvfb-run --server-args="-screen 0 1920x1080x24 +extension GLX +render -noreset" \ python3.12 /app/run.py "$@"
2. Run Chrome in a Python Script
import asyncio import logging from typing import TypeAlias from pyppeteer.launcher import launch _BrowserLaunchOptions: TypeAlias = dict[str, list[str] | bool] def _get_launch_options() -> _BrowserLaunchOptions: args = [ "--lang=ja-JP", "--no-sandbox", "--ignore-gpu-blocklist", "--enable-gpu-rasterization", "--enable-zero-copy", "--disable-gpu-process-crash-limit", "--use-angle=default", ] if logger.level == logging.DEBUG: args.extend(["--enable-logging", "--v=1"]) launch_options: _BrowserLaunchOptions = {"args": args, "ignoreHTTPSErrors": True} if logger.level == logging.DEBUG: launch_options["dumpio"] = True logger.debug(f"launch_options={launch_options}") return launch_options async def main() -> None: launch_options = _get_launch_options() browser = await launch(**launch_options) # do something you need await browser.close() if __name__ == "__main__": asyncio.get_event_loop().run_until_complete(main())
This is a code snippet. In this code, we only create the browser object, but you will need to further automate Chrome operations as per your requirements. The key point here is the launch options. If you get these options wrong, Chrome will not start. Pay particular attention to the arguments passed to args. In DEBUG mode, configure Chrome to output more logs. This way, if any issues arise, you can usually resolve them. If you cannot read the logs yourself, you can always rely on ChatGPT for assistance.
If you want to quickly verify that everything is working correctly, you can navigate to chrome://gpu
, capture a screenshot of the page, and upload the screenshot file to S3. This will help you confirm that GPU acceleration is enabled.
page = await browser.newPage() await page.goto("chrome://gpu") await page.screenshot({"path": "./screenshot.png"})
As a side note, there is always a possibility of encountering errors in every operation, such as opening a tab, navigating to a URL, or retrieving content. Therefore, I write my code to restart from the point of opening a tab if any single operation fails. This process is repeated until it succeeds, but after five failures, it gives up. When automating Chrome, you need to write your code defensively to this extent.
3. Update the Dockerfile to adjust the Python Project
Please add the following content to the Dockerfile we prepared earlier. I will omit the details on how to create the requirements.txt.
# Install python3.12 RUN add-apt-repository ppa:deadsnakes/ppa -y && \ apt-get update && \ apt-get install -y python3.12 python3.12-distutils && \ apt-get install -y wget && \ apt-get clean # Install pip RUN wget https://bootstrap.pypa.io/get-pip.py && \ python3.12 ./get-pip.py COPY requirements.txt . RUN pip install --no-cache-dir -r requirements.txt COPY . .
Set Up an Environment on AWS Batch for GPU-Accelerated Chrome
In this final step, we will set up an environment on AWS Batch that can utilize GPU-accelerated Chrome. For this example, we will use the g4dn instance type, which is optimized for GPU workloads.
Here is a snippet of the AWS CDK code to set up the necessary infrastructure:
export class BatchChromeStack extends cdk.Stack { constructor(scope: Construct, id: string, stage: string, props?: cdk.StackProps) { super(scope, id, props); const vpc: ec2.IVpc = this.getVpc(); const subnets = this.getSubnets(vpc); const securityGroup = this.getSecurityGroup(vpc); const instanceRole = this.createInstanceRoleAndProfile(); const { repository, image_name } = this.createAndDeployDockerImage(); const jobRole = this.createJobRole(); this.addSSMPolicyToJobRole(jobRole, stage); const bucket = this.createS3Bucket(); this.addS3PutObjectPolicyToRole(jobRole, bucket); const container = this.createContainer(image_name, jobRole, bucket, stage); repository.grantPull(container.executionRole); this.createEcsJobDefinition(container); const computeEnvironment = this.createComputeEnvironment(vpc, [securityGroup], subnets, instanceRole); this.createJobQueue(computeEnvironment); } // Omit many codes private createContainer(image_name: string, jobRole: iam.Role, bucket: s3.Bucket, stage: string): batch.EcsEc2ContainerDefinition { const logLevel = stage === 'production' ? 'INFO' : 'DEBUG'; return new batch.EcsEc2ContainerDefinition(this, `${this.NAME_PREFIX}ContainerDefinition`, { image: ecs.ContainerImage.fromRegistry(image_name), // g4dn.xlarge gpu: 1, cpu: 4, memory: cdk.Size.gibibytes(15), // 16GB - 1GB for OS jobRole: jobRole, logging: new ecs.AwsLogDriver({ streamPrefix: this.KEBAB_NAME_PREFIX }), environment: { BUCKET_NAME: bucket.bucketName, LOG_LEVEL: logLevel, }, }); } }
I have omitted quite a lot of details in this step. I did not include what you can search online or ask ChatGPT to get answers, as those are readily accessible resources.
The biggest issue I faced was that when I specified the memory size of 16GB, which is available on the g4dn.xlarge instance, in the EcsEc2ContainerDefinition, the instance failed to launch. However, it did launch with 15GB. I believe this is a quirk of AWS Batch.
If you need the full version of the CDK code or if something is not working correctly, feel free to reach out. If I feel inclined, I might provide more detailed information.
èçã«ãªã£ãã®ã§ãé ã®ä¸ãæ¸ãåºãã¦ã¿ã
ãªãããã®è¨äºãæ¸ãã®ãï¼
ç´9å¹´ã¶ãã®æ稿ã§ãã9å¹´åãæ å ±å ¬éãé£ããä¼ç¤¾(ã¨ããFinTechä¼æ¥)ããæ å ±å ¬éã価å¤ã¨èªãã¦ãããä¼ç¤¾(gumi)ã¸è»¢è·ãããããæå±ä¼æ¥ã®ååã§è¨äºãæ¸ããããã¤ãã³ãã«ç»å£ããããã¦ãã¾ãããçµæããã®å人ããã°ã«æ¸ããã¿ããªããªãæ¾ç½®ãã¦ãã¾ãããããã¦äºå¹´åãWOVN ã¨ããä¼ç¤¾ã«è»¢è·ããDeveloper ãã Product Owner (CSM-SM æã£ã¦ãã®ã« Scrum Master ãããªãã®ãã¨ããããã³ãæè¿) ã«å½¹å²ãå¤ããããã«æ¸ããã¿ããªããªãã¾ããã
ã¨ãããã2022å¹´9æã«èçãçºè¦ãã大ããç§ã®æ»ç観ãå¤ãã£ããããå人ããã°ã«ã¾ã¨ãã¦ã¿ãããã¨æãã¾ããç§èªèº«ãç§ä»¥å¤ã®ãããµãã¤ãã¼ã®æ¹ã ã®æããæ¥è¨ã«å¿ãæããããããã®è¨äºããå°ãã§ããåãå¢éã®èª°ãã®å±ã¿ãå©ãã«ãªãã°å¹¸ãã«æãã¾ãã
ä¼ããããã¨ã®ã¾ã¨ã
ã»ã¨ãã©ã®æ¹ã«è¨ãããã¨
- 40éããããããæ¤è¨ºã絶対åãã¦ï¼
- æ¥æ¬ã®å¤§å¦ç é¢ã®æ¨æºæ²»çãä¿¡ãããï¼
- çã¨å ±ã«æ©ããï¼
- éåãç¡ç ãé£äºãç¬é¡ãã³ãã¥ãã±ã¼ã·ã§ã³åã¨çå£ã«åãåããï¼
人ã«ãã£ã¦éããã¨
- 人ã«ãããã©ãèã®çæ¤ããããªã«çããªãã
- 人ã«ãããã©ãå ¨èº«éº»é ãæããªãã£ãã
- 人ã«ãããã©ãèã®é¨ååé¤ã®è¡å¾ã¯ãçã¿æ¢ãä¸è¦ã ã£ãã
å¨ã«ãã¤ã£ããã¨
- èªåãæ»ã¬ãã¨ãçã«èªè¦ããã¾ã§ã人ã¯ä½æ³ã«ãªã£ã¦ãåä¾ãªã®ã ã( ï½°`дー´)
çµç·¯
2022å¹´6æ
ä½ã¨ãªã10å¹´åã«è«æ¯ãæ²»çæ¸ã¿ã®æ¯ããã¿ããããªæ°ãããã(奥ããäºçªç®ã®å¥¥æ¯)
ããããåãå´ã®è³ã®å¥¥ãçãããé çãããã
2022å¹´8æ
æ¯ã®çç¶ã¯æ²»ã£ã¦ããããè³ã®å¥¥ãçããããè³é¼»ç§ã¨æ¯å»è ããã®é¸æã«è¿·ããã¨ããããè«æ¯ã ã£ããå«ã ãªã¼ã¨æãæ¯å»è ããã¸ããããã該å½ã®é¨ä½ã«è«æ¯ã¯è¦ã¤ããããæ¯ç³æé¤ãæ¯ç£¨ãæå°ããã磨ãæå°ãåãããå¸°å® å¾ããã磨ãä¸ãèã®å´é¢ã« 2mm ãããã®ç½ãå£å çã®ãããªåºæ¥ç©ãè¦ã¤ããã(9æã«ç½æ¿çã¨åãã) ã¨ããããããã磨ãã§æ¦ã£ã¦ãçããªãããæ¾ç½®ããã
2022å¹´9æ
è³ã®å¥¥ã®çã¿ãé çãæ°ã«ãªããè³é¼»ç§ã¸è¡ãããã¨æã£ããã妻ã®å§ãã§èªå® ã®è¿æã®ãããã¤ãã®å ç§ã¸ãããã®å çã¯ãéå»ãä»ã®ç é¢ã§ãåãããªãã£ãç§ã®ç æ°(æ¢ã«å¿«çãã¦ã)ãè¦æãã¦æ²»çãã¦ãããå®ç¸¾ããããä½äººãã®ãå»è ãããè¦ã¦ããçè·å¸«ã®å¦»ããè¦ã¦ãåå»ã¨ã®ãã¨ã
ããã¦ããããã¤ãå»ã«è¨ºã¦ããã£ãã¨ãããããã¯èçã®å¯è½æ§ãããããã大å¦ç é¢ã¸ã®ç´¹ä»ç¶æ¸ããã¨ãªã£ããè«æ¯ãããã®æ°æã¡ã§ããã¨ããã«çæ»ã«é¢ãããçãã¨èãã¦ãã¾ããã·ã§ãã¯ãåããç§ã¯æ··ä¹±ããªãããã¨ãããããä»äºã®äºå®ãè¦ãªããä¸é±éå¾ã«å¤§å¦ç é¢ã®æ¤æ»ã®äºå®ãå ¥ãã¦ããã£ãã
å¾ã«å¦»ããèãã話ã«ããã¨ãå ççã«ã¯ãå ã¡ãã¿ããã®ä»¶ããã£ããããçãããã¯ãæ©ãã«æ¤æ»ããã¹ãã ã¨æã£ãã ãã§ãç確å®ã¨ã¯æã£ã¦ããªãã£ãããããã¨ã¯ãããã·ã§ãã¯ãåããç§ã¯ç¿æ¥ããå¤ã«å¯ããªããªããæ¼ã¯å¾®ç±ã¨æªå¯ã«æ©ã¾ãããè³çãé çãé ·ããªã£ããããã¦ã2æ¥å¾ãåã³å¦»ã«é£ãããã¦ããããã¤ãå»ã®ã¨ããã¸è¡ããæ¤æ»äºç´ãä¸é±éå¾ã§ã¯ãªããæ°æ¥å¾ã®äºå®ã«æ©ãã¦ããããç¡ç å°å ¥å¤ãå¦æ¹ãã¦ããã£ããã¾ãã念ã®ããè¡æ¶²æ¤æ»ããã¦ããã£ããçµè«ãæªå¯ãé çã¯å¿æ°çã ã£ãã(ããã¯å¾ã«èª¿ã¹ããã¨ã ããçã¯æ«æã¾ã§çã¿ããªã)
ãã®å¾ãæãæã大å¦ç é¢ã¸è¡ããç´°è診ã¨ãããã©ã·ã§ç å¤ãæ¦ã£ã¦èª¿ã¹ãæ¤æ»ãåãããçµæãåºãã¾ã§ç殺ãç¶æ ã§ãä¸ç ã¯ç¶ããããã®é ãæ»ã«åãã¦ä½ããã¹ããã¨èãã¦ããã
ã¡ãªã¿ã«æ å½å»ã®åè¦ã§ã¯ããã®å°ããã ã¨ãè³ãé ã®çã¿ã¯å ¨ãé¢ä¿ãªãã¨æãããã¨ã®ãã¨ãããã¯ããã¨ããæ°ãã¤ãããã¨ã ãã©ã人ã¯ä½ã§ãçãæ¨æºæ²»çã®å¯ä½ç¨ã®ããã«ãã¦ãã¾ãããããã«æ¬äººãæ°ãã¤ãã®ã¯æ¬å½ã«é£ãããç§ã¯çèªèº«ã¯çã¿ãä¼´ããªãã¨ç¥ã£ã¦ããè ¹è½ã¡ããã
2022å¹´10æ
大å¦ç é¢ã§ç´°è診ã®çµæãèããã主治å»ããçµæã¯3ã§ãããã¨ä¼ãã¦ãããããããã¹ãã¼ã¸3ãªã®ãã人çãçµãã£ããªã¼ã¨èããããã§ããâ¦ãã¨çããã主治å»ããããããã¯ã©ã¹3ã§å®å¿ããªãã§ãã ãããã¨æ³¨æã§è¿ãããããï¼ä½ã話ãåã¿åã£ã¦ãªããå®å¿ããããããªãã¦ãéå½ãåãå ¥ãããã ãï¼ããâ¦ï¼ãããã話ãèãã¨ãæ¤æ»çµæã¯äºæ®µéã®ã¯ã©ã¹ã§è¡¨ç¾ããããããã大éæã«è¨ãã¨ã¯ã©ã¹1-2ã¯è¯æ§ã3ã¯ä¸æã4-5æªæ§ãã ããããã£ã¨è©³ãã調ã¹ãããã«ã次ã¯çæ¤ãã¾ãããã¨ã®ãã¨ãæ£é¨ãé¨å麻é ãã¦åãåã£ã¦ç çæ¤æ»ãããã詳ããå¤æããã®ã ã¨ããã¾ããä¸èª¿ã®çç±ãä¸æãªæéãç¶ãã®ãã¨ä¸å®ã«ãªãã
ã¡ãã£ã¨èçã®çæ¤ã«ã¤ãã¦ãããã§æ¤ç´¢ããã¨ãçã¿ãå¼·ãã¨ããå¤å¯ããªãã¨ããä¸é±éã¯çãã¨ããæ£ã ãªæ å ±ããè¦ã¤ãããå¹ãã主治å»ããã¯ã人ã«ãã£ã¦ç°ãªããã大å¡ã大ããäºãªãã¨æãã人ãå¤ãã¨ä¼ããããã
ããã¦ã10ææ«ã«çæ¤ãåããã麻é ã®éã¯4æ¬åºãããããã¾ã¼ãæ¯å»è ã§æ £ãã¦ããããããã»ã©çãæããªãããã®å¾ã¯çã¿ãä½ãæããªãã£ããåã£ã¦ããæä¸ã¯é»åã¡ã¹ã§æ¢è¡ãã¦ããããããæå¾ã«åé縫ã£ã¦çæ¤çµäºãåºè¡ç¢ºèªå¾ã«è§£æ£ã妻ã®å§ãã§ãããã«è¬å±ã§ããã½ãã³ãããã£ã¦é£²ãã ãå½æ¥ã麻é ãåãã¦ããç¼ããããªçã¿ãæããããé£äºä»¥å¤ã§å¼·ãçã¿ãæãããã¨ã¯ãªããç¿æ¥ããçã¿æ¢ãã飲ãã®ã¯æ¢ãããé£äºä¸ãã¡ãã£ã¨æ°ãæãã¨ãä½ã£ã糸ãåãã§æ²é³´ãä¸ãã¦ããããä¸æ¥ç®ããã©ã¼ã¡ã³ãé£ã¹ããããããã«å復ãã¦ãããçæ¤ã®çµæãåºãã¾ã§ãæ大ã§äºé±éãããããããã¾ããããã¢ã¤ã¢ã¤æéãç¶ããã¨ã«å¹ããã¨ã¯ãããçæ¤ã®ãã¨ãè³ã¨é ã®çã¿ãæ¶ãããè¿æã®ãããã¤ãå»ã®è©±ã«ããã¨ãèã®ç¥çµã¯ãããããªã¨ããã«ç¹ãã£ã¦ãããããã¼ã¨ã®ãã¨ã
2022å¹´11æ
11/7 ã«çæ¤ã®çµæãT1M0N0 ã®ç(é«åº¦ç°å½¢æ)ã¨çµæãèããåç´æ¹åã¯çæ¤ã§åãåã£ããæ°´å¹³æ¹åã«ã¯æ®ã£ã¦ããã¨ã®ãã¨ãæ¾ç½®ããå ´åãåºããå¯è½æ§ããããã®ãµã¤ãºã ã¨ãæããå¤ãæ¾å°ç·ããã¡ãªããã大ãããããããã«æè¡ã§åé¤ãè¯ãã¨ã®ãã¨ãå®å ¨ãã¼ã¸ã³ãã¨ã£ã¦å¤§ããåé¤ããããå³è¦ãä¼è©±ãè¡å¾ã¨å¤ãããªãã¨èª¬æãåããåé¤ã§æ±ºå¿ãããæè¡ä¸ãè¿ éç ç診æãè¡ãããããçã®åãæ®ããããã°ã追å ã§åé¤ããã¨ãã話ããããã¨ã¦ãæ¯ãããã¾ããè¡ä¸ã«ç¥çµã触ããåæããã¨ãèå ã«çºããé·æéåºãã¨ã®ãã¨ãæããããä¸çªæ©ãæè¡ã®äºç´ã§ã 12/2 ã¨ã®ãã¨ã§ãä¸é±éå¾ ã¡ãé ãâ¦ã¨æãã¤ã¤ããã®æ¥ã§äºç´ããã®ãããå®ã¯ããã®ä¸é±éããå¾ããæ¯ãè¿ãã¨ãã¨ã¦ãè¯ãæºåæéã¨ãªã£ãã
ç§ã®ä»äºã¯äººã¨è©±ããã¨ã ãã趣å³ã¯æçãªã®ã§ãè¨èã¨å³è¦ã温åãããã ãããããããæããâ¦ã
ãã®çã®ãµã¤ãºã ã¨ãåºæ¬çã«ã¯å¤§ä¸å¤«ã ãã©ã念ã®ãããé骨ããä¸ã® CT ãæ®ãã¾ãããã¨ãªãããã¡ããç¿é±ã«äºç´ãCT èªä½ã¯ãé å½±å¤ãç¹æ»´ã§ãããå¿ è¦ããããããããã¡ãã£ã¨å¤ªãéãåºããããããªã«è² æ ã§ã¯ãªãã£ããæ®å½±ä¸ããã£ã¨çãã£ããã©ãâ¦ãããã¦ãçµæããªã³ãã¸ã®è»¢ç§»ãçãããå¾®å¦ãªçµæãåºã¦ãã¾ããæ¾å°ç·æ師ããããã¯æªããã¨è¨ã£ã¦ããã主治å»ã¯ããããªå°ããã®é¢ä¿ãªããã©â¦ãã¼ããçµé観å¯ãã¾ãããã¨ã®ãã¨ãããã転移ã ã¨ã¹ãã¼ã¸3ã«ãªããããªã³ãåé¤ã®è¿½å æè¡ã«ãªãã¨ã®ãã¨ãçããªã³ãã«è»¢ç§»ããã¨ã大éæã«è¨ãã¨å ç«åãè½ã¡ããããé常ã«ã¾ããâ¦ãããããé¡ãé¦ã®ãªã³ããåé¤ããã¨å¾éºçã®å æã大å¤ããããããã
2022å¹´11æ (æºåæé)
çã¨ç¢ºå®ããã®ã§ãçã¨ã¯ä½ãããã§çå£ã«èª¿ã¹ãããã®çµæãç§ã®æ»ç観ã大ããå¤åãããç§ã¯ãã¤ãä½ã調ã¹ãéãéå¹æ§ã®ããç°¡åãªè¡åã示ãã¦ãããã®ã¯ç¡è¦ããã(ç§ãä½ãæç« ããã¬ã¼ã³è³æã¯ããã®ç³»çµ±ãªã®ã«w) éè¦ãªã®ã¯ãã¤ã³ãã»ããã¨ã¨ããã³ã¹ã¬ãã«ãçµæã次ã®èãã«è³ãã
- çã¯å¯è§£ãããå®æ²»ã¯é£ãã
- çã¨å ±ã«çãã(æ¬æ¥ã®å¯¿å½ã«è¿ã¥ãã)
- çã¯æ«æã¾ã§çã¿ãä¼´ããªã(ã ããåæã§è¦ã¤ããã®ã¯é£ãã)
- çã¿ãä¼´ãã®ã¯çã®æ²»çè¡çº
- æ²»çè¡çºã«èãããã身ä½ã¨å¿ãä½ã
- çã¨èº«ä½ã®ä¸å¥åº·ã¯ç´çµãã¦ããªã (çã§ãå¥åº·ã¯ããå¾ã)
- å¿ã¾ã§ç ã«ããå¿ è¦ã¯ãªã
- æ¥æ¬ã®å¤§å¦ç é¢ã®çå»çã¯ä¸ççã«ã¿ã¦é«ãæ°´æº
- æ¨æºæ²»çã¯ããã
- æ¨æºæ²»çã®ãè£å©ãã¨ãã¦ãä»ã®å»çè¡çºã¯ãã (æ¨æºæ²»çã®å¯ä½ç¨ã軽æ¸ãããå¹æãå¾æ¼ããã)
- ä»ã®å»çè¡çºã¯è©æ¬ºãå¤ããã (è¦æãæ¹ã¯ãããâ¦çµ¶å¯¾ã§ã¯ãªãããæ¸ããªã)
- å ç«åã測ãæ¹æ³ã¯ãªã(ãã®ææ¡ã¯å¤ããã)
- ã¨ã¯ããã40æ³ããå ç«åã¯æ ¼æ®µã«è½ã¡ã
- æ å ±ãç¡ç ãéåãé£äºãç¬é¡ã人ã¨ã®ã³ãã¥ãã±ã¼ã·ã§ã³ããçå£ãã«å¤§åã«ãã
ã¡ãªã¿ã«èçã«ã¤ãã¦ã¯æ¬¡ã®éãã
- æã¯ãåºæ¿ç©(é ãã¿ãã³ãè¾ããã®)ã®æåã好ããªäººãã¡ã«å¤ãã£ã
- ä»ã¯ãé¡ã®çã人ãã¡ã«å¤ã(æ¯ãèã«å½ããç¶ãããã)
- 30代ãªãæ¯ãç¯æ£ãã
- 40代ãªãæ¯ãå°ãåã£ã¦ä¸¸ãããããã¦ã¹ãã¼ã¹ãä»ãã
ç§ã¯45æ³ãªã®ã§ã大å¦ç é¢ã®ä¸»æ²»å»ã®å çããã®ææ¡ã§ãã©ã¹ããã¯ã®ãã¦ã¹ãã¼ã¹ã«ãããããã¯è¡å¾ã®èãåé¤ããçã¿ã軽æ¸ãããã¨ã«è¡å¾ã«æ°ãã¤ãããç§ã¯ããã¨ãã¨æ¯ãé£ããã°ãçããããèãé ¬ãåã¿è·¡ã ããã ã£ãã®ã§ããããã¦ã¹ãã¼ã¹ããé¢ããããªããããä¾åãã¦ããã
ãããããã¨ãããããç´äºé±éåã»ã©ä½¿ã£ã¦èº«ä½ãæºåãããã¨ã«ãããã¨ãããããã®ãããã®æªè¶³æ»ãããåºæ¥ãªãã£ãã¨ãè¨ãããããã§è¡ã£ããã¨ã«æå³ããã£ãã®ãã¯ãå ¨ãåãããªãããå¿ã®å®å®ã«ã¯ç¹ãã£ãããä½èèªè¨ã®æ¸¬å®çµæãåçã«å¤ãã£ãã
- æ¯æèµ·ãããæ°´ã ã飲ãã§ã10åéã®ã¤ã³ã¿ã¼ãã«ãã¬ã¼ãã³ã° (ã¢ã¯ãã¬ããã°åç §ã®ãã¨)
- æ¥ã«é«è² è·ã®èªéã¹ã¯ã¯ãã3ã»ãã (1ã»ããã§æ©ãã®ãå°é£ã«ãªããããééã¯éãã¦ã)
- éèä¸å¿ã®é£äºã¨æ¯æ¥45g ã®ç´è±ãé£ã¹ã (çèéã®ããã«èãç±³ãé£ã¹ã)
- å¯ãããã«ã18:00é£äºã20:00風å(40度ã§BARTHã«20å)ã22:00æè»(ãªã¬ãã¬åç §ã®ãã¨)
- 妻ã¨éãã (家ã§ãã©ãã¿ãããæ ç»é¤¨è¡ã£ãããå¤é£ããããæãç¹ãã§å¯ã¦ããã£ããw)
BARTH é«ãããâ¦ãã§ãç¡ç ã®ããã«èª²éããã
2022å¹´12æ
12/1 å ¥é¢ãã12/2 å ¨èº«éº»é ã«ã¦åé¤ãããã¦ããã®è¨äºãæ¸ãã¦ããã®ã 12/3 (ä»æ¥)ãç¹ã« 12/3 ã¯ããã°ã 9 å¹´æ¯ãã«æ´æ°ãããã¨æãç«ã¤ãããæã ã£ãã
12/1 妻ã«ä»ãæ·»ããã¦å ¥é¢æç¶ããè¡ããç æ£ã®ãããã«æ¡å ããããã¨ãè·ç©ãç½®ãã¦å¦»ã¨å ±ã«æ¡å ã®ã³ã³ããã¸è²·ãåºãã¸ãç é¢ã«æã¡è¾¼ãã ã®ã¯ãä¸çãã¹ããã©ãã¹ããã©å é»ç¨ã®ã±ã¼ãã«ããã¹ã¯ã®ã¿ã§ãä»ã®å¿ è¦ãªãã®ã¯ãã¬ã³ã¿ã«ã¨ç¾å°èª¿éãå¯è½ãããããã³ã³ããã¯é»åããã¼ãã¬ã³ã¿ã«ã¯éé¢æã®å¾æããå¯è½ãªã®ã§ãã¹ããã©ãããã°è²¡å¸ãä¸è¦ã
ã³ã³ããã§è³¼å ¥ãããã®ã¯æ¬¡ã®éãã
- æè¡æã«çç¨ããTåä½(ãµãã©ã)
- é£å¨ç¨æ´å¤ã¨ã¹ãã³ã¸
- ããã¯ã
ã¬ã³ã¿ã«æç¶ããããã®ã¯æ¬¡ã®éãã
- ãã¸ã£ã
- ãã¹ã¿ãªã«ã¨ãã§ã¤ã¹ã¿ãªã«
- æ¯ãã©ã·ãæ¯ç£¨ãç²ãã³ãããã·ã£ã³ãã¼ããªã³ã¹ãããã£ã¼ã½ã¼ã (ã¬ã³ã¿ã«å±ã ãã©è²·ãåã)
ãã®å¾ã妻ã¨é¢å ã®ã«ãã§ã§ã³ã¼ãã¼ã飲ãã§ãéè«ãã¦è§£æ£ãã³ããç¦ã§ä¸åº¦ç æ£ã«æ»ãã¨é¢ä¼ã§ããªããããè¡åã¯ä¼ãã«æ¥ãªãã¦è¯ãã¨ä¼ããããã ãè¡å¾ããã«ã¯ãä¼ããããã¼ã¨ã ãä¼ãã¦è§£æ£ããã®æ¥ã®ãæ¼ããã¯æãã¨æã£ã¦ãããã麻é ç§å»ãæ¯ç§å»ãå£è å¤ç§å»ã®å診ããæè¡åã®æ¯ç³åããªã©ãããããããªã«æã§ã¯ãªãã£ãããæ¼ã¨å¤ã¯ãç æ£ã®ã飯ãé£ã¹ãããã¨ã¦ãç¾å³ãã£ããçæ¤ã®å·ãçãã¦ãããé£ã¹ããã®å ¨ã¦ãç¾å³ãæããããããã®ããã ã¨æãããæ¼ã飯ã®å¾ã«ã¯ãæ°æã¡ãè½ã¡çãããããã«ã¹ã¯ã¯ããããã¾ãã£ãããã¯ããã¹ã¯ã¯ããã¯ç²¾ç¥å®å®å¤ã
å¤ãã·ã£ã¯ã¼ãæµ´ã³ãæ示éãã«è¶³ã®è£ã«æ²¹æ§ãã³ã§åå(æ¼¢åãã«ãã¼ã )ãæ¸ãå ¥ãããããã«å ¥ããããããããããåºãèä¸ãè °ãçããªããã¾ããç¿æ¥ã®æè¡ã®è¿ éç ç診æã®çµæããè¡å¾ã®çã¿ãæããªã£ã¦ãã¾ããçµå±ã1æéç½®ãã«ç®ãè¦ãã¦ãã¾ã£ãã
12/2 æä¸ã®æè¡ã§ããã¤ãè¡å¾ã¯ãã°ããã·ã£ã¯ã¼ãæµ´ã³ããªãã¨ã®è©±ã ã£ãã®ã§ã7:00 ã«ç 室ã«åãä»ãã®ã·ã£ã¯ã¼ãæµ´ã³ã¦è½ã¡çããåãæ»ãã8:00 ã«ãµãã©ããç· ãããªãçãè¦ã«ã¾ã¨ããæãéçºã«æºãã£ãã½ã·ã£ã²ã®ãã¤ãªã¼ããã·ã§ã³ãæ¶åããã®ã«ã¡ã³ã«æ¨æ¶ãã¦ã¹ããã©ãéµä»ãã®ç®±ã«å ¥ãã¦ããè¿ããå¾ ã£ãããã®å¾ããè¿ãã®çè·å¸«ãããæ¥ãã®ã§ããããªã室ã¸ããªã室ã¸ç§»åãã¦ããã¨ããªãäºå®ã®æ£è ã®æ¹ãã©ãã©ãåæµãã¦ãã¦ããããªã«å¤§å¢ãæããæè¡ãåããã®ãâ¦ã¨å§åãããã
ãã®å¾ãååãå¼ã°ããä½ç¹ã確èªãã¦ãªã室ã¸ç§»åã移åä¸ãæ§ã ãªæ©å¨ã大éã«ç½®ããã¦ããã®ãèå³æ·±ããåçãæ®ããããªã¼ã¨ãã§ããã§ãè¦åãã¦ãããããã«ãªã室ã«å°çãå·åã®ä¸»æ²»å»ãè¦å½ããããå¿ç´°ããªããã麻é ç§å»ã¨æ¨æ¶ãã¦æ示ã«å¾ããç¹æ»´ã®éãå ¥ãã¾ããã¼ã¨è¨ããããã¨ãä½åº¦ããã¹ãã¹åºãããçãã£ãã¨è¨ã£ãããå¥ã®éº»é ç§å»ãéãå ¥ãã¦ããããã¡ãã£ã¨ããããªãã§å¤§ä¸å¤«ï¼ã¨æã£ã¦ããããé ¸ç´ ãã¹ã¯ãã¤ãããããã¾ãã¯é ¸ç´ ã§ããã¼ãã¨è¨ãããå¾ã®è¨æ¶ããªãâ¦ã
æ°ãã¤ããæã主治å»ã®å çãç§ã®ä¹ã£ãããããæ¼ããªãããããçµããã¾ãããã¼ã10:30 ã§ããã¼ããã¨è©±ãããã¦ãã¦è¦éãããå çã®é¡ãè¦ãã¦å®å¿ãã¾ããã¼ã¨çããè¨æ¶ããã£ããããw
ããããå¾ æ©å®¤ã§30åå¾ ã¤ãã¨ã«ãåãæ°ãããã°æãã¦æ¬²ããã¨ã®ãã¨ã§ãåãããã¨ä¼ãããã大ããªã²ãããåºãã ãã§ã¹ãããªãã¦ãã¾ã£ããã¨ã¯è¨ããåãæ°æ¢ãã®è¬ãç¹æ»´ã«å ¥ãã¦ãããã
30åå¾ãç æ£ã®çè·å¸«ã«èº«æãå¼ãç¶ãããç 室ã¸ç§»åã移åä¸ãç æ£ã®çè·å¸«ããã«ãèãé«ãã§ããã¼ã¨ãéè«ãæ¯ãããã®ã§ãé å¼µã£ã¦åãçããã¦ã¿ãããè¨æ¶ãææ§ã§ä½ã¨çãããè¦ãã¦ããªããéä¸ãçè·å£«ããããå®ã¯å¥¥ãããæ¥ã¦ããã®ã§ãç æ£ã®å ¥ãå£ã§å°ãã ãä¼ãã¾ãã¨æãã¦ãããã妻ã«ã¯è¡å¾ã«ä¼ã£ã¦ç¡äºãç´æ¥ä¼ãããã£ãã®ã§ãä¼ãã¦æ¬å½ã«è¯ãã£ããããããç§ã¯å¦»ã«ä½ãä¼ããã®ããæèæ¦æ§ã¨ãã¦ãã¦ããã¾ãè¨æ¶ã«æ®ã£ã¦ããªããã¨ã¯è¨ã妻ãæ°ããèã®æè¡ããã¯ããªã®ã«ãã¯ã£ãã話ãã¦ãããã¨ã®ãã¨ã
ãã®å¾ãä¸æéãæç¡ãã§é ¸ç´ å¸å ¥ã®åãã¹ã¿ã¼ããå¯ã¦ããéãããã¨æã£ããå¯ãããã¹ããã©ã触ã£ã¦ä½ã¨ãããéãããé ¸ç´ ãã¹ã¯ãå¤ããå¾ãã»ã¼å裸ã®è²§ã¼ã£ã¡ãã¾ã¹ã¿ã¤ã«ãããã¸ã£ãã«çæ¿ããç¹æ»´ããæçç©è³ªãå ¥ãã¦ãããã¤ã¤å®éã«ãããã¨ã«ãã¨ããããã¹ããã©ã§æ¹ã ã¸ãæè¡çµãã£ã¦è¦éãããã¼ãã®é£çµ¡ãå ¥ãã¾ããã
ãã°ããããã¨ã主治å»ã®å çãæ¨æ¶ã«æ¥ã¦ããã¦ãä¸åã®åé¤ã§çµãããè¿ éç ç診æã¯ä¸ä¸å·¦å³å¥¥ã®5æ¹åã«åé¡ãªãã妻ã«ãããã説æãããã¨ãªã©æãã¦ããã£ããã¾ããå¾ã§å診ã§å¤§å¢ã§æ¥ããã©ãå¯ã¦ã¦è¯ããããã¼ã¨ã®ãã¨ãããã¦ãä»æ¥ããå¤ã飯é£ã¹ã¦è¯ããããç æ£ã«ä¼ãã¦ãããã¼ã¨ã®ãã¨ããâ¦é£ã¹ããã®ãæãããâ¦ã¨æã£ãããæ©ãéé¢ãããããææ¦ãããã¨ã«ãçµæãå®é£ã§ãããçã¿æ¢ãã®æä¸ãããã¦ããªãã®ã«çããªããâ¦ã
ãã®å¤ãç é¢ã®ãããã硬ãçç±ã調ã¹ãè§åº¦ãå¤ãããªã©ã®å·¥å¤«ã§ãè °ãèä¸ã®çã¿ã軽æ¸ããããã¨ãç¥ããç§çã«ã¯å¯ãæã«14度ãèµ·ãã¦ãæã¯46度ãè¯ãã£ããã¾ããç¹æ»´ããã¦ããã¨ãã¤ã¬ãè¿ããªãããé »ç¹ã«ãã¤ã¬ã«è¡ãã®ã ãããã®åº¦ã«è¡ãéæµãããããããå¿èããéã®åºãã£ã¦ãç®æãä½ãããã¨è§£æ¶ãããããã¨ãã½ã·ã£ã²çµç±ã§ã®ã«ã¡ã³ã«æãã¦ããã解決ã
12/3 硬ããããã¨ç¹æ»´ã®ããã§ããã¾ãããå¯ããããã¤ã6:00 ããããã£ãããæ¢ã¾ããªããªããã飯ãé£ã¹ã¦èã温ã¾ãã¨ããã£ããã¯æ¢ã¾ããå·ãããã®ã飲ãã¨ããã£ãããå§ã¾ããã¨ã«æ°ãã¤ãã軽ã調ã¹ã¦ã¿ãã¨å ¨èº«éº»é ã®ä¸æçãªå¾éºçããããã¨ããããã8:00é ã«çè·å¸«ããã«ãã風åã«å ¥ã£ã¦çæ¿ãããæ¨ãä¼ããã¨ãå®ã¯å¤æ¥ããå¼ã°ãã¦ããã®ã§ãå ã«ãã£ã¡ã«è¡ã£ã¦ã¼ã¨ã®ãã¨ãä»æ¹ãªãã®ã§ç¹æ»´ãå¼ããã£ã¦å¤æ¥ã¸è¡ãã¨ãéä¸ã§ä¸»æ²»å»ã®å çã¨åæµãã¡ãã£ã¨ç§»åãæä¼ã£ã¦ãããã¤ã¤åä»ã§å¾ ã£ã¦ã¦ãã¼ã¨åãããããã®å¾ã診å¯å®¤ã§è¨ºå¯ãåãããã®æ²»ãå ·åãªã 12/5 ã«éé¢ãã¦è¯ããç¹æ»´ãããã«å¤ããã¨ã«ãé½åæªããã°ããã£ã¨å ¥é¢ã§ãããã©â¦ã¨ãªããããããã絶対帰ãã¾ãï¼ã¨çããããã®å¾ãç 室ã§çè·å¸«ã«ç¹æ»´ãã¨ã£ã¦ãããã念é¡ã®ã·ã£ã¯ã¼ã¨ãçæ¿ãã麻é ç§å»ã«çã¿æ¢ãä¸åãå¦æ¹ããã¾ããã§ãããâ¦ã¨è¨ããããããªã«çã¿ãæãã¦ããã®ã¯ä½ã ã£ãã®ãã¨ãèªåèªèº«ã«åãããå¤åã主治å»ã®è ãè¯ããããããããªãããä¸æºåã§çãã¬ãã¦ãããã®ãå¹ããã®ãããããªãããæ¼ã飯ãé£ã¹ã¦ããã£ãããæ¢ã¾ã£ãã®ã§ãã¹ã¯ã¯ããããã¦ä¸ä¼ã¿ãã¦ãããé¢å ã®åºåã«éã³ã«è¡ããå¤ã®å·ãã空æ°ãå¸ã£ããããã£ããåçºãã³ã³ããã«å¯ã£ã¦ãè¶ãè³¼å ¥ããé»åã¬ã³ã¸ã§æ¸©ãã¦æãåããã¨ã«ã
ç¶ãã«é¢ãã¦
æé軸ãä»ã«è¿½ãã¤ããã®ã§ãä¸æ¦ãããã§çãç½®ãã¾ãããããããéé¢ããå¾ã転移ã«åãã¦äºé±éã«ä¸åãã¼ã¹ã§ãªã³ãç¯ã®æ§åãè¦ã¦è¡ãå¿ è¦ãããã¾ãããåã£ãé¨ä½ã®ç çæ¤æ»ã®çµæã確èªããå¿ è¦ãããã¾ããæä½äºå¹´ã¯ç é¢ã¸éããã¨ã«ãªããããæ°ãåããããç¶ããæ¸ããã¨æãã¾ãã
æå¾ã«
家æã妻ã®è¦ªæãå人ãååã«å¿é ãããã¦æ¬å½ã«ç³ã訳ãªãã¨æãã¤ã¤ããæ§ã ãªæ¹æ³ã§ãµãã¼ããããã ãæ¬å½ã«æè¬ãã¦ãã¾ããå¿ ãåããæ©ã¯è¿ãã¾ããç¹ã«å¦»ã«ã¯ãæ¬å½ã«æè¬ãã¦ãããããä½ãè¿ãã¦è¯ãã®ãæ³åãã¤ããªããã©ãä¸çãããã¦ä½ã幸ãçãªãã®ãè¿ãã¦è¡ãã¾ãã
RabbitMQ 3.x ãã Queue ã®ãã©ã¼ãªã³ã°æ¹æ³ãå¤æ´ã«ãªã£ã
ä»ã¾ã§, Queue ä½ææã«æå®ãã¦ãããã©ã¼ãªã³ã°ã®ãã©ã¡ã¼ã¿ã¯å»æ¢ã«ãªã, rabbitmqctl ã³ãã³ãã§æå®ããããã«å¤æ´ãªã£ã.
Perl ã® AnyEvent::RabbitMQ ã Python ã® kombu(celery) 㧠x-ha-policy ãæå®ããæ¹æ³ã¯, RabbitMQ 2.x ã¾ã§ããéç¨ããªã.*1
çµç·¯ã詳細ã¯, ä¸è¨äºã¤ãåç §ã®äº.
- RabbitMQ >> Blog Archive >> Breaking things with RabbitMQ 3.0 - Messaging that just works
- RabbitMQ - Highly Available Queues
æå®æ¹æ³
Web UI ã® Manage Console ãããæå®ã§ããã, ä»å㯠rabbitmqctl ã®ä¾ãæãã.*2
Usage ã¯ä¸è¨ã®éã.
$ rabbitmqctl set_policy <ããªã·ã¼ã®åå> <ãã¿ã¼ã³> <ã¢ã¼ã> [<åªå 度>]
ããªã·ã¼å | ããªã·ã¼ãä¸æã«ã, æ´æ°ãåé¤ã®æä½å¯¾è±¡ã¨ãã. |
---|---|
ãã¿ã¼ã³ | ãã¥ã¼åããã¿ã¼ã³ã«ãããããå ´å, ããªã·ã¼ã®å¯¾è±¡ã¨ãã. æ£è¦è¡¨ç¾ã使ãã. |
ã¢ã¼ã | RabbitMQ - Highly Available Queues åç §ã®äº. |
åªå 度 | æ°å¤ãé«ãç¨, åªå . æªæå®ã§ 0 ãå ¥ã. |
æå®ä¾
å ¨ã¦ã®ãã¥ã¼ããã©ã¼ãªã³ã°ãã(ãã®ããè¨å®w;).
$ rabbitmqctl set_policy all '^.*' '{"ha-mode": "all"}'
ãã¥ã¼åã®æ¥é è¾ã« ha ãä»ããå ´åã«ãã©ã¼ãªã³ã°ãã.
$ rabbitmqctl set_policy ha-all "^ha\." '{"ha-mode":"all"}'
ãã¥ã¼åã®æ¥é è¾ã« amq ãä»ããå ´å(ãã¥ã¼åãæå®ãã, RabbitMQ ã«èªåæ¡çªãããå ´å) "以å¤" ã«ãã©ã¼ãªã³ã°ãã.
$ rabbitmqctl set_policy ha-ignore-amq '^(?!amq\.).*' '{"ha-mode": "all"}'
éç¨ä¸ã«ããªã·ã¼ã®å¤æ´ãå¯è½ãããã, æ¤è¨¼ã¯ããããè¡ãäºå®.
éç¨ä¸ã«ããªã·ã¼ã®å¤æ´ã¯å¯è½. ã¾ã, ã¯ã©ã¹ã¿ãªã³ã°æã® Manage Console ã®ããªã·ã¼è¡¨è¨ãå¤ã ã£ãã®ã§, ä¸è¨ã®ã³ãã³ãã§åä½ç¢ºèªããæ¹ãè¯ã.
$ rabbitmqctl list_queues name policy pid owner_pid slave_pids messages_ready messages_unacknowledged messages
å°, ããªã·ã¼ã¯, ãã¿ã¼ã³ã«ããããã Exchange ã«ãé©ç¨ããã¦ãã. ããã, ã©ã®ãããªå½±é¿ãåã¼ãã®ãã¯èª¿æ»ä¸.
Python ã® amqplib ã¨ã py-amqp 㧠Message ã Consume ããé, ãããã« x-death ãä»ä¸ããã¦ããã¨è½ã¡ã件
ãã¼ã¿ã«è¬ã® 'A' ã¨ããåãå®ç¾©ããã¦ããã®ãåé¡. AMQP ã® Elementary domains ãè¦ãã®ã ããã© 'A' ãä½ãè¦å½ãããªãâ¦ãå©ãã¦åã人orz
ã¨ãããã, amqplib 1.0.2 ã¯, 以ä¸ã®é»éè¡ã§åé¿å¯è½. kombu 2.5.0 ãã amqplib ã«ä»£ãã py-amqp ãããã©ã«ãã§ä½¿ç¨ãããã®ã ããã©, ãã¡ãã¯ãããã.
from struct import unpack from decimal import Decimal from amqplib.client_0_8.serialization import AMQPReader def _patched_read_table(self): """ Read an AMQP table, and return as a Python dictionary. """ self.bitcount = self.bits = 0 tlen = unpack('>I', self.input.read(4))[0] table_data = AMQPReader(self.input.read(tlen)) result = {} while table_data.input.tell() < tlen: name = table_data.read_shortstr() ftype = ord(table_data.input.read(1)) if ftype == 65: # 'A' ãããæ°ããå ãã£ã!! len = unpack('>I', table_data.input.read(4))[0] ftype = ord(table_data.input.read(1)) if ftype == 83: # 'S' val = table_data.read_longstr() elif ftype == 73: # 'I' val = unpack('>i', table_data.input.read(4))[0] elif ftype == 68: # 'D' d = table_data.read_octet() n = unpack('>i', table_data.input.read(4))[0] val = Decimal(n) / Decimal(10 ** d) elif ftype == 84: # 'T' val = table_data.read_timestamp() elif ftype == 70: # 'F' val = table_data.read_table() # recurse else: raise ValueError('Unknown table item type: %s' % repr(ftype)) result[name] = val return result AMQPReader.read_table = _patched_read_table
Python Web Framework Advent Calendar 2012 (9æ¥ç®) Django Model 㧠Named Scope
åç½®ã
ãã®è¨äºã¯ã2012 Pythonアドベントカレンダー(Webフレームワーク) - connpass ã® 9 æ¥ç®ã®è¨äºã¨ãªãã¾ãã
ä»åã¯ãRails ã® Named Scope ã®çä¼¼ã Django Model ã§å®ç¾ããæ¹æ³ã¨ããããå©ç¨ããè«çåé¤ã®ç´¹ä»ãè¡ãã¾ãã
Django Model 㧠Named Scope ãå®ç¾ãã
ããããä½ããããã®ã?
ã¾ããECãµã¤ããã½ã·ã£ã²ã¼çã®ã¦ã¼ã¶æ å ±ãããæè¿ç»é²ããã¦ã¼ã¶ã®ä¸ããç´è¿ã®ã¢ã¯ã»ã¹é ã«ä¸ä½5人ãåå¾ããä¾ãæãã¾ãã
import datetime from django.utils.timezone import get_default_timezone # ä¸é±é以å ã®ç»é²ã "æè¿ç»é²ãã" ã¨ã¿ãªã dt = datetime.datetime.now() - datetime.timedelta(weeks=1) # utc ã§ãè¯ãããã©ãä½ã¨ãªããã¼ã«ã©ã¤ãº dt = get_default_timezone().localize(dt) User.objects.filter(created_at__gt=dt).order_by('-logged_in_at')[:5]
Named Scope ã使ç¨ããã¨ã次ã®ããã«ãªãã¾ãã
User.objects.by_newbie().order_by_active()[:5]
Named Scope ãä½ã
ã§ã¯ãå®éã®å®ç¾æ¹æ³ãç´¹ä»ãã¾ãã
import datetime from django.utils.timezone import get_default_timezone from django.db import models from django.db.models.query import QuerySet # Manager 㨠QuerySet ã§åæ§ã®ã¡ã½ããã使ç¨ããã®ã§ Mix-in Class ã¨ãã¦åãåºã class UserScopesMixin(object): _newbie_term = datetime.timedelta(weeks=1) def by_newbie(self): dt = datetime.datetime.now() - self._newbie_term dt = get_default_timezone().localize(dt) return self.filter(created_at__gt=dt) def order_by_active(self): return self.order_by('-logged_in_at') # QuerySet ã« Scope ã Mix-in ãã # ç¶æ¿é ã¯è³å¦åãããæã§ããããã®è¨äºã§ã¯ã社å ã®ç®ãããã®ã§ Mix-in Class ãå¾ãã«ç¾ åãã¾ã(w; # è足ã§ãããç§ã¯ãç§ç¨ã§ Python ãæ¸ãå ´åã«éããMix-in Class ãåã«ç¾ åããæ´¾ã§ã class UserQuerySet(QuerySet, UserScopesMixin): pass # Manager ã« Scope ã Mix-in ã, ä¸è¨ã§å®ç¾©ãã QuerySet ãè¿ãããã«ãã class UserManager(models.Manager, UserScopesMixin): def get_query_set(self): return UserQuerySet(self.model) # ä¸è¨ã§å®ç¾©ãã Manager ã objects ã«è¨å®ãã class User(models.Model): objects = UserManager() created_at = models.DateTimeField(auto_now_add=True, index=True) logged_in_at = models.DateTimeField(auto_now=True) @classmethod def get_active_newbies(cls, limit=5): return User.objects.by_newbie().order_by_active()[:limit]
çµå±ãget_active_newbies() ãå®ç¾©ããã®ã§ããã°ãNamed Scope ãªãã¦ä¸ç¨ã§ã¯ãªããï¼ã¨æãããããããã¾ããã
ããããget_active_newbies() ã®æ§ãªã¡ã½ãããå¤æ°å®ç¾©ããå ´åãã¹ãããªæ¸ããã®ã§ãªã¹ã¹ã¡ã§ãã
ã¾ããNamed Scope ãçã«ãªã£ã¦ããã¨ããããã QuerySet ãã«ã¹ã¿ã æ¸ã¿ã§ãããããä»ã®ã«ã¹ã¿ã QuerySet ãçµã¿è¾¼ãéã«å´åãæ¸ãã¨ããå¯ä½ç¨ãããã¾ãã*1
è«çåé¤ã®å®ä¾
ç©ççã«ã¬ã³ã¼ããåé¤ããã«ãåé¤ãã©ã°ãç«ã¦ã¦åé¤ããäºã«ããã¢ã¬ã
class LogicalDeleteScopesMixin(object): def by_alive(self): return self.filter(deleted_uuid='') def delete(self): self.update(deleted_uuid=uuid.uuid4(), deleted_at=datetime.datetime.now(pytz.utc)) class LogicalDeleteQuerySet(QuerySet, LogicalDeleteScopesMixin): pass class LogicalDeleteManager(models.Manager, LogicalDeleteScopesMixin): def get_query_set(self): return LogicalDeleteQuerySet(self.model).by_alive() # Mix-in Class ã§ãããããobject ãç¶æ¿ããããã # Django Model ã®å¶ç´ã«ãã models.Model ãç¶æ¿ããå¿ è¦ãããã class LogicalDeleteModelMixin(models.Model): class Meta: abstract = True class RedeletedError(Exception): pass objects = LogicalDeleteManager() # delete_at ãæå¹/ç¡å¹ã®ç¢ºèªã«å©ç¨ããã¨ã # ä¸æãã¼å¶ç´ãè¨ããéã«ãä¸ç§ä»¥å ã® delete ã使ããªãããã # æå¹/ç¡å¹ãå¤æããããã® UUID ãã£ã¼ã«ããè¨ããã # åæå¤ã« NULL ãæå®ããã¨ãNULL ã¯ã¬ã³ã¼ãæ¯ã«ç°ãªãå¤ã¨èªèãããããã # UUID ãã£ã¼ã«ããä¸æãã¼å¶ç´ã«å«ããããªãã # ããã§ãåæå¤ã«ã¯ç©ºæååãæ示çã«æå®ãã¦ããã deleted_uuid = models.CharField(max_length=255, db_index=True, default='') # 念ã®ãããè¨é²ã¨ãã¦åé¤æ¥æãæ®ãã¦ããã deleted_at = models.DateTimeField(blank=True, null=True) def delete(self): if self.deleted_uuid: raise self.RedeletedError, self.pk self.deleted_uuid = uuid.uuid4() self.deleted_at = datetime.datetime.now(pytz.utc) self.save()
æ©éãå ã»ã©ã® User Model ã§ä½¿ç¨ãã¦ã¿ã¾ãããã
# LogicalDeleteScopesMixin ãç¶æ¿ãã class UserScopesMixin(LogicalDeleteScopesMixin): pass # å 容ã«å¤æ´ããªãããçç¥ # LogicalDeleteScopesMixin ãç¶æ¿ã㦠UserScopesMixin ãå®ç¾©ããã®ã§ # UserQuerySet ã«å¤æ´ã¯ãªãã class UserQuerySet(QuerySet, UserScopesMixin): pass # by_alive() ã使ç¨ããå¿ è¦ããã class UserManager(models.Manager, UserScopesMixin): def get_query_set(self): return UserQuerySet(self.model).by_alive() class User(models.Model, LogicalDeleteModelMixin): pass # å 容ã«å¤æ´ããªãããçç¥
ãã®ä»
ç§ã¯ãPython æ´ = Django æ´ = åå¹´æªæºã§ãããDjango 以å¤ã®ä»ã® Python Web Framework ã®ç¥èã¯çç¡ã¨ããç¶æ ã§ãããä»åç´¹ä»ããã¦é ãã Named Scope ããClass Based View ã®åå¨ãããDjango 㯠OO è¨è¨ãæããã¬ã¼ã ã¯ã¼ã¯ã ã¨èªèãã¦ããããããããæ«æ°¸ããä»ãåãã§ããã°å¬ãããªããã¨èãã¦ããã¾ãã
åè URL
ZeroMQ Erlang Binding(NIF) ã® inproc 㨠Erlang ã®ç´ ã®ã¡ãã»ã¼ã¸éä¿¡ã®é度ãæ¯è¼ãã¦ã¿ã
ã³ã¼ãã¨çµæã¯ä¸è¨ã®éã
https://gist.github.com/3193117
Erlang ã§ä½ã£ããµã¼ãã« LL ã§ä½ã£ãã¯ã¼ã«ã¼ãã¶ãä¸ãããã¨èãã¦ãããã©ãããªããã¦ã§ã¤ã³ã°ãª ZeroMQ ãéã«å
¥ãã¦ã¿ããã¨æãç«ã¡ã¾ããã
ãºãã©ãªç§ã¯ãZeroMQ ã«ã¯ã¼ã«ã¼ã®ãã¼ããã©ã³ã¹ããã¦æ¬²ããã£ãã®ã§ãErlang ã®ä¸ã§ Queue ããã¤ã¹ã使ç¨ããããã«è¤æ°ã® Erlang ããã»ã¹ãã inproc ã§ã¡ãã»ã¼ã¸ãéä¿¡ãã¾ããäºå®ã§ããã
ããããããã¾ã§ç´ ã®ã¡ãã»ã¼ã¸éä¿¡ã¨é度ã«å·®ããããªããErlang ã®ä¸ã§èªåã§ãã¼ããã©ã³ã¹ããæ¹ãè¯ãããããªãã¨â¦æãç´ãã¦ã¾ãã
ã¡ãªã¿ã«ãinproc ã使ã£ã¦ã¿ã¦åãã¦æ°ãã¤ããã®ã§ãããinproc ã¯ä»ã®ãã©ã³ã¹ãã¼ãã¨ä¸è¨ã®ç¹ã§ç°ãªãã¾ãã
- bind 㨠connect ã«ä½¿ãã³ã³ããã¹ãã¯åãç©ã§ãªããã°ãããªã
- connect ã®åã«å¿ ã bind ãè¡ãå¿ è¦ããã
100ãã¹è¨ç®ã®ã·ã¼ããçæãã
ããºã«æ室ã«ã¦å¨ã®æ°å¦çã»ã³ã¹ããã¿è¤ãããããã®ã®ãè¨ç®é度ãé
ãã®ã§100ãã¹è¨ç®ã家æã§ããããã«ã¨æ示ãåããã
æ©éãPython ã§100ãã¹è¨ç®ã·ã¼ãã HTML å½¢å¼ã§åºåããã³ãã³ããä½æããã®ã ãã身è¿ã« Haskeller ãå±
ãã®ã ãã Haskell ã§æ¸ãã¦æ·»åãã¦ããããã¨æãç«ã£ããã±ã¼ãä¸åãã§è«ãè² ã£ã¦ãããã ãããï¼w;
ã¨ãããããæ·»ååã®ã³ã¼ããæãã¦ãããæ·»åå¾ã«ã¯ããã£ã¨ç¾ããé«æ©è½(ä¾ãã° HTML ã§åºåããæ©è½ãå ãã£ããâ¦)ã«ãªãäºå®ã
import System.Random import System.IO import Data.List gen_cells :: Integer -> Integer -> IO [String] gen_cells min max = do gen <- newStdGen return $ take 10 $ map (\n -> show n) $ randomRs (min, max) gen i2path :: Integer -> String i2path i = "./" ++ show i ++ ".txt" print_table :: String -> String -> [String] -> [String] -> IO () print_table path method x_cells y_cells = do let head = concat $ intersperse " " x_cells let head_line = method ++ " " ++ head let lines = head_line : y_cells withFile path WriteMode $ \handle -> do sequence_ $ map (hPutStrLn handle) lines mk_html' :: Integer -> String -> (Integer, Integer) -> (Integer, Integer) -> IO () mk_html' n method (x_min, x_max) (y_min, y_max) = do x_cells <- gen_cells x_min x_max y_cells <- gen_cells y_min y_max print_table (i2path n) method x_cells y_cells mk_html :: Integer -> IO () mk_html n | n `rem` 4 == 1 = mk_html' n "ï¼" (1, 99) (1, 99) | n `rem` 4 == 2 = mk_html' n "â" (50, 99) (0, 49) | n `rem` 4 == 3 = mk_html' n "Ã" (1, 99) (0, 9) | otherwise = mk_html' n "÷" (1, 99) (1, 9) main = sequence_ $ map mk_html [1..20]
æ©éããªãã¡ã¯ã¿ãã¦é ããã®ã§ã³ã¼ããå ¬é
{-# LANGUAGE TemplateHaskell, QuasiQuotes #-} import System.Random import System.FilePath import System.IO import Data.List import Control.Applicative import Text.Hamlet import Text.Blaze.Html.Renderer.String import Text.Blaze data Method = Plus | Minus | Mult | Div type Range = (Integer, Integer) type Cells = [Integer] type Answers a = [[a]] get_calc_fun :: Method -> Integer -> Integer -> Integer get_calc_fun Plus = (+) get_calc_fun Minus = (-) get_calc_fun Mult = (*) get_calc_fun Div = div method2str :: Method -> String method2str Plus = "ï¼" method2str Minus = "â" method2str Mult = "Ã" method2str Div = "÷" gen_cells :: Range -> IO Cells gen_cells range = (take 10 . randomRs range) <$> newStdGen calc_answer :: Method -> Cells -> Cells -> Answers Integer calc_answer method x_cells y_cells = let f = get_calc_fun method in [[f x y | x <- x_cells] | y <- y_cells] null_answer :: Answers Integer -> Answers String null_answer answers = map (map (const "")) answers i2path :: String -> Integer -> FilePath i2path p i = "." </> (p ++ show i) <.> "html" -- Integer ã String 㯠ToMarkup ã®ã¤ã³ã¹ã¿ã³ã¹ print_table :: ToMarkup a => FilePath -> Method -> Cells -> Cells -> Answers a -> IO () print_table path method x_cells y_cells answers = do let rows = zip y_cells answers writeFile path $ renderHtml [shamlet| !!! <head> <title>100cells <body> <table> <tr> <th>#{method2str method} $forall x <- x_cells <th>#{x} $forall (y, zs) <- rows <tr> <th>#{y} $forall z <- zs <td>#{z} |] mk_html' :: Integer -> Method -> Range -> Range-> IO () mk_html' n method x_range y_range = do x_cells <- gen_cells x_range y_cells <- gen_cells y_range let answers = calc_answer method x_cells y_cells print_table (i2path "a" n) method x_cells y_cells answers print_table (i2path "p" n) method x_cells y_cells $ null_answer answers mk_html :: Integer -> IO () mk_html n | n `rem` 4 == 1 = mk_html' n Plus ( 1, 99) (1, 99) | n `rem` 4 == 2 = mk_html' n Minus (50, 99) (0, 49) | n `rem` 4 == 3 = mk_html' n Mult ( 1, 99) (0, 9) | otherwise = mk_html' n Div ( 1, 99) (1, 9) main = mapM_ mk_html [1..20]